Browse Source

PCRE updates

git-svn-id: https://svn.code.sf.net/p/rathena/svn/branches/stable@1157 54d463be-8e91-2dee-dedb-b68131a5f0ec
amber 20 years ago
parent
commit
0b091d02ee
11 changed files with 1253 additions and 8 deletions
  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
 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
 02/21
 	* Added actual item_db.sql into sql-files. [Lupus]
 	* 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]
 	* 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 
 	  router or a firewall since there is no way of determining the 
 	  external IP address.  On the other hand, we should be able to 
 	  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 
 	  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
+# CC = gcc -pipe -DPCRE_SUPPORT
 # CC = g++
 # CC = g++
 # CC = gcc -pipe -DGCOLLECT
 # CC = gcc -pipe -DGCOLLECT
 # CC = gcc -pipe -DDMALLOC -DDMALLOC_FUNC_CHECK
 # CC = gcc -pipe -DDMALLOC -DDMALLOC_FUNC_CHECK
 # CC = /usr/local/bin/gcc -fbounds-checking -pipe -DBCHECK
 # CC = /usr/local/bin/gcc -fbounds-checking -pipe -DBCHECK
 
 
 # GCLIB = -lgc
 # GCLIB = -lgc
+# GCLIB = -L/usr/local/lib -lpcre
 GCLIB =
 GCLIB =
 # GCLIB = -ldmalloc
 # 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
 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
 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)
 	$(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)
 	$(CC) -o ../../$@ $> $(LIB_S)
 
 
 txtobj/%.o: %.c
 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/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/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.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/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/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
 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/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/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.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/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/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
 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;
 	WFIFOW(fd,0) = 0x8e;
 	WFIFOSET(fd, WFIFOW(fd,2));
 	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
 	// Celest
 	if (pc_calc_base_job2 (sd->status.class_) == 23 ) {
 	if (pc_calc_base_job2 (sd->status.class_) == 23 ) {
 		int next = pc_nextbaseexp(sd)>0 ? pc_nextbaseexp(sd) : sd->status.base_exp;
 		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];
 	char eventqueue[MAX_EVENTQUEUE][50];
 	int eventtimer[MAX_EVENTTIMER];
 	int eventtimer[MAX_EVENTTIMER];
 	short arenaflag;
 	short arenaflag;
+
+	void *chatdb;
 };
 };
 struct mob_data {
 struct mob_data {
 	struct block_list bl;
 	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)
     if(nd->bl.prev == NULL)
         return 1;
         return 1;
 
 
+#ifdef PCRE_SUPPORT
+    npc_chat_finalize(nd);
+#endif
+
     clif_clearchar_area(&nd->bl,1);
     clif_clearchar_area(&nd->bl,1);
     map_delblock(&nd->bl);
     map_delblock(&nd->bl);
     return 0;
     return 0;

+ 2 - 0
src/map/npc.h

@@ -8,6 +8,8 @@
 #define WARP_DEBUG_CLASS 722
 #define WARP_DEBUG_CLASS 722
 #define INVISIBLE_CLASS 32767
 #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_dequeue(struct map_session_data *sd);
 int npc_event_timer(int tid,unsigned int tick,int id,int data);
 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);
 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_marriage(struct script_state *st);
 int buildin_wedding_effect(struct script_state *st);
 int buildin_wedding_effect(struct script_state *st);
 int buildin_divorce(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_getitemname(struct script_state *st);
 int buildin_makepet(struct script_state *st);
 int buildin_makepet(struct script_state *st);
 int buildin_getexp(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_setreg(int num,int val);
 int mapreg_setregstr(int num,const char *str);
 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 {
 struct {
 	int (*func)(struct script_state *);
 	int (*func)(struct script_state *);
 	char *name;
 	char *name;
@@ -537,10 +544,14 @@ struct {
 	{buildin_isday,"isday",""}, // check whether it is day time [Celest]
 	{buildin_isday,"isday",""}, // check whether it is day time [Celest]
 	{buildin_isequipped,"isequipped","i*"}, // check whether another item/card has been equipped [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]
 	{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},
 	{NULL,NULL,NULL},
 };
 };
-int buildin_message(struct script_state *st); // [MouseJstr]
-
 
 
 enum {
 enum {
 	C_NOP,C_POS,C_INT,C_PARAM,C_FUNC,C_STR,C_CONSTSTR,C_ARG,
 	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;
 	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);
 char * parse_script(unsigned char *,int);
 int run_script(char *,int,int,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_label_db();
 struct dbt* script_get_userfunc_db();
 struct dbt* script_get_userfunc_db();