/* * ================================================================= * Filename: m_elmer.c * ================================================================= * Description: Command /elmer: makes someone talk like Elmer J. * Fudd, that is, letters 'l' and 'r' become 'w', for * example, "Shhhhhh! Be vewy, vewy quiet... I'm * hunting wabbits, heh-heh-heh." (More info at * http://www.geocities.com/Hollywood/Park/2326/ * character1.html#elmer.) Install this module * on all servers in order to make it work properly. * ================================================================= * Author: AngryWolf * Email: angrywolf@flashmail.com * ================================================================= * Feedback: * * I accept bugreports, ideas and opinions, and if you have any * questions, just send an email to me! * * Thank you for using my module! * * ================================================================= * Requirements: * ================================================================= * * o Unreal >=3.2-beta18 * o One of the supported operating systems (see unreal32docs.html) * * ================================================================= * Installation: * ================================================================= * * See http://angrywolf.linktipp.org/compiling.php?lang=en * * ================================================================= * Usage: * ================================================================= * * Command ELMER: * -------------- * * Syntax: /elmer [+|-] * * Examples: * * - To make someone talk like Elmer: * /elmer SomeNick * - To remove the previous setting from someone: * /elmer -SomeNick * * ================================================================= * Mirror files: * ================================================================= * * http://angrywolf.linktipp.org/m_elmer.c [Germany] * http://angrywolf.uw.hu/m_elmer.c [Hungary] * http://angrywolf.fw.hu/m_elmer.c [Hungary] * * ================================================================= * Changes: * ================================================================= * * $Log: m_elmer.c,v $ * Revision 1.6 2004/03/12 11:59:30 angrywolf * - Made some minor fixes. * * Revision 1.5 2004/03/08 21:25:12 angrywolf * - Fixed some bugs that could cause crash if you compile the module * statically (for example, under Windows). * * Revision 1.4 2004/02/23 17:37:34 angrywolf * - Unoccupied flags are not trustable, CVS .2138 took use * of the one I used before to mark users as Elmers. * Therefore I use a separate list now, even if it's * more memory intensive. * * Revision 1.3 2004/02/17 10:42:24 angrywolf * *** empty log message *** * * Revision 1.2 2004/02/17 10:35:50 angrywolf * - Fixed a letter case problem, reported by MichaelJE2. * * Revision 1.1 2004/01/29 13:59:28 angrywolf * Initial revision * * ================================================================= */ #include "config.h" #include "struct.h" #include "common.h" #include "sys.h" #include "numeric.h" #include "msg.h" #include "channel.h" #include #include #include #include #include #ifdef _WIN32 #include #endif #include #include "h.h" #ifdef STRIPBADWORDS #include "badwords.h" #endif #ifdef _WIN32 #include "version.h" #endif extern void sendto_one(aClient *to, char *pattern, ...); extern void sendto_realops(char *pattern, ...); #define MSG_ELMER "ELMER" #define TOK_ELMER "EL" #define IsParam(x) (parc > (x) && !BadPtr(parv[(x)])) #define IsNotParam(x) (parc <= (x) || BadPtr(parv[(x)])) #define DelHook(x) if (x) HookDel(x); x = NULL #define DelCommand(x) if (x) CommandDel(x); x = NULL static Command *AddCommand(Module *module, char *msg, char *token, iFP func); static int m_elmer(aClient *, aClient *, int, char *[]); static char *cb_privmsg(aClient *, aClient *, aClient *, char *, int); static char *cb_chanmsg(aClient *, aClient *, aChannel *, char *, int); static int cb_quit(aClient *, char *); static void free_elmerflags(); static Command *CmdElmer; static Hook *HookPrivMsg = NULL, *HookChanMsg = NULL, *HookQuit = NULL; /* * Unoccupied flags are not trustable, they may become used anytime. * Therefore I use a separate list. */ typedef struct _elmerflag ElmerFlag; struct _elmerflag { ElmerFlag *prev, *next; aClient *cptr; }; static ElmerFlag *ElmerFlags; ModuleHeader MOD_HEADER(m_elmer) = { "m_elmer", "$Id: m_elmer.c,v 1.6 2004/03/12 11:59:30 angrywolf Exp $", "Command /elmer", "3.2-b8-1", NULL }; DLLFUNC int MOD_INIT(m_elmer)(ModuleInfo *modinfo) { ElmerFlags = NULL; if (!(CmdElmer = AddCommand(modinfo->handle, MSG_ELMER, TOK_ELMER, m_elmer))) return MOD_FAILED; HookPrivMsg = HookAddPCharEx(modinfo->handle, HOOKTYPE_USERMSG, cb_privmsg); HookChanMsg = HookAddPCharEx(modinfo->handle, HOOKTYPE_CHANMSG, cb_chanmsg); HookQuit = HookAddEx(modinfo->handle, HOOKTYPE_LOCAL_QUIT, cb_quit); return MOD_SUCCESS; } DLLFUNC int MOD_LOAD(m_elmer)(int module_load) { return MOD_SUCCESS; } DLLFUNC int MOD_UNLOAD(m_elmer)(int module_unload) { free_elmerflags(); DelHook(HookQuit); DelHook(HookChanMsg); DelHook(HookPrivMsg); DelCommand(CmdElmer); return MOD_SUCCESS; } static Command *AddCommand(Module *module, char *msg, char *token, iFP func) { Command *cmd; if (CommandExists(msg)) { config_error("Command %s already exists", msg); return NULL; } if (CommandExists(token)) { config_error("Token %s already exists", token); return NULL; } cmd = CommandAdd(module, msg, token, func, MAXPARA, 0); #ifndef STATIC_LINKING if (ModuleGetError(module) != MODERR_NOERROR || !cmd) #else if (!cmd) #endif { #ifndef STATIC_LINKING config_error("Error adding command %s: %s", msg, ModuleGetErrorStr(module)); #else config_error("Error adding command %s", msg); #endif return NULL; } return cmd; } static ElmerFlag *find_elmer(aClient *cptr) { ElmerFlag *e; for (e = ElmerFlags; e; e = e->next) if (e->cptr == cptr) break; return e; } static void set_elmer(aClient *cptr) { ElmerFlag *e; e = (ElmerFlag *) MyMalloc(sizeof(cptr)); e->cptr = cptr; AddListItem(e, ElmerFlags); } static void clear_elmer(ElmerFlag *e) { DelListItem(e, ElmerFlags); MyFree(e); } static void free_elmerflags() { ElmerFlag *e; ListStruct *next; for (e = ElmerFlags; e; e = (ElmerFlag *) next) { next = (ListStruct *) e->next; DelListItem(e, ElmerFlags); MyFree(e); } } static char *convert_to_elmer(char *str) { char *p; for (p = str; *p; p++) switch(*p) { case 'l': case 'r': *p = 'w'; break; case 'L': case 'R': *p = 'W'; } return str; } static int cb_quit(aClient *sptr, char *comment) { ElmerFlag *e; if ((e = find_elmer(sptr))) clear_elmer(e); return 0; } static char *cb_privmsg(aClient *cptr, aClient *from, aClient *to, char *str, int notice) { return find_elmer(cptr) ? convert_to_elmer(str) : str; } static char *cb_chanmsg(aClient *cptr, aClient *from, aChannel *to, char *str, int notice) { return find_elmer(cptr) ? convert_to_elmer(str) : str; } static int m_elmer(aClient *cptr, aClient *sptr, int parc, char *parv[]) { aClient *acptr = NULL; ElmerFlag *is_elmer = NULL; char *nick = NULL; int add = 1; if (IsPerson(sptr) && !IsAnOper(sptr)) { sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]); return -1; } nick = IsParam(1) ? parv[1] : NULL; if (nick) { if (*nick == '+') nick++; else if (*nick == '-') { nick++; add = 0; } if (!*nick) nick = NULL; } if (!nick) { if (!IsServer(sptr)) sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, sptr->name, MSG_ELMER); return -1; } acptr = find_person(nick, NULL); if (!acptr) { if (!IsServer(sptr)) sendto_one(sptr, err_str(ERR_NOSUCHNICK), me.name, sptr->name, nick); return 0; } if (!MyConnect(acptr)) { sendto_one(acptr->from, ":%s %s %c%s", sptr->name, IsToken(cptr) ? TOK_ELMER : MSG_ELMER, add ? '+' : '-', acptr->name); return 0; } is_elmer = find_elmer(acptr); if (add) { if (is_elmer) { if (!IsServer(sptr)) sendto_one(sptr, ":%s %s %s :*** %s is already set to talk like Elmer", me.name, IsWebTV(sptr) ? "PRIVMSG" : "NOTICE", sptr->name, acptr->name); return 0; } set_elmer(acptr); sendto_realops("*** %s made %s!%s@%s talk like Elmer", sptr->name, acptr->name, acptr->user->username, GetHost(acptr)); sendto_serv_butone(&me, ":%s SMO o :*** %s made %s!%s@%s talk like Elmer", me.name, sptr->name, acptr->name, acptr->user->username, GetHost(acptr)); if (MyConnect(sptr) && acptr != sptr) sendto_one(sptr, ":%s %s %s :*** %s is now talking like Elmer", me.name, IsWebTV(acptr) ? "PRIVMSG" : "NOTICE", sptr->name, acptr->name); } else { if (!is_elmer) { if (!IsServer(sptr)) sendto_one(sptr, ":%s %s %s :*** %s is not talking like Elmer", me.name, IsWebTV(sptr) ? "PRIVMSG" : "NOTICE", sptr->name, acptr->name); return 0; } clear_elmer(is_elmer); sendto_realops("*** %s made %s!%s@%s no longer talk like Elmer", sptr->name, acptr->name, acptr->user->username, GetHost(acptr)); sendto_serv_butone(&me, ":%s SMO o :*** %s made %s!%s@%s no longer talk like Elmer", me.name, sptr->name, acptr->name, acptr->user->username, GetHost(acptr)); if (MyConnect(sptr) && acptr != sptr) sendto_one(sptr, ":%s %s %s :*** %s is no longer talking like Elmer", me.name, IsWebTV(acptr) ? "PRIVMSG" : "NOTICE", sptr->name, acptr->name); } return 0; }