summaryrefslogtreecommitdiff
path: root/src/map
diff options
context:
space:
mode:
Diffstat (limited to 'src/map')
-rw-r--r--src/map/Makefile6
-rw-r--r--src/map/clif.c4
-rw-r--r--src/map/map.h2
-rw-r--r--src/map/npc.c4
-rw-r--r--src/map/npc.h2
-rw-r--r--src/map/npc_chat.c502
-rw-r--r--src/map/script.c26
-rw-r--r--src/map/script.h4
8 files changed, 543 insertions, 7 deletions
diff --git a/src/map/Makefile b/src/map/Makefile
index 3a05cd7a8..884e8b902 100644
--- a/src/map/Makefile
+++ b/src/map/Makefile
@@ -13,10 +13,10 @@ sqlobj:
COMMON_OBJ = ../common/core.o ../common/socket.o ../common/timer.o ../common/grfio.o ../common/db.o ../common/lock.o ../common/nullpo.o ../common/malloc.o ../common/showmsg.o ../common/utils.o ../common/strlib.o
LIBS = -lz -lm
-map-server: txtobj/map.o txtobj/chrif.o txtobj/clif.o txtobj/pc.o txtobj/status.o txtobj/npc.o txtobj/chat.o txtobj/path.o txtobj/itemdb.o txtobj/mob.o txtobj/script.o txtobj/storage.o txtobj/skill.o txtobj/atcommand.o txtobj/charcommand.o txtobj/battle.o txtobj/intif.o txtobj/trade.o txtobj/party.o txtobj/vending.o txtobj/guild.o txtobj/pet.o txtobj/log.o $(COMMON_OBJ)
+map-server: txtobj/map.o txtobj/chrif.o txtobj/clif.o txtobj/pc.o txtobj/status.o txtobj/npc.o txtobj/npc_chat.o txtobj/chat.o txtobj/path.o txtobj/itemdb.o txtobj/mob.o txtobj/script.o txtobj/storage.o txtobj/skill.o txtobj/atcommand.o txtobj/charcommand.o txtobj/battle.o txtobj/intif.o txtobj/trade.o txtobj/party.o txtobj/vending.o txtobj/guild.o txtobj/pet.o txtobj/log.o $(COMMON_OBJ)
$(CC) -o ../../$@ $> $(LIBS) $(LIB_S)
-map-server_sql: sqlobj/map.o sqlobj/chrif.o sqlobj/clif.o sqlobj/pc.o sqlobj/status.o sqlobj/npc.o sqlobj/chat.o sqlobj/path.o sqlobj/itemdb.o sqlobj/mob.o sqlobj/script.o sqlobj/storage.o sqlobj/skill.o sqlobj/atcommand.o sqlobj/charcommand.o sqlobj/battle.o sqlobj/intif.o sqlobj/trade.o sqlobj/party.o sqlobj/vending.o sqlobj/guild.o sqlobj/pet.o sqlobj/mail.o sqlobj/log.o $(COMMON_OBJ)
+map-server_sql: sqlobj/map.o sqlobj/chrif.o sqlobj/clif.o sqlobj/pc.o sqlobj/status.o sqlobj/npc.o sqlobj/npc_chat.o sqlobj/chat.o sqlobj/path.o sqlobj/itemdb.o sqlobj/mob.o sqlobj/script.o sqlobj/storage.o sqlobj/skill.o sqlobj/atcommand.o sqlobj/charcommand.o sqlobj/battle.o sqlobj/intif.o sqlobj/trade.o sqlobj/party.o sqlobj/vending.o sqlobj/guild.o sqlobj/pet.o sqlobj/mail.o sqlobj/log.o $(COMMON_OBJ)
$(CC) -o ../../$@ $> $(LIB_S)
txtobj/%.o: %.c
@@ -31,6 +31,7 @@ txtobj/clif.o: clif.c map.h chrif.h clif.h mob.h intif.h pc.h npc.h itemdb.h cha
txtobj/pc.o: pc.c map.h clif.h intif.h pc.h npc.h mob.h itemdb.h battle.h skill.h script.h party.h guild.h pet.h trade.h storage.h chat.h vending.h ../common/timer.h ../common/mmo.h ../common/db.h ../common/showmsg.h
txtobj/status.o: status.c pc.h map.h clif.h status.h mob.h itemdb.h battle.h skill.h script.h pet.h guild.h ../common/timer.h ../common/mmo.h ../common/db.h ../common/showmsg.h
txtobj/npc.o: npc.c map.h npc.h clif.h pc.h script.h mob.h itemdb.h battle.h ../common/db.h ../common/timer.h ../common/mmo.h ../common/showmsg.h
+txtobj/npc_chat.o: npc_chat.c map.h npc.h clif.h pc.h script.h mob.h itemdb.h battle.h ../common/db.h ../common/timer.h ../common/mmo.h ../common/showmsg.h
txtobj/chat.o: chat.c map.h clif.h pc.h chat.h ../common/db.h ../common/mmo.h ../common/showmsg.h
txtobj/path.o: path.c map.h battle.h ../common/mmo.h ../common/showmsg.h
txtobj/itemdb.o: itemdb.c map.h battle.h itemdb.h ../common/db.h ../common/grfio.h ../common/mmo.h ../common/showmsg.h
@@ -55,6 +56,7 @@ sqlobj/clif.o: clif.c map.h chrif.h clif.h mob.h intif.h pc.h npc.h itemdb.h cha
sqlobj/pc.o: pc.c map.h clif.h intif.h pc.h npc.h mob.h itemdb.h battle.h skill.h script.h party.h guild.h pet.h trade.h storage.h chat.h vending.h log.h ../common/timer.h ../common/mmo.h ../common/db.h ../common/showmsg.h
sqlobj/status.o: status.c pc.h map.h clif.h status.h mob.h itemdb.h battle.h skill.h script.h pet.h guild.h ../common/timer.h ../common/mmo.h ../common/db.h ../common/showmsg.h
sqlobj/npc.o: npc.c map.h npc.h clif.h pc.h script.h mob.h itemdb.h battle.h ../common/db.h ../common/timer.h ../common/mmo.h ../common/showmsg.h
+sqlobj/npc_chat.o: npc_chat.c map.h npc.h clif.h pc.h script.h mob.h itemdb.h battle.h ../common/db.h ../common/timer.h ../common/mmo.h ../common/showmsg.h
sqlobj/chat.o: chat.c map.h clif.h pc.h chat.h ../common/db.h ../common/mmo.h ../common/showmsg.h
sqlobj/path.o: path.c map.h battle.h ../common/mmo.h ../common/showmsg.h
sqlobj/itemdb.o: itemdb.c map.h battle.h itemdb.h ../common/db.h ../common/grfio.h ../common/mmo.h ../common/showmsg.h
diff --git a/src/map/clif.c b/src/map/clif.c
index 0a0db934a..67c925f75 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -7964,6 +7964,10 @@ void clif_parse_GlobalMessage(int fd, struct map_session_data *sd) { // S 008c <
WFIFOW(fd,0) = 0x8e;
WFIFOSET(fd, WFIFOW(fd,2));
+#ifdef PCRE_SUPPORT
+ map_foreachinarea(npc_chat_sub, sd->bl.m, sd->bl.x-AREA_SIZE, sd->bl.y-AREA_SIZE, sd->bl.x+AREA_SIZE, sd->bl.y+AREA_SIZE, BL_NPC, RFIFOP(fd,4), strlen(RFIFOP(fd,4)), &sd->bl);
+#endif
+
// Celest
if (pc_calc_base_job2 (sd->status.class_) == 23 ) {
int next = pc_nextbaseexp(sd)>0 ? pc_nextbaseexp(sd) : sd->status.base_exp;
diff --git a/src/map/map.h b/src/map/map.h
index 92c334806..2963a316e 100644
--- a/src/map/map.h
+++ b/src/map/map.h
@@ -411,6 +411,8 @@ struct npc_data {
char eventqueue[MAX_EVENTQUEUE][50];
int eventtimer[MAX_EVENTTIMER];
short arenaflag;
+
+ void *chatdb;
};
struct mob_data {
struct block_list bl;
diff --git a/src/map/npc.c b/src/map/npc.c
index 1ba55699f..54a35c51c 100644
--- a/src/map/npc.c
+++ b/src/map/npc.c
@@ -153,6 +153,10 @@ int npc_delete(struct npc_data *nd)
if(nd->bl.prev == NULL)
return 1;
+#ifdef PCRE_SUPPORT
+ npc_chat_finalize(nd);
+#endif
+
clif_clearchar_area(&nd->bl,1);
map_delblock(&nd->bl);
return 0;
diff --git a/src/map/npc.h b/src/map/npc.h
index a68cc8e54..dbb351fa0 100644
--- a/src/map/npc.h
+++ b/src/map/npc.h
@@ -8,6 +8,8 @@
#define WARP_DEBUG_CLASS 722
#define INVISIBLE_CLASS 32767
+void npc_chat_finalize(struct npc_data *nd);
+int npc_chat_sub(struct block_list *bl, va_list ap);
int npc_event_dequeue(struct map_session_data *sd);
int npc_event_timer(int tid,unsigned int tick,int id,int data);
int npc_event(struct map_session_data *sd,const char *npcname,int);
diff --git a/src/map/npc_chat.c b/src/map/npc_chat.c
new file mode 100644
index 000000000..5ec8540ae
--- /dev/null
+++ b/src/map/npc_chat.c
@@ -0,0 +1,502 @@
+#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_, 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
diff --git a/src/map/script.c b/src/map/script.c
index 92ecd8690..24195b698 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -253,9 +253,9 @@ int buildin_failedremovecards(struct script_state *st);
int buildin_marriage(struct script_state *st);
int buildin_wedding_effect(struct script_state *st);
int buildin_divorce(struct script_state *st);
-int buildin_ispartneron(struct script_state *st);
-int buildin_getpartnerid(struct script_state *st);
-int buildin_warppartner(struct script_state *st);
+int buildin_ispartneron(struct script_state *st); // MouseJstr
+int buildin_getpartnerid(struct script_state *st); // MouseJstr
+int buildin_warppartner(struct script_state *st); // MouseJstr
int buildin_getitemname(struct script_state *st);
int buildin_makepet(struct script_state *st);
int buildin_getexp(struct script_state *st);
@@ -315,6 +315,13 @@ int run_func(struct script_state *st);
int mapreg_setreg(int num,int val);
int mapreg_setregstr(int num,const char *str);
+#ifdef PCRE_SUPPORT
+int buildin_defpattern(struct script_state *st); // MouseJstr
+int buildin_activatepset(struct script_state *st); // MouseJstr
+int buildin_deactivatepset(struct script_state *st); // MouseJstr
+int buildin_deletepset(struct script_state *st); // MouseJstr
+#endif
+
struct {
int (*func)(struct script_state *);
char *name;
@@ -537,10 +544,14 @@ struct {
{buildin_isday,"isday",""}, // check whether it is day time [Celest]
{buildin_isequipped,"isequipped","i*"}, // check whether another item/card has been equipped [Celest]
{buildin_isequippedcnt,"isequippedcnt","i*"}, // check how many items/cards are being equipped [Celest]
+#ifdef PCRE_SUPPORT
+ {buildin_defpattern, "defpattern", "iss"}, // Define pattern to listen for [MouseJstr]
+ {buildin_activatepset, "activatepset", "i"}, // Activate a pattern set [MouseJstr]
+ {buildin_deactivatepset, "deactivatepset", "i"}, // Deactive a pattern set [MouseJstr]
+ {buildin_deletepset, "deletepset", "i"}, // Delete a pattern set [MouseJstr]
+#endif
{NULL,NULL,NULL},
};
-int buildin_message(struct script_state *st); // [MouseJstr]
-
enum {
C_NOP,C_POS,C_INT,C_PARAM,C_FUNC,C_STR,C_CONSTSTR,C_ARG,
@@ -1403,6 +1414,11 @@ static int set_reg(struct map_session_data *sd,int num,char *name,void *v)
return 0;
}
+int set_var(struct map_session_data *sd, char *name, void *val)
+{
+ return set_reg(sd, add_str(name), name, val);
+}
+
/*==========================================
* 文字列への変換
*------------------------------------------
diff --git a/src/map/script.h b/src/map/script.h
index 759013e95..b30201a67 100644
--- a/src/map/script.h
+++ b/src/map/script.h
@@ -42,6 +42,10 @@ struct script_state {
char * parse_script(unsigned char *,int);
int run_script(char *,int,int,int);
+int set_var(struct map_session_data *sd, char *name, void *val);
+int conv_num(struct script_state *st,struct script_data *data);
+char* conv_str(struct script_state *st,struct script_data *data);
+
struct dbt* script_get_label_db();
struct dbt* script_get_userfunc_db();