/******************************************************************
 * 				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;
}