Crossfire Server, Trunk
dialog.cpp
Go to the documentation of this file.
1 
2 /*
3  * Crossfire -- cooperative multi-player graphical RPG and adventure game
4  *
5  * Copyright (c) 1999-2014 Mark Wedel and the Crossfire Development Team
6  * Copyright (c) 1992 Frank Tore Johansen
7  *
8  * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are
9  * welcome to redistribute it under certain conditions. For details, please
10  * see COPYING and LICENSE.
11  *
12  * The authors can be reached via e-mail at <crossfire@metalforge.org>.
13  */
14 
20 #include <stdlib.h>
21 #include <string.h>
22 
23 #include "global.h"
24 #include "define.h"
25 #include "object.h"
26 #include "dialog.h"
27 
28 const char *NPC_DIALOG_ARCH = "npc_dialog";
29 
34 void free_dialog_information(object *op) {
36  struct_dialog_reply *currep, *nextrep;
37 
39  return;
40 
42  if (!op->dialog_information)
43  return;
44 
45  current = op->dialog_information->all_messages;
46  while (current) {
47  next = current->next;
48  free(current->match);
49  free(current->message);
50  currep = current->replies;
51  while (currep) {
52  nextrep = currep->next;
53  free(currep->reply);
54  free(currep->message);
55  currep = nextrep;
56  }
57  free(current);
58  current = next;
59  }
60 
61  currep = op->dialog_information->all_replies;
62  while (currep) {
63  nextrep = currep->next;
64  free(currep->reply);
65  free(currep->message);
66  free(currep);
67  currep = nextrep;
68  }
69 
70  free(op->dialog_information);
71  op->dialog_information = NULL;
72 }
73 
81 static int matches(const char *exp, const char *text) {
82  char *pipe, *save = NULL, *msg;
83  int match = 0;
84 
85  if (exp[0] == '*')
86  return 1;
87 
88  msg = strdup(exp);
89 
90  pipe = strtok_r(msg, "|", &save);
91  while (pipe) {
92  if (re_cmp(text, pipe)) {
93  match = 1;
94  break;
95  }
96  pipe = strtok_r(NULL, "|", &save);
97  }
98 
99  free(msg);
100  return match;
101 }
102 
106 static bool is_cfdialog(const char *msg) {
107  return msg[0] == '{';
108 }
109 
110 void dialog_preparse(object *op) {
111  // Detect inline CFDialog JSON dialogs. Make sure there's a npc_dialog.
112  if (op->msg && is_cfdialog(op->msg)) {
116  op->event_bitmask &= ~BITMASK_VALID; // must force update to make event work
117  }
118  }
119 }
120 
127 static void parse_dialog_information(object *op) {
128  struct_dialog_message *message = NULL, *last = NULL;
129  struct_dialog_reply *reply = NULL;
130  char *current, *save = NULL, *msg, *cp;
131  int len;
132  /* Used for constructing message with */
133  char *tmp = NULL;
134  size_t tmplen = 0;
135 
137  return;
139 
140  op->dialog_information = (struct_dialog_information *)calloc(1, sizeof(struct_dialog_information));
141  if (op->dialog_information == NULL)
143 
144  if (!op->msg || is_cfdialog(op->msg))
145  return;
146 
147  msg = strdup(op->msg);
148  current = strtok_r(msg, "\n", &save);
149 
150  while (current) {
151  if (strncmp(current, "@match ", 7) == 0) {
152  if (message) {
153  message->message = tmp;
154  tmp = NULL;
155  tmplen = 0;
156  }
157 
158  message = (struct_dialog_message *)calloc(1, sizeof(struct_dialog_message));
159  if (last)
160  last->next = message;
161  else
162  op->dialog_information->all_messages = message;
163  last = message;
164 
165  message->match = strdup(current+7);
166  } else if ((strncmp(current, "@reply ", 7) == 0 && (len = 7)) || (strncmp(current, "@question ", 10) == 0 && (len = 10))) {
167  if (message) {
168  reply = (struct_dialog_reply *)calloc(1, sizeof(struct_dialog_reply));
169  reply->type = (len == 7 ? rt_reply : rt_question);
170  cp = strchr(current+len, ' ');
171  if (cp) {
172  *cp = '\0';
173  reply->reply = strdup(current+len);
174  reply->message = strdup(cp+1);
175  } else {
176  reply->reply = strdup(current+len);
177  reply->message = strdup(reply->reply);
178  LOG(llevDebug, "Warning: @reply/@question without message for %s!\n", op->name);
179  }
180  reply->next = message->replies;
181  message->replies = reply;
182 
183  reply = (struct_dialog_reply *)calloc(1, sizeof(struct_dialog_reply));
184  reply->reply = strdup(message->replies->reply);
185  reply->message = strdup(message->replies->message);
186  reply->type = message->replies->type;
187  reply->next = op->dialog_information->all_replies;
188  op->dialog_information->all_replies = reply;
189  } else
190  LOG(llevDebug, "Warning: @reply not in @match block for %s!\n", op->name);
191  } else if ((strncmp(current, "@identify", 9) == 0 && (len = 9))) {
192  if (message) {
193  message->identifies = true;
194  }
195  } else if (message) {
196  /* Needed to set initial \0 */
197  int wasnull = FALSE;
198  tmplen += strlen(current)+2;
199  if (!tmp)
200  wasnull = TRUE;
201  tmp = static_cast<char *>(realloc(tmp, tmplen*sizeof(char)));
202  if (!tmp)
204  if (wasnull)
205  tmp[0] = 0;
206  strncat(tmp, current, tmplen-strlen(tmp)-1);
207  strncat(tmp, "\n", tmplen-strlen(tmp)-1);
208  }
209  current = strtok_r(NULL, "\n", &save);
210  }
211 
212  if (message) {
213  if (!tmp)
214  message->message = strdup("");
215  else
216  message->message = tmp;
217  tmp = NULL;
218  tmplen = 0;
219  }
220 
221  free(msg);
222 }
223 
236 
237  for (*message = op->dialog_information->all_messages; *message; *message = (*message)->next) {
238  if (matches((*message)->match, text)) {
239  break;
240  }
241  }
242  if (!*message)
243  return 0;
244 
245  for (*reply = op->dialog_information->all_replies; *reply; *reply = (*reply)->next) {
246  if (strcmp((*reply)->reply, text) == 0)
247  break;
248  }
249 
250  return 1;
251 }
give.next
def next
Definition: give.py:44
global.h
struct_dialog_reply::next
struct struct_dialog_reply * next
Definition: dialog.h:20
LOG
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.cpp:58
SET_FLAG
#define SET_FLAG(xyz, p)
Definition: define.h:224
QUERY_FLAG
#define QUERY_FLAG(xyz, p)
Definition: define.h:226
FALSE
#define FALSE
Definition: compat.h:14
say.reply
string reply
Definition: say.py:77
Ice.tmp
int tmp
Definition: Ice.py:207
is_cfdialog
static bool is_cfdialog(const char *msg)
Definition: dialog.cpp:106
object_insert_in_ob
object * object_insert_in_ob(object *op, object *where)
Definition: object.cpp:2857
FLAG_DIALOG_PARSED
#define FLAG_DIALOG_PARSED
Definition: define.h:243
struct_dialog_reply::message
char * message
Definition: dialog.h:18
dialog_preparse
void dialog_preparse(object *op)
Definition: dialog.cpp:110
navar-midane_pickup.msg
list msg
Definition: navar-midane_pickup.py:13
struct_dialog_reply
Definition: dialog.h:16
push.match
bool match
Definition: push.py:61
struct_dialog_information
Definition: dialog.h:37
rt_reply
@ rt_reply
Definition: dialog.h:9
guild_entry.text
text
Definition: guild_entry.py:41
fatal
void fatal(enum fatal_error err)
Definition: utils.cpp:590
create_archetype
object * create_archetype(const char *name)
Definition: arch.cpp:278
diamondslots.message
string message
Definition: diamondslots.py:57
BITMASK_VALID
#define BITMASK_VALID
Definition: events.h:66
struct_dialog_reply::reply
char * reply
Definition: dialog.h:17
dialog.h
struct_dialog_message
Definition: dialog.h:26
get_dialog_message
int get_dialog_message(object *op, const char *text, struct_dialog_message **message, struct_dialog_reply **reply)
Definition: dialog.cpp:233
object_find_by_arch_name
object * object_find_by_arch_name(const object *who, const char *name)
Definition: object.cpp:4252
rt_question
@ rt_question
Definition: dialog.h:10
give.op
op
Definition: give.py:33
define.h
CLEAR_FLAG
#define CLEAR_FLAG(xyz, p)
Definition: define.h:225
TRUE
#define TRUE
Definition: compat.h:11
replace.current
current
Definition: replace.py:64
OUT_OF_MEMORY
@ OUT_OF_MEMORY
Definition: define.h:48
re_cmp
const char * re_cmp(const char *, const char *)
Definition: re-cmp.cpp:68
free_dialog_information
void free_dialog_information(object *op)
Definition: dialog.cpp:34
matches
static int matches(const char *exp, const char *text)
Definition: dialog.cpp:81
NPC_DIALOG_ARCH
const char * NPC_DIALOG_ARCH
Definition: dialog.cpp:28
object.h
llevDebug
@ llevDebug
Definition: logger.h:13
parse_dialog_information
static void parse_dialog_information(object *op)
Definition: dialog.cpp:127