Crossfire Server, Trunk
quest.c
Go to the documentation of this file.
1 /*
2  * Crossfire -- cooperative multi-player graphical RPG and adventure game
3  *
4  * Copyright (c) 1999-2014 Mark Wedel and the Crossfire Development Team
5  * Copyright (c) 1992 Frank Tore Johansen
6  *
7  * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are
8  * welcome to redistribute it under certain conditions. For details, please
9  * see COPYING and LICENSE.
10  *
11  * The authors can be reached via e-mail at <crossfire@metalforge.org>.
12  */
13 
28 #include "global.h"
29 
30 #include <assert.h>
31 #include <stdlib.h>
32 #include <string.h>
33 
34 #include "output_file.h"
35 #include "sproto.h"
36 
37 #include "quest.h"
38 #include "assets.h"
39 
40 /* Media tags for information messages prefix. */
41 #define TAG_START "[color=#aa55ff]"
42 #define TAG_END "[/color]"
43 
45 #define QC_CAN_RESTART -1
46 
48 typedef struct quest_state {
50  int state;
54  struct quest_state *next;
55 } quest_state;
56 
58 typedef struct quest_player {
60  struct quest_state *quests;
61  struct quest_player *next;
62 } quest_player;
63 
65 static quest_player *player_states = NULL;
66 
74  quest_step_definition *qsd = quest->steps;
75 
76  while (qsd) {
77  if (qsd->step == step)
78  return qsd;
79 
80  qsd = qsd->next;
81  }
82 
83  LOG(llevError, "quest %s has no required step %d\n", quest->quest_code, step);
84  return NULL;
85 }
86 
92  quest_state *qs = calloc(1, sizeof(quest_state));
93  if (qs == NULL)
95  return qs;
96 }
97 
103  FILE *file;
104  char final[MAX_BUF], read[MAX_BUF], data[MAX_BUF];
105  quest_state *qs = NULL, *prev = NULL;
106  int warned = 0, state;
107  quest_definition *quest = NULL;
108 
109  snprintf(final, sizeof(final), "%s/%s/%s/%s.quest", settings.localdir, settings.playerdir, pq->player_name, pq->player_name);
110 
111  file = fopen(final, "r");
112  if (!file) {
113  /* no quest yet, no big deal */
114  return;
115  }
116 
117  while (fgets(read, sizeof(read), file) != NULL) {
118  if (sscanf(read, "quest %s\n", data)) {
119  qs = get_new_quest_state();
120  qs->code = add_string(data);
122  continue;
123  }
124 
125  if (!qs) {
126  if (!warned)
127  LOG(llevError, "quest: invalid file format for %s\n", final);
128  warned = 1;
129  continue;
130  }
131 
132  if (sscanf(read, "state %d\n", &state)) {
133  qs->state = state;
134  if (quest != NULL && state != -1) {
136  if (step == NULL) {
137  LOG(llevError, "invalid quest step %d for %s in %s\n", state, quest->quest_code, final);
138  }
139  else if (step->is_completion_step)
140  qs->is_complete = 1;
141  }
142  continue;
143  }
144  if (strcmp(read, "end_quest\n") == 0) {
145  if (quest == NULL) {
146  LOG(llevDebug, "Unknown quest %s in quest file %s\n", qs->code, final);
147  free(qs);
148  } else {
149  if (prev == NULL) {
150  pq->quests = qs;
151  } else {
152  prev->next = qs;
153  }
154  prev = qs;
155  }
156  qs = NULL;
157  continue;
158  }
159  if (sscanf(read, "completed %d\n", &state)) {
160  qs->was_completed = state ? 1 : 0;
161  continue;
162  }
163 
164  LOG(llevError, "quest: invalid line in %s: %s\n", final, read);
165  }
166 
167  if (qs)
168  LOG(llevError, "quest: missing end_quest in %s\n", final);
169 
170  fclose(file);
171 }
172 
177 static void quest_write_player_data(const quest_player *pq) {
178  FILE *file;
179  OutputFile of;
180  char fname[MAX_BUF];
181  const quest_state *state;
182 
183  snprintf(fname, sizeof(fname), "%s/%s/%s/%s.quest", settings.localdir, settings.playerdir, pq->player_name, pq->player_name);
184 
185  file = of_open(&of, fname);
186  if (file == NULL) {
187  draw_ext_info(NDI_UNIQUE | NDI_ALL_DMS, 0, NULL, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_LOADSAVE, "File write error on server!");
188  return;
189  }
190 
191  state = pq->quests;
192 
193  while (state) {
194  fprintf(file, "quest %s\n", state->code);
195  fprintf(file, "state %d\n", state->state);
196  fprintf(file, "completed %d\n", state->was_completed);
197  fprintf(file, "end_quest\n");
198  state = state->next;
199  }
200 
201  if (!of_close(&of)) {
202  draw_ext_info(NDI_UNIQUE | NDI_ALL_DMS, 0, NULL, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_LOADSAVE, "File write error on server!");
203  return;
204  }
206 }
207 
215  quest_state *qs = pq->quests;
216 
217  while (qs) {
218  if (qs->code == name)
219  return qs;
220  qs = qs->next;
221  }
222 
223  return NULL;
224 }
225 
233  quest_state *qs = get_state(pq, name);
234 
235  if (!qs) {
236  qs = calloc(1, sizeof(quest_state));
237  if (!qs)
239  qs->code = add_refcount(name);
240  if (pq->quests != NULL) {
241  quest_state *last;
242  for (last = pq->quests ; last->next != NULL; last = last->next)
243  ;
244  last->next = qs;
245  } else {
246  pq->quests = qs;
247  }
248  }
249 
250  return qs;
251 }
252 
260 
261  while (pq) {
262  if (pq->player_name == pl->ob->name)
263  return pq;
264  pq = pq->next;
265  }
266 
267  return NULL;
268 }
269 
277  quest_player *pq = get_quest(pl);
278 
279  if (!pq) {
280  pq = calloc(1, sizeof(quest_player));
281  if (!pq)
283  pq->player_name = add_refcount(pl->ob->name);
284  pq->next = player_states;
285  player_states = pq;
287  }
288 
289  return pq;
290 }
291 
292 /* quest_set_state can call itself through the function update_quests, so it needs to be declared here */
293 static void quest_set_state(player* dm, player *pl, sstring quest_code, int state, int started);
294 
301 static int evaluate_quest_conditions(const quest_condition *condition, player *pl) {
302  const quest_condition *cond;
303  int current_step;
304 
305  if (!condition)
306  return 0;
307  cond = condition;
308  while (cond) {
309  current_step = quest_get_player_state(pl, cond->quest_code);
310  if (cond->minstep < 0 && cond->maxstep < 0) {
311  /* we are checking for the quest to have been completed. */
312  if (!quest_was_completed(pl, cond->quest_code))
313  return 0;
314  } else {
315  if (current_step < cond->minstep || current_step > cond->maxstep)
316  return 0;
317  }
318  cond = cond->next;
319  }
320  return 1;
321 }
322 
323 static void do_update(const quest_definition *quest, void *user) {
324  player *pl = (player *)user;
325  const quest_step_definition *step;
326  int new_step = 0;
327  step = quest->steps;
328  while (step) {
329  if (step->conditions)
331  new_step=new_step<step->step?step->step:new_step;
332  }
333  step = step->next;
334  }
335  if (new_step > 0) {
336  int current_step = quest_get_player_state(pl, quest->quest_code);
337  if (new_step > current_step) {
338  quest_set_state(NULL, pl, quest->quest_code, new_step, 0);
339  }
340  }
341 }
342 
347 static void update_quests(player *pl) {
349 }
350 
359 static void quest_set_state(player* dm, player *pl, sstring quest_code, int state, int started) {
361  quest_state *qs = get_or_create_state(pq, quest_code);
363  quest_step_definition *step;
364 
365  if (!quest) {
366  if (dm) {
367  draw_ext_info_format(NDI_UNIQUE, 0, dm->ob, MSG_TYPE_ADMIN_DM, MSG_TYPE_COMMAND_FAILURE, "Unknown quest %s!", quest_code);
368  } else {
369  LOG(llevError, "quest: asking for set_state of unknown quest %s!\n", quest_code);
370  }
371  return;
372  }
373 
374  if (!dm && state <= 0) {
375  LOG(llevDebug, "quest_set_player_state: warning: called with invalid state %d for quest %s, player %s\n", state, pl->ob->name, quest_code);
376  state = 100;
377  }
378 
379  if (started && qs->state == 0) {
380  if (!dm) {
381  LOG(llevDebug, "quest_set_player_state: warning: called for player %s not having started quest %s\n", pl->ob->name, quest_code);
382  }
383  }
384 
385  qs->state = state;
386  if (state == 0) {
387  qs->is_complete = 0;
388  return;
389  }
390 
391  step = quest_get_step(quest, state);
392  if (!step) {
393  if (dm) {
394  draw_ext_info_format(NDI_UNIQUE, 0, dm->ob, MSG_TYPE_ADMIN_DM, MSG_TYPE_COMMAND_FAILURE, "Couldn't find state definition %d for quest %s", state, quest_code);
395  } else {
396  LOG(llevError, "quest_set_player_state: couldn't find state definition %d for quest %s, player %s\n", state, quest_code, pl->ob->name);
397  }
398  return;
399  }
400 
401  if (step->is_completion_step) {
402  /* don't send an update note if the quest was already completed, this is just to show the outcome afterwards. */
403  if (!qs->is_complete)
404  draw_ext_info_format(NDI_UNIQUE|NDI_DELAYED, 0, pl->ob, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_QUESTS, "Quest %s completed.", quest->quest_title);
405  qs->was_completed = 1;
406  if (quest->quest_restart)
407  qs->state = QC_CAN_RESTART;
408  else
409  qs->is_complete =1;
410 
411  } else {
412  draw_ext_info_format(NDI_UNIQUE|NDI_DELAYED, 0, pl->ob, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_QUESTS, "New objective for the quest '%s':", quest->quest_title);
414  }
415 
416  if (pl->socket.notifications > 0) {
418 
419  if (qs->sent_to_client) {
420  SockList_AddString(sl, "updquest ");
421  } else {
422  SockList_AddString(sl, "addquest ");
423  }
424 
425  SockList_AddInt(sl, quest->client_code);
426  if (qs->sent_to_client == 0) {
427  SockList_AddLen16Data(sl, quest->quest_title, strlen(quest->quest_title));
428  if (quest->face && !(pl->socket.faces_sent[quest->face->number]&NS_FACESENT_FACE))
429  esrv_send_face(&pl->socket, quest->face, 0);
430  SockList_AddInt(sl, quest->face ? quest->face->number : 0);
431  SockList_AddChar(sl, quest->quest_restart ? 1 : 0);
432  SockList_AddInt(sl, quest->parent ? quest->parent->client_code : 0);
433  }
434 
435  SockList_AddChar(sl, (step == NULL || step->is_completion_step) ? 1 : 0);
436  assert(step != NULL);
438  strlen(step->step_description));
439 
440  qs->sent_to_client = 1;
441  }
442 
443  if (pl->has_directory)
445  update_quests(pl);
446  LOG(llevDebug, "quest_set_player_state %s %s %d\n", pl->ob->name, quest_code, state);
447 
448 }
449 
457 static void quest_display(player *pl, quest_player *pq, int showall, const char* name) {
460  const char *restart;
461  int completed_count = 0, restart_count = 0, total_count = 0, current_count = 0;
462 
463  state = pq->quests;
464  while (state) {
465  quest = quest_find_by_code(state->code);
466  if (quest->parent == NULL) {
467  total_count++;
468  /* count up the number of completed quests first */
469  if (state->state == QC_CAN_RESTART) {
470  restart_count++;
471  completed_count++;
472  } else if(state->is_complete) {
473  completed_count++;
474  }
475  }
476  state = state->next;
477  }
478  if (completed_count > 0) {
479  if (!showall) {
480  if (restart_count > 0)
482  "%s completed %d out of %d quests, of which %d may be restarted.", name, completed_count, quests_count(false), restart_count);
483  else
485  "%s completed %d quests", name, completed_count);
486  current_count = completed_count;
487  } else {
489  "%s completed the following quests:", name);
490  state = pq->quests;
491  while (state) {
492  quest = quest_find_by_code(state->code);
493  if (quest->parent == NULL) {
494  if (state->state == QC_CAN_RESTART || state->is_complete) {
495 
496  restart = state->state == QC_CAN_RESTART ? i18n(pl->ob, " (can be replayed)") : "";
498  "(%3d) %s%s", ++current_count, quest->quest_title, restart);
499  }
500  }
501  state = state->next;
502  }
503  }
504  }
505  if (total_count > completed_count) {
507  "%s started the following quests:", name);
508  state = pq->quests;
509  while (state) {
510  quest = quest_find_by_code(state->code);
511  if (quest->parent == NULL) {
512  if (state->state != QC_CAN_RESTART && state->is_complete==0) {
513  quest = quest_find_by_code(state->code);
515  "(%3d) %s", ++current_count, quest->quest_title);
516  }
517  }
518  state = state->next;
519  }
520  }
521 }
522 
530 static void quest_list(player *pl, player *who, int showall, const char* name) {
531  quest_player *pq;
532 
533  /* ensure we load data if not loaded yet */
534  pq = get_or_create_quest(who);
535  if (!pq->quests) {
536  draw_ext_info_format(NDI_UNIQUE, 0, pl->ob, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_QUESTS, "%s didn't start any quest.", name);
537  return;
538  }
539 
540  quest_display(pl, pq, showall, name);
541 }
542 
550 static quest_state *get_quest_by_number(player *pl, int number) {
553  int questnum = 0;
554 
555  if (number <= 0 || !pq) {
556  return NULL;
557  }
558  /* count through completed quests first */
559  state = pq->quests;
560  while (state) {
561  /* count up the number of completed quests first */
562  if (!(quest_find_by_code(state->code)->parent) && (state->state == QC_CAN_RESTART || state->is_complete))
563  if (++questnum == number) return state;
564  state = state->next;
565  }
566  /* then active ones */
567  state = pq->quests;
568  while (state) {
569  /* count up the number of completed quests first */
570  if (!(quest_find_by_code(state->code)->parent) && state->state != QC_CAN_RESTART && state->is_complete ==0)
571  if (++questnum == number) return state;
572  state = state->next;
573  }
574  /* Ok, we didn't find our quest, return NULL*/
575  return NULL;
576 }
577 
585 static void quest_info(player *pl, player* who, quest_state *qs, int level) {
586  quest_definition *quest, *child;
589  quest_step_definition *step;
590  const char *prefix;
591 
592  if (!qs) {
593  draw_ext_info(NDI_UNIQUE, 0, pl->ob, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_QUESTS, "Invalid quest number");
594  return;
595  }
597  if (!quest) {
598  /* already warned by quest_get */
599  draw_ext_info(NDI_UNIQUE, 0, pl->ob, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_QUESTS, "Quest: (internal error)");
600  return;
601  }
602 
604  if (QUERY_FLAG(pl->ob, FLAG_WIZ)) {
606  for (step = quest->steps; step != NULL; step = step->next) {
608  }
609  }
610  draw_ext_info_format(NDI_UNIQUE, 0, pl->ob, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_QUESTS, TAG_START "Description:" TAG_END " %s", quest->quest_description);
611 
612  step = quest_get_step(quest, qs->state);
613  if (qs->state == QC_CAN_RESTART || qs->is_complete) {
614  const char *restart = "";
615  if (quest->quest_restart)
616  restart = i18n(pl->ob, " (can be replayed)");
617  draw_ext_info_format(NDI_UNIQUE, 0, pl->ob, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_QUESTS, TAG_START "This quest has been completed%s.[/color]", restart);
618  }
619  prefix = "";
620  if (qs->state != QC_CAN_RESTART) {
621  /* ie, if we are in progress or completed for a non-restartable quest */
622  if (!step) {
623  /* already warned by quest_get_step */
624  draw_ext_info_format(NDI_UNIQUE, 0, pl->ob, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_QUESTS, " \nOutcome: (invalid quest)");
625  return;
626  }
627  if (level > 0) {
628  prefix = " * ";
629  } else if (qs->is_complete)
630  prefix = "Outcome";
631  else
632  prefix = "Current Status";
634  }
635 
636  /* ok, now check all of the player's other quests for any children, and print those in order */
637  state = pq->quests;
638  while (state) {
639  child = quest_find_by_code(state->code);
640  if (child->parent == quest)
641  quest_info(pl, who, state, level+1);
642  state = state->next;
643  }
644  return;
645 }
646 
651 static void free_state(quest_player *pq) {
652  quest_state *qs = pq->quests, *next;
653 
654  while (qs) {
655  next = qs->next;
656  free_string(qs->code);
657  free(qs);
658  qs = next;
659  }
660  pq->quests = NULL;
661 }
662 
663 
664 /* public functions */
665 
674  quest_state *s = get_state(q, quest_code);
676 
677  if (!s)
678  return 0;
679 
680  if (s->state == QC_CAN_RESTART && quest && quest->quest_restart)
681  return 0;
682 
683  return s->state;
684 }
685 
692 void quest_start(player *pl, sstring quest_code, int state) {
693  quest_player *pq;
694  quest_state *q;
696 
697  quest = quest_find_by_code(quest_code);
698  if (!quest) {
699  LOG(llevError, "quest_start: requested unknown quest %s\n", quest_code);
700  return;
701  }
702  pq = get_or_create_quest(pl);
703  q = get_or_create_state(pq, quest_code);
704 
705  if (state <= 0) {
706  state = 100;
707  LOG(llevDebug, "quest_start: negative state %d for %s quest %s\n", state, pl->ob->name, quest_code);
708  }
709 
710  /* if completed already, assume the player can redo it */
711  if (q->state > 0) {
712  LOG(llevDebug, "quest_start: warning: player %s has already started quest %s\n", pl->ob->name, quest_code);
713  }
714 
715  draw_ext_info_format(NDI_UNIQUE | NDI_DELAYED, 0, pl->ob, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_QUESTS, "New quest started: %s", quest->quest_title);
716 
717  quest_set_state(NULL, pl, quest_code, state, 0);
718 
719  /* saving state will be done in quest_set_state(). */
720 }
721 
728 void quest_set_player_state(player *pl, sstring quest_code, int state) {
729  quest_set_state(NULL, pl, quest_code, state, 1);
730 }
731 
740  quest_state *state = get_state(qp, quest_code);
741 
742  return (state && state->was_completed);
743 }
744 
750 void command_quest(object *op, const char *params) {
751  /* who to display information about, used when called in DM mode */
752  object *who;
753  const char *name;
754 
755  if (!op->contr) {
756  LOG(llevError, "command_quest called for a non player!\n");
757  return;
758  }
759 
760  if (!params || *params == '\0') {
761  command_help(op, "quest");
762  return;
763  }
764 
765  if (QUERY_FLAG(op, FLAG_WIZ)) {
766  char* dup = strdup(params);
767  char* space = strchr(dup, ' ');
768  player* other;
769  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN_DM, MSG_TYPE_COMMAND_QUESTS, "Command 'quest' called in DM mode.");
770  if (space == NULL) {
771  free(dup);
772  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN_DM, MSG_TYPE_COMMAND_FAILURE, "Please specify a player name.");
773  return;
774  }
775  params = params + (space - dup) + 1;
776  *space = '\0';
777  other = find_player_partial_name(dup);
778  if (other == NULL) {
779  draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN_DM, MSG_TYPE_COMMAND_FAILURE, "%s is not online, or ambiguous name.", dup);
780  free(dup);
781  return;
782  }
783  free(dup);
784  who = other->ob;
785  name = who->name;
786  } else {
787  who = op;
788  name = i18n(op, "You");
789  }
790 
791  if (strcmp(params, "list all") == 0) {
792  quest_list(op->contr, who->contr, 1, name);
793  return;
794  }
795 
796  if (strcmp(params, "list") == 0) {
797  quest_list(op->contr, who->contr, 0, name);
798  return;
799  }
800 
801  if (strncmp(params, "info ", 5) == 0) {
802  int number = atoi(params+5);
803  quest_info(op->contr, who->contr, get_quest_by_number(who->contr, number), 0);
804  return;
805  }
806 
807  /*
808  * Quest display for clients using the quest system, similar to 'info' above
809  * but using the (shared) quest's client_code instead of the (player unique) index.
810  */
811  if (strncmp(params, "info_c ", 7) == 0) {
812  int number = atoi(params+7);
813  quest_player *qp = get_quest(who->contr);
814  quest_state *qs = qp ? qp->quests : NULL;
815  while (qs) {
817  if (q && q->client_code == (uint32_t)number) {
818  break;
819  }
820  qs = qs->next;
821  }
822  if (qs) {
823  quest_info(op->contr, who->contr, qs, 0);
824  return;
825  }
827  return;
828  }
829 
830  if (QUERY_FLAG(op, FLAG_WIZ) && strncmp(params, "set ", 4) == 0) {
831  char *dup = strdup(params + 4);
832  char *space = strrchr(dup, ' ');
833  int state, number;
834  quest_state* q;
835  if (space == NULL) {
836  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN_DM, MSG_TYPE_COMMAND_FAILURE, "Syntax is: quest (player name) (quest number) (state).");
837  free(dup);
838  return;
839  }
840  *space = '\0';
841  number = atoi(dup);
842  q = get_quest_by_number(who->contr, number);
843  if (q == NULL) {
844  draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN_DM, MSG_TYPE_COMMAND_FAILURE, "Invalid quest number %d.", number);
845  free(dup);
846  return;
847  }
848  state = atoi(space + 1);
849  quest_set_state(op->contr, who->contr, q->code, state, 0);
850  free(dup);
852  return;
853  }
854 
855  command_help(op, "quest");
856 }
857 
859 typedef struct {
861  int level;
862 } dump;
868 static void output_quests(const quest_definition *quest, void *user) {
869  dump *d = (dump *)user;
870  if (d->parent != quest->parent)
871  return;
872 
873  char prefix[MAX_BUF];
874  prefix[0] = '\0';
875  for (int i = 0; i < d->level; i++) {
876  strncat(prefix, "-", MAX_BUF - 1);
877  }
878  prefix[MAX_BUF - 1] = '\0';
879 
880  int stepcount = 0;
881  quest_step_definition *step = quest->steps;
882  while (step) {
883  stepcount++;
884  step = step->next;
885  }
886 
887  fprintf(logfile, "%s%s - %s - %d steps (%srestartable)\n", prefix, quest->quest_code, quest->quest_title, stepcount, quest->quest_restart ? "" : "not ");
888 
889  dump r;
890  r.parent = quest;
891  r.level = d->level + 1;
893 }
894 
899 void dump_quests(void) {
900  dump d;
901  d.parent = NULL;
902  d.level = 0;
904  exit(0);
905 }
906 
910 void free_quest(void) {
912 
913  while (pq) {
914  next = pq->next;
915  free_state(pq);
917  free(pq);
918  pq = next;
919  }
920  player_states = NULL;
921 }
922 
929  quest_player *states = NULL;
930  quest_state *state = NULL;
931  SockList sl;
932  size_t size;
934  quest_step_definition *step;
935 
936  if (pl->socket.notifications < 1)
937  return;
938 
939  states = get_or_create_quest(pl);
940 
941  SockList_Init(&sl);
942  SockList_AddString(&sl, "addquest ");
943  for (state = states->quests; state != NULL; state = state->next) {
944 
945  quest = quest_get_by_code(state->code);
946  if (state->state == -1)
947  step = NULL;
948  else
949  step = quest_get_step(quest, state->state);
950 
951  size = 2 + (2 + strlen(quest->quest_title)) + 4 + 1 + (2 + (step != NULL ? strlen(step->step_description) : 0));
952 
953  if (SockList_Avail(&sl) < size) {
954  Send_With_Handling(&pl->socket, &sl);
955  SockList_Reset(&sl);
956  SockList_AddString(&sl, "addquest ");
957  }
958 
959  SockList_AddInt(&sl, quest->client_code);
960  SockList_AddLen16Data(&sl, quest->quest_title, strlen(quest->quest_title));
961  if (quest->face && !(pl->socket.faces_sent[quest->face->number]&NS_FACESENT_FACE))
962  esrv_send_face(&pl->socket, quest->face, 0);
963  SockList_AddInt(&sl, quest->face ? quest->face->number : 0);
964  SockList_AddChar(&sl, quest->quest_restart ? 1 : 0);
965  SockList_AddInt(&sl, quest->parent ? quest->parent->client_code : 0);
966  SockList_AddChar(&sl, (step == NULL || step->is_completion_step) ? 1 : 0);
967  if (step != NULL)
968  SockList_AddLen16Data(&sl, step->step_description, strlen(step->step_description));
969  else
970  SockList_AddShort(&sl, 0);
971 
972  state->sent_to_client = 1;
973  }
974 
975  Send_With_Handling(&pl->socket, &sl);
976  SockList_Term(&sl);
977 }
978 
987  quest_player *qp = get_quest(pl);
988  if (qp != NULL && qp->quests != NULL) {
990  }
991 }
get_quest_by_number
static quest_state * get_quest_by_number(player *pl, int number)
Definition: quest.c:550
give.next
def next
Definition: give.py:44
output_file.h
SockList_AddInt
void SockList_AddInt(SockList *sl, uint32_t data)
Definition: lowlevel.c:124
global.h
NS_FACESENT_FACE
#define NS_FACESENT_FACE
Definition: newserver.h:137
add_refcount
sstring add_refcount(sstring str)
Definition: shstr.c:210
castle_read.prefix
string prefix
Definition: castle_read.py:31
add_string
sstring add_string(const char *str)
Definition: shstr.c:124
free_state
static void free_state(quest_player *pq)
Definition: quest.c:651
quest_condition::quest_code
sstring quest_code
Definition: quest.h:24
MSG_TYPE_COMMAND_SUCCESS
#define MSG_TYPE_COMMAND_SUCCESS
Definition: newclient.h:530
llevError
@ llevError
Definition: logger.h:11
quest_set_state
static void quest_set_state(player *dm, player *pl, sstring quest_code, int state, int started)
Definition: quest.c:359
quest_for_each
void quest_for_each(quest_op op, void *user)
Definition: assets.cpp:709
quest_condition::maxstep
int maxstep
Definition: quest.h:27
do_update
static void do_update(const quest_definition *quest, void *user)
Definition: quest.c:323
QUERY_FLAG
#define QUERY_FLAG(xyz, p)
Definition: define.h:226
quest_display
static void quest_display(player *pl, quest_player *pq, int showall, const char *name)
Definition: quest.c:457
quests_count
static int quests_count
Definition: mapper.cpp:918
SockList_AddString
void SockList_AddString(SockList *sl, const char *data)
Definition: lowlevel.c:154
pl::socket
socket_struct socket
Definition: player.h:107
pl
Definition: player.h:105
dump
static int dump(const std::set< std::string > &items, const char *name)
Definition: AssetsManager.cpp:55
quest_was_completed
int quest_was_completed(player *pl, sstring quest_code)
Definition: quest.c:738
quest_info
static void quest_info(player *pl, player *who, quest_state *qs, int level)
Definition: quest.c:585
mad_mage_user.file
file
Definition: mad_mage_user.py:15
pl::ob
object * ob
Definition: player.h:176
NDI_ALL_DMS
#define NDI_ALL_DMS
Definition: newclient.h:264
quest_step_definition::step
int step
Definition: quest.h:34
MSG_TYPE_COMMAND_QUESTS
#define MSG_TYPE_COMMAND_QUESTS
Definition: newclient.h:527
quest_state::was_completed
int was_completed
Definition: quest.c:51
dump::parent
const quest_definition * parent
Definition: quest.c:860
SockList_AddLen16Data
void SockList_AddLen16Data(SockList *sl, const void *data, size_t len)
Definition: lowlevel.c:188
quest_player::next
struct quest_player * next
Definition: quest.c:61
SockList_Reset
void SockList_Reset(SockList *sl)
Definition: lowlevel.c:71
player_states
static quest_player * player_states
Definition: quest.c:65
quest_state
struct quest_state quest_state
quest_step_definition
Definition: quest.h:33
MSG_TYPE_COMMAND
#define MSG_TYPE_COMMAND
Definition: newclient.h:404
get_or_create_quest
static quest_player * get_or_create_quest(player *pl)
Definition: quest.c:276
settings
struct Settings settings
Definition: init.c:39
quest_state::sent_to_client
int sent_to_client
Definition: quest.c:53
SockList_Avail
size_t SockList_Avail(const SockList *sl)
Definition: lowlevel.c:243
MSG_TYPE_ADMIN_DM
#define MSG_TYPE_ADMIN_DM
Definition: newclient.h:497
free_string
void free_string(sstring str)
Definition: shstr.c:280
quest
Definition: quest.py:1
autojail.who
who
Definition: autojail.py:3
item.q
q
Definition: item.py:32
quest_step_definition::next
struct quest_step_definition * next
Definition: quest.h:37
obj::name
sstring name
Definition: object.h:314
quest_step_definition::is_completion_step
int is_completion_step
Definition: quest.h:36
esrv_send_face
void esrv_send_face(socket_struct *ns, const Face *face, int nocache)
Definition: image.c:71
of_close
int of_close(OutputFile *of)
Definition: output_file.c:61
quest_player::quests
struct quest_state * quests
Definition: quest.c:60
fatal
void fatal(enum fatal_error err)
Definition: utils.c:580
SockList_AddShort
void SockList_AddShort(SockList *sl, uint16_t data)
Definition: lowlevel.c:113
NDI_DELAYED
#define NDI_DELAYED
Definition: newclient.h:269
SockList_AddChar
void SockList_AddChar(SockList *sl, unsigned char c)
Definition: lowlevel.c:103
dump
Definition: quest.c:859
quest_definition::parent
struct quest_definition * parent
Definition: quest.h:52
get_state
static quest_state * get_state(quest_player *pq, sstring name)
Definition: quest.c:214
command_help
void command_help(object *op, const char *params)
Definition: c_misc.c:1769
navar-midane_time.data
data
Definition: navar-midane_time.py:11
get_or_create_state
static quest_state * get_or_create_state(quest_player *pq, sstring name)
Definition: quest.c:232
sstring
const typedef char * sstring
Definition: global.h:40
quest_read_player_data
static void quest_read_player_data(quest_player *pq)
Definition: quest.c:102
sproto.h
quest_state::is_complete
int is_complete
Definition: quest.c:52
quest_get_by_code
quest_definition * quest_get_by_code(sstring code)
Definition: assets.cpp:700
logfile
EXTERN FILE * logfile
Definition: global.h:134
SockList_Init
void SockList_Init(SockList *sl)
Definition: lowlevel.c:52
TAG_END
#define TAG_END
Definition: quest.c:42
MAX_BUF
#define MAX_BUF
Definition: define.h:35
MSG_TYPE_ADMIN_LOADSAVE
#define MSG_TYPE_ADMIN_LOADSAVE
Definition: newclient.h:499
free_quest
void free_quest(void)
Definition: quest.c:910
SockList_Term
void SockList_Term(SockList *sl)
Definition: lowlevel.c:62
Settings::playerdir
const char * playerdir
Definition: global.h:245
quest_condition::minstep
int minstep
Definition: quest.h:25
MSG_TYPE_COMMAND_FAILURE
#define MSG_TYPE_COMMAND_FAILURE
Definition: newclient.h:531
get_quest
static quest_player * get_quest(player *pl)
Definition: quest.c:258
quest_find_by_code
quest_definition * quest_find_by_code(sstring code)
Definition: assets.cpp:689
quest_first_player_save
void quest_first_player_save(player *pl)
Definition: quest.c:986
FLAG_WIZ
#define FLAG_WIZ
Definition: define.h:231
quest.h
NDI_UNIQUE
#define NDI_UNIQUE
Definition: newclient.h:262
dump_quests
void dump_quests(void)
Definition: quest.c:899
quest_state::next
struct quest_state * next
Definition: quest.c:54
quest_state
Definition: quest.c:48
quest_player
struct quest_player quest_player
quest_list
static void quest_list(player *pl, player *who, int showall, const char *name)
Definition: quest.c:530
quest_step_definition::conditions
quest_condition * conditions
Definition: quest.h:38
LOG
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.c:51
quest_condition
Definition: quest.h:23
get_new_quest_state
static quest_state * get_new_quest_state(void)
Definition: quest.c:91
of_open
FILE * of_open(OutputFile *of, const char *fname)
Definition: output_file.c:30
quest_player::player_name
sstring player_name
Definition: quest.c:59
give.op
op
Definition: give.py:33
pl::has_directory
uint32_t has_directory
Definition: player.h:149
quest_definition
Definition: quest.h:42
quest_state::code
sstring code
Definition: quest.c:49
roll-o-matic.params
params
Definition: roll-o-matic.py:193
assets.h
quest_send_initial_states
void quest_send_initial_states(player *pl)
Definition: quest.c:928
output_quests
static void output_quests(const quest_definition *quest, void *user)
Definition: quest.c:868
quest_state::state
int state
Definition: quest.c:50
find_player_partial_name
player * find_player_partial_name(const char *plname)
Definition: player.c:111
socket_struct::faces_sent
uint8_t * faces_sent
Definition: newserver.h:96
quest_set_player_state
void quest_set_player_state(player *pl, sstring quest_code, int state)
Definition: quest.c:728
draw_ext_info
void draw_ext_info(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *message)
Definition: main.c:309
quest_player
Definition: quest.c:58
i18n
const char * i18n(const object *who, const char *code)
Definition: languages.c:55
command_quest
void command_quest(object *op, const char *params)
Definition: quest.c:750
player_get_delayed_buffer
SockList * player_get_delayed_buffer(player *pl)
Definition: player.c:4452
quest.state
state
Definition: quest.py:13
quest_step_definition::step_description
sstring step_description
Definition: quest.h:35
quest_write_player_data
static void quest_write_player_data(const quest_player *pq)
Definition: quest.c:177
socket_struct::notifications
uint16_t notifications
Definition: newserver.h:129
quest_condition::next
struct quest_condition * next
Definition: quest.h:29
dump::level
int level
Definition: quest.c:861
OUT_OF_MEMORY
@ OUT_OF_MEMORY
Definition: define.h:48
quest_get_step
static quest_step_definition * quest_get_step(quest_definition *quest, int step)
Definition: quest.c:73
quest_get_player_state
int quest_get_player_state(player *pl, sstring quest_code)
Definition: quest.c:672
Send_With_Handling
void Send_With_Handling(socket_struct *ns, SockList *sl)
Definition: lowlevel.c:440
MSG_TYPE_ADMIN
#define MSG_TYPE_ADMIN
Definition: newclient.h:402
SockList
Definition: newclient.h:681
quest_start
void quest_start(player *pl, sstring quest_code, int state)
Definition: quest.c:692
TAG_START
#define TAG_START
Definition: quest.c:41
evaluate_quest_conditions
static int evaluate_quest_conditions(const quest_condition *condition, player *pl)
Definition: quest.c:301
draw_ext_info_format
void draw_ext_info_format(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *format,...)
Definition: main.c:319
ring_occidental_mages.r
r
Definition: ring_occidental_mages.py:6
QC_CAN_RESTART
#define QC_CAN_RESTART
Definition: quest.c:45
llevDebug
@ llevDebug
Definition: logger.h:13
update_quests
static void update_quests(player *pl)
Definition: quest.c:347
give.name
name
Definition: give.py:27
OutputFile
Definition: output_file.h:41
level
Definition: level.py:1
Settings::localdir
const char * localdir
Definition: global.h:244