Crossfire Server, Trunk
quest.cpp
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 struct quest_state {
50  int state;
55 };
56 
58 struct quest_player {
62 };
63 
65 static quest_player *player_states = NULL;
66 
74  for (const auto qs : quest->steps) {
75  if (qs->step == step)
76  return qs;
77  }
78 
79  LOG(llevError, "quest %s has no required step %d\n", quest->quest_code, step);
80  return NULL;
81 }
82 
88  quest_state *qs = static_cast<quest_state *>(calloc(1, sizeof(quest_state)));
89  if (qs == NULL)
91  return qs;
92 }
93 
99  FILE *file;
100  char final[MAX_BUF], read[MAX_BUF], data[MAX_BUF];
101  quest_state *qs = NULL, *prev = NULL;
102  int warned = 0, state;
103  quest_definition *quest = NULL;
104 
105  snprintf(final, sizeof(final), "%s/%s/%s/%s.quest", settings.localdir, settings.playerdir, pq->player_name, pq->player_name);
106 
107  file = fopen(final, "r");
108  if (!file) {
109  /* no quest yet, no big deal */
110  return;
111  }
112 
113  while (fgets(read, sizeof(read), file) != NULL) {
114  if (sscanf(read, "quest %s\n", data)) {
115  qs = get_new_quest_state();
116  qs->code = add_string(data);
118  continue;
119  }
120 
121  if (!qs) {
122  if (!warned)
123  LOG(llevError, "quest: invalid file format for %s\n", final);
124  warned = 1;
125  continue;
126  }
127 
128  if (sscanf(read, "state %d\n", &state)) {
129  qs->state = state;
130  if (quest != NULL && state != -1) {
132  if (step == NULL) {
133  LOG(llevError, "invalid quest step %d for %s in %s\n", state, quest->quest_code, final);
134  }
135  else if (step->is_completion_step)
136  qs->is_complete = 1;
137  }
138  continue;
139  }
140  if (strcmp(read, "end_quest\n") == 0) {
141  if (quest == NULL) {
142  LOG(llevDebug, "Unknown quest %s in quest file %s\n", qs->code, final);
143  free(qs);
144  } else {
145  if (prev == NULL) {
146  pq->quests = qs;
147  } else {
148  prev->next = qs;
149  }
150  prev = qs;
151  }
152  qs = NULL;
153  continue;
154  }
155  if (sscanf(read, "completed %d\n", &state)) {
156  qs->was_completed = state ? 1 : 0;
157  continue;
158  }
159 
160  LOG(llevError, "quest: invalid line in %s: %s\n", final, read);
161  }
162 
163  if (qs)
164  LOG(llevError, "quest: missing end_quest in %s\n", final);
165 
166  fclose(file);
167 }
168 
173 static void quest_write_player_data(const quest_player *pq) {
174  FILE *file;
175  OutputFile of;
176  char fname[MAX_BUF];
177  const quest_state *state;
178 
179  snprintf(fname, sizeof(fname), "%s/%s/%s/%s.quest", settings.localdir, settings.playerdir, pq->player_name, pq->player_name);
180 
181  file = of_open(&of, fname);
182  if (file == NULL) {
183  draw_ext_info(NDI_UNIQUE | NDI_ALL_DMS, 0, NULL, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_LOADSAVE, "File write error on server!");
184  return;
185  }
186 
187  state = pq->quests;
188 
189  while (state) {
190  fprintf(file, "quest %s\n", state->code);
191  fprintf(file, "state %d\n", state->state);
192  fprintf(file, "completed %d\n", state->was_completed);
193  fprintf(file, "end_quest\n");
194  state = state->next;
195  }
196 
197  if (!of_close(&of)) {
198  draw_ext_info(NDI_UNIQUE | NDI_ALL_DMS, 0, NULL, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_LOADSAVE, "File write error on server!");
199  return;
200  }
202 }
203 
211  quest_state *qs = pq->quests;
212 
213  while (qs) {
214  if (qs->code == name)
215  return qs;
216  qs = qs->next;
217  }
218 
219  return NULL;
220 }
221 
229  quest_state *qs = get_state(pq, name);
230 
231  if (!qs) {
232  qs = static_cast<quest_state *>(calloc(1, sizeof(quest_state)));
233  if (!qs)
235  qs->code = add_refcount(name);
236  if (pq->quests != NULL) {
237  quest_state *last;
238  for (last = pq->quests ; last->next != NULL; last = last->next)
239  ;
240  last->next = qs;
241  } else {
242  pq->quests = qs;
243  }
244  }
245 
246  return qs;
247 }
248 
256 
257  while (pq) {
258  if (pq->player_name == pl->ob->name)
259  return pq;
260  pq = pq->next;
261  }
262 
263  return NULL;
264 }
265 
273  quest_player *pq = get_quest(pl);
274 
275  if (!pq) {
276  pq = static_cast<quest_player *>(calloc(1, sizeof(quest_player)));
277  if (!pq)
279  pq->player_name = add_refcount(pl->ob->name);
280  pq->next = player_states;
281  player_states = pq;
283  }
284 
285  return pq;
286 }
287 
288 /* quest_set_state can call itself through the function update_quests, so it needs to be declared here */
289 static void quest_set_state(player* dm, player *pl, sstring quest_code, int state, int started);
290 
297 static int evaluate_quest_conditions(const std::vector<quest_condition *> conditions, player *pl) {
298  int current_step;
299 
300  if (conditions.empty())
301  return 0;
302  for (const auto cond : conditions) {
303  current_step = quest_get_player_state(pl, cond->quest_code);
304  if (cond->minstep < 0 && cond->maxstep < 0) {
305  /* we are checking for the quest to have been completed. */
306  if (!quest_was_completed(pl, cond->quest_code))
307  return 0;
308  } else {
309  if (current_step < cond->minstep || current_step > cond->maxstep)
310  return 0;
311  }
312  }
313  return 1;
314 }
315 
316 static void do_update(const quest_definition *quest, void *user) {
317  player *pl = (player *)user;
318  int new_step = 0;
319  for (const quest_step_definition *step : quest->steps) {
321  new_step=new_step<step->step?step->step:new_step;
322  }
323  }
324  if (new_step > 0) {
325  int current_step = quest_get_player_state(pl, quest->quest_code);
326  if (new_step > current_step) {
327  quest_set_state(NULL, pl, quest->quest_code, new_step, 0);
328  }
329  }
330 }
331 
336 static void update_quests(player *pl) {
338 }
339 
348 static void quest_set_state(player* dm, player *pl, sstring quest_code, int state, int started) {
350  quest_state *qs = get_or_create_state(pq, quest_code);
352  quest_step_definition *step;
353 
354  if (!quest) {
355  if (dm) {
356  draw_ext_info_format(NDI_UNIQUE, 0, dm->ob, MSG_TYPE_ADMIN_DM, MSG_TYPE_COMMAND_FAILURE, "Unknown quest %s!", quest_code);
357  } else {
358  LOG(llevError, "quest: asking for set_state of unknown quest %s!\n", quest_code);
359  }
360  return;
361  }
362 
363  if (!dm && state <= 0) {
364  LOG(llevDebug, "quest_set_player_state: warning: called with invalid state %d for quest %s, player %s\n", state, pl->ob->name, quest_code);
365  state = 100;
366  }
367 
368  if (started && qs->state == 0) {
369  if (!dm) {
370  LOG(llevDebug, "quest_set_player_state: warning: called for player %s not having started quest %s\n", pl->ob->name, quest_code);
371  }
372  }
373 
374  qs->state = state;
375  if (state == 0) {
376  qs->is_complete = 0;
377  return;
378  }
379 
380  step = quest_get_step(quest, state);
381  if (!step) {
382  if (dm) {
383  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);
384  } else {
385  LOG(llevError, "quest_set_player_state: couldn't find state definition %d for quest %s, player %s\n", state, quest_code, pl->ob->name);
386  }
387  return;
388  }
389 
390  if (step->is_completion_step) {
391  /* don't send an update note if the quest was already completed, this is just to show the outcome afterwards. */
392  if (!qs->is_complete)
393  draw_ext_info_format(NDI_UNIQUE|NDI_DELAYED, 0, pl->ob, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_QUESTS, "Quest %s completed.", quest->quest_title);
394  qs->was_completed = 1;
395  if (quest->quest_restart)
396  qs->state = QC_CAN_RESTART;
397  else
398  qs->is_complete =1;
399 
400  } else {
401  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);
403  }
404 
405  if (pl->socket->notifications > 0) {
407 
408  if (qs->sent_to_client) {
409  SockList_AddString(sl, "updquest ");
410  } else {
411  SockList_AddString(sl, "addquest ");
412  }
413 
414  SockList_AddInt(sl, quest->client_code);
415  if (qs->sent_to_client == 0) {
416  SockList_AddLen16Data(sl, quest->quest_title, strlen(quest->quest_title));
417  if (quest->face && !(pl->socket->faces_sent[quest->face->number]&NS_FACESENT_FACE))
418  esrv_send_face(pl->socket, quest->face, 0);
419  SockList_AddInt(sl, quest->face ? quest->face->number : 0);
420  SockList_AddChar(sl, quest->quest_restart ? 1 : 0);
421  SockList_AddInt(sl, quest->parent ? quest->parent->client_code : 0);
422  }
423 
424  SockList_AddChar(sl, (step == NULL || step->is_completion_step) ? 1 : 0);
425  assert(step != NULL);
427  strlen(step->step_description));
428 
429  qs->sent_to_client = 1;
430  }
431 
432  if (pl->has_directory)
434  update_quests(pl);
435  LOG(llevDebug, "quest_set_player_state %s %s %d\n", pl->ob->name, quest_code, state);
436 
437 }
438 
446 static void quest_display(player *pl, quest_player *pq, int showall, const char* name) {
449  const char *restart;
450  int completed_count = 0, restart_count = 0, total_count = 0, current_count = 0;
451 
452  state = pq->quests;
453  while (state) {
454  quest = quest_find_by_code(state->code);
455  if (quest->parent == NULL) {
456  total_count++;
457  /* count up the number of completed quests first */
458  if (state->state == QC_CAN_RESTART) {
459  restart_count++;
460  completed_count++;
461  } else if(state->is_complete) {
462  completed_count++;
463  }
464  }
465  state = state->next;
466  }
467  if (completed_count > 0) {
468  if (!showall) {
469  if (restart_count > 0)
471  "%s completed %d out of %zu quests, of which %d may be restarted.", name, completed_count, quests_count(false), restart_count);
472  else
474  "%s completed %d quests", name, completed_count);
475  current_count = completed_count;
476  } else {
478  "%s completed the following quests:", name);
479  state = pq->quests;
480  while (state) {
481  quest = quest_find_by_code(state->code);
482  if (quest->parent == NULL) {
483  if (state->state == QC_CAN_RESTART || state->is_complete) {
484 
485  restart = state->state == QC_CAN_RESTART ? i18n(pl->ob, " (can be replayed)") : "";
487  "(%3d) %s%s", ++current_count, quest->quest_title, restart);
488  }
489  }
490  state = state->next;
491  }
492  }
493  }
494  if (total_count > completed_count) {
496  "%s started the following quests:", name);
497  state = pq->quests;
498  while (state) {
499  quest = quest_find_by_code(state->code);
500  if (quest->parent == NULL) {
501  if (state->state != QC_CAN_RESTART && state->is_complete==0) {
502  quest = quest_find_by_code(state->code);
504  "(%3d) %s", ++current_count, quest->quest_title);
505  }
506  }
507  state = state->next;
508  }
509  }
510 }
511 
519 static void quest_list(player *pl, player *who, int showall, const char* name) {
520  quest_player *pq;
521 
522  /* ensure we load data if not loaded yet */
523  pq = get_or_create_quest(who);
524  if (!pq->quests) {
525  draw_ext_info_format(NDI_UNIQUE, 0, pl->ob, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_QUESTS, "%s didn't start any quest.", name);
526  return;
527  }
528 
529  quest_display(pl, pq, showall, name);
530 }
531 
539 static quest_state *get_quest_by_number(player *pl, int number) {
542  int questnum = 0;
543 
544  if (number <= 0 || !pq) {
545  return NULL;
546  }
547  /* count through completed quests first */
548  state = pq->quests;
549  while (state) {
550  /* count up the number of completed quests first */
551  if (!(quest_find_by_code(state->code)->parent) && (state->state == QC_CAN_RESTART || state->is_complete))
552  if (++questnum == number) return state;
553  state = state->next;
554  }
555  /* then active ones */
556  state = pq->quests;
557  while (state) {
558  /* count up the number of completed quests first */
559  if (!(quest_find_by_code(state->code)->parent) && state->state != QC_CAN_RESTART && state->is_complete ==0)
560  if (++questnum == number) return state;
561  state = state->next;
562  }
563  /* Ok, we didn't find our quest, return NULL*/
564  return NULL;
565 }
566 
574 static void quest_info(player *pl, player* who, quest_state *qs, int level) {
575  quest_definition *quest, *child;
578  const char *prefix;
579 
580  if (!qs) {
581  draw_ext_info(NDI_UNIQUE, 0, pl->ob, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_QUESTS, "Invalid quest number");
582  return;
583  }
585  if (!quest) {
586  /* already warned by quest_get */
587  draw_ext_info(NDI_UNIQUE, 0, pl->ob, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_QUESTS, "Quest: (internal error)");
588  return;
589  }
590 
592  if (QUERY_FLAG(pl->ob, FLAG_WIZ)) {
594  std::for_each(quest->steps.cbegin(), quest->steps.cend(), [&pl] (const auto &step) {
595  draw_ext_info_format(NDI_UNIQUE, 0, pl->ob, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_QUESTS, " " TAG_START "Step:" TAG_END " %d (%s)", step->step, step->step_description);
596  });
597  }
598  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);
599 
601  if (qs->state == QC_CAN_RESTART || qs->is_complete) {
602  const char *restart = "";
603  if (quest->quest_restart)
604  restart = i18n(pl->ob, " (can be replayed)");
605  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);
606  }
607  prefix = "";
608  if (qs->state != QC_CAN_RESTART) {
609  /* ie, if we are in progress or completed for a non-restartable quest */
610  if (!step) {
611  /* already warned by quest_get_step */
612  draw_ext_info_format(NDI_UNIQUE, 0, pl->ob, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_QUESTS, " \nOutcome: (invalid quest)");
613  return;
614  }
615  if (level > 0) {
616  prefix = " * ";
617  } else if (qs->is_complete)
618  prefix = "Outcome";
619  else
620  prefix = "Current Status";
622  }
623 
624  /* ok, now check all of the player's other quests for any children, and print those in order */
625  state = pq->quests;
626  while (state) {
627  child = quest_find_by_code(state->code);
628  if (child->parent == quest)
629  quest_info(pl, who, state, level+1);
630  state = state->next;
631  }
632  return;
633 }
634 
639 static void free_state(quest_player *pq) {
640  quest_state *qs = pq->quests, *next;
641 
642  while (qs) {
643  next = qs->next;
644  free_string(qs->code);
645  free(qs);
646  qs = next;
647  }
648  pq->quests = NULL;
649 }
650 
651 
652 /* public functions */
653 
662  quest_state *s = get_state(q, quest_code);
664 
665  if (!s)
666  return 0;
667 
668  if (s->state == QC_CAN_RESTART && quest && quest->quest_restart)
669  return 0;
670 
671  return s->state;
672 }
673 
680 void quest_start(player *pl, sstring quest_code, int state) {
681  quest_player *pq;
682  quest_state *q;
684 
685  quest = quest_find_by_code(quest_code);
686  if (!quest) {
687  LOG(llevError, "quest_start: requested unknown quest %s\n", quest_code);
688  return;
689  }
690  pq = get_or_create_quest(pl);
691  q = get_or_create_state(pq, quest_code);
692 
693  if (state <= 0) {
694  state = 100;
695  LOG(llevDebug, "quest_start: negative state %d for %s quest %s\n", state, pl->ob->name, quest_code);
696  }
697 
698  /* if completed already, assume the player can redo it */
699  if (q->state > 0) {
700  LOG(llevDebug, "quest_start: warning: player %s has already started quest %s\n", pl->ob->name, quest_code);
701  }
702 
703  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);
704 
705  quest_set_state(NULL, pl, quest_code, state, 0);
706 
707  /* saving state will be done in quest_set_state(). */
708 }
709 
716 void quest_set_player_state(player *pl, sstring quest_code, int state) {
717  quest_set_state(NULL, pl, quest_code, state, 1);
718 }
719 
728  quest_state *state = get_state(qp, quest_code);
729 
730  return (state && state->was_completed);
731 }
732 
738 void command_quest(object *op, const char *params) {
739  /* who to display information about, used when called in DM mode */
740  object *who;
741  const char *name;
742 
743  if (!op->contr) {
744  LOG(llevError, "command_quest called for a non player!\n");
745  return;
746  }
747 
748  if (!params || *params == '\0') {
749  command_help(op, "quest");
750  return;
751  }
752 
753  if (QUERY_FLAG(op, FLAG_WIZ)) {
754  char* dup = strdup(params);
755  char* space = strchr(dup, ' ');
756  player* other;
757  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN_DM, MSG_TYPE_COMMAND_QUESTS, "Command 'quest' called in DM mode.");
758  if (space == NULL) {
759  free(dup);
760  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN_DM, MSG_TYPE_COMMAND_FAILURE, "Please specify a player name.");
761  return;
762  }
763  params = params + (space - dup) + 1;
764  *space = '\0';
765  other = find_player_partial_name(dup);
766  if (other == NULL) {
767  draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN_DM, MSG_TYPE_COMMAND_FAILURE, "%s is not online, or ambiguous name.", dup);
768  free(dup);
769  return;
770  }
771  free(dup);
772  who = other->ob;
773  name = who->name;
774  } else {
775  who = op;
776  name = i18n(op, "You");
777  }
778 
779  if (strcmp(params, "list all") == 0) {
780  quest_list(op->contr, who->contr, 1, name);
781  return;
782  }
783 
784  if (strcmp(params, "list") == 0) {
785  quest_list(op->contr, who->contr, 0, name);
786  return;
787  }
788 
789  if (strncmp(params, "info ", 5) == 0) {
790  int number = atoi(params+5);
791  quest_info(op->contr, who->contr, get_quest_by_number(who->contr, number), 0);
792  return;
793  }
794 
795  /*
796  * Quest display for clients using the quest system, similar to 'info' above
797  * but using the (shared) quest's client_code instead of the (player unique) index.
798  */
799  if (strncmp(params, "info_c ", 7) == 0) {
800  int number = atoi(params+7);
801  quest_player *qp = get_quest(who->contr);
802  quest_state *qs = qp ? qp->quests : NULL;
803  while (qs) {
805  if (q && q->client_code == (uint32_t)number) {
806  break;
807  }
808  qs = qs->next;
809  }
810  if (qs) {
811  quest_info(op->contr, who->contr, qs, 0);
812  return;
813  }
815  return;
816  }
817 
818  if (QUERY_FLAG(op, FLAG_WIZ) && strncmp(params, "set ", 4) == 0) {
819  char *dup = strdup(params + 4);
820  char *space = strrchr(dup, ' ');
821  int state, number;
822  quest_state* q;
823  if (space == NULL) {
824  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN_DM, MSG_TYPE_COMMAND_FAILURE, "Syntax is: quest (player name) (quest number) (state).");
825  free(dup);
826  return;
827  }
828  *space = '\0';
829  number = atoi(dup);
830  q = get_quest_by_number(who->contr, number);
831  if (q == NULL) {
832  draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN_DM, MSG_TYPE_COMMAND_FAILURE, "Invalid quest number %d.", number);
833  free(dup);
834  return;
835  }
836  state = atoi(space + 1);
837  quest_set_state(op->contr, who->contr, q->code, state, 0);
838  free(dup);
840  return;
841  }
842 
843  command_help(op, "quest");
844 }
845 
847 struct dump {
849  int level;
850 };
856 static void output_quests(const quest_definition *quest, void *user) {
857  dump *d = (dump *)user;
858  if (d->parent != quest->parent)
859  return;
860 
861  char prefix[MAX_BUF];
862  prefix[0] = '\0';
863  for (int i = 0; i < d->level; i++) {
864  strncat(prefix, "-", MAX_BUF - 1);
865  }
866  prefix[MAX_BUF - 1] = '\0';
867 
868  fprintf(logfile, "%s%s - %s - %zu steps (%srestartable)\n", prefix, quest->quest_code, quest->quest_title, quest->steps.size(), quest->quest_restart ? "" : "not ");
869 
870  dump r;
871  r.parent = quest;
872  r.level = d->level + 1;
874 }
875 
880 void dump_quests(void) {
881  dump d;
882  d.parent = NULL;
883  d.level = 0;
885  exit(0);
886 }
887 
891 void free_quest(void) {
893 
894  while (pq) {
895  next = pq->next;
896  free_state(pq);
898  free(pq);
899  pq = next;
900  }
901  player_states = NULL;
902 }
903 
910  quest_player *states = NULL;
911  quest_state *state = NULL;
912  SockList sl;
913  size_t size;
915  quest_step_definition *step;
916 
917  if (pl->socket->notifications < 1)
918  return;
919 
920  states = get_or_create_quest(pl);
921 
922  SockList_Init(&sl);
923  SockList_AddString(&sl, "addquest ");
924  for (state = states->quests; state != NULL; state = state->next) {
925 
926  quest = quest_get_by_code(state->code);
927  if (state->state == -1)
928  step = NULL;
929  else
930  step = quest_get_step(quest, state->state);
931 
932  size = 2 + (2 + strlen(quest->quest_title)) + 4 + 1 + (2 + (step != NULL ? strlen(step->step_description) : 0));
933 
934  if (SockList_Avail(&sl) < size) {
935  Send_With_Handling(pl->socket, &sl);
936  SockList_Reset(&sl);
937  SockList_AddString(&sl, "addquest ");
938  }
939 
940  SockList_AddInt(&sl, quest->client_code);
941  SockList_AddLen16Data(&sl, quest->quest_title, strlen(quest->quest_title));
942  if (quest->face && !(pl->socket->faces_sent[quest->face->number]&NS_FACESENT_FACE))
943  esrv_send_face(pl->socket, quest->face, 0);
944  SockList_AddInt(&sl, quest->face ? quest->face->number : 0);
945  SockList_AddChar(&sl, quest->quest_restart ? 1 : 0);
946  SockList_AddInt(&sl, quest->parent ? quest->parent->client_code : 0);
947  SockList_AddChar(&sl, (step == NULL || step->is_completion_step) ? 1 : 0);
948  if (step != NULL)
949  SockList_AddLen16Data(&sl, step->step_description, strlen(step->step_description));
950  else
951  SockList_AddShort(&sl, 0);
952 
953  state->sent_to_client = 1;
954  }
955 
956  Send_With_Handling(pl->socket, &sl);
957  SockList_Term(&sl);
958 }
959 
968  quest_player *qp = get_quest(pl);
969  if (qp != NULL && qp->quests != NULL) {
971  }
972 }
give.next
def next
Definition: give.py:44
output_file.h
SockList_AddInt
void SockList_AddInt(SockList *sl, uint32_t data)
Definition: lowlevel.cpp:124
global.h
NS_FACESENT_FACE
#define NS_FACESENT_FACE
Definition: newserver.h:137
castle_read.prefix
string prefix
Definition: castle_read.py:31
settings
struct Settings settings
Definition: init.cpp:138
output_quests
static void output_quests(const quest_definition *quest, void *user)
Definition: quest.cpp:856
MSG_TYPE_COMMAND_SUCCESS
#define MSG_TYPE_COMMAND_SUCCESS
Definition: newclient.h:530
llevError
@ llevError
Definition: logger.h:11
quest_for_each
void quest_for_each(quest_op op, void *user)
Definition: assets.cpp:540
LOG
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.cpp:51
of_close
int of_close(OutputFile *of)
Definition: output_file.cpp:61
of_open
FILE * of_open(OutputFile *of, const char *fname)
Definition: output_file.cpp:30
player
Definition: player.h:105
get_or_create_quest
static quest_player * get_or_create_quest(player *pl)
Definition: quest.cpp:272
QUERY_FLAG
#define QUERY_FLAG(xyz, p)
Definition: define.h:226
quest_write_player_data
static void quest_write_player_data(const quest_player *pq)
Definition: quest.cpp:173
get_new_quest_state
static quest_state * get_new_quest_state(void)
Definition: quest.cpp:87
quest_first_player_save
void quest_first_player_save(player *pl)
Definition: quest.cpp:967
quests_count
static int quests_count
Definition: mapper.cpp:891
SockList_AddString
void SockList_AddString(SockList *sl, const char *data)
Definition: lowlevel.cpp:154
quest_set_state
static void quest_set_state(player *dm, player *pl, sstring quest_code, int state, int started)
Definition: quest.cpp:348
player::ob
object * ob
Definition: player.h:176
quest_info
static void quest_info(player *pl, player *who, quest_state *qs, int level)
Definition: quest.cpp:574
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,...) PRINTF_ARGS(6
mad_mage_user.file
file
Definition: mad_mage_user.py:15
NDI_ALL_DMS
#define NDI_ALL_DMS
Definition: newclient.h:264
quest_step_definition::step
int step
Definition: quest.h:30
MSG_TYPE_COMMAND_QUESTS
#define MSG_TYPE_COMMAND_QUESTS
Definition: newclient.h:527
get_quest
static quest_player * get_quest(player *pl)
Definition: quest.cpp:254
quest_state::was_completed
int was_completed
Definition: quest.cpp:51
dump::parent
const quest_definition * parent
Definition: quest.cpp:848
get_quest_by_number
static quest_state * get_quest_by_number(player *pl, int number)
Definition: quest.cpp:539
SockList_AddLen16Data
void SockList_AddLen16Data(SockList *sl, const void *data, size_t len)
Definition: lowlevel.cpp:188
SockList_Reset
void SockList_Reset(SockList *sl)
Definition: lowlevel.cpp:71
free_state
static void free_state(quest_player *pq)
Definition: quest.cpp:639
quest_step_definition
Definition: quest.h:29
MSG_TYPE_COMMAND
#define MSG_TYPE_COMMAND
Definition: newclient.h:404
quest_state::sent_to_client
int sent_to_client
Definition: quest.cpp:53
SockList_Avail
size_t SockList_Avail(const SockList *sl)
Definition: lowlevel.cpp:243
MSG_TYPE_ADMIN_DM
#define MSG_TYPE_ADMIN_DM
Definition: newclient.h:497
quest
Definition: quest.py:1
autojail.who
who
Definition: autojail.py:3
item.q
q
Definition: item.py:32
add_refcount
sstring add_refcount(sstring str)
Definition: shstr.cpp:210
quest_step_definition::is_completion_step
int is_completion_step
Definition: quest.h:32
esrv_send_face
void esrv_send_face(socket_struct *ns, const Face *face, int nocache)
Definition: image.cpp:72
do_update
static void do_update(const quest_definition *quest, void *user)
Definition: quest.cpp:316
add_string
sstring add_string(const char *str)
Definition: shstr.cpp:124
SockList_AddShort
void SockList_AddShort(SockList *sl, uint16_t data)
Definition: lowlevel.cpp:113
NDI_DELAYED
#define NDI_DELAYED
Definition: newclient.h:269
SockList_AddChar
void SockList_AddChar(SockList *sl, unsigned char c)
Definition: lowlevel.cpp:103
dump_quests
void dump_quests(void)
Definition: quest.cpp:880
dump
Definition: quest.cpp:847
quest_get_step
static quest_step_definition * quest_get_step(quest_definition *quest, int step)
Definition: quest.cpp:73
quest_definition::parent
struct quest_definition * parent
Definition: quest.h:47
update_quests
static void update_quests(player *pl)
Definition: quest.cpp:336
quest_list
static void quest_list(player *pl, player *who, int showall, const char *name)
Definition: quest.cpp:519
command_help
void command_help(object *op, const char *params)
Definition: c_misc.cpp:1772
navar-midane_time.data
data
Definition: navar-midane_time.py:11
sstring
const typedef char * sstring
Definition: global.h:47
sproto.h
quest_state::is_complete
int is_complete
Definition: quest.cpp:52
logfile
FILE * logfile
Definition: init.cpp:114
quest_player::quests
quest_state * quests
Definition: quest.cpp:60
quest_get_by_code
quest_definition * quest_get_by_code(sstring code)
Definition: assets.cpp:531
SockList_Init
void SockList_Init(SockList *sl)
Definition: lowlevel.cpp:52
quest_display
static void quest_display(player *pl, quest_player *pq, int showall, const char *name)
Definition: quest.cpp:446
get_or_create_state
static quest_state * get_or_create_state(quest_player *pq, sstring name)
Definition: quest.cpp:228
fatal
void fatal(enum fatal_error err)
Definition: utils.cpp:570
quest_set_player_state
void quest_set_player_state(player *pl, sstring quest_code, int state)
Definition: quest.cpp:716
MAX_BUF
#define MAX_BUF
Definition: define.h:35
MSG_TYPE_ADMIN_LOADSAVE
#define MSG_TYPE_ADMIN_LOADSAVE
Definition: newclient.h:499
free_string
void free_string(sstring str)
Definition: shstr.cpp:280
quest_send_initial_states
void quest_send_initial_states(player *pl)
Definition: quest.cpp:909
SockList_Term
void SockList_Term(SockList *sl)
Definition: lowlevel.cpp:62
Settings::playerdir
const char * playerdir
Definition: global.h:250
quest_get_player_state
int quest_get_player_state(player *pl, sstring quest_code)
Definition: quest.cpp:660
TAG_END
#define TAG_END
Definition: quest.cpp:42
MSG_TYPE_COMMAND_FAILURE
#define MSG_TYPE_COMMAND_FAILURE
Definition: newclient.h:531
quest_find_by_code
quest_definition * quest_find_by_code(sstring code)
Definition: assets.cpp:520
FLAG_WIZ
#define FLAG_WIZ
Definition: define.h:231
quest.h
NDI_UNIQUE
#define NDI_UNIQUE
Definition: newclient.h:262
quest_start
void quest_start(player *pl, sstring quest_code, int state)
Definition: quest.cpp:680
quest_state
Definition: quest.cpp:48
QC_CAN_RESTART
#define QC_CAN_RESTART
Definition: quest.cpp:45
quest_read_player_data
static void quest_read_player_data(quest_player *pq)
Definition: quest.cpp:98
quest_player::player_name
sstring player_name
Definition: quest.cpp:59
give.op
op
Definition: give.py:33
quest_definition
Definition: quest.h:37
quest_state::code
sstring code
Definition: quest.cpp:49
get_state
static quest_state * get_state(quest_player *pq, sstring name)
Definition: quest.cpp:210
quest_player::next
quest_player * next
Definition: quest.cpp:61
quest_was_completed
int quest_was_completed(player *pl, sstring quest_code)
Definition: quest.cpp:726
roll-o-matic.params
params
Definition: roll-o-matic.py:193
assets.h
quest_state::state
int state
Definition: quest.cpp:50
find_player_partial_name
player * find_player_partial_name(const char *plname)
Definition: player.cpp:114
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.cpp:308
quest_player
Definition: quest.cpp:58
command_quest
void command_quest(object *op, const char *params)
Definition: quest.cpp:738
quest_step_definition::conditions
std::vector< quest_condition * > conditions
Definition: quest.h:33
player_get_delayed_buffer
SockList * player_get_delayed_buffer(player *pl)
Definition: player.cpp:4465
quest.state
state
Definition: quest.py:13
quest_step_definition::step_description
sstring step_description
Definition: quest.h:31
dump::level
int level
Definition: quest.cpp:849
TAG_START
#define TAG_START
Definition: quest.cpp:41
OUT_OF_MEMORY
@ OUT_OF_MEMORY
Definition: define.h:48
altar_valkyrie.pl
pl
Definition: altar_valkyrie.py:28
Send_With_Handling
void Send_With_Handling(socket_struct *ns, SockList *sl)
Definition: lowlevel.cpp:444
MSG_TYPE_ADMIN
#define MSG_TYPE_ADMIN
Definition: newclient.h:402
SockList
Definition: newclient.h:681
free_quest
void free_quest(void)
Definition: quest.cpp:891
quest_state::next
quest_state * next
Definition: quest.cpp:54
player_states
static quest_player * player_states
Definition: quest.cpp:65
ring_occidental_mages.r
r
Definition: ring_occidental_mages.py:6
llevDebug
@ llevDebug
Definition: logger.h:13
evaluate_quest_conditions
static int evaluate_quest_conditions(const std::vector< quest_condition * > conditions, player *pl)
Definition: quest.cpp:297
i18n
const char * i18n(const object *who, const char *code)
Definition: languages.cpp:42
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:249