/****************************************************************** * plugin_spooge_AR.sma * This is a major modification of plugin_wipeout_autoresponse.sma * by wipeout(with code borrowed from Luke Sankey). I started * messing with admin_mod and was impressed with idea of the auto * response script as an for giving information, making smart ass * comments, and enforceing certain on my server since it spends * most of its time without an ADMIN logged on. I quickly got * tired of re-compiling to change or add responses so I decided * to make the responses available via a text file that could be * read on plugin initialization and on demand from the admin. This * is my first attempt at a major script mod. * * You need to create an Autoresponse file ("AR.TXT"). The following * lines (preceded by a #) describe the syntax of each line. It is * highly recommended that you cut and paste theses lines into * your "AR.TXT" file. The # will be treadted as a comment. * When you add autoresponses to your file leave NO blank lines. * A blank line will terminate the parser. If you want spacing * use a single # sign on the "blank" line. You can comment out * responses using the # sign. # Auto Response file for plugin_spooge_AR.sma. This file contains # auto resonse message, and commands to execute based upon player # entered SAY commands. # All # signs in the first column indicate that the line is a comment. # Place no blank lines in this file as it will tell the file parser # to quit. # Use no semicolons in messages or tokens. # # format of response lines. # <Number>;<Command>;<Message>;<Keyword1>;<Keyword2> # Number -- Number of keywords Value 1-2 no spaces. # Command -- Command to execute Value 0-9,a-z no spaces. # 0 - Just respond # 1 - Respond with user name Suffix. # 2 - Respond with user name Prefix. # 3 - Respond to a Next Map Query. # 4 - Respond to a whats this map query. # 5 - Respond to ff query. # 6 - Temporarily gag user due to extreme language. # 7 - Send response just to the user. # 8 - Respond using CSAY. # 9 - Respond using TSAY. # 10 - Slap a person for using a key phrase or word. # 11 - Show Server Time # Message -- Auto response message. # Keyword1-- First Keyword. Keep is short spaces are significant. # Keyword2-- Second Keyword. Keep is short spaces are significant. # If you have no entry in one of the fields leave it blank but # with one space. # Dont leave out the command. # # The First entry is the Server anouncement. 0;0;<Server AR>; ; * * Thanks to Sank, yensid, Jaguar, and Alfred * Date April 14, 2001 *********************************************************************/ /*************************************************************** * Include base modules, defines, and protypes. ***************************************************************/ #include <core> #include <console> #include <string> #include <admin> #include <adminlib> /*************************************************************** * Defines. ***************************************************************/ #define MAX_AUTORESPONSES 100 /* Maximum number of responses */ #define MAX_KEYWORDS 2 /* Maximum number of keywords per response */ #define ACCESS_PAR 8192 /* Access level for re-parser. */ /*************************************************************** * Global declarations (for use within this plugin). * Dam I wish this language had structures. ***************************************************************/ /* The following five arrays contiain the information extracted * from the autoresponse file. */ new AR_responses [MAX_AUTORESPONSES][MAX_TEXT_LENGTH]; /* Auto responses. */ new NumKeywords [MAX_AUTORESPONSES]; /* Number of keywords. */ new Keyword1 [MAX_AUTORESPONSES][20];/* 1st Keyword. */ new Keyword2 [MAX_AUTORESPONSES][20];/* 2nd Keyword. */ new strCommand [MAX_AUTORESPONSES] ;/* Command options. */ new TotalResponses=0; /* Total responses. */ new AR_FileStatus=0; /* Flag to indiacate if no AR file has been found. */ new STRING_VERSION[MAX_DATA_LENGTH] = "2.04"; new ResponseToUse = -1; new ARDebugFlag = 0; /* Global flag used to enable debug print outs. */ new DegbugUser[MAX_NAME_LENGTH]; /* buffer for the user name to send all debug messages to. */ new SlapFlag = 0; /* Flag to enable slapping of people using words in the word list. */ /**************************************************************** * This module is used to toggle on and off bitch slapping. ****************************************************************/ public bitch_Slap (HLCommand, HLData, HLUserName, UserIndex) { new adminName[MAX_NAME_LENGTH]; /* Convert Halflife Data elements to Strings?? */ convert_string(HLUserName, adminName, MAX_NAME_LENGTH); if (SlapFlag) { printf ("<<SPOOGE AR>> Bitch Slap Off^n"); messageex(adminName,"<<SPOOGE AR>> Bitch Slap Off",print_console); SlapFlag = 0; } else { printf ("<<SPOOGE AR>> Bitch Slap On^n"); messageex(adminName,"<<SPOOGE AR>> Bitch Slap On",print_console); SlapFlag = 1; } return PLUGIN_HANDLED; } /**************************************************************** * This module is used to toggle on and off the AR file debug printouts. ****************************************************************/ public ar_debug (HLCommand, HLData, HLUserName, UserIndex) { /* Convert Halflife Data elements to Strings?? */ convert_string(HLUserName, DegbugUser, MAX_NAME_LENGTH); if (ARDebugFlag) { printf ("<<SPOOGE AR>> Debug Off^n"); messageex(DegbugUser,"<<SPOOGE AR>> Debug Off",print_console); ARDebugFlag = 0; } else { printf ("<<SPOOGE AR>> Debug On^n"); messageex(DegbugUser,"<<SPOOGE AR>> Debug On",print_console); ARDebugFlag = 1; } return PLUGIN_HANDLED; } /**************************************************************** * This file reads and parses the autoresponse file. I moved * this out of the plugin initialization file so it can be * eventually called with a "reparse ar file" command so that * you do not have to restart the server to install new * autoresponse file entries. ****************************************************************/ public parse_response_file() { /* Convert Halflife Data elements to Strings?? */ new gotLine; /* Flag to indicate if a line was extracted from the file */ new lineNumber=0; /* Line number in file to process. */ new lineStr [MAX_TEXT_LENGTH]; /* line buffer. */ new tempStr [30]; new Text[MAX_TEXT_LENGTH]; /* Buffer for text messsages. */ /* Enter Do loop reading and extracting data from the file. */ /* Note that the two uncommented out printf statements result*/ /* rather verbose console printouts. Comment them out or */ /* delete them if you desire. */ TotalResponses = 0; AR_FileStatus = fileexists("AR.TXT"); if ( AR_FileStatus > 0) { printf ("<<SPOOGE AR>> Parsing AR file^n"); do { gotLine = readfile("AR.TXT",lineStr, lineNumber, MAX_TEXT_LENGTH); if (gotLine) { if (ARDebugFlag) { printf ("Got line %s^n",lineStr); } lineNumber++; /* Increment line number. */ if (strncmp(lineStr, "#", 1) == 0) { /* Ignoreing comment. */ } else { /* Parse the autoresponse line grabbed from the auto response file. */ strtok(lineStr,";", NumKeywords [TotalResponses],1); NumKeywords [TotalResponses] = strtonum (NumKeywords [TotalResponses]); strtok("",";",tempStr,2); strCommand [TotalResponses] = strtonum (tempStr); strtok("",";",AR_responses [TotalResponses],MAX_TEXT_LENGTH); strtok("",";",Keyword1 [TotalResponses],20); strtok("",";",Keyword2 [TotalResponses],20); if (ARDebugFlag) { printf("K:%d C:%d AR:%s k1:%s k2:%s^n",NumKeywords [TotalResponses],strCommand [TotalResponses],AR_responses [TotalResponses],Keyword1 [TotalResponses],Keyword2 [TotalResponses]); } TotalResponses++; } } /* Exit out of parser if we have an array overflow condition. */ if (TotalResponses == MAX_AUTORESPONSES) { return PLUGIN_CONTINUE; } } while (gotLine); snprintf(Text, MAX_TEXT_LENGTH, "<<SPOOGE AR>> AR.TXT file found and %i lines processed.",TotalResponses); printf ("%s.^n",Text); if (ARDebugFlag) { messageex(DegbugUser,Text,print_console); } } else { printf ("<<SPOOGE AR>> Cannot find AR file^n"); if (ARDebugFlag) { messageex(DegbugUser,"<<SPOOGE AR>> Cannot find AR.TXT file.",print_console); } } return PLUGIN_HANDLED; } /**************************************************************** * Locate response subroutine. This function will look for the * first keyword match in a user speech string. It then sets * ResponseToUse for processing in the main function. ****************************************************************/ public scanForKeywords(Speech[]) { new Text[MAX_TEXT_LENGTH]; /* Buffer for text messsages. */ new numKeywordsToFind; new keywordsFound; new responseIndex=-1; if (ARDebugFlag) { snprintf(Text, MAX_TEXT_LENGTH,"<<AR>> Entering Keyword Search with %s",Speech); printf ("%s^n",Text); messageex(DegbugUser,Text,print_console); } /* Initialize the response to use index and the Response index. */ ResponseToUse = -1; responseIndex = -1; /* Enter do/while to scan for an appropriate response. */ do { responseIndex++; /* Increment index into auto-response array. */ /* Determine the number of keywords we need to find in this search. */ numKeywordsToFind = NumKeywords [responseIndex]; keywordsFound = numKeywordsToFind; if (ARDebugFlag) { snprintf(Text, MAX_TEXT_LENGTH,"<<SPOOGE AR>> Num Keywords:%d",numKeywordsToFind); printf ("%s^n",Text); messageex(DegbugUser,Text,print_console); } /* Execute the indicated number of keyword searches. */ if (numKeywordsToFind == 1)/* One Keyword. */ { if (ARDebugFlag) { snprintf(Text, MAX_TEXT_LENGTH,"<<SPOOGE AR>> Looking for \%s\",Keyword1 [responseIndex]); printf ("%s^n",Text); messageex(DegbugUser,Text,print_console); } if (strcasestr(Speech, Keyword1 [responseIndex]) != -1) keywordsFound-=1; } else if (numKeywordsToFind == 2) /* Two Keywords. */ { if (ARDebugFlag) { snprintf(Text, MAX_TEXT_LENGTH,"<<SPOOGE AR>> Looking for \%s\ and \%s\",Keyword1 [responseIndex],Keyword2 [responseIndex]); printf ("%s^n",Text); messageex(DegbugUser,Text,print_console); } if (strcasestr(Speech, Keyword1 [responseIndex]) != -1) keywordsFound-=1; if (strcasestr(Speech, Keyword2 [responseIndex]) != -1) keywordsFound-=1; } else /* Bad keyword number. */ { /* Ignore bad number of keywords ... Ignore the Auto response case. */ keywordsFound = 1; } /* If the keyword(s) were found, preserver the response index. */ if (keywordsFound == 0) { ResponseToUse = responseIndex; if (ARDebugFlag) { snprintf(Text, MAX_TEXT_LENGTH, "<<SPOOGE AR>> Found Keywords. Index:%d",ResponseToUse); printf ("%s^n",Text); messageex(DegbugUser,Text,print_console); } } } while ((keywordsFound > 0) && (responseIndex < TotalResponses)); } /*************************************************************** * Main say command auto resonder routine. This function does the * bulk of the response work. Originaly this routine (written by * sank and wipeout, required hardcoded keywords, responsed, and * actions. My changes are intended to allow this function to * get keywords and responses via a message file, as well as * a vector to a variety of commands to exeute. Some of * these could be made privledged. * * Command actions: * 0 - Just respond * 1 - Respond with user name Suffix. * 2 - Respond with user name Prefix. * 3 - Respond to a Next Map Query. * 4 - Respond to a whats this map query. * 5 - Respond to ff query. * 6 - Temporarily gag user due to extreme language. * 7 - Send response just to the user. * 8 - Respond using CSAY. * 9 - Respond using TSAY. * 10 - Slap a person for using a key phrase or word. ****************************************************************/ public HandleSay(HLCommand, HLData, HLUserName, UserIndex) { new CommandHL [MAX_COMMAND_LENGTH]; /* Command Buffer. */ new Speech[MAX_DATA_LENGTH]; /* Player buffer string. */ new User[MAX_NAME_LENGTH]; /* User name buffer. */ new Text[MAX_TEXT_LENGTH]; /* Buffer for dynamic text. */ new CmdBuffer [MAX_COMMAND_LENGTH]; /* Command Buffer for server action. */ /* If no AR.TXT file was found just return. */ if ( AR_FileStatus <= 0) return PLUGIN_CONTINUE; /* Convert Halflife Data elements to Strings?? */ convert_string(HLCommand,CommandHL, MAX_COMMAND_LENGTH); convert_string(HLData, Speech, MAX_DATA_LENGTH); convert_string(HLUserName, User, MAX_NAME_LENGTH); /* Remove quotes from the speech string. */ strstripquotes(Speech); /* Evalutate string for occurance of keyword. */ scanForKeywords(Speech); /* Code Segment to slap peeps for use of censord words in the */ /* cvar words file. */ if (SlapFlag) { if (check_words(Speech)==0) { snprintf(Text, MAX_TEXT_LENGTH, "Tisk Tisk %s such a mouth!",User); say(Text); new SessionID; get_userSessionID (User,SessionID); numtostr(SessionID,CmdBuffer); plugin_exec("admin_slap",CmdBuffer); } } /* Exit out of this function if the index is out of range. */ if ((ResponseToUse < 0) || (ResponseToUse > TotalResponses) || (ResponseToUse > MAX_AUTORESPONSES)) { return PLUGIN_CONTINUE; } if (ARDebugFlag) { snprintf(Text, MAX_TEXT_LENGTH, "<<SPOOGE AR>> Creating Response With Index %d",ResponseToUse); printf ("%s^n",Text); messageex(DegbugUser,Text,print_console); } /* Process and present a the message. */ switch (strCommand [ResponseToUse]) { case 0: /* Just Respond. */ { snprintf(Text, MAX_TEXT_LENGTH, "%s %s.", AR_responses [1], AR_responses [ResponseToUse]); say(Text); } case 1: /* Respond with user name Suffix. */ { snprintf(Text, MAX_TEXT_LENGTH, "%s %s %s.", AR_responses [1], AR_responses [ResponseToUse],User); say(Text); } case 2: /* Respond with user name Prefix. */ { snprintf(Text, MAX_TEXT_LENGTH, "%s %s %s.", AR_responses [1], User, AR_responses [ResponseToUse]); say(Text); } case 3: /* Respond to a Next Map Query. */ { new NextMap[MAX_NAME_LENGTH]; nextmap(NextMap, MAX_NAME_LENGTH); snprintf(Text, MAX_TEXT_LENGTH, "%s %s %s.", AR_responses [1], AR_responses [ResponseToUse],NextMap); say(Text); } case 4: /* Respond to a whats this map query. */ { new ThisMap[MAX_NAME_LENGTH]; currentmap(ThisMap, MAX_NAME_LENGTH); snprintf(Text, MAX_TEXT_LENGTH, "%s %s %s.", AR_responses [1], AR_responses [ResponseToUse],ThisMap); say(Text); } case 5: /* Respond to ff query. */ { if (getvar("mp_friendlyfire") == 1) { snprintf(Text, MAX_TEXT_LENGTH, "%s Friendly fire is ON! Watch your fire!", AR_responses [1]); } else { snprintf(Text, MAX_TEXT_LENGTH, "%s Friendly fire is OFF! Still don't shoot teammates!", AR_responses [0]); } say(Text); } case 6: /* Temporarily gag user due to extreme language. */ { new SessionID; get_userSessionID (User,SessionID); snprintf(CmdBuffer, MAX_DATA_LENGTH, "%d 3",SessionID); plugin_exec("admin_gag",CmdBuffer); snprintf(Text, MAX_TEXT_LENGTH, "%s %s %s.", AR_responses [1], User, AR_responses [ResponseToUse]); say(Text); snprintf(Text, MAX_TEXT_LENGTH, "%s %s mouth will be washed out with soap for 3 minutes.", AR_responses [1], User); say(Text); } case 7: /* Just Respond but only to the user. */ { snprintf(Text, MAX_TEXT_LENGTH, "%s %s.", AR_responses [1], AR_responses [ResponseToUse]); messageex(User,Text,print_chat); } case 8: /* Just Respond using CSAY. */ { snprintf(Text, MAX_TEXT_LENGTH, "%s.", AR_responses [ResponseToUse]); centersay(Text,5,63,187,239); } case 9: /* Just Respond using TSAY. */ { snprintf(Text, MAX_TEXT_LENGTH, "%s.", AR_responses [ResponseToUse]); typesay(Text,5,63,187,239); } case 10: /* Slap a person for saying trash. */ { new SessionID; get_userSessionID (User,SessionID); numtostr(SessionID,CmdBuffer); plugin_exec("admin_slap",CmdBuffer); snprintf(Text, MAX_TEXT_LENGTH, "%s %s.", AR_responses [1], AR_responses [ResponseToUse]); say(Text); } case 11: /* Show the server time. */ { new serverTime [MAX_TEXT_LENGTH]; servertime(serverTime,MAX_TEXT_LENGTH,"none"); snprintf(Text, MAX_TEXT_LENGTH, "%s %s %s.", AR_responses [1],AR_responses [ResponseToUse] ,serverTime); say(Text); } default: { /* Just drop out of this switch. */ } } return PLUGIN_CONTINUE; } /**************************************************************** * Plug in initialization function. ****************************************************************/ public plugin_init() { /* Register the plugin components. */ plugin_registerinfo("Ken Whites Server Autoresponse Plugin", "Responds to certain chat messages.", STRING_VERSION); plugin_registercmd("admin_parsearfile", "parse_response_file", ACCESS_PAR); plugin_registercmd("admin_ardebug", "ar_debug",ACCESS_PAR); plugin_registercmd("admin_bitchslap", "bitch_Slap",ACCESS_BAN); plugin_registercmd("say", "HandleSay", ACCESS_ALL); plugin_registerhelp("say", ACCESS_ALL, "say next map: Displays the next map."); plugin_registerhelp("say", ACCESS_ALL, "say current map: Displays the current map."); plugin_registerhelp("say", ACCESS_ALL, "say server ip: Displays the server's IP address."); plugin_registerhelp("admin_parsearfile", ACCESS_ALL, "admin_parsearfile: Re-pareses autoresponse file."); plugin_registerhelp("admin_ardebug", ACCESS_ALL, "admin_ardebug: Toggles on/off autoresponse debugging."); plugin_registerhelp("admin_bitchslap", ACCESS_ALL, "admin_bitchslap: Toggles on/off disallowed word slapping."); /* Parse the auto response file. */ parse_response_file(); return PLUGIN_CONTINUE; }