mirror of
https://github.com/Jackzmc/sourcemod-plugins.git
synced 2025-05-06 16:43:21 +00:00
Merge branch 'master' of github.com:Jackzmc/sourcemod-plugins
This commit is contained in:
commit
6ab22e8a60
5 changed files with 106 additions and 121 deletions
Binary file not shown.
|
@ -2,9 +2,12 @@
|
|||
|
||||
#define DEBUG
|
||||
|
||||
#define PLUGIN_VERSION "0.00"
|
||||
#define UPDATE_INTERVAL 6.0
|
||||
#define UPDATE_INTERVAL_SLOW 15.0
|
||||
// Update intervals (only sends when > 0 players)
|
||||
// The update interval when there are active viewers
|
||||
#define UPDATE_INTERVAL 5.0
|
||||
// The update interval when there are no viewers on.
|
||||
// We still need to poll to know how many viewers are watching
|
||||
#define UPDATE_INTERVAL_SLOW 20.0
|
||||
|
||||
#include <sourcemod>
|
||||
#include <sdktools>
|
||||
|
@ -18,9 +21,9 @@ public Plugin myinfo =
|
|||
{
|
||||
name = "Admin Panel",
|
||||
author = "Jackz",
|
||||
description = "",
|
||||
version = PLUGIN_VERSION,
|
||||
url = ""
|
||||
description = "Plugin to integrate with admin panel",
|
||||
version = "1.0.0",
|
||||
url = "https://github.com/jackzmc/l4d2-admin-dash"
|
||||
};
|
||||
|
||||
ConVar cvar_debug;
|
||||
|
@ -82,10 +85,10 @@ public void OnPluginStart()
|
|||
#define DATE_FORMAT "%F at %I:%M %p"
|
||||
Action Command_PanelStatus(int client, int args) {
|
||||
ReplyToCommand(client, "Active: %b", updateTimer != null);
|
||||
ReplyToCommand(client, "Last Error Code: %d", lastErrorCode);
|
||||
ReplyToCommand(client, "#Players: %d", numberOfPlayers);
|
||||
ReplyToCommand(client, "Update Interval: %0f s", fastUpdateMode ? UPDATE_INTERVAL : UPDATE_INTERVAL_SLOW);
|
||||
char buffer[32];
|
||||
ReplyToCommand(client, "Last Error Code: %d", lastErrorCode);
|
||||
if(lastSuccessTime > 0)
|
||||
FormatTime(buffer, sizeof(buffer), DATE_FORMAT, lastSuccessTime);
|
||||
else
|
||||
|
@ -99,7 +102,7 @@ void TryStartTimer(bool fast = true) {
|
|||
fastUpdateMode = fast;
|
||||
float interval = fast ? UPDATE_INTERVAL : UPDATE_INTERVAL_SLOW;
|
||||
updateTimer = CreateTimer(interval, Timer_PostStatus, _, TIMER_REPEAT);
|
||||
PrintToServer("[AdminPanel] Timer created, updating every %.1f seconds", interval);
|
||||
PrintToServer("[AdminPanel] Updating every %.1f seconds", interval);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -205,7 +208,7 @@ void Callback_PostStatus(HTTPResponse response, any value, const char[] error) {
|
|||
PrintToServer("[AdminPanel] Response: OK/204");
|
||||
// We have subscribers, kill timer and recreate it in fast mode (if not already):
|
||||
if(!fastUpdateMode) {
|
||||
PrintToServer("[AdminPanel] We have subscribers, increasing interval");
|
||||
PrintToServer("[AdminPanel] Switching to fast update interval for active viewers.");
|
||||
if(updateTimer != null)
|
||||
delete updateTimer;
|
||||
TryStartTimer(true);
|
||||
|
@ -215,7 +218,7 @@ void Callback_PostStatus(HTTPResponse response, any value, const char[] error) {
|
|||
lastErrorCode = 0;
|
||||
// We have no subscribers, kill timer and recreate it in slow mode (if not already):
|
||||
if(fastUpdateMode) {
|
||||
PrintToServer("[AdminPanel] No subscribers, decreasing interval");
|
||||
PrintToServer("[AdminPanel] Switching to slow update interval, no viewers");
|
||||
if(updateTimer != null)
|
||||
delete updateTimer;
|
||||
TryStartTimer(false);
|
||||
|
@ -366,6 +369,7 @@ JSONObject GetPlayer(int client) {
|
|||
player.SetInt("joinTime", playerJoinTime[client]);
|
||||
player.SetInt("permHealth", GetEntProp(client, Prop_Send, "m_iHealth"));
|
||||
if(team == 2) {
|
||||
// Include idle players (player here is their idle bot)
|
||||
if(IsFakeClient(client)) {
|
||||
int idlePlayer = L4D_GetIdlePlayerOfBot(client);
|
||||
if(idlePlayer > 0) {
|
||||
|
|
|
@ -559,6 +559,19 @@ stock void PrintChatToAdmins(const char[] format, any ...) {
|
|||
}
|
||||
PrintToServer("%s", buffer);
|
||||
}
|
||||
stock void CPrintChatToAdmin(const char[] format, any ...) {
|
||||
char buffer[254];
|
||||
VFormat(buffer, sizeof(buffer), format, 2);
|
||||
for(int i = 1; i < MaxClients; i++) {
|
||||
if(IsClientConnected(i) && IsClientInGame(i)) {
|
||||
AdminId admin = GetUserAdmin(i);
|
||||
if(admin != INVALID_ADMIN_ID) {
|
||||
CPrintToChat(i, "%s", buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
PCrintToServer("%s", buffer);
|
||||
}
|
||||
stock bool IsValidAdmin(int client, const char[] flags) {
|
||||
int ibFlags = ReadFlagString(flags);
|
||||
if ((GetUserFlagBits(client) & ibFlags) == ibFlags) {
|
||||
|
@ -567,21 +580,7 @@ stock bool IsValidAdmin(int client, const char[] flags) {
|
|||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
stock void NotifyAllAdmins(const char[] format, any ...) {
|
||||
char buffer[254];
|
||||
VFormat(buffer, sizeof(buffer), format, 2);
|
||||
for(int i = 1; i < MaxClients; i++) {
|
||||
if(IsClientConnected(i) && IsClientInGame(i)) {
|
||||
AdminId admin = GetUserAdmin(i);
|
||||
if(admin != INVALID_ADMIN_ID && admin.ImmunityLevel > 0) {
|
||||
PrintToChat(i, "%s", buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
PrintToServer("%s", buffer);
|
||||
}
|
||||
}
|
||||
|
||||
stock float GetNearestEntityDistance(int originEntity, char[] classname) {
|
||||
float compareVec[3], entityVecOrigin[3];
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include <sdkhooks>
|
||||
#include <jutils>
|
||||
#include <left4dhooks>
|
||||
#include <multicolors>
|
||||
|
||||
enum {
|
||||
Immune_None,
|
||||
|
@ -18,15 +19,6 @@ enum {
|
|||
}
|
||||
|
||||
bool lateLoaded, isFinaleEnding;
|
||||
// bool isPlayerTroll[MAXPLAYERS+1], isUnderAttack[MAXPLAYERS+1];
|
||||
// ImmunityFlag immunityFlags[MAXPLAYERS+1];
|
||||
// int iJoinTime[MAXPLAYERS+1];
|
||||
// int iIdleStartTime[MAXPLAYERS+1];
|
||||
// int iLastFFTime[MAXPLAYERS+1];
|
||||
// int iJumpAttempts[MAXPLAYERS+1];
|
||||
|
||||
// float playerTotalDamageFF[MAXPLAYERS+1];
|
||||
// float autoFFScaleFactor[MAXPLAYERS+1];
|
||||
|
||||
enum struct PlayerData {
|
||||
int joinTime;
|
||||
|
@ -107,6 +99,7 @@ public void OnPluginStart() {
|
|||
AutoExecConfig(true, "l4d2_tkstopper");
|
||||
|
||||
HookEvent("finale_vehicle_ready", Event_FinaleVehicleReady);
|
||||
HookEvent("finale_start", Event_FinaleStart);
|
||||
HookEvent("player_team", Event_PlayerDisconnect);
|
||||
|
||||
HookEvent("charger_carry_start", Event_ChargerCarry);
|
||||
|
@ -140,7 +133,7 @@ public void OnPluginStart() {
|
|||
}
|
||||
LoadTranslations("common.phrases");
|
||||
}
|
||||
public void Event_GamemodeChange(ConVar cvar, const char[] oldValue, const char[] newValue) {
|
||||
void Event_GamemodeChange(ConVar cvar, const char[] oldValue, const char[] newValue) {
|
||||
cvar.GetString(gamemode, sizeof(gamemode));
|
||||
if(StrEqual(gamemode, "coop")) {
|
||||
isEnabled = true;
|
||||
|
@ -151,55 +144,17 @@ public void Event_GamemodeChange(ConVar cvar, const char[] oldValue, const char[
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Special Infected Events
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
public Action Event_ChargerCarry(Event event, const char[] name, bool dontBroadcast) {
|
||||
int userid = event.GetInt("victim");
|
||||
int victim = GetClientOfUserId(userid);
|
||||
if(victim) {
|
||||
if(StrEqual(name, "charger_carry_start")) {
|
||||
pData[victim].underAttack = true;
|
||||
} else {
|
||||
CreateTimer(1.0, Timer_StopSpecialAttackImmunity, userid);
|
||||
}
|
||||
}
|
||||
return Plugin_Continue;
|
||||
Action Event_ChargerCarry(Event event, const char[] name, bool dontBroadcast) {
|
||||
return SetUnderAttack("charger_carry_start");
|
||||
}
|
||||
|
||||
public Action Event_HunterPounce(Event event, const char[] name, bool dontBroadcast) {
|
||||
int userid = event.GetInt("victim");
|
||||
int victim = GetClientOfUserId(userid);
|
||||
if(victim) {
|
||||
if(StrEqual(name, "lunge_pounce")) {
|
||||
pData[victim].underAttack = true;
|
||||
} else {
|
||||
CreateTimer(1.0, Timer_StopSpecialAttackImmunity, userid);
|
||||
}
|
||||
}
|
||||
return Plugin_Continue;
|
||||
Action Event_HunterPounce(Event event, const char[] name, bool dontBroadcast) {
|
||||
return SetUnderAttack(event, "lunge_pounce");
|
||||
}
|
||||
|
||||
public Action Event_SmokerChoke(Event event, const char[] name, bool dontBroadcast) {
|
||||
int userid = event.GetInt("victim");
|
||||
int victim = GetClientOfUserId(userid);
|
||||
if(victim) {
|
||||
if(StrEqual(name, "choke_start")) {
|
||||
pData[victim].underAttack = true;
|
||||
} else {
|
||||
CreateTimer(1.0, Timer_StopSpecialAttackImmunity, userid);
|
||||
}
|
||||
}
|
||||
return Plugin_Continue;
|
||||
Action Event_SmokerChoke(Event event, const char[] name, bool dontBroadcast) {
|
||||
return SetUnderAttack("choke_start");
|
||||
}
|
||||
public Action Event_JockeyRide(Event event, const char[] name, bool dontBroadcast) {
|
||||
int userid = event.GetInt("victim");
|
||||
int victim = GetClientOfUserId(userid);
|
||||
if(victim) {
|
||||
if(StrEqual(name, "jockey_ride")) {
|
||||
pData[victim].underAttack = true;
|
||||
} else {
|
||||
CreateTimer(1.0, Timer_StopSpecialAttackImmunity, userid);
|
||||
}
|
||||
}
|
||||
return Plugin_Continue;
|
||||
Action Event_JockeyRide(Event event, const char[] name, bool dontBroadcast) {
|
||||
return SetUnderAttack("jockey_ride");
|
||||
}
|
||||
|
||||
Action Timer_StopSpecialAttackImmunity(Handle h, int userid) {
|
||||
|
@ -209,6 +164,19 @@ Action Timer_StopSpecialAttackImmunity(Handle h, int userid) {
|
|||
}
|
||||
return Plugin_Continue;
|
||||
}
|
||||
|
||||
Action SetUnderAttack(Event event, const char[] checkString) {
|
||||
int userid = event.GetInt("victim");
|
||||
int victim = GetClientOfUserId(userid);
|
||||
if(victim) {
|
||||
if(StrEqual(name, checkString)) {
|
||||
pData[victim].underAttack = true;
|
||||
} else {
|
||||
CreateTimer(1.0, Timer_StopSpecialAttackImmunity, userid);
|
||||
}
|
||||
}
|
||||
return Plugin_Continue;
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// IDLE
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -233,16 +201,14 @@ public Action Event_PlayerToBot(Event event, char[] name, bool dontBroadcast) {
|
|||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Misc events
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
public void Event_FinaleVehicleReady(Event event, const char[] name, bool dontBroadcast) {
|
||||
void Event_FinaleVehicleReady(Event event, const char[] name, bool dontBroadcast) {
|
||||
isFinaleEnding = true;
|
||||
for(int i = 1; i <= MaxClients; i++) {
|
||||
if(pData[i].isTroll && IsClientConnected(i) && IsClientInGame(i)) {
|
||||
PrintChatToAdmins("Note: %N is still marked as troll and will be banned after this game. Use \"/ignore <player> tk\" to ignore them.", i);
|
||||
}
|
||||
}
|
||||
WarnStillMarked();
|
||||
PrintToServer("[TKStopper] Escape vehicle active, 2x rff in effect");
|
||||
}
|
||||
|
||||
void Event_FinaleStart(Event event, const char[] name, bool dontBroadcast) {
|
||||
WarnStillMarked();
|
||||
}
|
||||
public void OnMapEnd() {
|
||||
isFinaleEnding = false;
|
||||
}
|
||||
|
@ -272,13 +238,17 @@ public void OnClientDisconnect(int client) {
|
|||
}
|
||||
|
||||
// Only clear things when they fully left on their own accord:
|
||||
public void Event_PlayerDisconnect(Event event, const char[] name, bool dontBroadcast) {
|
||||
void Event_PlayerDisconnect(Event event, const char[] name, bool dontBroadcast) {
|
||||
if(!event.GetBool("disconnect") || !isEnabled) return;
|
||||
|
||||
int client = GetClientOfUserId(event.GetInt("userid"));
|
||||
if(client > 0 && event.GetInt("team") <= 2) {
|
||||
if (pData[client].isTroll && !IsFakeClient(client)) {
|
||||
BanClient(client, hBanTime.IntValue, BANFLAG_AUTO | BANFLAG_AUTHID, "Excessive FF (Auto)", "Excessive Friendly Fire", "TKStopper");
|
||||
if(hBanTime.IntValue > 0)
|
||||
CPrintChatToAdmins("{olive}%N{default} has been banned for %d minutes (marked as troll). If this was a mistake, you can discard their ban from the admin panel at {yellow}https://admin.jackz.me", client, hBanTime.IntValue);
|
||||
else
|
||||
CPrintChatToAdmins("{olive}%N{default} has been permanently banned (marked as troll). If this was a mistake, you can discard their ban from the admin panel at {yellow}https://admin.jackz.me", client);
|
||||
pData[client].isTroll = false;
|
||||
}
|
||||
|
||||
|
@ -286,7 +256,7 @@ public void Event_PlayerDisconnect(Event event, const char[] name, bool dontBroa
|
|||
float minutesSinceiLastFFTime = GetLastFFMinutes(client);
|
||||
float activeRate = GetActiveRate(client);
|
||||
PrintToConsoleAll("[TKStopper] FF Summary for %N:", client);
|
||||
PrintToConsoleAll("\t\t%.2f TK-FF buffer (%.2f total ff, %d freq.) | %.3f (buf %f) rFF rate | lastff %.1f min ago | %d suicide jumps",
|
||||
PrintToConsoleAll("\t%.2f TK-FF buffer (%.2f total ff, %d freq.) | %.3f (buf %f) rFF rate | lastff %.1f min ago | %d suicide jumps",
|
||||
pData[client].TKDamageBuffer,
|
||||
pData[client].totalDamageFF,
|
||||
pData[client].totalFFCount,
|
||||
|
@ -306,7 +276,7 @@ public void Event_PlayerDisconnect(Event event, const char[] name, bool dontBroa
|
|||
}
|
||||
}
|
||||
|
||||
public Action Event_OnTakeDamage(int victim, int& attacker, int& inflictor, float& damage, int& damagetype, int& weapon, float damageForce[3], float damagePosition[3]) {
|
||||
Action Event_OnTakeDamage(int victim, int& attacker, int& inflictor, float& damage, int& damagetype, int& weapon, float damageForce[3], float damagePosition[3]) {
|
||||
if(isEnabled && damage > 0.0 && victim <= MaxClients && attacker <= MaxClients && attacker > 0 && victim > 0) {
|
||||
if(GetClientTeam(victim) != GetClientTeam(attacker) || attacker == victim)
|
||||
return Plugin_Continue;
|
||||
|
@ -352,15 +322,15 @@ public Action Event_OnTakeDamage(int victim, int& attacker, int& inflictor, flo
|
|||
if(pData[victim].jumpAttempts > hSuicideLimit.IntValue) {
|
||||
if(hSuicideAction.IntValue == 1) {
|
||||
LogMessage("[NOTICE] Kicking %N for suicide attempts", victim, hBanTime.IntValue);
|
||||
NotifyAllAdmins("[Notice] Kicking %N for suicide attempts", victim, hBanTime.IntValue);
|
||||
PrintToChatAdmins("[Notice] Kicking %N for suicide attempts", victim, hBanTime.IntValue);
|
||||
KickClient(victim, "Troll");
|
||||
} else if(hSuicideAction.IntValue == 2) {
|
||||
LogMessage("[NOTICE] Banning %N for suicide attempts for %d minutes.", victim, hBanTime.IntValue);
|
||||
NotifyAllAdmins("[Notice] Banning %N for suicide attempts for %d minutes.", victim, hBanTime.IntValue);
|
||||
PrintToChatAdmins("[Notice] Banning %N for suicide attempts for %d minutes.", victim, hBanTime.IntValue);
|
||||
BanClient(victim, hBanTime.IntValue, BANFLAG_AUTO | BANFLAG_AUTHID, "Suicide fall attempts", "Troll", "TKStopper");
|
||||
} else if(hSuicideAction.IntValue == 3) {
|
||||
LogMessage("[NOTICE] %N will be banned for suicide attempts for %d minutes. ", victim, hBanTime.IntValue);
|
||||
NotifyAllAdmins("[Notice] %N will be banned for suicide attempts for %d minutes. Use \"/ignore <player> tk\" to make them immune.", victim, hBanTime.IntValue);
|
||||
PrintToChatAdmins("[Notice] %N will be banned for suicide attempts for %d minutes. Use \"/ignore <player> tk\" to make them immune.", victim, hBanTime.IntValue);
|
||||
pData[victim].isTroll = true;
|
||||
}
|
||||
}
|
||||
|
@ -427,15 +397,15 @@ public Action Event_OnTakeDamage(int victim, int& attacker, int& inflictor, flo
|
|||
if(!pData[attacker].pendingAction) {
|
||||
if(hTKAction.IntValue == 1) {
|
||||
LogMessage("[TKStopper] Kicking %N for excessive FF (%.2f HP)", attacker, pData[attacker].TKDamageBuffer);
|
||||
NotifyAllAdmins("[Notice] Kicking %N for excessive FF (%.2f HP)", attacker, pData[attacker].TKDamageBuffer);
|
||||
PrintToChatAdmins("[Notice] Kicking %N for excessive FF (%.2f HP)", attacker, pData[attacker].TKDamageBuffer);
|
||||
KickClient(attacker, "Excessive FF");
|
||||
} else if(hTKAction.IntValue == 2) {
|
||||
LogMessage("[TKStopper] Banning %N for excessive FF (%.2f HP) for %d minutes.", attacker, pData[attacker].TKDamageBuffer, hBanTime.IntValue);
|
||||
NotifyAllAdmins("[Notice] Banning %N for excessive FF (%.2f HP) for %d minutes.", attacker, pData[attacker].TKDamageBuffer, hBanTime.IntValue);
|
||||
PrintToChatAdmins("[Notice] Banning %N for excessive FF (%.2f HP) for %d minutes.", attacker, pData[attacker].TKDamageBuffer, hBanTime.IntValue);
|
||||
BanClient(attacker, hBanTime.IntValue, BANFLAG_AUTO | BANFLAG_AUTHID, "Excessive FF (Auto)", "Excessive Friendly Fire (Automatic)", "TKStopper");
|
||||
} else if(hTKAction.IntValue == 3) {
|
||||
LogMessage("[TKStopper] %N will be banned for FF on disconnect (%.2f HP) for %d minutes. ", attacker, pData[attacker].TKDamageBuffer, hBanTime.IntValue);
|
||||
NotifyAllAdmins("[Notice] %N will be banned for FF on disconnect (%.2f HP) for %d minutes. Use \"/ignore <player> tk\" to make them immune.", attacker, pData[attacker].TKDamageBuffer, hBanTime.IntValue);
|
||||
CPrintToChatAdmins("[Notice] %N will be banned for %d minutes for attempted teamkilling (%.2f HP) when they disconnect. Use {olive}/ignore <player> tk{default} to make them immune.", attacker, hBanTime.IntValue, pData[attacker].TKDamageBuffer);
|
||||
pData[attacker].isTroll = true;
|
||||
}
|
||||
pData[attacker].pendingAction = true;
|
||||
|
@ -482,7 +452,7 @@ public Action Event_OnTakeDamage(int victim, int& attacker, int& inflictor, flo
|
|||
|
||||
/// COMMANDS
|
||||
|
||||
public Action Command_TKInfo(int client, int args) {
|
||||
Action Command_TKInfo(int client, int args) {
|
||||
int time = GetTime();
|
||||
if(!isEnabled) {
|
||||
ReplyToCommand(client, "Warn: Plugin is disabled in current gamemode (%s)", gamemode);
|
||||
|
@ -509,28 +479,28 @@ public Action Command_TKInfo(int client, int args) {
|
|||
return Plugin_Handled;
|
||||
}
|
||||
int target = target_list[0];
|
||||
ReplyToCommand(client, "FF Review for '%N':", target);
|
||||
CReplyToCommand(client, "FF Review for {yellow}%N", target);
|
||||
if(pData[target].isTroll) {
|
||||
ReplyToCommand(client, "- will be banned on disconnect for TK -", target);
|
||||
CReplyToCommand(client, "{olive}- will be banned on disconnect for TK -", target);
|
||||
}
|
||||
if(pData[target].immunityFlags == Immune_TK) {
|
||||
ReplyToCommand(client, "Immunity: Teamkiller Detection", target);
|
||||
CReplyToCommand(client, "Immunity: {yellow}Teamkiller Detection", target);
|
||||
} else if(pData[target].immunityFlags == Immune_RFF) {
|
||||
ReplyToCommand(client, "Immunity: Auto reverse-ff", target);
|
||||
CReplyToCommand(client, "Immunity: {yellow}Auto reverse-ff", target);
|
||||
} else if(view_as<int>(pData[target].immunityFlags) > 0) {
|
||||
ReplyToCommand(client, "Immunity: Teamkiller Detection, Auto reverse-ff", target);
|
||||
CReplyToCommand(client, "Immunity: {yellow}Teamkiller Detection, Auto reverse-ff", target);
|
||||
} else {
|
||||
ReplyToCommand(client, "Immunity: (none, use /ignore <player> [immunity] to toggle)", target);
|
||||
CReplyToCommand(client, "Immunity: (none, use {green}/ignore <player> [immunity]{default} to toggle)", target);
|
||||
}
|
||||
float minutesSinceiLastFFTime = GetLastFFMinutes(target);
|
||||
float activeRate = GetActiveRate(target);
|
||||
ReplyToCommand(client, "FF Frequency: %d (active %d, %d forgotten)", pData[target].totalFFCount, pData[target].ffCount, (pData[target].totalFFCount - pData[target].ffCount));
|
||||
ReplyToCommand(client, "Total FF Damage: %.1f HP (%.1f min ago last ff)", pData[target].totalDamageFF, minutesSinceiLastFFTime);
|
||||
CReplyToCommand(client, "FF Frequency: {yellow}%d {default}(recent: %d, %d forgiven)", pData[target].totalFFCount, pData[target].ffCount, (pData[target].totalFFCount - pData[target].ffCount));
|
||||
CReplyToCommand(client, "Total FF Damage: {yellow}%.1f HP{default} (last fff %.1f min ago)", pData[target].totalDamageFF, minutesSinceiLastFFTime);
|
||||
if(~pData[target].immunityFlags & Immune_TK)
|
||||
ReplyToCommand(client, "Recent FF (TKDetectBuff): %.1f", pData[target].TKDamageBuffer);
|
||||
CReplyToCommand(client, "Recent FF (TKDetectBuffer): {yellow}%.1f", pData[target].TKDamageBuffer);
|
||||
if(~pData[target].immunityFlags & Immune_RFF)
|
||||
ReplyToCommand(client, "Auto Reverse-FF: %.1fx return rate", activeRate);
|
||||
ReplyToCommand(client, "Attempted suicide jumps: %d", pData[target].jumpAttempts);
|
||||
CReplyToCommand(client, "Auto Reverse-FF: {yellow}%.1fx return rate", activeRate);
|
||||
CReplyToCommand(client, "Attempted suicide jumps: {yellow}%d", pData[target].jumpAttempts);
|
||||
} else {
|
||||
for(int i = 1; i <= MaxClients; i++) {
|
||||
if(IsClientConnected(i) && IsClientInGame(i) && !IsFakeClient(i)) {
|
||||
|
@ -557,25 +527,25 @@ public Action Command_TKInfo(int client, int args) {
|
|||
}
|
||||
|
||||
|
||||
public Action Command_IgnorePlayer(int client, int args) {
|
||||
Action Command_IgnorePlayer(int client, int args) {
|
||||
char arg1[32], arg2[16];
|
||||
GetCmdArg(1, arg1, sizeof(arg1));
|
||||
GetCmdArg(2, arg2, sizeof(arg2));
|
||||
|
||||
if(args < 2) {
|
||||
ReplyToCommand(client, "Usage: sm_ignore <player> <tk/teamkill/rff/reverseff>");
|
||||
CReplyToCommand(client, "Usage: {yellow}sm_ignore <player> <tk|teamkill / rff|reverseff>");
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
int flags = 0;
|
||||
if(StrEqual(arg2, "tk") || StrEqual(arg2, "teamkill")) {
|
||||
flags = Immune_TK;
|
||||
} else if(StrEqual(arg2, "all") || StrEqual(arg2, "a")) {
|
||||
} else if(arg2[0] == 'a') {
|
||||
flags = Immune_TK | Immune_RFF;
|
||||
} else if(StrEqual(arg2, "reverseff") || StrEqual(arg2, "rff")) {
|
||||
flags = Immune_RFF;
|
||||
} else {
|
||||
ReplyToCommand(client, "Usage: sm_ignore <player> <tk/teamkill/rff/reverseff>");
|
||||
CReplyToCommand(client, "Usage: {yellow}sm_ignore <player> <tk|teamkill / rff|reverseff>");
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
|
@ -607,10 +577,10 @@ public Action Command_IgnorePlayer(int client, int args) {
|
|||
if (flags & Immune_TK) {
|
||||
if (pData[target].immunityFlags & Immune_TK) {
|
||||
LogAction(client, target, "\"%L\" re-enabled teamkiller detection for \"%L\"", client, target);
|
||||
ShowActivity2(client, "[FTT] ", "%N has re-enabled teamkiller detection for %N", client, target);
|
||||
CShowActivity2(client, "[FTT] ", "{yellow}%N has re-enabled teamkiller detection for {olive}%N", client, target);
|
||||
} else {
|
||||
LogAction(client, target, "\"%L\" ignored teamkiller detection for \"%L\"", client, target);
|
||||
ShowActivity2(client, "[FTT] ", "%N has ignored teamkiller detection for %N", client, target);
|
||||
CShowActivity2(client, "[FTT] ", "{yellow}%N has ignored teamkiller detection for {olive}%N", client, target);
|
||||
}
|
||||
pData[target].immunityFlags ^= Immune_TK;
|
||||
}
|
||||
|
@ -620,7 +590,7 @@ public Action Command_IgnorePlayer(int client, int args) {
|
|||
LogAction(client, target, "\"%L\" re-enabled auto reverse friendly-fire for \"%L\"", client, target);
|
||||
} else {
|
||||
LogAction(client, target, "\"%L\" disabled auto reverse friendly-fire for \"%L\"", client, target);
|
||||
ShowActivity2(client, "[FTT] ", "%N has disabled auto reverse friendly-fire for %N", client, target);
|
||||
CShowActivity2(client, "[FTT] ", "{yellow}%N has disabled auto reverse friendly-fire for {olive}%N", client, target);
|
||||
pData[target].autoRFFScaleFactor = 0.0;
|
||||
}
|
||||
pData[target].immunityFlags ^= Immune_RFF;
|
||||
|
@ -654,9 +624,9 @@ void GetImmunityFlagName(int flag, char[] buffer, int bufferLength) {
|
|||
if(flag == Immune_RFF) {
|
||||
strcopy(buffer, bufferLength, "Reverse Friendly-Fire");
|
||||
} else if(flag == Immune_TK) {
|
||||
strcopy(buffer, bufferLength, "Reverse Friendly-Fire");
|
||||
strcopy(buffer, bufferLength, "Teamkiller Detection");
|
||||
} else {
|
||||
strcopy(buffer, bufferLength, "-unknown flag-");
|
||||
strcopy(buffer, bufferLength, "-error: unknown flag-");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -674,6 +644,13 @@ void _CheckNative(int target, int flag) {
|
|||
ThrowNativeError(SP_ERROR_NATIVE, "Flag is invalid");
|
||||
}
|
||||
}
|
||||
void WarnStillMarked() {
|
||||
for(int i = 1; i <= MaxClients; i++) {
|
||||
if(pData[i].isTroll && IsClientConnected(i) && IsClientInGame(i)) {
|
||||
CPrintChatToAdmins("Note: {yellow}%N is still marked as troll and will be banned after this game. Use {olive}/ignore <player> tk{default} to ignore them.", i);
|
||||
}
|
||||
}
|
||||
}
|
||||
/// STOCKS
|
||||
|
||||
float GetLastFFMinutes(int client) {
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
#define PLUGIN_VERSION "1.0"
|
||||
#define MAX_PLAYER_HISTORY 25
|
||||
#define MAX_NOTES_TO_SHOW 10
|
||||
#define MAX_NOTES_TO_SHOW 5
|
||||
#define DATABASE_CONFIG_NAME "stats"
|
||||
|
||||
#include <sourcemod>
|
||||
|
@ -374,7 +374,7 @@ public void Event_FirstSpawn(Event event, const char[] name, bool dontBroadcast)
|
|||
if(client > 0 && client <= MaxClients && !IsFakeClient(client)) {
|
||||
static char auth[32];
|
||||
GetClientAuthId(client, AuthId_Steam2, auth, sizeof(auth));
|
||||
DB.Format(query, sizeof(query), "SELECT notes.content, stats_users.last_alias, markedBy FROM `notes` JOIN stats_users ON markedBy = stats_users.steamid WHERE notes.`steamid` = '%s'", auth);
|
||||
DB.Format(query, sizeof(query), "SELECT notes.content, stats_users.last_alias, markedBy FROM `notes` JOIN stats_users ON markedBy = stats_users.steamid WHERE notes.`steamid` = '%s' ORDER BY id ASC", auth);
|
||||
DB.Query(DB_FindNotes, query, GetClientUserId(client));
|
||||
}
|
||||
}
|
||||
|
@ -417,7 +417,9 @@ public void DB_FindNotes(Database db, DBResultSet results, const char[] error, a
|
|||
CPrintChatToAdmins("{yellow}> Notes for %N", client);
|
||||
int actions = 0;
|
||||
int repP = 0, repN = 0;
|
||||
int count = 0;
|
||||
while(results.FetchRow()) {
|
||||
count++;
|
||||
DBResult result;
|
||||
results.FetchString(0, reason, sizeof(reason));
|
||||
results.FetchString(1, noteCreator, sizeof(noteCreator), result);
|
||||
|
@ -432,10 +434,13 @@ public void DB_FindNotes(Database db, DBResultSet results, const char[] error, a
|
|||
repP++;
|
||||
} else if(StrEqual(reason, "-rep")) {
|
||||
repN++;
|
||||
} else {
|
||||
} else if(count < MAX_NOTES_TO_SHOW) {
|
||||
CPrintChatToAdmins(" {olive}%s: {default}%s", noteCreator, reason);
|
||||
}
|
||||
}
|
||||
if(count >= MAX_NOTES_TO_SHOW) {
|
||||
CPrintChatToAdmins(" ... and {olive}%d {default}more", MAX_NOTES_COUNT - count);
|
||||
}
|
||||
|
||||
if(actions > 0) {
|
||||
CPrintChatToAdmins(" > {olive}%d Auto Actions Applied", actions);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue