diff options
author | Valaris <Valaris@54d463be-8e91-2dee-dedb-b68131a5f0ec> | 2006-01-29 16:00:45 +0000 |
---|---|---|
committer | Valaris <Valaris@54d463be-8e91-2dee-dedb-b68131a5f0ec> | 2006-01-29 16:00:45 +0000 |
commit | a2675f07d7da22a7c6ae11f545bf8f671e785a82 (patch) | |
tree | 4b825dc642cb6eb9a060e54bf8d69288fbee4904 /src/map/npc_chat.c | |
parent | b8801ae9585201eaaf9fdf80d9c7117ee18f52e2 (diff) | |
download | hercules-a2675f07d7da22a7c6ae11f545bf8f671e785a82.tar.gz hercules-a2675f07d7da22a7c6ae11f545bf8f671e785a82.tar.bz2 hercules-a2675f07d7da22a7c6ae11f545bf8f671e785a82.tar.xz hercules-a2675f07d7da22a7c6ae11f545bf8f671e785a82.zip |
Clearing trunk.
git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@5091 54d463be-8e91-2dee-dedb-b68131a5f0ec
Diffstat (limited to 'src/map/npc_chat.c')
-rw-r--r-- | src/map/npc_chat.c | 502 |
1 files changed, 0 insertions, 502 deletions
diff --git a/src/map/npc_chat.c b/src/map/npc_chat.c deleted file mode 100644 index c15a26bf0..000000000 --- a/src/map/npc_chat.c +++ /dev/null @@ -1,502 +0,0 @@ -#ifdef PCRE_SUPPORT - -#include <stdio.h> -#include <ctype.h> -#include <stdlib.h> -#include <string.h> -#include <stdarg.h> -#ifdef __WIN32 -#define __USE_W32_SOCKETS -#include <windows.h> -#else -#include <unistd.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#endif -#include <time.h> - -#include "../common/timer.h" -#include "../common/malloc.h" -#include "../common/version.h" -#include "../common/nullpo.h" -#include "../common/showmsg.h" - -#include "map.h" -#include "status.h" -#include "npc.h" -#include "chat.h" -#include "script.h" -#include "battle.h" - -#include "pcre.h" - -/** - * Written by MouseJstr in a vision... (2/21/2005) - * - * This allows you to make npc listen for spoken text (global - * messages) and pattern match against that spoken text using perl - * regular expressions. - * - * Please feel free to copy this code into your own personal ragnarok - * servers or distributions but please leave my name. Also, please - * wait until I've put it into the main eA branch which means I - * believe it is ready for distribution. - * - * So, how do people use this? - * - * The first and most important function is defpattern - * - * defpattern 1, "[^:]+: (.*) loves (.*)", "label"; - * - * this defines a new pattern in set 1 using perl syntax - * (http://www.troubleshooters.com/codecorn/littperl/perlreg.htm) - * and tells it to jump to the supplied label when the pattern - * is matched. - * - * each of the matched Groups will result in a variable being - * set ($p1$ through $p9$ with $p0$ being the entire string) - * before the script gets executed. - * - * activatepset 1; - * - * This activates a set of patterns.. You can have many pattern - * sets defined and many active all at once. This feature allows - * you to set up "conversations" and ever changing expectations of - * the pattern matcher - * - * deactivatepset 1; - * - * turns off a pattern set; - * - * deactivatepset -1; - * - * turns off ALL pattern sets; - * - * deletepset 1; - * - * deletes a pset - */ - -/* Structure containing all info associated with a single pattern - block */ - -struct pcrematch_entry { - struct pcrematch_entry *next_; - char *pattern_; - pcre *pcre_; - pcre_extra *pcre_extra_; - char *label_; -}; - -/* A set of patterns that can be activated and deactived with a single - command */ - -struct pcrematch_set { - struct pcrematch_set *next_, *prev_; - struct pcrematch_entry *head_; - int setid_; -}; - -/* - * Entire data structure hung off a NPC - * - * The reason I have done it this way (a void * in npc_data and then - * this) was to reduce the number of patches that needed to be applied - * to a ragnarok distribution to bring this code online. I - * also wanted people to be able to grab this one file to get updates - * without having to do a large number of changes. - */ - -struct npc_parse { - struct pcrematch_set *active_; - struct pcrematch_set *inactive_; -}; - - -/** - * delete everythign associated with a entry - * - * This does NOT do the list management - */ - -void finalize_pcrematch_entry(struct pcrematch_entry *e) { - free(e->pcre_); - free(e->pcre_extra_); - aFree(e->pattern_); - aFree(e->label_); -} - -/** - * Lookup (and possibly create) a new set of patterns by the set id - */ -static struct pcrematch_set * lookup_pcreset(struct npc_data *nd,int setid) -{ - struct pcrematch_set *pcreset; - struct npc_parse *npcParse = (struct npc_parse *) nd->chatdb; - if (npcParse == NULL) - nd->chatdb = npcParse = (struct npc_parse *) - aCalloc(sizeof(struct npc_parse), 1); - - pcreset = npcParse->active_; - - while (pcreset != NULL) { - if (pcreset->setid_ == setid) - break; - pcreset = pcreset->next_; - } - if (pcreset == NULL) - pcreset = npcParse->inactive_; - - while (pcreset != NULL) { - if (pcreset->setid_ == setid) - break; - pcreset = pcreset->next_; - } - - if (pcreset == NULL) { - pcreset = (struct pcrematch_set *) - aCalloc(sizeof(struct pcrematch_set), 1); - pcreset->next_ = npcParse->inactive_; - if (pcreset->next_ != NULL) - pcreset->next_->prev_ = pcreset; - pcreset->prev_ = 0; - npcParse->inactive_ = pcreset; - pcreset->setid_ = setid; - } - - return pcreset; -} - -/** - * activate a set of patterns. - * - * if the setid does not exist, this will silently return - */ - -static void activate_pcreset(struct npc_data *nd,int setid) { - struct pcrematch_set *pcreset; - struct npc_parse *npcParse = (struct npc_parse *) nd->chatdb; - if (npcParse == NULL) - return; // Nothing to activate... - pcreset = npcParse->inactive_; - while (pcreset != NULL) { - if (pcreset->setid_ == setid) - break; - pcreset = pcreset->next_; - } - if (pcreset == NULL) - return; // not in inactive list - if (pcreset->next_ != NULL) - pcreset->next_->prev_ = pcreset->prev_; - if (pcreset->prev_ != NULL) - pcreset->prev_->next_ = pcreset->next_; - else - npcParse->inactive_ = pcreset->next_; - - pcreset->prev_ = NULL; - pcreset->next_ = npcParse->active_; - if (pcreset->next_ != NULL) - pcreset->next_->prev_ = pcreset; - npcParse->active_ = pcreset; -} - -/** - * deactivate a set of patterns. - * - * if the setid does not exist, this will silently return - */ - -static void deactivate_pcreset(struct npc_data *nd,int setid) { - struct pcrematch_set *pcreset; - struct npc_parse *npcParse = (struct npc_parse *) nd->chatdb; - if (npcParse == NULL) - return; // Nothing to deactivate... - if (setid == -1) { - while(npcParse->active_ != NULL) - deactivate_pcreset(nd, npcParse->active_->setid_); - return; - } - pcreset = npcParse->active_; - while (pcreset != NULL) { - if (pcreset->setid_ == setid) - break; - pcreset = pcreset->next_; - } - if (pcreset == NULL) - return; // not in active list - if (pcreset->next_ != NULL) - pcreset->next_->prev_ = pcreset->prev_; - if (pcreset->prev_ != NULL) - pcreset->prev_->next_ = pcreset->next_; - else - npcParse->active_ = pcreset->next_; - - pcreset->prev_ = NULL; - pcreset->next_ = npcParse->inactive_; - if (pcreset->next_ != NULL) - pcreset->next_->prev_ = pcreset; - npcParse->inactive_ = pcreset; -} - -/** - * delete a set of patterns. - */ -static void delete_pcreset(struct npc_data *nd,int setid) { - int active = 1; - struct pcrematch_set *pcreset; - struct npc_parse *npcParse = (struct npc_parse *) nd->chatdb; - if (npcParse == NULL) - return; // Nothing to deactivate... - pcreset = npcParse->active_; - while (pcreset != NULL) { - if (pcreset->setid_ == setid) - break; - pcreset = pcreset->next_; - } - if (pcreset == NULL) { - active = 0; - pcreset = npcParse->inactive_; - while (pcreset != NULL) { - if (pcreset->setid_ == setid) - break; - pcreset = pcreset->next_; - } - } - if (pcreset == NULL) - return; - - if (pcreset->next_ != NULL) - pcreset->next_->prev_ = pcreset->prev_; - if (pcreset->prev_ != NULL) - pcreset->prev_->next_ = pcreset->next_; - else if(active == 1) - npcParse->active_ = pcreset->next_; - else - npcParse->inactive_ = pcreset->next_; - - pcreset->prev_ = NULL; - pcreset->next_ = NULL; - - while (pcreset->head_) { - struct pcrematch_entry *n = pcreset->head_->next_;; - finalize_pcrematch_entry(pcreset->head_); - pcreset->head_ = n; - } - - aFree(pcreset); -} - -/** - * create a new pattern entry - */ -static struct pcrematch_entry *create_pcrematch_entry(struct pcrematch_set * set) { - struct pcrematch_entry * e = (struct pcrematch_entry *) - aCalloc(sizeof(struct pcrematch_entry), 1); - struct pcrematch_entry * last = set->head_; - - // Normally we would have just stuck it at the end of the list but - // this doesn't sink up with peoples usage pattern. They wanted - // the items defined first to have a higher priority then the - // items defined later.. as a result, we have to do some work up - // front.. - - /* if we are the first pattern, stick us at the end */ - if (last == NULL) { - set->head_ = e; - return e; - } - - /* Look for the last entry */ - while (last->next_ != NULL) - last = last->next_; - - last->next_ = e; - e->next_ = NULL; - - return e; -} - -/** - * define/compile a new pattern - */ - -void npc_chat_def_pattern(struct npc_data *nd, int setid, - const char *pattern, const char *label) -{ - const char *err; - int erroff; - - struct pcrematch_set * s = lookup_pcreset(nd, setid); - struct pcrematch_entry *e = create_pcrematch_entry(s); - e->pattern_ = aStrdup(pattern); - e->label_ = aStrdup(label); - e->pcre_ = pcre_compile(pattern, PCRE_CASELESS, &err, &erroff, NULL); - e->pcre_extra_ = pcre_study(e->pcre_, 0, &err); -} - -/** - * Delete everything associated with a NPC concerning the pattern - * matching code - * - * this could be more efficent but.. how often do you do this? - */ -void npc_chat_finalize(struct npc_data *nd) -{ - struct npc_parse *npcParse = (struct npc_parse *) nd->chatdb; - if (npcParse == NULL) - return; - - while(npcParse->active_) - delete_pcreset(nd, npcParse->active_->setid_); - - while(npcParse->inactive_) - delete_pcreset(nd, npcParse->inactive_->setid_); -} - -/** - * Handler called whenever a global message is spoken in a NPC's area - */ -int npc_chat_sub(struct block_list *bl, va_list ap) -{ - struct npc_data *nd = (struct npc_data *)bl; - struct npc_parse *npcParse = (struct npc_parse *) nd->chatdb; - unsigned char *msg; - int len, pos, i; - struct map_session_data *sd; - struct npc_label_list *lst; - struct pcrematch_set *pcreset; - - // Not interested in anything you might have to say... - if (npcParse == NULL || npcParse->active_ == NULL) - return 0; - - msg = va_arg(ap,unsigned char*); - len = va_arg(ap,int); - sd = va_arg(ap,struct map_session_data *); - - // grab the active list - pcreset = npcParse->active_; - - // interate across all active sets - while (pcreset != NULL) { - struct pcrematch_entry *e = pcreset->head_; - // interate across all patterns in that set - while (e != NULL) { - int offsets[20]; - char buf[255]; - // perform pattern match - int r = pcre_exec(e->pcre_, e->pcre_extra_, (char *) msg, len, 0, - 0, offsets, sizeof(offsets) / sizeof(offsets[0])); - if (r >= 0) { - // save out the matched strings - switch (r) { - case 10: - memcpy(buf, &msg[offsets[18]], offsets[19]); - buf[offsets[19]] = '\0'; - set_var(sd, "$p9$", buf); - case 9: - memcpy(buf, &msg[offsets[16]], offsets[17]); - buf[offsets[17]] = '\0'; - set_var(sd, "$p8$", buf); - case 8: - memcpy(buf, &msg[offsets[14]], offsets[15]); - buf[offsets[15]] = '\0'; - set_var(sd, "$p7$", buf); - case 7: - memcpy(buf, &msg[offsets[12]], offsets[13]); - buf[offsets[13]] = '\0'; - set_var(sd, "$p6$", buf); - case 6: - memcpy(buf, &msg[offsets[10]], offsets[11]); - buf[offsets[11]] = '\0'; - set_var(sd, "$p5$", buf); - case 5: - memcpy(buf, &msg[offsets[8]], offsets[9]); - buf[offsets[9]] = '\0'; - set_var(sd, "$p4$", buf); - case 4: - memcpy(buf, &msg[offsets[6]], offsets[7]); - buf[offsets[7]] = '\0'; - set_var(sd, "$p3$", buf); - case 3: - memcpy(buf, &msg[offsets[4]], offsets[5]); - buf[offsets[5]] = '\0'; - set_var(sd, "$p2$", buf); - case 2: - memcpy(buf, &msg[offsets[2]], offsets[3]); - buf[offsets[3]] = '\0'; - set_var(sd, "$p1$", buf); - case 1: - memcpy(buf, &msg[offsets[0]], offsets[1]); - buf[offsets[1]] = '\0'; - set_var(sd, "$p0$", buf); - } - - // find the target label.. this sucks.. - lst=nd->u.scr.label_list; - pos = -1; - for (i = 0; i < nd->u.scr.label_list_num; i++) { - if (strncmp(lst[i].name, e->label_, sizeof(lst[i].name)) == 0) { - pos = lst[i].pos; - break; - } - } - if (pos == -1) { - printf("Unable to find label: %s", e->label_); - // unable to find label... do something.. - return 0; - } - // run the npc script - run_script(nd->u.scr.script,pos,sd->bl.id,nd->bl.id); - return 0; - } - e = e->next_; - } - pcreset = pcreset->next_; - } - - return 0; -} - -// Various script builtins used to support these functions - -int buildin_defpattern(struct script_state *st) { - int setid=conv_num(st,& (st->stack->stack_data[st->start+2])); - char *pattern=conv_str(st,& (st->stack->stack_data[st->start+3])); - char *label=conv_str(st,& (st->stack->stack_data[st->start+4])); - struct npc_data *nd=(struct npc_data *)map_id2bl(st->oid); - - npc_chat_def_pattern(nd, setid, pattern, label); - - return 0; -} - -int buildin_activatepset(struct script_state *st) { - int setid=conv_num(st,& (st->stack->stack_data[st->start+2])); - struct npc_data *nd=(struct npc_data *)map_id2bl(st->oid); - - activate_pcreset(nd, setid); - - return 0; -} -int buildin_deactivatepset(struct script_state *st) { - int setid=conv_num(st,& (st->stack->stack_data[st->start+2])); - struct npc_data *nd=(struct npc_data *)map_id2bl(st->oid); - - deactivate_pcreset(nd, setid); - - return 0; -} -int buildin_deletepset(struct script_state *st) { - int setid=conv_num(st,& (st->stack->stack_data[st->start+2])); - struct npc_data *nd=(struct npc_data *)map_id2bl(st->oid); - - delete_pcreset(nd, setid); - - return 0; -} - - -#endif |