/* Dessloks's Friendly Fire Monitor (FFMon) Version 1.30 See readme, changelog and howto for more information. */ #pragma dynamic 24576 // 16384 #include <core> #include <console> #include <string> #include <admin> #include <adminlib> /* * Im folgenden Block werden die moeglichen Bestrafungen eingestellt. * Die einzelnen Zahlen sind zu addieren und spaeter im Konfigurationsblock * einzustellen */ #define ACCESS_FFMON ACCESS_BAN #define ACTION_NONE 0 #define ACTION_KICK 1 #define ACTION_BAN 2 #define ACTION_SLAP 4 #define ACTION_BURY 8 #define ACTION_CHICKEN 16 #define ACTION_OVERRIDE_BAN 32 #define ACTION_SLAY 64 /* If you want to use adminmod to change to the next map when a skunk is detected set this define to 1. Using adminmod for changing to the nextmap seems to get the map cycle out of order. The alternative is to set a server cvar that makes the engine think the round is over and switch to the next map. */ #define FORCE_NEXTMAP_ADMINMOD 0 /* If you want to turn the debugging on, which logs to the server console */ /* and to your log files, set this to 1. 0 is off. */ #define DEBUG 0 /* To use adminmod's beta menu feature, set this to 1. For adminmod 2.50.50 you need to put amv_enable_beta "menu 1" in your adminmod.cfg or server.cfg file. Set to 0 to use the old experimental method. */ #define USE_ADMINMOD_MENUS 1 #define ACCESS_CONSOLE 131072 new STRING_VERSION[MAX_DATA_LENGTH] = "$Revision: 1.20 $"; #define TD_CLEAN_SLATE 0 #define TK_CLEAN_SLATE 0 #define USER_ID_INVALID -1 #define SKUNK_TYPE_NORMAL 0 #define SKUNK_TYPE_TRADITIONAL 1 new g_TdCount[MAX_PLAYERS + 1] = {TD_CLEAN_SLATE,...}; new g_TkCount[MAX_PLAYERS + 1] = {TK_CLEAN_SLATE,...}; new g_tkedby[MAX_PLAYERS + 1] = {USER_ID_INVALID,...}; new g_Chickened[MAX_PLAYERS + 1] = {0}; // TK revenge action stored here if the attacker is dead // revenge is taken out the start of the next round new g_TkRevenge[MAX_PLAYERS + 1] = {ACTION_NONE}; new g_RoundStart = 0; new g_RoundSpawn = 0; new g_RoundStartTimer= 0; new g_VoteStarted = 0; new g_CtScore = 0; new g_TScore = 0; new g_DebugMessages = 0; new g_LastTkBan[MAX_AUTHID_LENGTH]; /* Menu defines and variables */ #define MAX_TK_OPTIONS 10 #define MENU_STATE_OPEN 0 #define MENU_STATE_KILLED 1 new g_TkMenuAction[MAX_TK_OPTIONS + 1][MAX_TEXT_LENGTH]; new g_MenuStates[MAX_PLAYERS + 1][3]; /* * * Configuration variables available through commands and their default values * */ /* * german comments by [-=THH=-]Stillsetzhut (stillsetzhut@thh-clan.de) for adminmod.de * * Der Konfigurationblock. Hier koennen die Grundeinstellungen des FFMon vorgenommen werden. */ new g_Enabled = 1; /* Schaltet das komplette Plugin ein */ new g_TkProtection = 1; /* TK Schutz ein/aus */ new g_TkLimit = 3; /* TK limit bevor gebannt wird */ new g_TkLimitBanTime = 30; /* Bannzeit bei Erreichen des TK Limits */ new g_TkMenu = 1; /* schaltet das TK Menu ein */ new g_TkReset = 0; /* Setzt das TK Konto am Ende der Runde auf 0 */ new g_TkSave = 1; /* Speichert TK's */ new g_TkSaveTime = 24; /* Stunden in denen TK's gespeichert werden */ new g_TkSaveLimit = 6; /* wieviele TK'S sind in der TkSaveTime erlaubt */ new g_TkSaveBanTime = 1440; /* Bannzeit bei Erreichen von TKSavelimit (def: 1440 min = 24 Stunden) */ new g_TkSavePurgeTime = 24; /* Stunden nach denen die gespeicherten TK's bereinigt werden */ new g_TdProtection = 1; /* TD Schutz ein/aus */ new g_TdLimit = 5; /* TD limit wird gleichgesetzt = 1 TK */ new g_TdAction = ACTION_SLAY; /* Massnahme bei TD's */ new g_AllowPunish = 47; /* HIER KOMMT DIE ZAHL HINEIN; DIE IHR AUS DEM OBEREN BLOCK ERRECHNET HABT */ new g_UserSlapCount = 1; /* Zahl der Schlaege wenn der TK'te slap nutzt */ new g_UserOverrideLevel = 0; /* Rechtelevel um einen TK Bann aufzuheben */ new g_BuryGlowTime = 30; /* Leuchtzeit bei TK Bestrafung bury */ new g_RoundStartTime = 10; /* Rundenstartzeit mit verschaerfter Bestrafung */ new g_RoundStartBanTime = 300; /* Bannzeit bei TK's in der Rundenstartzeit */ new g_RoundStartBanTk = 1; /* Bann bei TK's in der Rundenstartzeit erlauben */ new g_RoundStartTdSlap = 1; /* Schlagen bei TD's in der Rundenstartzeit */ new g_RoundStartTdSlapTimes = 5; /* Anzahl der Schlaege bei TD's in der Rundenstartzeit */ new g_RoundStartTdAction = ACTION_BAN; /* Art der Bestrafung bei TD's in der Rundenstartzeit */ new g_RoundStartTdCount = 3; /* TD limit in der Rundenstartzeit bevor gebannt wird */ new g_RoundStartTdBanTime = 2; /* Bannzeit fuer TD's in der Rundenstartzeit*/ new g_SpawnShotProtection = 0; /* Schnellschuss Schutz */ new g_SpawnShotAction = ACTION_KICK; /* Bestrafung gegen Schnellschuesse */ new g_SpawnShotTime = 2; /* Zeit des Schutzes gegen Schnellschuesse */ new g_SpawnShotBanTime = 10; /* Bannzeit gegen Schnellschuesse */ new g_SkunkProtection = 1; /* wechselt zur naechsten Map bei Dominanz eines Teams */ new g_SkunkType = SKUNK_TYPE_NORMAL; /* Typ der Teamueberwachung */ new g_SkunkLimit = 10; /* Win Differenz bei der zur naechsten Map gewechselt wird */ new g_Immunity = 0; /* admin Immunitaet ein/aus */ new g_ImmunityLevel = 65536; /* Rechtelevel fuer Immunitaet */ new g_DisplayScores = 1; /* Zeigt den Spielstand am Ende jeder Runde */ new g_LogMessages = 1; /* Schreibt Ausgaben des FFMon in die logfiles */ new g_DisplayConsgreet = 1; /* Schaltet die Konsolenbegruessung ein/aus */ new g_BlockAttackMessages = 1; /* Unterdrueckt das Schreiben von Beschaedigungen in die Lofiles */ new g_StartVote = 1; /* Startet einen Mapvote vor Erreichen von mp_winlimit */ new g_StartVoteRound = 2; /* Zahl der Runden vor Erreichen von mp_winlimit um Mapvote auszuloesen */ #if DEBUG == 1 new g_HeapStart = 0; #endif /* * * * Helper functions * */ HeapCheckStart() { #if DEBUG == 1 g_HeapStart = heapspace(); #endif } HeapCheckStop(sFunctionName[]) { strlen(sFunctionName); #if DEBUG == 1 new sDebugMessage[MAX_DATA_LENGTH]; new iHeap2; iHeap2 = heapspace(); snprintf (sDebugMessage, MAX_DATA_LENGTH, "%s: Heapspace started with %i, ended with %i.", sFunctionName, g_HeapStart, iHeap2); LogMessage(sDebugMessage); #endif } DebugMessage(sMessage[]) { if (g_DebugMessages) { LogMessage(sMessage); } } LogMessage(sMessage[]) { new sRealMessage[MAX_DATA_LENGTH]; if (g_LogMessages) { snprintf(sRealMessage, MAX_DATA_LENGTH, "[FFMon] %s", sMessage); log(sRealMessage); } } SayMessage(sMessage[]) { new sRealMessage[MAX_DATA_LENGTH]; snprintf(sRealMessage, MAX_DATA_LENGTH, "<FFMon> %s", sMessage); //typesay( sRealMessage, 10, 255, 255, 255 ); say(sRealMessage); } IsImmune(sUser[]) { new iImmune = 0; if (g_Immunity) { if (access(g_ImmunityLevel, sUser) != 0) { iImmune = 1; } } return iImmune; } // // Generate the file name for this user // GetTkFileName(sWONID[], sFileName[]) { snprintf(sFileName, MAX_DATA_LENGTH, "ffmon/%s.tks", sWONID); } // // remove the tk file for this WONID // RemoveTkFile(sWONID[]) { new sFileName[MAX_DATA_LENGTH]; GetTkFileName(sWONID, sFileName); deletefile(sFileName); RemoveFromMasterTkFile(sWONID); } // // This function should only be called after AddTk, RemoveTk // or AgeTks. That will ensure that the list is up to date // since all this function does is get a line count // GetTkCount(sWONID[]) { new sFileName[MAX_DATA_LENGTH]; GetTkFileName(sWONID, sFileName); return filesize(sFileName); } // // Read in all currently active TKs for the given file // ReadTkInfo(sFileName[], iTks[], iStartTk, iFileOffset) { new sData[MAX_DATA_LENGTH]; new iCurLine = iFileOffset; new iCurTime = systemtime(); new iCurPos = iStartTk; if (fileexists(sFileName)) { while (readfile(sFileName, sData, iCurLine, MAX_DATA_LENGTH)) { new iTkTime = strtonum(sData); if (iTkTime + (g_TkSaveTime * 60 * 60) > iCurTime) { // tk hasn't expired yet. save iTks[iCurPos] = iTkTime; } else { // tks are in order in the file, so once we find one that is // expired, they all will be expired after this one. // so we are done break; } iCurLine++; iCurPos++; } } return iCurPos; } // // returns true if user has reached the limit // AddTk(sWONID[]) { new sFileName[MAX_DATA_LENGTH]; new iTks[MAX_DATA_LENGTH] = {0}; new iCount = 0; if (g_TkSave) { GetTkFileName(sWONID, sFileName); // stick the new one in the head of the list iTks[0] = systemtime(); // read the data from the file, starting at the first line iCount = ReadTkInfo(sFileName, iTks, 1, 1); // now save the TK info SaveTkInfo(sFileName, iTks, iCount); // add to the master list AddToMasterTkFile(sWONID); } } // // Function removes the last TK from the file // RemoveTk(sWONID[]) { // we pass in 2 so that we skip the first entry in the file // the first entry in the file is always the most recent AgeTksEx(sWONID, 2); } AgeTks(sWONID[]) { // pass in 1 for the offset meaning to start with the first // entry in the file, not skipping any AgeTksEx(sWONID, 1); } // // age the TKs in the file. Offset specifies where to start // in the file. // AgeTksEx(sWONID[], iOffset, iRemove = 1) { new sFileName[MAX_DATA_LENGTH]; new iTks[MAX_DATA_LENGTH] = {0}; new iCount = 0; GetTkFileName(sWONID, sFileName); if (fileexists(sFileName)) { // read the info from the file for active TKs iCount = ReadTkInfo(sFileName, iTks, 0, iOffset); SaveTkInfo(sFileName, iTks, iCount); if ( (iCount == 0) && (iRemove) ) { RemoveFromMasterTkFile(sWONID); } } } // // Save off the TK info // if there isn't any, remove the file // SaveTkInfo(sFileName[], iTks[], iCount) { new sData[MAX_DATA_LENGTH]; if (iCount > 0) { // clear the file resetfile(sFileName); // write out all the TKs for this ID for (new i = 0; i < iCount; i++) { snprintf(sData, MAX_DATA_LENGTH, "%d", iTks[i]); writefile(sFileName, sData); } } else { // no more TKs so just delete the file deletefile(sFileName); } } CheckPeriodicPurge() { // maybe this should be a vault.ini entry new sVaultData[MAX_DATA_LENGTH]; new iCurTime = systemtime(); new iLastTime = iCurTime; if (get_vaultdata("FFMON_TKSAVELASTPURGE", sVaultData, MAX_DATA_LENGTH ) != 0) { iLastTime = strtonum(sVaultData); // check to see if the purge time has elapsed or the maximum // amount of time between purges has elapsed. This check forces // a purge at least once a week. if ( ((iLastTime + (g_TkSavePurgeTime * 60 * 60)) < iCurTime) || ((iLastTime + (7 * 24 * 60 * 60)) < iCurTime) ) { // time to do a purge PurgeTkFiles(); UpdateLastPurgeTime(); } } else { // first time UpdateLastPurgeTime(); } } UpdateLastPurgeTime() { SetVaultInt("FFMON_TKSAVELASTPURGE", systemtime()); } // // Walk all of the tk files and age them... we do this // once a day to try and keep the number of files down. // PurgeTkFiles() { new sMasterFilename[MAX_TEXT_LENGTH]; new sFilename[MAX_TEXT_LENGTH]; new sData[MAX_DATA_LENGTH]; new iCurLine = 1; new iCurTime = systemtime(); new iTotal = 0; new iRemoved = 0; // get the current master file name GetMasterTkFileName(sMasterFilename); if (fileexists(sMasterFilename)) { while (readfile(sMasterFilename, sData, iCurLine, MAX_DATA_LENGTH)) { if (strlen(sData) > 0) { iTotal++; // get the filename for later GetTkFileName(sData, sFilename); // age the tks for this guy AgeTksEx(sData, 1, 0); // if the file is gone, then remove from the master list if (!fileexists(sFilename)) { writefile(sMasterFilename, "", iCurLine); iRemoved++; } } iCurLine++; } } snprintf(sData, MAX_DATA_LENGTH, "%d of %d entries removed in %d seconds w/%d players online", iRemoved, iTotal, iCurTime - systemtime(), playercount()); LogMessage(sData); } // // add this WONID to the master file that keeps track of all the // TK files we have. We do this so we can purge the files at // some later date. The reason we need this stupid master file // is because no functionality exists to walk the files in the // directory on linux. // AddToMasterTkFile(sWONID[]) { new sFilename[MAX_TEXT_LENGTH]; new sData[MAX_DATA_LENGTH]; new iCurLine = 1; new iFound = 0; new iEmptyLine = -1; // get the current master file name GetMasterTkFileName(sFilename); if (fileexists(sFilename)) { while (readfile(sFilename, sData, iCurLine, MAX_DATA_LENGTH)) { new sMessage[MAX_DATA_LENGTH]; if (streq(sData, sWONID)) { // already in the file iFound = 1; break; } new iLen = strlen(sData); if ( (iLen == 0) && (iEmptyLine == -1) ) { // found an open slot // save this line for later snprintf(sMessage, MAX_DATA_LENGTH, "AddToMasterTkFile - Found empty line %d", iCurLine); LogMessage(sMessage); iEmptyLine = iCurLine; } iCurLine++; } } // did not find anyplace for it, append if (!iFound) { DebugMessage("AddToMasterTkFile - new AuthID, adding to file"); writefile(sFilename, sWONID, iEmptyLine); } } // // remove a wonid from the file // because file access is limited to a few functions // we just set the line to be blank if we remove it // RemoveFromMasterTkFile(sWONID[]) { new sFilename[MAX_TEXT_LENGTH]; new sData[MAX_DATA_LENGTH]; new iCurLine = 1; // get the current master file name GetMasterTkFileName(sFilename); if (fileexists(sFilename)) { while (readfile(sFilename, sData, iCurLine, MAX_DATA_LENGTH)) { if (streq(sData, sWONID)) { // already in the file writefile(sFilename, "", iCurLine); break; } iCurLine++; } } } GetMasterTkFileName(sFilename[]) { strcpy(sFilename, "ffmon\tks.def", MAX_TEXT_LENGTH); } #if USE_ADMINMOD_MENUS != 1 BindToMenuselect(iUserIndex) { new sTarget[MAX_NAME_LENGTH]; new sAuthID[MAX_AUTHID_LENGTH]; new iSessionID; new iTeam; new iWONID; new iDead; playerinfo(iUserIndex, sTarget, MAX_NAME_LENGTH, iSessionID, iWONID, iTeam, iDead, sAuthID); execclient(sTarget, "bind 1 ^"menuselect 1^";bind 2 ^"menuselect 2^";bind 3 ^"menuselect 3^""); execclient(sTarget, "bind 4 ^"menuselect 4^";bind 5 ^"menuselect 5^";bind 6 ^"menuselect 6^""); execclient(sTarget, "bind 7 ^"menuselect 7^";bind 8 ^"menuselect 8^";bind 9 ^"menuselect 9^""); execclient(sTarget, "bind 0 ^"menuselect 0^""); } BindToSlot(iUserIndex) { new sTarget[MAX_NAME_LENGTH]; new sAuthID[MAX_AUTHID_LENGTH]; new iSessionID; new iTeam; new iWONID; new iDead; playerinfo(iUserIndex, sTarget, MAX_NAME_LENGTH, iSessionID, iWONID, iTeam, iDead, sAuthID); execclient(sTarget, "bind 1 ^"slot1^";bind 2 ^"slot2^";bind 3 ^"slot3^""); execclient(sTarget, "bind 4 ^"slot4^";bind 5 ^"slot5^";bind 6 ^"slot6^""); execclient(sTarget, "bind 7 ^"slot7^";bind 8 ^"slot8^";bind 9 ^"slot9^""); execclient(sTarget, "bind 0 ^"slot10^""); } #endif ResetMenu(iUserIndex) { // reset some menu states g_MenuStates[iUserIndex][MENU_STATE_OPEN] = 0; g_MenuStates[iUserIndex][MENU_STATE_KILLED] = 0; } BuildTkMenu(sMenu[]) { new sMenuTemp[MAX_TEXT_LENGTH]; new iMenuNum = 1; new iAction = 0; new mKeys[10] = {1,2,4,8,16,32,64,128,256,512}; // forgive is always available snprintf(sMenuTemp, MAX_TEXT_LENGTH, "%d. Forgive^n", iMenuNum); strcat(sMenu, sMenuTemp, MAX_TEXT_LENGTH); g_TkMenuAction[iMenuNum - 1] = "say forgive"; iAction += mKeys[iMenuNum - 1]; iMenuNum++; // slay if ((g_AllowPunish & ACTION_SLAY) == ACTION_SLAY) { snprintf(sMenuTemp, MAX_TEXT_LENGTH, "%d. Slay^n", iMenuNum); strcat(sMenu, sMenuTemp, MAX_TEXT_LENGTH); g_TkMenuAction[iMenuNum - 1] = "say slay"; iAction += mKeys[iMenuNum - 1]; iMenuNum++; } if ((g_AllowPunish & ACTION_KICK) == ACTION_KICK) { snprintf(sMenuTemp, MAX_TEXT_LENGTH, "%d. Kick^n", iMenuNum); strcat(sMenu, sMenuTemp, MAX_TEXT_LENGTH); g_TkMenuAction[iMenuNum - 1] = "say kick"; iAction += mKeys[iMenuNum - 1]; iMenuNum++; } if ((g_AllowPunish & ACTION_SLAP) == ACTION_SLAP) { snprintf(sMenuTemp, MAX_TEXT_LENGTH, "%d. Slap^n", iMenuNum); strcat(sMenu, sMenuTemp, MAX_TEXT_LENGTH); g_TkMenuAction[iMenuNum - 1] = "say slap"; iAction += mKeys[iMenuNum - 1]; iMenuNum++; } if ((g_AllowPunish & ACTION_BAN) == ACTION_BAN) { snprintf(sMenuTemp, MAX_TEXT_LENGTH, "%d. Ban^n", iMenuNum); strcat(sMenu, sMenuTemp, MAX_TEXT_LENGTH); g_TkMenuAction[iMenuNum - 1] = "say ban"; iAction += mKeys[iMenuNum - 1]; iMenuNum++; } if ((g_AllowPunish & ACTION_BURY) == ACTION_BURY) { snprintf(sMenuTemp, MAX_TEXT_LENGTH, "%d. Bury^n", iMenuNum); strcat(sMenu, sMenuTemp, MAX_TEXT_LENGTH); g_TkMenuAction[iMenuNum - 1] = "say bury"; iAction += mKeys[iMenuNum - 1]; iMenuNum++; } if ((g_AllowPunish & ACTION_CHICKEN) == ACTION_CHICKEN) { snprintf(sMenuTemp, MAX_TEXT_LENGTH, "%d. Chicken^n", iMenuNum); strcat(sMenu, sMenuTemp, MAX_TEXT_LENGTH); g_TkMenuAction[iMenuNum - 1] = "say chicken"; iAction += mKeys[iMenuNum - 1]; iMenuNum++; } // put in the quit option strcat(sMenu, "^n0. Quit^n", MAX_TEXT_LENGTH); iAction += mKeys[9]; // fill in a blank entry to mark the end of the list g_TkMenuAction[iMenuNum - 1] = ""; return iAction; } DisplayTkMenu(iUserIndex) { new iSessionID = 0; new iWONID = 0; new iTeam = 0; new iDead = 0; new iActionKeys = 0; new sMenuText[MAX_TEXT_LENGTH]; new sUserName[MAX_NAME_LENGTH]; new sAuthID[MAX_AUTHID_LENGTH]; // Put in the title strcpy(sMenuText, "TK Options^n^n", MAX_TEXT_LENGTH); // Get the menu string and action value iActionKeys = BuildTkMenu(sMenuText); playerinfo(iUserIndex, sUserName, MAX_NAME_LENGTH, iSessionID, iWONID, iTeam, iDead, sAuthID); g_MenuStates[iUserIndex][MENU_STATE_OPEN] = 1; // display the menu #if USE_ADMINMOD_MENUS == 1 menu(sUserName, sMenuText, iActionKeys); #else messageex(sUserName, sMenuText, print_tty); set_timer("TkMenuTimer", 8, 1, sUserName); iActionKeys += 1; #endif } ClearTkMenu(iUserIndex) { if (g_MenuStates[iUserIndex][MENU_STATE_OPEN] == 1) { // clear the variables ResetMenu(iUserIndex); #if USE_ADMINMOD_MENUS != 1 new iSessionID = 0; new iWONID = 0; new iTeam = 0; new iDead = 0; new sUserName[MAX_NAME_LENGTH]; new sAuthID[MAX_AUTHID_LENGTH]; // rebind the keys BindToSlot(iUserIndex); // clear the menu playerinfo(iUserIndex, sUserName, MAX_NAME_LENGTH, iSessionID, iWONID, iTeam, iDead, sAuthID); messageex(sUserName, "", print_tty); #endif } } public TkMenuTimer(Timer, Repeat, HLName, HLParam) { new iUserIndex; new sName[MAX_NAME_LENGTH]; convert_string(HLParam, sName, MAX_NAME_LENGTH); get_userindex(sName, iUserIndex); ClearTkMenu(iUserIndex); } ShowScore() { new iScoreDisplayed = PLUGIN_CONTINUE; new s[MAX_DATA_LENGTH]; if (g_DisplayScores) { snprintf(s, MAX_DATA_LENGTH, "Terrorists %d -- Counter-terrorists %d", g_TScore, g_CtScore); SayMessage(s); iScoreDisplayed = PLUGIN_HANDLED; } return iScoreDisplayed; } BanUser(sWONID[], iBanTime, iAllowOverride = 1) { ban(sWONID, iBanTime, uid_wonID); if (iAllowOverride) { strcpy(g_LastTkBan, sWONID, MAX_AUTHID_LENGTH); } } UnbanUser(sWONID[]) { unban(sWONID); strcpy(g_LastTkBan, "", MAX_AUTHID_LENGTH); } stock DoAction(sWONID[], iAction, iBanTime) { new iResult; switch (iAction) { case ACTION_KICK: { kick(sWONID); iResult = 1; } case ACTION_SLAP: { for (new i = 0; i <= g_UserSlapCount; i++) slap(sWONID); iResult = 1; } case ACTION_SLAY: { slay(sWONID); iResult = 1; } case ACTION_BAN: { BanUser(sWONID, iBanTime); iResult = 1; } case ACTION_BURY: { BuryUser(sWONID); iResult = 1; } case ACTION_CHICKEN: { ChickenUser(sWONID); iResult = 1; } default: iResult = 0; } return iResult; } GetActionString(iAction, sAction[]) { switch (iAction) { case ACTION_KICK: strcpy(sAction, "kicked", MAX_TEXT_LENGTH); case ACTION_SLAP: strcpy(sAction, "slapped", MAX_TEXT_LENGTH); case ACTION_SLAY: strcpy(sAction, "executed", MAX_TEXT_LENGTH); case ACTION_BAN: strcpy(sAction, "banned", MAX_TEXT_LENGTH); case ACTION_BURY: strcpy(sAction, "buried", MAX_TEXT_LENGTH); case ACTION_CHICKEN: strcpy(sAction, "chickened", MAX_TEXT_LENGTH); default: strcpy(sAction, "none", MAX_TEXT_LENGTH); } } ChickenUser(sWONID[]) { new sCommand[MAX_DATA_LENGTH]; new iIndex; snprintf( sCommand, MAX_DATA_LENGTH, "%s 10", sWONID); plugin_exec("admin_chicken", sCommand); get_userindex(sWONID, iIndex); g_Chickened[iIndex] = 1; } UnchickenUsers() { new i; for (i = 1; i <= maxplayercount(); i++) { UnchickenUser(i); } } UnchickenUser(iIndex) { if (g_Chickened[iIndex]) { new sName[MAX_NAME_LENGTH]; new sAuthID[MAX_AUTHID_LENGTH]; new iUserID; new iWONID; new iTeam; new iDead; playerinfo(iIndex, sName, MAX_NAME_LENGTH, iUserID, iWONID, iTeam, iDead, sAuthID); plugin_exec("admin_unchicken", sName); g_Chickened[iIndex] = 0; } } BuryUser(sWONID[]) { new x; new y; new z; execclient(sWONID, "slot1"); // drop his first weapon execclient(sWONID, "+attack"); execclient(sWONID, "-attack"); execclient(sWONID, "drop"); execclient(sWONID, "slot2"); // drop his pistol (if any) execclient(sWONID, "+attack"); execclient(sWONID, "-attack"); execclient(sWONID, "drop"); execclient(sWONID, "slot5"); // drop the bomb (if any) execclient(sWONID, "+attack"); execclient(sWONID, "-attack"); execclient(sWONID, "drop"); execclient(sWONID, "say Help! I've been buried and I can't get up!"); if (g_BuryGlowTime > 0) { if (set_timer("bury_noglow", g_BuryGlowTime, 1, sWONID)) glow(sWONID, 0, 255, 0); } get_userorigin(sWONID, x, y, z); teleport(sWONID, x, y, (z-20)); } public bury_noglow(Timer, Repeat, HLName, HLParam) { new sName[MAX_NAME_LENGTH]; convert_string(HLParam, sName, MAX_NAME_LENGTH); glow(sName, 0, 0, 0); return PLUGIN_HANDLED; } ParseAction(sAction[]) { new iAdd = 1; new iPunish = 0; // default is to try to add the action to the allowed list if (sAction[0] == '-') { iAdd = 0; } // remove the leading + or - strtrim(sAction, "+-", 0); // get the action iPunish = check_action(sAction); if (iPunish != 0) { if (iAdd) { // if the action isn't in the list then add it in if ((g_AllowPunish & iPunish) != iPunish) { g_AllowPunish += iPunish; } } else { // if the action is in the list then subtract it out if ((g_AllowPunish & iPunish) == iPunish) { g_AllowPunish -= iPunish; } } } } check_action( sAction[] ) { new iResult = 0; if (strlen(sAction) > 0) { if (strncmp(sAction, "kick", 4) == 0) { iResult = ACTION_KICK; } else if (strncmp(sAction, "ban", 3) == 0) { iResult = ACTION_BAN; } else if (strncmp(sAction, "slay", 4) == 0) { iResult = ACTION_SLAY; } else if (strncmp(sAction, "chicken", 7) == 0) { iResult = ACTION_CHICKEN; } else if (strncmp(sAction, "slap", 4) == 0) { iResult = ACTION_SLAP; } else if (strncmp(sAction, "bury", 4) == 0) { iResult = ACTION_BURY; } else if (strncmp(sAction, "overrideban", 11) == 0) { iResult = ACTION_OVERRIDE_BAN; } } return iResult; } BuildPunnishmentList(sOut[]) { strcpy(sOut, "", MAX_TEXT_LENGTH); if ((g_AllowPunish & ACTION_SLAY) == ACTION_SLAY) strcat(sOut, "slay", MAX_TEXT_LENGTH); if ((g_AllowPunish & ACTION_KICK) == ACTION_KICK) strcat(sOut, " kick", MAX_TEXT_LENGTH); if ((g_AllowPunish & ACTION_SLAP) == ACTION_SLAP) strcat(sOut, " slap", MAX_TEXT_LENGTH); if ((g_AllowPunish & ACTION_BAN) == ACTION_BAN) strcat(sOut, " ban", MAX_TEXT_LENGTH); if ((g_AllowPunish & ACTION_BURY) == ACTION_BURY) strcat(sOut, " bury", MAX_TEXT_LENGTH); if ((g_AllowPunish & ACTION_CHICKEN) == ACTION_CHICKEN) strcat(sOut, " chicken", MAX_TEXT_LENGTH); if ((g_AllowPunish & ACTION_OVERRIDE_BAN) == ACTION_OVERRIDE_BAN) strcat(sOut, " overrideban", MAX_TEXT_LENGTH); } stock SetVaultInt(sParam[], iValue) { new sVaultData[MAX_DATA_LENGTH]; snprintf(sVaultData, MAX_DATA_LENGTH, "%d", iValue); set_vaultdata(sParam, sVaultData); } stock SetVaultParam(sParam[], iValue) { if (iValue) set_vaultdata(sParam, "on"); else set_vaultdata(sParam, "off"); } stock LoadConfiguration() { new sVaultData[MAX_DATA_LENGTH]; if (get_vaultdata("FFMON_ENABLED", sVaultData, MAX_DATA_LENGTH ) != 0) g_Enabled = check_param(sVaultData); if (get_vaultdata("FFMON_TK", sVaultData, MAX_DATA_LENGTH ) != 0) g_TkProtection = check_param(sVaultData); if (get_vaultdata("FFMON_TKLIMIT", sVaultData, MAX_DATA_LENGTH ) != 0) g_TkLimit = strtonum(sVaultData); if (get_vaultdata("FFMON_TKBANTIME", sVaultData, MAX_DATA_LENGTH ) != 0) g_TkLimitBanTime = strtonum(sVaultData); if (get_vaultdata("FFMON_TKMENU", sVaultData, MAX_DATA_LENGTH ) != 0) g_TkMenu = check_param(sVaultData); if (get_vaultdata("FFMON_TKSAVE", sVaultData, MAX_DATA_LENGTH ) != 0) g_TkSave = check_param(sVaultData); if (get_vaultdata("FFMON_TKSAVETIME", sVaultData, MAX_DATA_LENGTH ) != 0) g_TkSaveTime = strtonum(sVaultData); if (get_vaultdata("FFMON_TKSAVELIMIT", sVaultData, MAX_DATA_LENGTH ) != 0) g_TkSaveLimit = strtonum(sVaultData); if (get_vaultdata("FFMON_TKSAVEBANTIME", sVaultData, MAX_DATA_LENGTH ) != 0) g_TkSaveBanTime = strtonum(sVaultData); if (get_vaultdata("FFMON_TKSAVEPURGETIME", sVaultData, MAX_DATA_LENGTH ) != 0) g_TkSavePurgeTime = strtonum(sVaultData); if (get_vaultdata("FFMON_TKRESET", sVaultData, MAX_DATA_LENGTH ) != 0) g_TkReset = check_param(sVaultData); if (get_vaultdata("FFMON_TD", sVaultData, MAX_DATA_LENGTH ) != 0) g_TdProtection = check_param(sVaultData); if (get_vaultdata("FFMON_TDLIMIT", sVaultData, MAX_DATA_LENGTH ) != 0) g_TdLimit = strtonum(sVaultData); if (get_vaultdata("FFMON_TDACTION", sVaultData, MAX_DATA_LENGTH ) != 0) g_TdAction = strtonum(sVaultData); if (get_vaultdata("FFMON_ALLOWPUNISH", sVaultData, MAX_DATA_LENGTH ) != 0) g_AllowPunish = strtonum(sVaultData); if (get_vaultdata("FFMON_USERSLAPCOUNT", sVaultData, MAX_DATA_LENGTH ) != 0) g_UserSlapCount = strtonum(sVaultData); if (get_vaultdata("FFMON_OVERRIDELEVEL", sVaultData, MAX_DATA_LENGTH ) != 0) g_UserOverrideLevel = strtonum(sVaultData); if (get_vaultdata("FFMON_BURYGLOWTIME", sVaultData, MAX_DATA_LENGTH ) != 0) g_BuryGlowTime = strtonum(sVaultData); if (get_vaultdata("FFMON_RS", sVaultData, MAX_DATA_LENGTH ) != 0) g_RoundStartTime = strtonum(sVaultData); if (get_vaultdata("FFMON_RSBANTK", sVaultData, MAX_DATA_LENGTH ) != 0) g_RoundStartBanTk = check_param(sVaultData); if (get_vaultdata("FFMON_RSBANTKTIME", sVaultData, MAX_DATA_LENGTH ) != 0) g_RoundStartBanTime = strtonum(sVaultData); if (get_vaultdata("FFMON_RSTDSLAP", sVaultData, MAX_DATA_LENGTH ) != 0) g_RoundStartTdSlap = strtonum(sVaultData); if (get_vaultdata("FFMON_RSTDSLAPCOUNT", sVaultData, MAX_DATA_LENGTH ) != 0) g_RoundStartTdSlapTimes = strtonum(sVaultData); if (get_vaultdata("FFMON_RSTDACTION", sVaultData, MAX_DATA_LENGTH ) != 0) g_RoundStartTdAction = strtonum(sVaultData); if (get_vaultdata("FFMON_RSTDCOUNT", sVaultData, MAX_DATA_LENGTH ) != 0) g_RoundStartTdCount = strtonum(sVaultData); if (get_vaultdata("FFMON_RSTDBANTIME", sVaultData, MAX_DATA_LENGTH ) != 0) g_RoundStartTdBanTime = strtonum(sVaultData); if (get_vaultdata("FFMON_SS", sVaultData, MAX_DATA_LENGTH ) != 0) g_SpawnShotProtection = check_param(sVaultData); if (get_vaultdata("FFMON_SSTIME", sVaultData, MAX_DATA_LENGTH ) != 0) g_SpawnShotTime = strtonum(sVaultData); if (get_vaultdata("FFMON_SSACTION", sVaultData, MAX_DATA_LENGTH ) != 0) g_SpawnShotAction = strtonum(sVaultData); if (get_vaultdata("FFMON_SSBANTIME", sVaultData, MAX_DATA_LENGTH ) != 0) g_SpawnShotBanTime = strtonum(sVaultData); if (get_vaultdata("FFMON_SKUNK", sVaultData, MAX_DATA_LENGTH ) != 0) g_SkunkProtection = check_param(sVaultData); if (get_vaultdata("FFMON_SKUNKTYPE", sVaultData, MAX_DATA_LENGTH ) != 0) g_SkunkType = strtonum(sVaultData); if (get_vaultdata("FFMON_SKUNKLIMIT", sVaultData, MAX_DATA_LENGTH ) != 0) g_SkunkLimit = strtonum(sVaultData); if (get_vaultdata("FFMON_IMMUNITY", sVaultData, MAX_DATA_LENGTH ) != 0) g_Immunity = check_param(sVaultData); if (get_vaultdata("FFMON_IMMUNITYLEVEL", sVaultData, MAX_DATA_LENGTH ) != 0) g_ImmunityLevel = strtonum(sVaultData); if (get_vaultdata("FFMON_SCORES", sVaultData, MAX_DATA_LENGTH ) != 0) g_DisplayScores = check_param(sVaultData); if (get_vaultdata("FFMON_LOG", sVaultData, MAX_DATA_LENGTH ) != 0) g_LogMessages = check_param(sVaultData); if (get_vaultdata("FFMON_CONSGREET", sVaultData, MAX_DATA_LENGTH ) != 0) g_DisplayConsgreet = check_param(sVaultData); if (get_vaultdata("FFMON_BLOCKATTACK", sVaultData, MAX_DATA_LENGTH ) != 0) g_BlockAttackMessages = check_param(sVaultData); if (get_vaultdata("FFMON_STARTVOTE", sVaultData, MAX_DATA_LENGTH ) != 0) g_StartVote = check_param(sVaultData); if (get_vaultdata("FFMON_STARTVOTEROUND", sVaultData, MAX_DATA_LENGTH ) != 0) g_StartVoteRound = strtonum(sVaultData); //LogMessage("Configuration values loaded."); } stock SaveConfiguration() { SetVaultParam("FFMON_ENABLED", g_Enabled); SetVaultParam("FFMON_TK", g_TkProtection); SetVaultParam("FFMON_DEBUG", g_DebugMessages); SetVaultInt("FFMON_TKLIMIT", g_TkLimit); SetVaultInt("FFMON_TKBANTIME", g_TkLimitBanTime); SetVaultParam("FFMON_TKMENU", g_TkMenu); SetVaultParam("FFMON_TKRESET", g_TkReset); SetVaultParam("FFMON_TKSAVE", g_TkSave); SetVaultInt("FFMON_TKSAVETIME", g_TkSaveTime); SetVaultInt("FFMON_TKSAVELIMIT", g_TkSaveLimit); SetVaultInt("FFMON_TKSAVEBANTIME", g_TkSaveBanTime); SetVaultInt("FFMON_TKSAVEPURGETIME", g_TkSavePurgeTime); SetVaultParam("FFMON_TD", g_TdProtection); SetVaultInt("FFMON_TDLIMIT", g_TdLimit); SetVaultInt("FFMON_TDACTION", g_TdAction); SetVaultInt("FFMON_ALLOWPUNISH", g_AllowPunish); SetVaultInt("FFMON_USERSLAPCOUNT", g_UserSlapCount); SetVaultInt("FFMON_OVERRIDELEVEL", g_UserOverrideLevel); SetVaultInt("FFMON_BURYGLOWTIME", g_BuryGlowTime); SetVaultInt("FFMON_RS", g_RoundStartTime); SetVaultParam("FFMON_RSBANTK", g_RoundStartBanTk); SetVaultInt("FFMON_RSBANTKTIME", g_RoundStartBanTime); SetVaultInt("FFMON_RSTDSLAP", g_RoundStartTdSlap); SetVaultInt("FFMON_RSTDSLAPCOUNT", g_RoundStartTdSlapTimes); SetVaultInt("FFMON_RSTDACTION", g_RoundStartTdAction); SetVaultInt("FFMON_RSTDCOUNT", g_RoundStartTdCount); SetVaultInt("FFMON_RSTDBANTIME", g_RoundStartTdBanTime); SetVaultParam("FFMON_SS", g_SpawnShotProtection); SetVaultInt("FFMON_SSTIME", g_SpawnShotTime); SetVaultInt("FFMON_SSACTION", g_SpawnShotAction); SetVaultInt("FFMON_SSBANTIME", g_SpawnShotBanTime); SetVaultParam("FFMON_SKUNK", g_SkunkProtection); SetVaultInt("FFMON_SKUNKTYPE", g_SkunkType); SetVaultInt("FFMON_SKUNKLIMIT", g_SkunkLimit); SetVaultParam("FFMON_IMMUNITY", g_Immunity); SetVaultInt("FFMON_IMMUNITYLEVEL", g_ImmunityLevel); SetVaultParam("FFMON_SCORES", g_DisplayScores); SetVaultParam("FFMON_LOG", g_LogMessages); SetVaultParam("FFMON_CONSGREET", g_DisplayConsgreet); SetVaultParam("FFMON_BLOCKATTACK", g_BlockAttackMessages); SetVaultParam("FFMON_STARTVOTE", g_StartVote); SetVaultInt("FFMON_STARTVOTEROUND", g_StartVoteRound); //LogMessage("Configuration values saved."); } ShowNextMap() { new s[MAX_DATA_LENGTH]; new sMessage[MAX_TEXT_LENGTH]; nextmap(s, MAX_DATA_LENGTH); snprintf(sMessage, MAX_TEXT_LENGTH, "The next map will be %s.", s); SayMessage(sMessage); } DisplayTk() { new sName[MAX_NAME_LENGTH]; new iUserID; new iWONID; new iTeam; new s[MAX_TEXT_LENGTH]; new sAuthID[MAX_AUTHID_LENGTH]; new i; new iDead; new iMaxPlayers = maxplayercount(); for (i = 1; i <= iMaxPlayers; i++) { /* get the players name for this slot */ if (playerinfo(i, sName, MAX_NAME_LENGTH, iUserID, iWONID, iTeam, iDead, sAuthID)) { if (iUserID != 0) { snprintf(s, MAX_TEXT_LENGTH, "FFMon: %s: %d TK(s).", sName, g_TkCount[i]); selfmessage(s); } } } } DisplayTd() { new sName[MAX_NAME_LENGTH]; new sAuthID[MAX_AUTHID_LENGTH]; new iUserID; new iWONID; new iTeam; new iDead; new s[MAX_TEXT_LENGTH]; new i; new iMaxPlayers = maxplayercount(); for (i = 1; i <= iMaxPlayers; i++) { /* get the players name for this slot */ if (playerinfo(i, sName, MAX_NAME_LENGTH, iUserID, iWONID, iTeam, iDead, sAuthID)) { if (iUserID != 0) { snprintf(s, MAX_TEXT_LENGTH, "FFMon: %s: %d TD(s).", sName, g_TdCount[i]); selfmessage(s); } } } } DisplayConsgreet() { new s[MAX_TEXT_LENGTH]; if (g_DisplayConsgreet) { consgreet(""); consgreet("Friendly Fire Monitor by Desslok <desslok@taradox.com>."); consgreet(""); if (g_TkProtection) { snprintf(s, MAX_TEXT_LENGTH, "%d unforgiven TKs: %d min ban.", g_TkLimit, g_TkLimitBanTime); consgreet(s); } if (g_TdProtection) { new sAction[MAX_TEXT_LENGTH]; GetActionString(g_TdAction, sAction); snprintf(s, MAX_TEXT_LENGTH, "%d team attacks: %s.", g_TdLimit, sAction); consgreet(s); } if (g_RoundStartBanTk || g_RoundStartTdSlap || g_RoundStartTdAction) { snprintf(s, MAX_TEXT_LENGTH, "Round start: %d sec.", g_RoundStartTime); consgreet(s); } if (g_RoundStartBanTk) { snprintf(s, MAX_TEXT_LENGTH, "Round start TKs: %d min ban.", g_RoundStartBanTime); consgreet(s); } if (g_RoundStartTdSlap) { snprintf(s, MAX_TEXT_LENGTH, "Round start team attacks: %d slaps.", g_RoundStartTdSlapTimes); consgreet(s); } if (g_RoundStartTdAction) { new sAction[MAX_TEXT_LENGTH]; GetActionString(g_RoundStartTdAction, sAction); snprintf(s, MAX_TEXT_LENGTH, "Round start %d team attacks: %s.", g_RoundStartTdCount, sAction); consgreet(s); } if (g_SpawnShotProtection && g_SpawnShotAction) { new sAction[MAX_TEXT_LENGTH]; GetActionString(g_SpawnShotAction, sAction); snprintf(s, MAX_TEXT_LENGTH, "Spawn shooters in first %d sec get %s.", g_SpawnShotTime, sAction); consgreet(s); } consgreet(""); strcpy(s, "TK options: forgive", MAX_TEXT_LENGTH); if ((g_AllowPunish & ACTION_SLAY) == ACTION_SLAY) strcat(s, " slay", MAX_TEXT_LENGTH); if ((g_AllowPunish & ACTION_KICK) == ACTION_KICK) strcat(s, " kick", MAX_TEXT_LENGTH); if ((g_AllowPunish & ACTION_BAN) == ACTION_BAN) strcat(s, " ban", MAX_TEXT_LENGTH); if ((g_AllowPunish & ACTION_SLAP) == ACTION_SLAP) strcat(s, " slap", MAX_TEXT_LENGTH); if ((g_AllowPunish & ACTION_BURY) == ACTION_BURY) strcat(s, " bury", MAX_TEXT_LENGTH); if ((g_AllowPunish & ACTION_CHICKEN) == ACTION_CHICKEN) strcat(s, " chicken", MAX_TEXT_LENGTH); consgreet(s); consgreet("Say overrideban to remove an unjustified ban."); } } DisplayHelp() { selfmessage("FFMon Public Commands"); selfmessage("---------------------"); selfmessage("admin_ffmon status - show status"); selfmessage("admin_ffmon showtk - show TK counts"); selfmessage("admin_ffmon showtd - show TD counts"); selfmessage(""); selfmessage("FFMon Admin Commands (typing any command with no value will show its current setting)"); selfmessage("--------------------"); selfmessage("admin_ffmon on|off - turn on or off FFMon"); selfmessage("admin_ffmon help - show help"); selfmessage("admin_ffmon tk on|off (default: on) - TK monitoring"); selfmessage("admin_ffmon tklimit <value> (default: 3) - TK limit before banning"); selfmessage("admin_ffmon tkbantime <value> (default: 30) - ban time for TK abusers"); selfmessage("admin_ffmon tkmenu on|off (default: off) - TK experimental menu"); selfmessage("admin_ffmon tkreset on|off (default: off) - reset TK counts at end of each round"); selfmessage("admin_ffmon td on|off (default: on) - TD monitoring"); selfmessage("admin_ffmon tdlimit <value> (default: 5) - TD limit before slaying"); selfmessage("admin_ffmon tdaction slay|kick|ban|bury|chicken (default: slay) - action when users hit tdlimit"); selfmessage(""); selfmessage("admin_ffmon allowpunish <kick|ban|slap|bury|chicken|overrideban|all> (default: all - chicken)"); selfmessage("admin_ffmon userslapcount <value> (default: 1) - number of times to slap when slaptk is used"); selfmessage("admin_ffmon overridelevel <value> (default: 0) - level req to override bans--anybody by default"); selfmessage("admin_ffmon buryglowtime <value> (default: 30) - amount of time to glow after a bury"); selfmessage(""); selfmessage("admin_ffmon rs <value> (default: 10) - seconds to monitor at round start, 0 to disable"); selfmessage("admin_ffmon rsbantk on|off (default: on) - ban TKers immediately during round start time"); selfmessage("admin_ffmon rsbantktime <value> (default: 300) - minutes to ban round start TKers"); selfmessage("admin_ffmon rstdslap on|off (default: on) - slap TDers during round start time"); selfmessage("admin_ffmon rstdslapcount <value> (default: 5) - # of times to slap TDers during round start"); selfmessage("admin_ffmon rstdaction none|slay|kick|ban (default: ban) - action to take against TD abusers"); selfmessage("admin_ffmon rstdcount <value> (default: 3) - limit for TD abusers at round start"); selfmessage("admin_ffmon rstdbantime <value> (default: 2) - minutes to ban a TD abuser"); selfmessage(""); selfmessage("admin_ffmon ss on|off (default: off) - Spawn shot monitoring"); selfmessage("admin_ffmon sstime <value> (default: 2) - seconds to monitor spawn shooting"); selfmessage("admin_ffmon ssaction none|slay|kick|ban|bury (default: kick) - action against spawn shooters"); selfmessage("admin_ffmon ssbantime <value> (default: 5) - minutes to ban spawn shooters"); selfmessage(""); selfmessage("admin_ffmon skunk on|off (default: on) - Skunk monitoring"); selfmessage("admin_ffmon skunktype 0|1 (default: 0) - 0=normal,1=trad: trad skunk only if losing team has 0"); selfmessage("admin_ffmon skunklimit <value> (default: 10) - Score difference limit for a skunk"); selfmessage(""); selfmessage("admin_ffmon immunity on|off (default: off) - immunity for admins from TK/TD"); selfmessage("admin_ffmon immunitylevel <value> (default: 65536) - level required for immunity"); selfmessage(""); selfmessage("admin_ffmon scores on|off (default: on) - Display team scores at end round (incl win notifications)"); selfmessage("admin_ffmon log on|off (default: on) - FFMon info message to log files"); selfmessage("admin_ffmon consgreet on|off (default: on) - console greeting at connect time"); selfmessage("admin_ffmon blockattack on|off (default: on) - block attack messages from to log files"); selfmessage(""); selfmessage("admin_ffmon startvote on|off (default: on) - start an hlds vote before mp_winlimit"); selfmessage("admin_ffmon startvoteround <value> (default: 2) - number of rnds before mp_winlimit to start vote"); } SetLogDetail() { new iCurLogDetail = getvar("mp_logdetail"); new iLogDetail = 0; // try to be smart about this so we don't enable more log detail // than we actually need for performance reasons if (g_SpawnShotProtection) { iLogDetail += 1; } if (g_TkProtection || g_TdProtection || g_RoundStartBanTk) { iLogDetail += 2; } if (iCurLogDetail < iLogDetail) { new s[MAX_TEXT_LENGTH]; snprintf(s, MAX_TEXT_LENGTH, "mp_logdetail %d", iLogDetail); exec(s); } if (g_BlockAttackMessages) { // block attack info from being written to the log file exec("logd_block 58"); } } ForceNextMap() { /* Since adminmod will report a different nextmap then what the HL engine will use as the nextmap we will just set mp_maxrounds to 1 so that the engine will trigger a map change. This should prevent the map cycle from gettin too out of sync and should make map changing more like a normal map switch. */ #if FORCE_NEXTMAP_ADMINMOD == 1 // adminmod way of changing maps nextmap(s, MAX_DATA_LENGTH); changelevel(s, 4); #else // store the current maxround value so it can be restored later. SetVaultInt("FFMON_FORCENEXTMAP", getvar("mp_maxrounds")); exec("mp_maxrounds 1"); #endif } ForceNextMapUndo() { #if FORCE_NEXTMAP_ADMINMOD == 0 // return mp_maxrounds to what it was before in case we used it to switch maps new VaultData[MAX_DATA_LENGTH]; new iVaultData = -1; if (get_vaultdata("FFMON_FORCENEXTMAP", VaultData, MAX_DATA_LENGTH ) != 0) iVaultData = strtonum(VaultData); if (iVaultData != 9999) { new s[MAX_TEXT_LENGTH]; snprintf(s, MAX_TEXT_LENGTH, "mp_maxrounds %d", iVaultData); exec(s); SetVaultInt("FFMON_FORCENEXTMAP", 9999); } #endif } DisplayParamState(sDesc[], iValue) { new sState[MAX_DATA_LENGTH] = "OFF"; new s[MAX_TEXT_LENGTH]; if (iValue) { sState = "ON"; } snprintf(s, MAX_TEXT_LENGTH, "FFMon: %s is %s.", sDesc, sState); selfmessage(s); } DisplayParamValue(sDesc[], iValue) { new s[MAX_TEXT_LENGTH]; snprintf(s, MAX_TEXT_LENGTH, "FFMon: %s is %d.", sDesc, iValue); selfmessage(s); } DisplayParamString(sDesc[], sValue[]) { new s[MAX_TEXT_LENGTH]; snprintf(s, MAX_TEXT_LENGTH, "FFMon: %s: %s.", sDesc, sValue); selfmessage(s); } public roundstartover() { DebugMessage("Round start time complete."); new i; g_RoundStart = 0; for (i = 1; i <= MAX_PLAYERS; i++) { g_tkedby[i] = USER_ID_INVALID; } } public roundspawntimer() { DebugMessage("Spawn time complete."); g_RoundSpawn = 0; } // // I'm having problems with timers from adminmod. In some cases I // do not receive a callback for the timer and therefore never mark // the end of the round start or spawn times. So instead of setting // a timer, we will detect the beginning of the round events // manually... kinda stinks but it should work. This function will // be called from the checktd and checktk routines before any // processing is done. // CheckTimers() { if (g_RoundStart || g_RoundSpawn) { new iSystemTime = systemtime(); if ((g_RoundSpawn) && (iSystemTime > g_RoundStartTimer + g_SpawnShotTime)) { roundspawntimer(); } if ((g_RoundStart) && (iSystemTime > g_RoundStartTimer + g_RoundStartTime)) { roundstartover(); } } } CheckTkLimit(iID, sWONID[], sName[]) { new iHandled = 0; if ( (GetTkCount(sWONID) >= g_TkSaveLimit) && (!IsImmune(sName)) ) { new sMessage[MAX_TEXT_LENGTH]; BanUser(sWONID, g_TkSaveBanTime, 0); snprintf( sMessage, MAX_TEXT_LENGTH, "%s has TKed %i times in %d hours. Banned for %i min.", sName, g_TkSaveLimit, g_TkSaveTime, g_TkSaveBanTime ); //typesay( sMessage, 10, 255, 255, 255 ); SayMessage(sMessage); LogMessage("Multiple TKer (saved) banned."); RemoveTkFile(sWONID); iHandled = 1; } if ( (g_TkCount[iID] >= g_TkLimit) && (!IsImmune(sName)) && !iHandled ) { new sMessage[MAX_TEXT_LENGTH]; BanUser(sWONID, g_TkLimitBanTime); snprintf( sMessage, MAX_TEXT_LENGTH, "%s has TKed %i times and was banned for %i min.", sName, g_TkLimit, g_TkLimitBanTime ); //typesay( sMessage, 10, 255, 255, 255 ); SayMessage(sMessage); LogMessage("Multiple TKer banned."); iHandled = 1; } return iHandled; } /* * * * LogD specific functions * * * */ public ffmon_checktk(HLCommand, HLData, HLUserName, UserIndex) { if (!g_Enabled) return PLUGIN_CONTINUE; HeapCheckStart(); new iIDA; new sIDA[MAX_NUMBER_LENGTH]; new iUserIDA; new iWONIDA; new iTeamA; new sNameA[MAX_NAME_LENGTH]; new sAuthIDA[MAX_AUTHID_LENGTH]; new iIDV; new sIDV[MAX_NUMBER_LENGTH]; new iUserIDV; new iWONIDV; new iTeamV; new sNameV[MAX_NAME_LENGTH]; new sAuthIDV[MAX_AUTHID_LENGTH]; new sData[MAX_DATA_LENGTH]; new sMessage[MAX_TEXT_LENGTH]; new iDead; CheckTimers(); convert_string(HLData, sData, MAX_DATA_LENGTH); strsplit(sData, " ", sIDA, 3, sIDV, 3 ); iIDA = strtonum(sIDA); iIDV = strtonum(sIDV); if (iIDA == 0) { LogMessage("ffmon_checktk attacker ID is 0"); return PLUGIN_CONTINUE; } if (iIDV == 0) { LogMessage("ffmon_checktk victim ID is 0"); return PLUGIN_CONTINUE; } if (!playerinfo(iIDA, sNameA, MAX_NAME_LENGTH, iUserIDA, iWONIDA, iTeamA, iDead, sAuthIDA)) { LogMessage("ffmon_checktk attacker playerinfo failed"); return PLUGIN_CONTINUE; } if (!playerinfo(iIDV, sNameV, MAX_NAME_LENGTH, iUserIDV, iWONIDV, iTeamV, iDead, sAuthIDV)) { LogMessage("ffmon_checktk victim playerinfo failed"); return PLUGIN_CONTINUE; } /* * * check to see if this is a spawn killer * This is most useful for maps like awp_map and what not * */ if (iTeamV != iTeamA) { HeapCheckStop("ffmon_checktk"); if (g_RoundSpawn && g_SpawnShotProtection) { if (!IsImmune(sNameA)) { if (DoAction(sAuthIDA, g_SpawnShotAction, g_SpawnShotBanTime)) { new sAction[MAX_TEXT_LENGTH]; GetActionString(g_SpawnShotAction, sAction); snprintf( sMessage, MAX_TEXT_LENGTH, "%s was %s for spawn killing in first %i sec.", sNameA, sAction, g_SpawnShotTime); //typesay( sMessage, 10, 255, 255, 255 ); SayMessage(sMessage); snprintf(sMessage, MAX_TEXT_LENGTH, "Spawn killer %s.", sAction); LogMessage(sMessage); } } } return PLUGIN_CONTINUE; } if (g_RoundStart && g_RoundStartBanTk) { if (!IsImmune(sNameA)) { BanUser(sAuthIDA, g_RoundStartBanTime); snprintf( sMessage, MAX_TEXT_LENGTH, "%s was banned for %i min for TKing in first %i sec.", sNameA, g_RoundStartBanTime, g_RoundStartTime); //typesay( sMessage, 10, 255, 255, 255 ); SayMessage(sMessage); LogMessage("Round start TKer banned."); } } else { if (!g_TkProtection) return PLUGIN_CONTINUE; g_tkedby[iIDV] = iIDA; g_TkCount[iIDA] += 1; AddTk(sAuthIDA); if (!CheckTkLimit(iIDA, sAuthIDA, sNameA)) { new sMessage2[MAX_TEXT_LENGTH]; snprintf( sMessage, MAX_TEXT_LENGTH, "%s TK Warning %i of %i... you don't want to get to %i.", sNameA, g_TkCount[iIDA], g_TkLimit, g_TkLimit ); typesay( sMessage, 10, 255, 255, 255 ); //SayMessage(sMessage); snprintf( sMessage, MAX_TEXT_LENGTH, "%s TKed you. ", sNameA); strcpy(sMessage2, "Options: forgive", MAX_TEXT_LENGTH); // build the string that shows what options the user has if ((g_AllowPunish & ACTION_SLAY) == ACTION_SLAY) strcat(sMessage2, " slay", MAX_TEXT_LENGTH); if ((g_AllowPunish & ACTION_KICK) == ACTION_KICK) strcat(sMessage2, " kick", MAX_TEXT_LENGTH); if ((g_AllowPunish & ACTION_BAN) == ACTION_BAN) strcat(sMessage2, " ban", MAX_TEXT_LENGTH); if ((g_AllowPunish & ACTION_SLAP) == ACTION_SLAP) strcat(sMessage2, " slap", MAX_TEXT_LENGTH); if ((g_AllowPunish & ACTION_BURY) == ACTION_BURY) strcat(sMessage2, " bury", MAX_TEXT_LENGTH); if ((g_AllowPunish & ACTION_CHICKEN) == ACTION_CHICKEN) strcat(sMessage2, " chicken", MAX_TEXT_LENGTH); // for a pretty print (tsay) set iPrintType = 1 new iPrintType = 0; if (iPrintType) { strcat(sMessage, "^n", MAX_TEXT_LENGTH); strcat(sMessage, sMessage2, MAX_TEXT_LENGTH); messageex(sAuthIDV, sMessage, print_pretty); } else { // normal chat message messageex(sAuthIDV, sMessage, print_chat); messageex(sAuthIDV, sMessage2, print_chat); } if (g_TkMenu) { DisplayTkMenu(iIDV); #if USE_ADMINMOD_MENUS != 1 BindToMenuselect(iIDV); #endif } } HeapCheckStop("ffmon_checktk"); } return PLUGIN_HANDLED; } public ffmon_checktd(HLCommand, HLData, HLUserName, UserIndex) { if (!g_Enabled) return PLUGIN_CONTINUE; HeapCheckStart(); new iIDA; new iIDV; new iUserIDA; new iUserIDV; new iWONIDA; new iWONIDV; new iTeamA; new iTeamV; new iDead; new sIDA[MAX_NUMBER_LENGTH]; new sIDV[MAX_NUMBER_LENGTH]; new sData[MAX_DATA_LENGTH]; new sNameA[MAX_NAME_LENGTH]; new sNameV[MAX_NAME_LENGTH]; new sAuthIDA[MAX_AUTHID_LENGTH]; new sAuthIDV[MAX_AUTHID_LENGTH]; new sTDMessage[MAX_DATA_LENGTH]; new i; CheckTimers(); convert_string(HLData, sData, MAX_DATA_LENGTH); strsplit(sData, " ", sIDA, 3, sIDV, 3 ); iIDA = strtonum( sIDA ); iIDV = strtonum( sIDV ); if (iIDA == 0) { LogMessage("ffmon_checktd attacker ID is 0"); return PLUGIN_CONTINUE; } if (iIDV == 0) { LogMessage("ffmon_checktd victim ID is 0"); return PLUGIN_CONTINUE; } if (!playerinfo(iIDA, sNameA, MAX_NAME_LENGTH, iUserIDA, iWONIDA, iTeamA, iDead, sAuthIDA)) { LogMessage("ffmon_checktd attacker playerinfo failed"); return PLUGIN_CONTINUE; } if (!playerinfo(iIDV, sNameV, MAX_NAME_LENGTH, iUserIDV, iWONIDV, iTeamV, iDead, sAuthIDV)) { LogMessage("ffmon_checktd victim playerinfo failed"); return PLUGIN_CONTINUE; } // check to see if the player hurt themselves if (iIDA == iIDV) return PLUGIN_CONTINUE; if ( (iTeamV != iTeamA) ) { // spawn shot -- if dead then the spawn kill will get it if (g_RoundSpawn && g_SpawnShotProtection && !iDead) { if ( (!IsImmune(sNameA)) && (DoAction(sAuthIDA, g_SpawnShotAction, g_SpawnShotBanTime)) ) { new sAction[MAX_TEXT_LENGTH]; GetActionString(g_SpawnShotAction, sAction); snprintf( sTDMessage, MAX_TEXT_LENGTH, "%s was %s for spawn shooting in first %i sec.", sNameA, sAction, g_SpawnShotTime); //typesay( sTDMessage, 10, 255, 255, 255 ); SayMessage(sTDMessage); snprintf(sTDMessage, MAX_TEXT_LENGTH, "Spawn shooter %s.", sAction); LogMessage(sTDMessage); } } return PLUGIN_CONTINUE; } if (!g_TdProtection) return PLUGIN_CONTINUE; g_TdCount[iIDA] += 1; snprintf(sTDMessage, MAX_DATA_LENGTH, "%s,\nTHAT'S YOUR TEAMMATE, HOLD YOUR FIRE.", sNameA); messageex(sNameA, sTDMessage, print_pretty); /* special handling if this is the beginning of the round */ if (g_RoundStart) { if ( (g_RoundStartTdSlap) && (!IsImmune(sNameA)) ) { for (i = 0; i < g_RoundStartTdSlapTimes; i++) slap(sAuthIDA); } if ( (g_TdCount[iIDA] == g_RoundStartTdCount) && (!IsImmune(sNameA)) ) { if (DoAction(sAuthIDA, g_RoundStartTdAction, g_RoundStartTdBanTime)) { new sAction[MAX_TEXT_LENGTH]; GetActionString(g_RoundStartTdAction, sAction); snprintf( sTDMessage, MAX_TEXT_LENGTH, "%s was %s for team attacking %d times in first %i sec.", sNameA, sAction, g_RoundStartTdCount, g_RoundStartTime); //typesay( sTDMessage, 10, 255, 255, 255 ); SayMessage(sTDMessage); snprintf(sTDMessage, MAX_TEXT_LENGTH, "Round start TD abuser %s.", sAction); LogMessage(sTDMessage); } } } /* has the user reached their TD limit? */ if ( (g_TdCount[iIDA] == g_TdLimit) && (!IsImmune(sNameA)) ) { if (DoAction(sAuthIDA, g_TdAction, g_TkLimitBanTime)) { new sAction[MAX_TEXT_LENGTH]; GetActionString(g_TdAction, sAction); snprintf( sTDMessage, MAX_TEXT_LENGTH, "%s was %s for team attacking %d times.", sNameA, sAction, g_TdLimit); //typesay( sTDMessage, 10, 255, 255, 255 ); SayMessage(sTDMessage); g_TdCount[iIDA] = 0; g_TkCount[iIDA] += 1; AddTk(sAuthIDA); CheckTkLimit(iIDA, sAuthIDA, sNameA); } } HeapCheckStop("ffmon_checktd"); return PLUGIN_HANDLED; } public ffmon_worldaction(HLCommand, HLData, HLUserName, UserIndex) { if (!g_Enabled) return PLUGIN_CONTINUE; HeapCheckStart(); new i; new sParams[MAX_DATA_LENGTH]; convert_string(HLData, sParams, MAX_DATA_LENGTH); if (streq(sParams, "Round_Start")) { UnchickenUsers(); for (i = 1; i <= MAX_PLAYERS; i++) { // clear team attack counts g_TdCount[i] = 0; if (g_TkReset) { g_TkCount[i] = 0; } // do any cached revenge actions if (g_TkRevenge[i] != ACTION_NONE) { new sName[MAX_NAME_LENGTH]; new sAuthID[MAX_AUTHID_LENGTH]; new sAction[MAX_TEXT_LENGTH]; new sData[MAX_DATA_LENGTH]; new iUserID; new iWONID; new iTeam; new iDead; if (playerinfo(i, sName, MAX_NAME_LENGTH, iUserID, iWONID, iTeam, iDead, sAuthID)) { GetActionString(g_TkRevenge[i], sAction); DoAction(sAuthID, g_TkRevenge[i], 5); snprintf(sData, MAX_DATA_LENGTH, "%s was %s as TK revenge.", sName, sAction); SayMessage(sData); } g_TkRevenge[i] = ACTION_NONE; } } /* old timer code if (set_timer("roundstartover", g_RoundStartTime, 0)) { g_RoundStart = 1; } else { LogMessage("Round start timer failed!"); } if (set_timer("roundspawntimer", g_SpawnShotTime, 0)) { g_RoundSpawn = 1; } else { LogMessage("Spawn timer failed!"); } */ // new manual timer code g_RoundStartTimer = systemtime(); g_RoundStart = 1; g_RoundSpawn = 1; } HeapCheckStop("ffmon_worldaction"); return PLUGIN_HANDLED; } public ffmon_teamaction(HLCommand, HLData, HLUserName, UserIndex) { if (!g_Enabled) return PLUGIN_CONTINUE; new sParams[MAX_DATA_LENGTH]; new sTeam[MAX_DATA_LENGTH]; new sAction[MAX_DATA_LENGTH]; convert_string(HLData, sParams, MAX_DATA_LENGTH); strbreak(sParams, sTeam, sAction, MAX_DATA_LENGTH); if ( (strmatch(sAction, "CTs_Win", strlen("CTs_Win"))) || (strmatch(sAction, "Terrorists_Win", strlen("Terrorists_Win"))) || (strmatch(sAction, "Bomb_Defused", strlen("Bomb_Defused"))) || (strmatch(sAction, "Target_Bombed", strlen("Target_Bombed"))) || (strmatch(sAction, "Target_Saved", strlen("Target_Saved"))) || (strmatch(sAction, "Hostages_Not_Rescued", strlen("Hostages_Not_Rescued"))) || (strmatch(sAction, "All_Hostages_Rescued", strlen("All_Hostages_Rescued"))) || (strmatch(sAction, "VIP_Assassinated", strlen("All_Hostages_Rescued"))) || (strmatch(sAction, "VIP_Escaped", strlen("All_Hostages_Rescued"))) ) { new sScores[MAX_DATA_LENGTH]; new sCtScore[MAX_DATA_LENGTH]; new sTScore[MAX_DATA_LENGTH]; new sSkip[MAX_DATA_LENGTH]; new s[MAX_DATA_LENGTH]; new sWinning[MAX_DATA_LENGTH]; new sLosing[MAX_DATA_LENGTH]; new c; new iDiff; new iWinLimit; new iWinning; new iLosing; strbreak(sAction, sSkip, sScores, MAX_DATA_LENGTH); strbreak(sScores, sCtScore, sTScore, MAX_DATA_LENGTH); c = strchr(sCtScore, '#') + 1; g_CtScore = strtonum(sCtScore[c]); c = strchr(sTScore, '#') + 1; g_TScore = strtonum(sTScore[c]); ShowScore(); if (g_CtScore > g_TScore) { iDiff = g_CtScore - g_TScore; iWinning = g_CtScore; iLosing = g_TScore; strcpy(sWinning, "Counter-terrorist", MAX_DATA_LENGTH); strcpy(sLosing, "Terrorist", MAX_DATA_LENGTH); } else { iDiff = g_TScore - g_CtScore; iWinning = g_TScore; iLosing = g_CtScore; strcpy(sLosing, "Counter-terrorist", MAX_DATA_LENGTH); strcpy(sWinning, "Terrorist", MAX_DATA_LENGTH); } iWinLimit = getvar("mp_winlimit"); if ( (iDiff == (g_SkunkLimit - 1)) && (iWinning != iWinLimit) && (g_SkunkProtection) && ( (g_SkunkType == SKUNK_TYPE_NORMAL) || ((g_SkunkType == SKUNK_TYPE_TRADITIONAL) && (iLosing == 0)) ) ) { /* announce possible skunk */ snprintf(s, MAX_DATA_LENGTH, "Possible skunk by the %ss next round.", sWinning); //typesay( s, 10, 255, 255, 255 ); SayMessage(s); } else if ( (iDiff == g_SkunkLimit) && (g_SkunkProtection) && ( (g_SkunkType == SKUNK_TYPE_NORMAL) || ((g_SkunkType == SKUNK_TYPE_TRADITIONAL) && (iLosing == 0)) ) ) { /* annouce skunk and go to the next map */ snprintf(s, MAX_DATA_LENGTH, "%ss skunk the %ss!", sWinning, sLosing); //typesay( s, 10, 255, 255, 255 ); SayMessage(s); ShowNextMap(); ForceNextMap(); } else if ( (iWinLimit > 0) && (iWinning == (iWinLimit - 1)) && (iLosing == (iWinLimit - 1)) && (g_DisplayScores) ) { snprintf(s, MAX_DATA_LENGTH, "SUDDEN DEATH!! Winner take all!", sWinning); //typesay( s, 10, 255, 255, 255 ); SayMessage(s); } else if ( (iWinLimit > 0) && (iWinning == (iWinLimit - 1)) && (g_DisplayScores) ) { snprintf(s, MAX_DATA_LENGTH, "Possible %s victory next round.", sWinning); //typesay( s, 10, 255, 255, 255 ); SayMessage(s); } else if ( (iWinLimit > 0) && (iWinning >= (iWinLimit)) && (g_DisplayScores) ) { snprintf(s, MAX_DATA_LENGTH, "%ss win!!!", sWinning); //typesay( s, 10, 255, 255, 255 ); SayMessage(s); ShowNextMap(); } // start a map vote if requested if ( (g_StartVote) && (!g_VoteStarted) && ((iWinLimit - iWinning) == g_StartVoteRound) ) { DebugMessage("Starting map vote due to round count"); plugin_exec("admin_startvote", ""); g_VoteStarted = 1; } } return PLUGIN_CONTINUE; } /* * * * Adminmod functions * */ public HandleSay(HLCommand, HLData, HLUserName, UserIndex) { if (!g_Enabled) return PLUGIN_CONTINUE; new iUserIDA; new iWONIDA; new iTeamA; new sNameA[MAX_NAME_LENGTH]; new sNameV[MAX_NAME_LENGTH]; new sAuthIDA[MAX_AUTHID_LENGTH]; new sAuthIDV[MAX_AUTHID_LENGTH]; new sData[MAX_DATA_LENGTH]; new iUserIDV; new iWONIDV; new iTeamV; new iDeadA; new iDeadV; new iReturn = PLUGIN_CONTINUE; convert_string(HLData, sData, MAX_DATA_LENGTH); strstripquotes(sData); sData[0] = sData[0] | 32; if ( (sData[0] != 'f') && (sData[0] != 'p') && (sData[0] != 'k') && (sData[0] != 'b') && (sData[0] != 's') && (sData[0] != 'c') && (sData[0] != 'o') && (sData[0] != '!') ) return PLUGIN_CONTINUE; if ( (g_tkedby[UserIndex] != USER_ID_INVALID) && (!playerinfo(g_tkedby[UserIndex], sNameA, MAX_NAME_LENGTH, iUserIDA, iWONIDA, iTeamA, iDeadA, sAuthIDA)) ) { LogMessage("HandleSay attacker playerinfo failed"); return PLUGIN_CONTINUE; } if (!playerinfo(UserIndex, sNameV, MAX_NAME_LENGTH, iUserIDV, iWONIDV, iTeamV, iDeadV, sAuthIDV)) { LogMessage("HandleSay victim playerinfo failed"); return PLUGIN_CONTINUE; } if ( (g_tkedby[UserIndex] != USER_ID_INVALID) && ((strncasecmp(sData, "forgive", 7) == 0) || (strncasecmp(sData, "!forgive", 8) == 0)) ) { g_TkCount[g_tkedby[UserIndex]] -= 1; RemoveTk(sAuthIDA); g_tkedby[UserIndex] = USER_ID_INVALID; snprintf( sData, MAX_DATA_LENGTH, "%s decided to forgive %s and forfeit revenge.", sNameV, sNameA); SayMessage(sData); iReturn = PLUGIN_HANDLED; } else if ( (g_tkedby[UserIndex] != USER_ID_INVALID) && ((strncasecmp(sData,"slay",4) == 0) || (strncasecmp(sData,"!slay",5) == 0) || (strncasecmp(sData,"punishtk",8) == 0) || (strncasecmp(sData,"!punishtk",9) == 0)) ) { if ( (g_AllowPunish & ACTION_SLAY) && (!IsImmune(sNameA)) ) { if (!iDeadA) { slay(sAuthIDA); snprintf( sData, MAX_DATA_LENGTH, "%s decided to have %s executed for TK revenge.", sNameV, sNameA); } else { snprintf( sData, MAX_DATA_LENGTH, "%s is dead. Revenge will happen next round.", sNameA); g_TkRevenge[g_tkedby[UserIndex]] = ACTION_SLAY; } g_tkedby[UserIndex] = USER_ID_INVALID; SayMessage(sData); iReturn = PLUGIN_HANDLED; } } else if ( (g_tkedby[UserIndex] != USER_ID_INVALID) && ((strncasecmp(sData,"ban",3) == 0) || (strncasecmp(sData,"!ban",4) == 0)) ) { if ( (g_AllowPunish & ACTION_BAN) && (!IsImmune(sNameA)) ) { BanUser(sAuthIDA, g_TkLimitBanTime); g_tkedby[UserIndex] = USER_ID_INVALID; snprintf( sData, MAX_DATA_LENGTH, "%s decided to have %s banned for TK revenge.", sNameV, sNameA); SayMessage(sData); iReturn = PLUGIN_HANDLED; } } else if ( (g_tkedby[UserIndex] != USER_ID_INVALID) && ((strncasecmp(sData,"kick",4) == 0) || (strncasecmp(sData,"!kick",5) == 0)) ) { if ( (g_AllowPunish & ACTION_KICK) && (!IsImmune(sNameA)) ) { kick(sAuthIDA); g_tkedby[UserIndex] = USER_ID_INVALID; snprintf( sData, MAX_DATA_LENGTH, "%s decided to have %s kicked for TK revenge.", sNameV, sNameA); SayMessage(sData); iReturn = PLUGIN_HANDLED; } } else if ( (g_tkedby[UserIndex] != USER_ID_INVALID) && ((strncasecmp(sData,"slap",4) == 0) || (strncasecmp(sData,"!slap",5) == 0)) ) { if ( (g_AllowPunish & ACTION_SLAP) && (!IsImmune(sNameA)) ) { if (!iDeadA) { new i; for (i = 0; i <= g_UserSlapCount; i++) slap(sAuthIDA); snprintf( sData, MAX_DATA_LENGTH, "%s decided to have %s slapped for TK revenge.", sNameV, sNameA); } else { snprintf( sData, MAX_DATA_LENGTH, "%s is dead. Revenge will happen next round.", sNameA); g_TkRevenge[g_tkedby[UserIndex]] = ACTION_SLAP; } g_tkedby[UserIndex] = USER_ID_INVALID; SayMessage(sData); iReturn = PLUGIN_HANDLED; } } else if ( (g_tkedby[UserIndex] != USER_ID_INVALID) && ((strncasecmp(sData,"bury",4) == 0) || (strncasecmp(sData,"!bury",5) == 0)) ) { if ( (g_AllowPunish & ACTION_BURY) && (!IsImmune(sNameA)) ) { if (!iDeadA) { BuryUser(sAuthIDA); snprintf( sData, MAX_DATA_LENGTH, "%s decided to have %s buried for TK revenge.", sNameV, sNameA); } else { snprintf( sData, MAX_DATA_LENGTH, "%s is dead. Revenge will happen next round.", sNameA); g_TkRevenge[g_tkedby[UserIndex]] = ACTION_BURY; } g_tkedby[UserIndex] = USER_ID_INVALID; SayMessage(sData); iReturn = PLUGIN_HANDLED; } } else if ( (g_tkedby[UserIndex] != USER_ID_INVALID) && ((strncasecmp(sData,"chicken",7) == 0) || (strncasecmp(sData,"!chicken",8) == 0)) ) { if ( (g_AllowPunish & ACTION_CHICKEN) && (!IsImmune(sNameA)) ) { if (!iDeadA) { ChickenUser(sAuthIDA); snprintf( sData, MAX_DATA_LENGTH, "%s decided to have %s turned into a chicken for TK revenge.", sNameV, sNameA); } else { snprintf( sData, MAX_DATA_LENGTH, "%s is dead. Revenge will happen next round.", sNameA); g_TkRevenge[g_tkedby[UserIndex]] = ACTION_CHICKEN; } g_tkedby[UserIndex] = USER_ID_INVALID; SayMessage(sData); iReturn = PLUGIN_HANDLED; } } else if ((strncasecmp(sData,"score",5) == 0) || (strncasecmp(sData,"!score",6) == 0)) { return ShowScore(); } else if ((strncasecmp(sData,"overrideban",11) == 0) || (strncasecmp(sData,"!overrideban",12) == 0)) { if (strlen(g_LastTkBan) != 0) { if ( (g_AllowPunish & ACTION_OVERRIDE_BAN) && (access(g_UserOverrideLevel, sNameV) != 0) ) { UnbanUser(g_LastTkBan); snprintf( sData, MAX_DATA_LENGTH, "%s removed the last ban.", sNameV); SayMessage(sData); LogMessage("Last ban overridden."); iReturn = PLUGIN_HANDLED; } } } return iReturn; } public plugin_connect(HLUserName, HLIP, UserIndex) { new i; if (UserIndex >= 1 && UserIndex <= MAX_PLAYERS) { g_TkCount[UserIndex] = TK_CLEAN_SLATE; // load the tk count from the file new sName[MAX_NAME_LENGTH]; new sAuthID[MAX_AUTHID_LENGTH]; new iUserID; new iWONID; new iTeam; new iDead; playerinfo(UserIndex, sName, MAX_NAME_LENGTH, iUserID, iWONID, iTeam, iDead, sAuthID); AgeTks(sAuthID); for (i = 1; i <= MAX_PLAYERS; i++) { if (g_tkedby[i] == UserIndex) { g_tkedby[i] = USER_ID_INVALID; } } g_tkedby[UserIndex] = USER_ID_INVALID; g_TdCount[UserIndex] = TD_CLEAN_SLATE; g_TkRevenge[UserIndex] = ACTION_NONE; ResetMenu(UserIndex); } DisplayConsgreet(); return PLUGIN_CONTINUE; } public plugin_disconnect(HLUserName, UserIndex) { new i; if (UserIndex >= 1 && UserIndex <= MAX_PLAYERS) { g_TkCount[UserIndex] = TK_CLEAN_SLATE; for (i = 1; i <= MAX_PLAYERS; i++) { if (g_tkedby[i] == UserIndex) { g_tkedby[i] = USER_ID_INVALID; } } g_tkedby[UserIndex] = USER_ID_INVALID; g_TdCount[UserIndex] = TD_CLEAN_SLATE; g_TkRevenge[UserIndex] = ACTION_NONE; UnchickenUser(UserIndex); ClearTkMenu(UserIndex); } return PLUGIN_CONTINUE; } public admin_ffmon(HLCommand, HLData, HLUserName, UserIndex) { new sData[MAX_DATA_LENGTH]; new sCommand[MAX_DATA_LENGTH]; new sArgument[MAX_DATA_LENGTH]; new iDisplayStatus = 0; convert_string(HLData, sData, MAX_DATA_LENGTH); strinit(sCommand); strinit(sArgument); if (!strlen(sData)) { if (!access(ACCESS_FFMON, "")) { iDisplayStatus = 1; } else { DisplayHelp(); return PLUGIN_HANDLED; } } else { strsplit(sData, " ", sCommand, MAX_DATA_LENGTH, sArgument, MAX_DATA_LENGTH); } if (streq(sCommand, "status")) { iDisplayStatus = 1; } else if (streq(sCommand, "showtk")) { DisplayTk(); return PLUGIN_HANDLED; } else if (streq(sCommand, "showtd")) { DisplayTd(); return PLUGIN_HANDLED; } if (!access(ACCESS_FFMON, "")) { selfmessage("FFMon: You are not allowed to use this command"); return PLUGIN_HANDLED; } if (streq(sCommand, "help")) { DisplayHelp(); return PLUGIN_HANDLED; } else if (streq(sCommand, "on")) { g_Enabled = 1; SaveConfiguration(); iDisplayStatus = 1; } else if (streq(sCommand, "off")) { g_Enabled = 0; SaveConfiguration(); iDisplayStatus = 1; } if (iDisplayStatus) { DisplayParamState("FFMon", g_Enabled); } if (streq(sCommand, "debug") || iDisplayStatus) { if (strlen(sArgument)) { g_DebugMessages = check_param(sArgument); SaveConfiguration(); } DisplayParamState("Debug messages", g_DebugMessages); } if (streq(sCommand, "tk") || iDisplayStatus) { if (strlen(sArgument)) { g_TkProtection = check_param(sArgument); SaveConfiguration(); } DisplayParamState("TK monitoring", g_TkProtection); } if (streq(sCommand, "tklimit") || iDisplayStatus) { if (strlen(sArgument)) { g_TkLimit = strtonum(sArgument); SaveConfiguration(); } if (g_TkLimit < 1) g_TkLimit = 1; DisplayParamValue("TK limit before banning", g_TkLimit); } if (streq(sCommand, "tkbantime") || iDisplayStatus) { if (strlen(sArgument)) { g_TkLimitBanTime = strtonum(sArgument); SaveConfiguration(); } DisplayParamValue("TK limit ban time", g_TkLimitBanTime); } if (streq(sCommand, "tkmenu") || iDisplayStatus) { if (strlen(sArgument)) { g_TkMenu = check_param(sArgument); SaveConfiguration(); } DisplayParamState("TK menu", g_TkMenu); } if (streq(sCommand, "tkreset") || iDisplayStatus) { if (strlen(sArgument)) { g_TkReset = check_param(sArgument); SaveConfiguration(); } DisplayParamState("TK reset", g_TkReset); } if (streq(sCommand, "tksave") || iDisplayStatus) { if (strlen(sArgument)) { g_TkSave = check_param(sArgument); SaveConfiguration(); } DisplayParamState("TK save", g_TkSave); } if (streq(sCommand, "tksavetime") || iDisplayStatus) { if (strlen(sArgument)) { g_TkSaveTime = strtonum(sArgument); SaveConfiguration(); } DisplayParamValue("TK save time", g_TkSaveTime); } if (streq(sCommand, "tksavelimit") || iDisplayStatus) { if (strlen(sArgument)) { g_TkSaveLimit = strtonum(sArgument); SaveConfiguration(); } DisplayParamValue("TK save limit", g_TkSaveLimit); } if (streq(sCommand, "tksavebantime") || iDisplayStatus) { if (strlen(sArgument)) { g_TkSaveBanTime = strtonum(sArgument); SaveConfiguration(); } DisplayParamValue("TK save ban time", g_TkSaveBanTime); } if (streq(sCommand, "tksavepurgetime") || iDisplayStatus) { if (strlen(sArgument)) { g_TkSavePurgeTime = strtonum(sArgument); SaveConfiguration(); } DisplayParamValue("TK save purge time", g_TkSavePurgeTime); } if (streq(sCommand, "td") || iDisplayStatus) { if (strlen(sArgument)) { g_TdProtection = check_param(sArgument); SaveConfiguration(); } DisplayParamState("TD monitoring", g_TdProtection); } if (streq(sCommand, "tdlimit") || iDisplayStatus) { if (strlen(sArgument)) { g_TdLimit = strtonum(sArgument); SaveConfiguration(); } if (g_TdLimit < 1) g_TdLimit = 1; DisplayParamValue("TD limit before slaying", g_TdLimit); } if (streq(sCommand, "tdaction") || iDisplayStatus) { if (strlen(sArgument)) { g_TdAction = check_action(sArgument); SaveConfiguration(); } new sAction[MAX_TEXT_LENGTH]; GetActionString(g_TdAction, sAction); DisplayParamString("TD abuser", sAction); } if (streq(sCommand, "allowpunish") || iDisplayStatus) { new sCurrent[MAX_DATA_LENGTH]; new sNext[MAX_DATA_LENGTH]; if (strlen(sArgument)) { strsep(sData, " ", sCommand, MAX_DATA_LENGTH, sArgument, MAX_DATA_LENGTH); // walk the command line added each option while (strlen(sArgument)) { strsep(sArgument, " ", sCurrent, MAX_DATA_LENGTH, sNext, MAX_DATA_LENGTH); // do the appropriate thing with this action ParseAction(sCurrent); // move to the next item strcpy(sArgument, sNext, MAX_DATA_LENGTH); } SaveConfiguration(); } sCurrent = ""; BuildPunnishmentList(sCurrent); DisplayParamString("Punishments allowed", sCurrent); } if (streq(sCommand, "userslapcount") || iDisplayStatus) { if (strlen(sArgument)) { g_UserSlapCount = strtonum(sArgument); SaveConfiguration(); } if (g_UserSlapCount < 1) g_UserSlapCount = 1; DisplayParamValue("User slap count after TK", g_UserSlapCount); } if (streq(sCommand, "overridelevel") || iDisplayStatus) { if (strlen(sArgument)) { g_UserOverrideLevel = strtonum(sArgument); SaveConfiguration(); } DisplayParamValue("User override access level", g_UserOverrideLevel); } if (streq(sCommand, "buryglowtime") || iDisplayStatus) { if (strlen(sArgument)) { g_BuryGlowTime = strtonum(sArgument); SaveConfiguration(); } DisplayParamValue("Glow time after a bury", g_BuryGlowTime); } if (streq(sCommand, "rs") || iDisplayStatus) { if (strlen(sArgument)) { g_RoundStartTime = strtonum(sArgument); SaveConfiguration(); } DisplayParamValue("Round start time", g_RoundStartTime); } if (streq(sCommand, "rsbantk") || iDisplayStatus) { if (strlen(sArgument)) { g_RoundStartBanTk = check_param(sArgument); SaveConfiguration(); } DisplayParamState("Round start TK banning", g_RoundStartBanTk); } if (streq(sCommand, "rsbantktime") || iDisplayStatus) { if (strlen(sArgument)) { g_RoundStartBanTime = strtonum(sArgument); SaveConfiguration(); } DisplayParamValue("Round start TK ban time", g_RoundStartBanTime); } if (streq(sCommand, "rstdslap") || iDisplayStatus) { if (strlen(sArgument)) { g_RoundStartTdSlap = check_param(sArgument); SaveConfiguration(); } DisplayParamState("Round start TD slapping", g_RoundStartTdSlap); } if (streq(sCommand, "rstdslapcount") || iDisplayStatus) { if (strlen(sArgument)) { g_RoundStartTdSlapTimes = strtonum(sArgument); SaveConfiguration(); } DisplayParamValue("Round start TD slap count", g_RoundStartTdSlapTimes); } if (streq(sCommand, "rstdaction") || iDisplayStatus) { if (strlen(sArgument)) { g_RoundStartTdAction = check_action(sArgument); SaveConfiguration(); } new sAction[MAX_TEXT_LENGTH]; GetActionString(g_RoundStartTdAction, sAction); DisplayParamString("Round start TD abuser", sAction); } if (streq(sCommand, "rstdcount") || iDisplayStatus) { if (strlen(sArgument)) { g_RoundStartTdCount = strtonum(sArgument); SaveConfiguration(); } DisplayParamValue("Round start TD count for action", g_RoundStartTdCount); } if (streq(sCommand, "rstdbantime") || iDisplayStatus) { if (strlen(sArgument)) { g_RoundStartTdBanTime = strtonum(sArgument); SaveConfiguration(); } DisplayParamValue("Round start TD ban time", g_RoundStartTdBanTime); } if (streq(sCommand, "ss") || iDisplayStatus) { if (strlen(sArgument)) { g_SpawnShotProtection = check_param(sArgument); SaveConfiguration(); } DisplayParamState("Spawn shot monitoring", g_SpawnShotProtection); } if (streq(sCommand, "sstime") || iDisplayStatus) { if (strlen(sArgument)) { g_SpawnShotTime = strtonum(sArgument); SaveConfiguration(); } DisplayParamValue("Spawn shot monitor time", g_SpawnShotTime); } if (streq(sCommand, "ssaction") || iDisplayStatus) { if (strlen(sArgument)) { g_SpawnShotAction = check_action(sArgument); SaveConfiguration(); } new sAction[MAX_TEXT_LENGTH]; GetActionString(g_SpawnShotAction, sAction); DisplayParamString("Spawn shooters", sAction); } if (streq(sCommand, "ssbantime") || iDisplayStatus) { if (strlen(sArgument)) { g_SpawnShotBanTime = strtonum(sArgument); SaveConfiguration(); } DisplayParamValue("Spawn shot ban time", g_SpawnShotBanTime); } if (streq(sCommand, "skunk") || iDisplayStatus) { if (strlen(sArgument)) { g_SkunkProtection = check_param(sArgument); SaveConfiguration(); } DisplayParamState("Skunk monitoring", g_SkunkProtection); } if (streq(sCommand, "skunktype") || iDisplayStatus) { if (strlen(sArgument)) { g_SkunkType = strtonum(sArgument); SaveConfiguration(); } DisplayParamValue("Skunk type", g_SkunkType); } if (streq(sCommand, "skunklimit") || iDisplayStatus) { if (strlen(sArgument)) { g_SkunkLimit = strtonum(sArgument); SaveConfiguration(); } DisplayParamValue("Skunk limit", g_SkunkLimit); } if (streq(sCommand, "immunity") || iDisplayStatus) { if (strlen(sArgument)) { g_Immunity = check_param(sArgument); SaveConfiguration(); } DisplayParamState("Admin immunity", g_Immunity); } if (streq(sCommand, "immunitylevel") || iDisplayStatus) { if (strlen(sArgument)) { g_ImmunityLevel = strtonum(sArgument); SaveConfiguration(); } DisplayParamValue("Immunity level", g_ImmunityLevel); } if (streq(sCommand, "scores") || iDisplayStatus) { if (strlen(sArgument)) { g_DisplayScores = check_param(sArgument); SaveConfiguration(); } DisplayParamState("Team score display", g_DisplayScores); } if (streq(sCommand, "log") || iDisplayStatus) { if (strlen(sArgument)) { g_LogMessages = check_param(sArgument); SaveConfiguration(); } DisplayParamState("Message logging", g_LogMessages); } if (streq(sCommand, "consgreet") || iDisplayStatus) { if (strlen(sArgument)) { g_DisplayConsgreet = check_param(sArgument); SaveConfiguration(); } DisplayParamState("Console greeting", g_DisplayConsgreet); } if (streq(sCommand, "blockattack") || iDisplayStatus) { if (strlen(sArgument)) { g_BlockAttackMessages = check_param(sArgument); SaveConfiguration(); } DisplayParamState("Attack message blocking", g_BlockAttackMessages); } if (streq(sCommand, "startvote") || iDisplayStatus) { if (strlen(sArgument)) { g_StartVote = check_param(sArgument); SaveConfiguration(); } DisplayParamState("Round vote starting", g_StartVote); } if (streq(sCommand, "startvoteround") || iDisplayStatus) { if (strlen(sArgument)) { g_StartVoteRound = strtonum(sArgument); SaveConfiguration(); } DisplayParamValue("Start vote round", g_StartVoteRound); } return PLUGIN_HANDLED; } public menuselect(HLCommand, HLData, HLUserName, UserIndex) { if (!g_Enabled) return PLUGIN_CONTINUE; new iSessionID = 0; new iWONID = 0; new iTeam = 0; new iDead = 0; new sName[MAX_NAME_LENGTH]; new sAuthID[MAX_AUTHID_LENGTH]; new Data[MAX_DATA_LENGTH]; if (!g_TkMenu) return PLUGIN_CONTINUE; convert_string(HLData, Data, MAX_DATA_LENGTH); new iMenu = strtonum(Data); if (g_MenuStates[UserIndex][MENU_STATE_OPEN] == 0) { /*User was not in the menu*/ g_MenuStates[UserIndex][MENU_STATE_KILLED] = 0; return PLUGIN_CONTINUE; } if (g_MenuStates[UserIndex][MENU_STATE_KILLED] == 1) { /*User was in menu system when a vote got called*/ g_MenuStates[UserIndex][MENU_STATE_KILLED] = 0; DisplayTkMenu(UserIndex); return PLUGIN_CONTINUE; } if (iMenu > 10 || iMenu < 0) { /*There is no case for this, someone else can deal with it*/ return PLUGIN_CONTINUE; } playerinfo(UserIndex, sName, MAX_NAME_LENGTH, iSessionID, iWONID, iTeam, iDead, sAuthID); ClearTkMenu(UserIndex); if (iMenu > 0 && iMenu < MAX_TK_OPTIONS) { // do whatever action they chose execclient(sName, g_TkMenuAction[iMenu - 1]); } return PLUGIN_HANDLED; } /* Watch for vote commands and lurk around them */ public handlevote(HLCommand, HLData, HLUserName, UserIndex) { new sName[MAX_NAME_LENGTH]; new sAuthID[MAX_AUTHID_LENGTH]; new iSessionID; new iTeam; new iWONID; new iDead; new i; for (i = 1; i <= maxplayercount(); i++) { strinit(sName); if (playerinfo(i, sName, MAX_NAME_LENGTH, iSessionID, iWONID, iTeam, iDead, sAuthID) == 1) { g_MenuStates[i][MENU_STATE_KILLED] = 1; } } return PLUGIN_CONTINUE; } public resetstate(HLCommand, HLData, HLUserName, UserIndex) { ResetMenu(UserIndex); return PLUGIN_CONTINUE; } public admin_ffmon_purge(HLCommand, HLData, HLUserName, UserIndex) { PurgeTkFiles(); } public admin_ffmon_reload(HLCommand, HLData, HLUserName, UserIndex) { LoadConfiguration(); } public plugin_init() { plugin_registerinfo("FFMon", "Helps manage a Friendly Fire server.", STRING_VERSION); plugin_registercmd("ffmon_checktk", "ffmon_checktk", ACCESS_CONSOLE); plugin_registercmd("ffmon_worldaction", "ffmon_worldaction", ACCESS_CONSOLE); plugin_registercmd("ffmon_teamaction", "ffmon_teamaction", ACCESS_CONSOLE); plugin_registercmd("ffmon_checktd", "ffmon_checktd", ACCESS_CONSOLE); plugin_registercmd("admin_ffmon", "admin_ffmon", ACCESS_FFMON, "admin_ffmon"); plugin_registercmd("admin_ffmon_purge", "admin_ffmon_purge", ACCESS_FFMON, "admin_ffmon_purge"); plugin_registercmd("admin_ffmon_reload", "admin_ffmon_reload", ACCESS_FFMON, "admin_ffmon_reload"); plugin_registercmd("say","HandleSay",ACCESS_ALL); /* menu specific handlers */ plugin_registercmd("admin_vote_map", "handlevote", ACCESS_ALL, ""); plugin_registercmd("admin_vote_kick", "handlevote", ACCESS_ALL, ""); plugin_registercmd("admin_vsay", "handlevote", ACCESS_ALL, ""); plugin_registercmd("menuselect", "menuselect", ACCESS_ALL); plugin_registercmd("radio1", "resetstate", ACCESS_ALL); plugin_registercmd("radio2", "resetstate", ACCESS_ALL); plugin_registercmd("radio3", "resetstate", ACCESS_ALL); plugin_registercmd("buy", "resetstate", ACCESS_ALL); plugin_registercmd("buyequip", "resetstate", ACCESS_ALL); plugin_registercmd("chooseteam", "resetstate", ACCESS_ALL); /* end menu specific */ exec( "logd_reg 57 admin_command ffmon_checktk" ); exec( "logd_reg 58 admin_command ffmon_checktd" ); exec( "logd_reg 61 admin_command ffmon_teamaction" ); exec( "logd_reg 62 admin_command ffmon_worldaction" ); LoadConfiguration(); SetLogDetail(); ForceNextMapUndo(); CheckPeriodicPurge(); g_VoteStarted = 0; g_CtScore = 0; g_TScore = 0; return PLUGIN_CONTINUE; }