فهرست منبع

PCRE updates

git-svn-id: https://svn.code.sf.net/p/rathena/svn/branches/stable@1157 54d463be-8e91-2dee-dedb-b68131a5f0ec
amber 20 سال پیش
والد
کامیت
0b091d02ee
11فایلهای تغییر یافته به همراه1253 افزوده شده و 8 حذف شده
  1. 6 1
      Changelog-SVN.txt
  2. 2 0
      Makefile
  3. 702 0
      npc/other/eliza.txt
  4. 4 2
      src/map/Makefile
  5. 4 0
      src/map/clif.c
  6. 2 0
      src/map/map.h
  7. 4 0
      src/map/npc.c
  8. 2 0
      src/map/npc.h
  9. 502 0
      src/map/npc_chat.c
  10. 21 5
      src/map/script.c
  11. 4 0
      src/map/script.h

+ 6 - 1
Changelog-SVN.txt

@@ -1,5 +1,10 @@
 Date	Added
 
+02/22
+	* Added perl regular expression support.. look at src/map/npc_chat.c
+	  for all the dirt on the new features.  To build it, you have
+	  to enable the PCRE_SUPPORT #define and you also have to
+	  build/install the pcre library. [SVN 1157: MouseJstr]
 02/21
 	* Added actual item_db.sql into sql-files. [Lupus]
 	* Added actual mob_db.sql into sql-files. If you use SQL Mob DB then update it [Lupus]
@@ -2000,4 +2005,4 @@ Date	Added
 	  router or a firewall since there is no way of determining the 
 	  external IP address.  On the other hand, we should be able to 
 	  eliminate the lan_conf file since we know our IP addresses as well 
-	  as our netmask.
+	  as our netmask.

+ 2 - 0
Makefile

@@ -1,11 +1,13 @@
 
 CC = gcc -pipe
+# CC = gcc -pipe -DPCRE_SUPPORT
 # CC = g++
 # CC = gcc -pipe -DGCOLLECT
 # CC = gcc -pipe -DDMALLOC -DDMALLOC_FUNC_CHECK
 # CC = /usr/local/bin/gcc -fbounds-checking -pipe -DBCHECK
 
 # GCLIB = -lgc
+# GCLIB = -L/usr/local/lib -lpcre
 GCLIB =
 # GCLIB = -ldmalloc
 

+ 702 - 0
npc/other/eliza.txt

@@ -0,0 +1,702 @@
+prontera.gat,152,181,5	script	MouseJstr	763,{
+
+//  hello
+Lquote0:
+        npctalk "How do you do.  Please state your problem.";
+        break;
+//  computer
+Lquote1:
+        set $foo,rand(4);
+	if($foo == 0) goto Lquote1a;
+	if($foo == 1) goto Lquote1b;
+	if($foo == 2) goto Lquote1c;
+	if($foo == 3) goto Lquote1d;
+Lquote1a:
+        npctalk "Do computers worry you?";
+        break;
+Lquote1b:
+        npctalk "What do you think about machines?";
+        break;
+Lquote1c:
+        npctalk "Why do you mention computers?";
+        break;
+Lquote1d:
+        npctalk "What do you think machines have to do with your problem?";
+        break;
+// name
+Lquote2:
+        npctalk "I am not interested in names";
+        break;
+// sorry
+Lquote3:
+        set $foo,rand(3);
+	if($foo == 0) goto Lquote3a;
+	if($foo == 1) goto Lquote3b;
+	if($foo == 2) goto Lquote3c;
+
+Lquote3a:
+        npctalk "Please don't apologize";
+        break;
+
+Lquote3b:
+        npctalk "Apologies are not necessary";
+        break;
+
+Lquote3c:
+        npctalk "What feelings do you have when you apologize";
+        break;
+
+//    I remember $p2$
+Lquote4:
+        set $foo,rand(6);
+	if($foo == 0) goto Lquote4a;
+	if($foo == 1) goto Lquote4b;
+	if($foo == 2) goto Lquote4c;
+	if($foo == 3) goto Lquote4d;
+	if($foo == 4) goto Lquote4e;
+	if($foo == 5) goto Lquote4f;
+
+Lquote4a:
+        npctalk "Do you often think of "+$p2$+"?";
+        break;
+
+Lquote4b:
+        npctalk "Does thinking of "+$p2$+" bring anything else to mind?";
+        break;
+
+Lquote4c:
+        npctalk "What else do you remember?";
+        break;
+
+Lquote4d:
+        npctalk "Why do you recall "+$p2$+" right now?";
+        break;
+
+Lquote4e:
+        npctalk "What in the present situation reminds you of "+$p2$+"?";
+        break;
+
+Lquote4f:
+        npctalk "What is the connection between me and "+$p2$+"?";
+        break;
+
+//    do you remember
+Lquote5:
+        set $foo,rand(4);
+	if($foo == 0) goto Lquote5a;
+	if($foo == 1) goto Lquote5b;
+	if($foo == 2) goto Lquote5c;
+	if($foo == 3) goto Lquote5d;
+Lquote5a:
+        npctalk "Did you think I would forget "+$p2$+" ?";
+        break;
+
+Lquote5b:
+        npctalk "Why do you think I should recall "+$p2$+" now";
+        break;
+
+Lquote5c:
+        npctalk "What about "+$p2$+"";
+        break;
+
+Lquote5d:
+        npctalk "You mentioned "+$p2$+"";
+        break;
+
+// if
+Lquote6:
+        set $foo,rand(4);
+	if($foo == 0) goto Lquote6a;
+	if($foo == 1) goto Lquote6b;
+	if($foo == 2) goto Lquote6c;
+	if($foo == 3) goto Lquote6d;
+Lquote6a:
+        npctalk "Do you really think its likely that "+$p2$+"";
+        break;
+
+Lquote6b:
+        npctalk "Do you wish that "+$p2$+"?";
+        break;
+
+Lquote6c:
+        npctalk "What do you think about "+$p2$+"?";
+        break;
+
+Lquote6d:
+        npctalk "Really-- if "+$p2$+"?";
+        break;
+
+//  i dreamt
+Lquote7:
+        set $foo,rand(3);
+	if($foo == 0) goto Lquote7a;
+	if($foo == 1) goto Lquote7b;
+	if($foo == 2) goto Lquote7c;
+Lquote7a:
+        npctalk "Really-- "+$p2$+"";
+        break;
+
+Lquote7b:
+        npctalk "Have you ever fantasized "+$p2$+" while you were awake?";
+        break;
+
+Lquote7c:
+        npctalk "Have you dreamt "+$p2$+" before?";
+        break;
+
+//   dream about
+
+Lquote8:
+        npctalk "How do you feel about "+$p2$+" in reality?";
+        break;
+
+//  dream
+Lquote9:
+        set $foo,rand(4);
+	if($foo == 0) goto Lquote9a;
+	if($foo == 1) goto Lquote9b;
+	if($foo == 2) goto Lquote9c;
+	if($foo == 3) goto Lquote9d;
+Lquote9a:
+        npctalk "What does this dream suggest to you?";
+        break;
+
+Lquote9b:
+        npctalk "Do you dream often?";
+        break;
+
+Lquote9c:
+        npctalk "What persons appear in your dreams?";
+        break;
+
+Lquote9d:
+        npctalk "Don't you believe that dream has to do with your problem?";
+        break;
+
+//   my mother
+Lquote10:
+        set $foo,rand(2);
+	if($foo == 0) goto Lquote10a;
+	if($foo == 1) goto Lquote10b;
+Lquote10a:
+        npctalk "Who else in your family "+$p2$+"";
+        break;
+
+Lquote10b:
+        npctalk "Tell me more about your family";
+        break;
+
+//   my father
+Lquote11:
+        set $foo,rand(3);
+	if($foo == 0) goto Lquote11a;
+	if($foo == 1) goto Lquote11b;
+	if($foo == 2) goto Lquote11c;
+Lquote11a:
+        npctalk "Your father";
+        break;
+
+Lquote11b:
+        npctalk "Does he influence you strongly?";
+        break;
+
+Lquote11c:
+        npctalk "What else comes to mind when you think of your father?";
+        break;
+
+//   I want
+Lquote12:
+        set $foo,rand(3);
+	if($foo == 0) goto Lquote12a;
+	if($foo == 1) goto Lquote12b;
+	if($foo == 2) goto Lquote12c;
+Lquote12a:
+        npctalk "What would it mean if you got "+$p2$+"";
+        break;
+
+Lquote12b:
+        npctalk "Why do you want "+$p2$+"";
+        break;
+
+Lquote12c:
+        npctalk "Suppose you got "+$p2$+" soon";
+        break;
+
+//    I am glad 
+Lquote13:
+        set $foo,rand(3);
+	if($foo == 0) goto Lquote13a;
+	if($foo == 1) goto Lquote13b;
+	if($foo == 2) goto Lquote13c;
+Lquote13a:
+        npctalk "How have I helped you to be "+$p2$+"";
+        break;
+
+Lquote13b:
+        npctalk "What makes you happy just now";
+        break;
+
+Lquote13c:
+        npctalk "Can you explain why you are suddenly "+$p2$+"";
+        break;
+
+//    I am sad 
+Lquote14:
+        set $foo,rand(2);
+	if($foo == 0) goto Lquote14a;
+	if($foo == 1) goto Lquote14b;
+Lquote14a:
+        npctalk "I am sorry to hear you are depressed";
+        break;
+
+Lquote14b:
+        npctalk "I'm sure its not pleasant to be sad";
+        break;
+
+//   $p2 are like "+$p3$+"
+Lquote15:
+        npctalk "What resemblance do you see between "+$p2$+" and "+$p3$+"";
+        break;
+
+//   "+$p2$+" is like "+$p3$+"
+Lquote16:
+        set $foo,rand(4);
+	if($foo == 0) goto Lquote16a;
+	if($foo == 1) goto Lquote16b;
+	if($foo == 2) goto Lquote16c;
+	if($foo == 3) goto Lquote16d;
+Lquote16a:
+        npctalk "In what way is it that "+$p2$+" is like "+$p3$+"";
+        break;
+
+Lquote16b:
+        npctalk "What resemblance do you see?";
+        break;
+
+Lquote16c:
+        npctalk "Could there really be some connection?";
+        break;
+
+Lquote16d:
+        npctalk "How?";
+        break;
+//   alike
+Lquote17:
+        set $foo,rand(2);
+	if($foo == 0) goto Lquote17a;
+	if($foo == 1) goto Lquote17b;
+Lquote17a:
+        npctalk "In what way?";
+        break;
+
+Lquote17b:
+        npctalk "What similarities are there?";
+        break;
+//    same 
+Lquote18:
+        npctalk "What other connections do you see?";
+        break;
+
+//   I was "+$p2$+"
+Lquote19:
+        set $foo,rand(3);
+	if($foo == 0) goto Lquote19a;
+	if($foo == 1) goto Lquote19b;
+	if($foo == 2) goto Lquote19c;
+Lquote19a:
+        npctalk "Were you really?";
+        break;
+
+Lquote19b:
+        npctalk "Perhaps I already knew you were "+$p2$+"";
+        break;
+
+Lquote19c:
+        npctalk "Why do you tell me you were "+$p2$+" now?";
+        break;
+
+//    was I
+Lquote20:
+        set $foo,rand(3);
+	if($foo == 0) goto Lquote20a;
+	if($foo == 1) goto Lquote20b;
+	if($foo == 2) goto Lquote20c;
+Lquote20a:
+        npctalk "What if you were "+$p2$+" ?";
+        break;
+
+Lquote20b:
+        npctalk "Do you thin you were "+$p2$+"";
+        break;
+
+Lquote20c:
+        npctalk "What would it mean if you were "+$p2$+"";
+        break;
+
+//    I am
+Lquote21:
+        set $foo,rand(2);
+	if($foo == 0) goto Lquote21a;
+	if($foo == 1) goto Lquote21b;
+Lquote21a:
+        npctalk "In what way are you "+$p2$+"";
+        break;
+
+Lquote21b:
+        npctalk "Do you want to be "+$p2$+" ?";
+        break;
+
+//   am I
+Lquote22:
+        set $foo,rand(4);
+	if($foo == 0) goto Lquote22a;
+	if($foo == 1) goto Lquote22b;
+	if($foo == 2) goto Lquote22c;
+	if($foo == 3) goto Lquote22d;
+Lquote22a:
+        npctalk "Do you believe you are "+$p2$+"";
+        break;
+
+Lquote22b:
+        npctalk "Would you want to be "+$p2$+"";
+        break;
+
+Lquote22c:
+        npctalk "You wish I would tell you you are "+$p2$+"";
+        break;
+
+Lquote22d:
+        npctalk "What would it mean if you were "+$p2$+"";
+        break;
+
+//   am
+Lquote23:
+        set $foo,rand(2);
+	if($foo == 0) goto Lquote23a;
+	if($foo == 1) goto Lquote23b;
+
+Lquote23a:
+        npctalk "Why do you say AM?";
+        break;
+
+Lquote23b:
+        npctalk "I don't understand that";
+        break;
+
+//    are you
+Lquote24:
+        set $foo,rand(3);
+	if($foo == 0) goto Lquote24a;
+	if($foo == 1) goto Lquote24b;
+	if($foo == 2) goto Lquote24c;
+Lquote24a:
+        npctalk "Why are you interested in whether I am "+$p2$+" or not?";
+        break;
+
+Lquote24b:
+        npctalk "Would you prefer if I weren't "+$p2$+"";
+        break;
+
+Lquote24c:
+        npctalk "Perhaps I am "+$p2$+" in your fantasies";
+        break;
+
+//   you are 
+Lquote25:
+        npctalk "What makes you think I am "+$p2$+" ?";
+        break;
+
+//   because
+Lquote26:
+        set $foo,rand(3);
+	if($foo == 0) goto Lquote26a;
+	if($foo == 1) goto Lquote26b;
+	if($foo == 2) goto Lquote26c;
+Lquote26a:
+        npctalk "Is that the real reason?";
+        break;
+
+Lquote26b:
+        npctalk "What other reasons might there be?";
+        break;
+
+Lquote26c:
+        npctalk "Does that reason seem to explain anything else?";
+        break;
+
+//    were you 
+Lquote27:
+        set $foo,rand(3);
+	if($foo == 0) goto Lquote27a;
+	if($foo == 1) goto Lquote27b;
+	if($foo == 2) goto Lquote27c;
+Lquote27a:
+        npctalk "Perhaps I was "+$p2$+"";
+        break;
+
+Lquote27b:
+        npctalk "What do you think?";
+        break;
+
+Lquote27c:
+        npctalk "What if I had been "+$p2$+"";
+        break;
+
+//   I can't 
+Lquote28:
+        set $foo,rand(2);
+	if($foo == 0) goto Lquote28a;
+	if($foo == 1) goto Lquote28b;
+Lquote28a:
+        npctalk "Maybe you could "+$p2$+" now";
+        break; 
+
+Lquote28b:
+        npctalk "What if you could "+$p2$+" ?";
+        break;
+
+//    I feel 
+Lquote29:
+        npctalk "Do you often feel "+$p2$+" ?";
+        break;
+
+//    I felt
+Lquote30:
+        npctalk "What other feelings do you have?";
+        break;
+
+//   $p1$ I $p2$ you $p3$
+Lquote31:
+        npctalk "Perhaps in your fantasy we "+$p3$+" each other?";
+        break;
+
+//   why don't you 
+Lquote32:
+        set $foo,rand(3);
+	if($foo == 0) goto Lquote32a;
+	if($foo == 1) goto Lquote32b;
+	if($foo == 2) goto Lquote32c;
+Lquote32a:
+        npctalk "Should you "+$p2$+" yourself?";
+        break;
+
+Lquote32b:
+        npctalk "Do you believe I don't "+$p2$+"";
+        break;
+
+Lquote32c:
+        npctalk "Perhaps I will "+$p2$+" in good time";
+        break;
+
+//   yes 
+Lquote33:
+        set $foo,rand(3);
+	if($foo == 0) goto Lquote33a;
+	if($foo == 1) goto Lquote33b;
+	if($foo == 2) goto Lquote33c;
+Lquote33a:
+        npctalk "You seem quite positive";
+        break;
+
+Lquote33b:
+        npctalk "You are sure?";
+        break;
+
+Lquote33c:
+        npctalk "I understand";
+        break;
+
+//    no
+Lquote34:
+        set $foo,rand(3);
+	if($foo == 0) goto Lquote34a;
+	if($foo == 1) goto Lquote34b;
+	if($foo == 2) goto Lquote34c;
+Lquote34a:
+        npctalk "Why not?";
+        break;
+
+Lquote34b:
+        npctalk "You are being a bit negative";
+        break;
+
+Lquote34c:
+        npctalk "Are you saying NO just to be negative?";
+        break;
+
+//    someone
+Lquote35:
+        npctalk "Can you be more specific?";
+        break;
+
+//    everyone 
+Lquote36:
+        set $foo,rand(4);
+	if($foo == 0) goto Lquote36a;
+	if($foo == 1) goto Lquote36b;
+	if($foo == 2) goto Lquote36c;
+	if($foo == 3) goto Lquote36d;
+Lquote36a:
+        npctalk "surely not everyone";
+        break;
+
+Lquote36b:
+        npctalk "Can you think of anyone in particular?";
+        break;
+
+Lquote36c:
+        npctalk "Who for example?";
+        break;
+
+Lquote36d:
+        npctalk "You are thinking of a special person?";
+        break;
+
+//  always 
+Lquote37:
+        set $foo,rand(4);
+	if($foo == 0) goto Lquote37a;
+	if($foo == 1) goto Lquote37b;
+	if($foo == 2) goto Lquote37c;
+	if($foo == 3) goto Lquote37d;
+Lquote37a:
+        npctalk "Can you think of a specific example?";
+        break;
+
+Lquote37b:
+        npctalk "When?";
+        break;
+
+Lquote37c:
+        npctalk "What incident are you thinking of?";
+        break;
+
+Lquote37d:
+        npctalk "Really-- always?";
+        break;
+
+//   what
+Lquote38:
+        set $foo,rand(5);
+	if($foo == 0) goto Lquote38a;
+	if($foo == 1) goto Lquote38b;
+	if($foo == 2) goto Lquote38c;
+	if($foo == 3) goto Lquote38d;
+	if($foo == 4) goto Lquote38e;
+Lquote38a:
+        npctalk "Why do you ask?";
+        break;
+
+Lquote38b:
+        npctalk "Does that question interest you?";
+        break;
+
+Lquote38c:
+        npctalk "What is it you really want to know?";
+        break;
+
+Lquote38d:
+        npctalk "What do you think?";
+        break;
+
+Lquote38e:
+        npctalk "What comes to your mind when you ask that?";
+        break;
+
+//   perhaps 
+Lquote39:
+        npctalk "You do not seem quite certain";
+        break;
+
+//   are
+Lquote40:
+        set $foo,rand(2);
+	if($foo == 0) goto Lquote40a;
+	if($foo == 1) goto Lquote40b;
+Lquote40a:
+        npctalk "Did you think they might not be "+$p2$+"";
+        break;
+
+Lquote40b:
+        npctalk "Possibly they are "+$p2$;
+        break;
+
+//   default
+Lquote41:
+        set $foo,rand(6);
+	if($foo == 0) goto Lquote41a;
+	if($foo == 1) goto Lquote41b;
+	if($foo == 2) goto Lquote41c;
+	if($foo == 3) goto Lquote41d;
+	if($foo == 4) goto Lquote41e;
+	if($foo == 5) goto Lquote41f;
+Lquote41a:
+        npctalk "Very interesting";
+        break;
+
+Lquote41b:
+        npctalk "I am not sure I understand you fully";
+        break;
+
+Lquote41c:
+        npctalk "What does that suggest to you?";
+        break;
+
+Lquote41d:
+        npctalk "Please continue";
+        break;
+
+Lquote41e:
+        npctalk "Go on";
+        break;
+
+Lquote41f:
+        npctalk "Do you feel strongly about discussing such things?";
+        break;
+OnInit:
+        defpattern 1, "([^:]+):.*\\shello.*", "Lquote0";
+        defpattern 1, "([^:]+):.*\\scomputer.*", "Lquote1";
+        defpattern 1, "([^:]+):.*\\sname.*", "Lquote2";
+        defpattern 1, "([^:]+):.*\\ssorry.*", "Lquote3";
+        defpattern 1, "([^:]+):.*\\si\\s+remember\\s+(.*)", "Lquote4";
+        defpattern 1, "([^:]+):.*\\sdo\\s+you\\s+remember\\s+(.*)", "Lquote5";
+        defpattern 1, "([^:]+):.*\\sif\\s+(.*)", "Lquote6";
+        defpattern 1, "([^:]+):.*\\si\\s+dreamt\\s+(.*)", "Lquote7";
+        defpattern 1, "([^:]+):.*\\sdream\\s+about\\s+(.*)", "Lquote8";
+        defpattern 1, "([^:]+):.*\\sdream\\s+(.*)", "Lquote9";
+        defpattern 1, "([^:]+):.*\\smy\\s+mother\\s+(.*)", "Lquote10";
+        defpattern 1, "([^:]+):.*\\smy\\s+father\\s+(.*)", "Lquote11";
+        defpattern 1, "([^:]+):.*\\si\\s+want\\s+(.*)", "Lquote12";
+        defpattern 1, "([^:]+):.*\\si\\s+am\\s+glad\\s+(.*)", "Lquote13";
+        defpattern 1, "([^:]+):\\s+(.*)\\s+i\\s+am\\s+sad\\s+(.*)", "Lquote14";
+        defpattern 1, "([^:]+):\\s+(.*)\\s+are\\s+like\\s+(.*)", "Lquote15";
+        defpattern 1, "([^:]+):\\s+(.*)\\s+is\\s+like\\s+(.*)", "Lquote16";
+        defpattern 1, "([^:]+):.*\\salike\\s+(.*)", "Lquote17";
+        defpattern 1, "([^:]+):.*\\ssame\\s+(.*)", "Lquote18";
+        defpattern 1, "([^:]+):.*\\si\\s+was\\s+(.*)", "Lquote19";
+        defpattern 1, "([^:]+):.*\\swas\\s+i\\s+(.*)", "Lquote20";
+        defpattern 1, "([^:]+):.*\\si\\s+am\\s+(.*)", "Lquote21";
+        defpattern 1, "([^:]+):.*\\sam\\s+i\\s+(.*)", "Lquote22";
+        defpattern 1, "([^:]+):.*\\sam\\s+(.*)", "Lquote23";
+        defpattern 1, "([^:]+):.*\\sare\\s+you\\s+(.*)", "Lquote24";
+        defpattern 1, "([^:]+):.*\\syou\\s+are\\s+(.*)", "Lquote25";
+        defpattern 1, "([^:]+):.*\\sbecause\\s+(.*)", "Lquote26";
+        defpattern 1, "([^:]+):.*\\swere\\s+you\\s+(.*)", "Lquote27";
+        defpattern 1, "([^:]+):.*\\si\\s+(cant|can't|cannot)\\s+(.*)", "Lquote28";
+        defpattern 1, "([^:]+):.*\\si\\s+feel\\s+(.*)", "Lquote29";
+        defpattern 1, "([^:]+):.*\\si\\s+felt\\s+(.*)", "Lquote30";
+        defpattern 1, "([^:]+):.*\\si\\s+(.*)\\s+you\\s+(.*)", "Lquote31";
+        defpattern 1, "([^:]+):.*\\swhy\\s+(don't|dont)\\s+you\\s+(.*)", "Lquote32";
+        defpattern 1, "([^:]+):.*\\syes\\s+(.*)", "Lquote33";
+        defpattern 1, "([^:]+):.*\\sno\\s+(.*)", "Lquote34";
+        defpattern 1, "([^:]+):.*\\ssomeone\\s+(.*)", "Lquote35";
+        defpattern 1, "([^:]+):.*\\severyone\\s+(.*)", "Lquote36";
+        defpattern 1, "([^:]+):.*\\salways\\s+(.*)", "Lquote37";
+        defpattern 1, "([^:]+):.*\\swhat\\s+(.*)", "Lquote38";
+        defpattern 1, "([^:]+):.*\\sperhaps\\s+(.*)", "Lquote39";
+        defpattern 1, "([^:]+):.*\\sare\\s+(.*)", "Lquote40";
+        defpattern 1, "([^:]+):(.*)", "Lquote41";
+
+        activatepset 1;
+        break;
+}

+ 4 - 2
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

+ 4 - 0
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;

+ 2 - 0
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;

+ 4 - 0
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;

+ 2 - 0
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);

+ 502 - 0
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

+ 21 - 5
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);
+}
+
 /*==========================================
  * •¶Žš—ñ‚ւ̕ϊ·
  *------------------------------------------

+ 4 - 0
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();