Crossfire Server, Trunk  R20513
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 
38 #define QC_CAN_RESTART -1
39 
41 typedef struct quest_state {
43  int state;
47  struct quest_state *next;
48 } quest_state;
49 
51 typedef struct quest_player {
53  struct quest_state *quests;
54  struct quest_player *next;
55 } quest_player;
56 
58 static quest_player *player_states = NULL;
59 
61 typedef struct quest_condition {
63  int minstep;
65  int maxstep;
69 
71 typedef struct quest_step_definition {
72  int step;
74  int is_completion_step:1;
78 
80 typedef struct quest_definition {
85  int face;
91 
92 static int quests_loaded = 0;
93 static quest_definition *quests = NULL;
100  quest_step_definition *step = calloc(1, sizeof(quest_step_definition));
101  if (!step)
103  return step;
104 }
105 
111  quest_condition *cond = calloc(1, sizeof(quest_condition));
112  if (!cond)
114  return cond;
115 }
116 
117 
123  quest_definition *quest = calloc(1, sizeof(quest_definition));
124  if (!quest)
126  return quest;
127 }
128 
136  quest_definition *quest;
137 
138  quest = quests;
139  while (quest) {
140  if (quest->quest_code == code)
141  return quest;
142 
143  quest = quest->next;
144  }
145  return NULL;
146 }
147 
154 #define QUESTFILE_NEXTQUEST 0
155 #define QUESTFILE_QUEST 1
156 #define QUESTFILE_QUESTDESC 2
157 #define QUESTFILE_STEP 3
158 #define QUESTFILE_STEPDESC 4
159 #define QUESTFILE_STEPCOND 5
161 
162 
168 static int load_quests_from_file(const char *filename) {
169  int i, in = QUESTFILE_NEXTQUEST, condition_parsed;
170  int minstep, maxstep;
171  char namedquest[MAX_BUF];
172  quest_definition *quest = NULL;
173  quest_condition *cond = NULL;
174  char includefile[MAX_BUF];
175  sstring questname;
176  quest_step_definition *step = NULL;
177  char final[MAX_BUF], read[MAX_BUF];
178  FILE *file;
179  StringBuffer *buf;
180 
181  int loaded_quests =0, found =0;
182  snprintf(final, sizeof(final), "%s/%s/%s", settings.datadir, settings.mapdir, filename);
183  file = fopen(final, "r");
184  if (!file) {
185  LOG(llevError, "Can't open %s for reading quests\n", filename);
186  return -1;
187  }
188 
189  while (fgets(read, sizeof(read), file) != NULL) {
190  if (in == QUESTFILE_STEPCOND) {
191  if (strcmp(read, "end_setwhen\n") == 0) {
192  in = QUESTFILE_STEP;
193  continue;
194  }
195  /* we are reading in a list of conditions for the 'setwhen' block for a quest step
196  * There will be one entry per line, containing the quest, and the steps that it applies to.
197  * This may be expressed as one of the following
198  * questcode 20 (the quest questcode must be at step 20)
199  * questcode <=20 (the quest questcode must not be beyond step 20)
200  * questcode 10-20 (the quest questcode must be between steps 10 and 20)
201  * questcode finished (the quest questcode must have been completed)
202  */
203 
204  minstep = 0;
205  maxstep = 0;
206  condition_parsed = 0;
207  namedquest[0]='\0';
208  if (sscanf(read, "%s %d-%d\n", namedquest, &minstep, &maxstep)!=3) {
209  if (sscanf(read, "%s <=%d\n", namedquest, &maxstep)== 2) {
210  minstep=0;
211  condition_parsed =1;
212  } else if (sscanf(read, "%s %d\n", namedquest, &minstep)==2) {
213  maxstep = minstep;
214  condition_parsed =1;
215  } else if (strstr(read, "finished")) {
216  if (sscanf(read, "%s finished\n", namedquest)==1) {
217  minstep = maxstep = -1;
218  condition_parsed =1;
219  }
220  }
221  } else
222  condition_parsed =1;
223  if (!condition_parsed) {
224  LOG(llevError, "Invalid line '%s' in setwhen block for quest %s=n", read, quest->quest_code);
225  continue;
226  }
227 
228  cond = quest_create_condition();
229  cond->minstep = minstep;
230  cond->maxstep = maxstep;
231  cond->quest_code = add_string(namedquest);
232  cond->next = step->conditions;
233  step->conditions = cond;
234  LOG(llevDebug, "condition added for step %d of quest %s, looking for quest %s between steps %d and %d\n",
235  step->step, quest->quest_code, cond->quest_code, cond->minstep, cond->maxstep);
236  continue;
237  }
238  if (in == QUESTFILE_STEPDESC) {
239  if (strcmp(read, "end_description\n") == 0) {
240  char *message;
241 
242  in = QUESTFILE_STEP;
243 
244  message = stringbuffer_finish(buf);
245  buf = NULL;
246 
247  step->step_description = add_string(message);
248  free(message);
249 
250  continue;
251  }
252 
253  stringbuffer_append_string(buf, read);
254  continue;
255  }
256 
257  if (in == QUESTFILE_STEP) {
258  if (strcmp(read, "end_step\n") == 0) {
259  step = NULL;
260  in = QUESTFILE_QUEST;
261  continue;
262  }
263  if (strcmp(read, "finishes_quest\n") == 0) {
264  step->is_completion_step=1;
265  continue;
266  }
267  if (strcmp(read, "description\n") == 0) {
268  buf = stringbuffer_new();
269  in = QUESTFILE_STEPDESC;
270  continue;
271  }
272  if (strcmp(read, "setwhen\n") == 0) {
273  in = QUESTFILE_STEPCOND;
274  continue;
275  }
276  LOG(llevError, "quests: invalid line %s in definition of quest %s in file %s!\n",
277  read, quest->quest_code, filename);
278  continue;
279  }
280 
281  if (in == QUESTFILE_QUESTDESC) {
282  if (strcmp(read, "end_description\n") == 0) {
283  char *message;
284 
285  in = QUESTFILE_QUEST;
286 
287  message = stringbuffer_finish(buf);
288  buf = NULL;
289 
290  quest->quest_description = add_string(message);
291  free(message);
292 
293  continue;
294  }
295  stringbuffer_append_string(buf, read);
296  continue;
297  }
298 
299  if (in == QUESTFILE_QUEST) {
300  if (strcmp(read, "end_quest\n") == 0) {
301  quest = NULL;
302  in = QUESTFILE_NEXTQUEST;
303  continue;
304  }
305 
306  if (strcmp(read, "description\n") == 0) {
307  in = QUESTFILE_QUESTDESC;
308  buf = stringbuffer_new();
309  continue;
310  }
311 
312  if (strncmp(read, "title ", 6) == 0) {
313  read[strlen(read) - 1] = '\0';
314  quest->quest_title = add_string(read + 6);
315  continue;
316  }
317 
318  if (sscanf(read, "step %d\n", &i)) {
319  step = quest_create_step();
320  step->step = i;
321  step->next = quest->steps;
322  quest->steps = step;
323  in = QUESTFILE_STEP;
324  continue;
325  }
326 
327  if (sscanf(read, "restart %d\n", &i)) {
328  quest->quest_restart = i;
329  continue;
330  }
331  if (strncmp(read, "parent ", 7) == 0) {
332  read[strlen(read) - 1] = '\0';
333  questname = add_string(read + 7);
334  if (!quest_get_by_code(questname)) {
335  LOG(llevError, "Quest %s lists %s, as a parent, but this hasn't been defined\n", quest->quest_code, questname);
336  } else {
337  quest->parent = quest_get_by_code(questname);
338  }
339  free_string(questname);
340  continue;
341  }
342 
343  if (strncmp(read, "face ", 5) == 0) {
344  int face;
345  read[strlen(read) - 1] = '\0';
346  face = find_face(read + 5, 0);
347  if (face == 0) {
348  LOG(llevError, "Quest %s has invalid face %s.\n", quest->quest_code, read + 5);
349  } else {
350  quest->face = face;
351  }
352  continue;
353  }
354  }
355 
356  if (read[0] == '#')
357  continue;
358 
359  if (strncmp(read, "quest ", 6) == 0) {
360  quest = quest_create_definition();
361  read[strlen(read) - 1] = '\0';
362  quest->quest_code = add_string(read + 6);
363  if (quest_get_by_code(quest->quest_code)) {
364  LOG(llevError, "Quest %s is listed in file %s, but this quest has already been defined\n", quest->quest_code, filename);
365  }
366  /* Set a default face, which will be overwritten if a face is defined. */
367  quest->face = find_face("quest_generic.111", 0);
368  quest->next = quests;
369  if (quests != NULL)
370  quest->client_code = quests->client_code + 1;
371  else
372  quest->client_code = 1;
373  quests = quest;
374  in = QUESTFILE_QUEST;
375  loaded_quests++;
376  continue;
377  }
378  if (sscanf(read, "include %s\n", includefile)) {
379  char inc_path[HUGE_BUF];
380  path_combine_and_normalize(filename, includefile, inc_path, sizeof(inc_path));
381  found = load_quests_from_file(inc_path);
382  if (found >=0) {
383  LOG(llevDebug, "loaded %d quests from file %s\n", found, inc_path);
384  loaded_quests += found;
385  } else {
386  LOG(llevError, "Failed to load quests from file %s\n", inc_path);
387  }
388  continue;
389  }
390 
391  if (strcmp(read, "\n") == 0)
392  continue;
393 
394  LOG(llevError, "quest: invalid file format for %s, I don't know what to do with the line %s\n", final, read);
395  }
396 
397  fclose(file);
398 
399  if (in != 0) {
400  LOG(llevError, "quest: quest definition file %s read in, ends with state %d\n", final, in);
401 
402  /* The buffer may not have been freed. */
403  if (buf != NULL) {
404  stringbuffer_finish(buf);
405  }
406  }
407 
408  return loaded_quests;
409 }
410 
412 static void quest_load_definitions(void) {
413  int found = 0;
414  if (quests_loaded)
415  return;
416  quests_loaded = 1;
417  found = load_quests_from_file("world.quests");
418  if (found >= 0) {
419  LOG(llevInfo, "%d quests found.\n", found);
420  } else {
421  LOG(llevError, "Quest Loading Failed\n");
422  }
423 }
424 
432  quest_step_definition *qsd = quest->steps;
433 
434  while (qsd) {
435  if (qsd->step == step)
436  return qsd;
437 
438  qsd = qsd->next;
439  }
440 
441  LOG(llevError, "quest %s has no required step %d\n", quest->quest_code, step);
442  return NULL;
443 }
444 
451  quest_definition *quest;
452 
454 
455  quest = quest_get_by_code(code);
456  if (!quest) {
457  LOG(llevError, "quest %s required but not found!\n", code);
458  return NULL;
459  }
460  return quest;
461 }
462 
468  quest_state *qs = calloc(1, sizeof(quest_state));
469  if (qs == NULL)
471  return qs;
472 }
473 
479  FILE *file;
480  char final[MAX_BUF], read[MAX_BUF], data[MAX_BUF];
481  quest_state *qs = NULL, *prev = NULL;
482  int warned = 0, state;
483  quest_definition *quest = NULL;
484 
485  /* needed, so we can check ending steps. */
487 
488  snprintf(final, sizeof(final), "%s/%s/%s/%s.quest", settings.localdir, settings.playerdir, pq->player_name, pq->player_name);
489 
490  file = fopen(final, "r");
491  if (!file) {
492  /* no quest yet, no big deal */
493  return;
494  }
495 
496  while (fgets(read, sizeof(read), file) != NULL) {
497  if (sscanf(read, "quest %s\n", data)) {
498  qs = get_new_quest_state();
499  qs->code = add_string(data);
500  quest = quest_get_by_code(qs->code);
501  continue;
502  }
503 
504  if (!qs) {
505  if (!warned)
506  LOG(llevError, "quest: invalid file format for %s\n", final);
507  warned = 1;
508  continue;
509  }
510 
511  if (sscanf(read, "state %d\n", &state)) {
512  qs->state = state;
513  if (quest != NULL && state != -1) {
515  if (step == NULL) {
516  LOG(llevError, "invalid quest step %d for %s in %s\n", state, quest->quest_code, final);
517  }
518  else if (step->is_completion_step)
519  qs->is_complete = 1;
520  }
521  continue;
522  }
523  if (strcmp(read, "end_quest\n") == 0) {
524  if (quest == NULL) {
525  LOG(llevDebug, "Unknown quest %s in quest file %s\n", qs->code, final);
526  free(qs);
527  } else {
528  if (prev == NULL) {
529  pq->quests = qs;
530  } else {
531  prev->next = qs;
532  }
533  prev = qs;
534  }
535  qs = NULL;
536  continue;
537  }
538  if (sscanf(read, "completed %d\n", &state)) {
539  qs->was_completed = state ? 1 : 0;
540  continue;
541  }
542 
543  LOG(llevError, "quest: invalid line in %s: %s\n", final, read);
544  }
545 
546  if (qs)
547  LOG(llevError, "quest: missing end_quest in %s\n", final);
548 
549  fclose(file);
550 }
551 
556 static void quest_write_player_data(const quest_player *pq) {
557  FILE *file;
558  OutputFile of;
559  char fname[MAX_BUF];
560  const quest_state *state;
561 
562  snprintf(fname, sizeof(fname), "%s/%s/%s/%s.quest", settings.localdir, settings.playerdir, pq->player_name, pq->player_name);
563 
564  file = of_open(&of, fname);
565  if (file == NULL) {
566  draw_ext_info(NDI_UNIQUE | NDI_ALL_DMS, 0, NULL, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_LOADSAVE, "File write error on server!");
567  return;
568  }
569 
570  state = pq->quests;
571 
572  while (state) {
573  fprintf(file, "quest %s\n", state->code);
574  fprintf(file, "state %d\n", state->state);
575  fprintf(file, "completed %d\n", state->was_completed);
576  fprintf(file, "end_quest\n");
577  state = state->next;
578  }
579 
580  if (!of_close(&of)) {
581  draw_ext_info(NDI_UNIQUE | NDI_ALL_DMS, 0, NULL, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_LOADSAVE, "File write error on server!");
582  return;
583  }
585 }
586 
594  quest_state *qs = pq->quests;
595 
596  while (qs) {
597  if (qs->code == name)
598  return qs;
599  qs = qs->next;
600  }
601 
602  return NULL;
603 }
604 
612  quest_state *qs = get_state(pq, name);
613 
614  if (!qs) {
615  qs = calloc(1, sizeof(quest_state));
616  if (!qs)
618  qs->code = add_refcount(name);
619  if (pq->quests != NULL) {
620  quest_state *last;
621  for (last = pq->quests ; last->next != NULL; last = last->next)
622  ;
623  last->next = qs;
624  } else {
625  pq->quests = qs;
626  }
627  }
628 
629  return qs;
630 }
631 
639 
640  while (pq) {
641  if (pq->player_name == pl->ob->name)
642  return pq;
643  pq = pq->next;
644  }
645 
646  return NULL;
647 }
648 
656  quest_player *pq = get_quest(pl);
657 
658  if (!pq) {
659  pq = calloc(1, sizeof(quest_player));
660  if (!pq)
662  pq->player_name = add_refcount(pl->ob->name);
663  pq->next = player_states;
664  player_states = pq;
666  }
667 
668  return pq;
669 }
670 
671 /* quest_set_state can call itself through the function update_quests, so it needs to be declared here */
672 static void quest_set_state(player* dm, player *pl, sstring quest_code, int state, int started);
673 
680 static int evaluate_quest_conditions(const quest_condition *condition, player *pl) {
681  const quest_condition *cond;
682  int current_step;
683 
684  if (!condition)
685  return 0;
686  cond = condition;
687  while (cond) {
688  current_step = quest_get_player_state(pl, cond->quest_code);
689  if (cond->minstep < 0 && cond->maxstep < 0) {
690  /* we are checking for the quest to have been completed. */
691  if (!quest_was_completed(pl, cond->quest_code))
692  return 0;
693  } else {
694  if (current_step < cond->minstep || current_step > cond->maxstep)
695  return 0;
696  }
697  cond = cond->next;
698  }
699  return 1;
700 }
701 
706 static void update_quests(player *pl) {
707  const quest_definition *quest;
708  const quest_step_definition *step;
709 
710  /* we are going to check the conditions for every step, and then find the highest
711  * numbered step for which all conditions match, this will then be updated if that
712  * is a later stage than the player is at currently.
713  */
714  int new_step, current_step;
715  quest = quests;
716  while (quest) {
717  new_step=0;
718  step = quest->steps;
719  while (step) {
720  if (step->conditions)
721  if (evaluate_quest_conditions(step->conditions, pl)) {
722  new_step=new_step<step->step?step->step:new_step;
723  }
724  step = step->next;
725  }
726  if (new_step > 0) {
727  current_step = quest_get_player_state(pl, quest->quest_code);
728  if (new_step > current_step) {
729  quest_set_state(NULL, pl, quest->quest_code, new_step, 0);
730  }
731  }
732  quest = quest->next;
733  }
734 }
735 
744 static void quest_set_state(player* dm, player *pl, sstring quest_code, int state, int started) {
746  quest_state *qs = get_or_create_state(pq, quest_code);
747  quest_definition *quest = quest_get(quest_code);
748  quest_step_definition *step;
749 
750  if (!quest) {
751  if (dm) {
752  draw_ext_info_format(NDI_UNIQUE, 0, dm->ob, MSG_TYPE_ADMIN_DM, MSG_TYPE_COMMAND_FAILURE, "Unknown quest %s!", quest_code);
753  } else {
754  LOG(llevError, "quest: asking for set_state of unknown quest %s!\n", quest_code);
755  }
756  return;
757  }
758 
759  if (state <= 0) {
760  if (!dm) {
761  LOG(llevDebug, "quest_set_player_state: warning: called with invalid state %d for quest %s, player %s\n", state, pl->ob->name, quest_code);
762  }
763  state = 100;
764  }
765 
766  step = quest_get_step(quest, state);
767  if (!step) {
768  if (dm) {
769  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);
770  } else {
771  LOG(llevError, "quest_set_player_state: couldn't find state definition %d for quest %s, player %s\n", state, quest_code, pl->ob->name);
772  }
773  return;
774  }
775 
776  if (started && qs->state == 0) {
777  if (!dm) {
778  LOG(llevDebug, "quest_set_player_state: warning: called for player %s not having started quest %s\n", pl->ob->name, quest_code);
779  }
780  }
781 
782  qs->state = state;
783  if (step->is_completion_step) {
784  /* don't send an update note if the quest was already completed, this is just to show the outcome afterwards. */
785  if (!qs->is_complete)
786  draw_ext_info_format(NDI_UNIQUE, 0, pl->ob, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_INFO, "Quest %s completed.", quest->quest_title);
787  qs->was_completed = 1;
788  if (quest->quest_restart)
789  qs->state = QC_CAN_RESTART;
790  else
791  qs->is_complete =1;
792 
793  } else {
794  draw_ext_info_format(NDI_UNIQUE, 0, pl->ob, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_INFO, "New objective for the quest '%s':", quest->quest_title);
796  }
797 
798  if (pl->socket.notifications > 0) {
799  SockList sl;
800  SockList_Init(&sl);
801 
802  if (qs->sent_to_client) {
803  SockList_AddString(&sl, "updquest ");
804  } else {
805  SockList_AddString(&sl, "addquest ");
806  }
807 
808  SockList_AddInt(&sl, quest->client_code);
809  if (qs->sent_to_client == 0) {
810  SockList_AddLen16Data(&sl, quest->quest_title, strlen(quest->quest_title));
811  if (quest->face && !(pl->socket.faces_sent[quest->face]&NS_FACESENT_FACE))
812  esrv_send_face(&pl->socket, quest->face, 0);
813  SockList_AddInt(&sl, quest->face);
814  SockList_AddChar(&sl, quest->quest_restart ? 1 : 0);
815  SockList_AddInt(&sl, quest->parent ? quest->parent->client_code : 0);
816  }
817 
818  SockList_AddChar(&sl, (step == NULL || step->is_completion_step) ? 1 : 0);
819  assert(step != NULL);
821  strlen(step->step_description));
822 
823  Send_With_Handling(&pl->socket, &sl);
824  SockList_Term(&sl);
825 
826  qs->sent_to_client = 1;
827  }
828 
829  if (pl->has_directory)
831  update_quests(pl);
832  LOG(llevDebug, "quest_set_player_state %s %s %d\n", pl->ob->name, quest_code, state);
833 
834 }
835 
843 static void quest_display(player *pl, quest_player *pq, int showall, const char* name) {
845  quest_definition *quest;
846  const char *restart;
847  int completed_count = 0, restart_count = 0, total_count = 0, current_count = 0;
848 
849  state = pq->quests;
850  while (state) {
851  quest = quest_get(state->code);
852  if (quest->parent == NULL) {
853  total_count++;
854  /* count up the number of completed quests first */
855  if (state->state == QC_CAN_RESTART) {
856  restart_count++;
857  completed_count++;
858  } else if(state->is_complete) {
859  completed_count++;
860  }
861  }
862  state = state->next;
863  }
864  if (completed_count > 0) {
865  if (!showall) {
866  if (restart_count > 0)
868  "%s completed %d quests, of which %d may be restarted", name, completed_count, restart_count);
869  else
871  "%s completed %d quests", name, completed_count);
872  current_count = completed_count;
873  } else {
875  "%s completed the following quests:", name);
876  state = pq->quests;
877  while (state) {
878  quest = quest_get(state->code);
879  if (quest->parent == NULL) {
880  if (state->state == QC_CAN_RESTART || state->is_complete) {
881 
882  restart = state->state == QC_CAN_RESTART?" (can be replayed)":"";
884  "(%3d) %s%s", ++current_count, quest->quest_title, restart);
885  }
886  }
887  state = state->next;
888  }
889  }
890  }
891  if (total_count > completed_count) {
893  "%s started the following quests:", name);
894  state = pq->quests;
895  while (state) {
896  quest = quest_get(state->code);
897  if (quest->parent == NULL) {
898  if (state->state != QC_CAN_RESTART && state->is_complete==0) {
899  quest = quest_get(state->code);
901  "(%3d) %s", ++current_count, quest->quest_title);
902  }
903  }
904  state = state->next;
905  }
906  }
907 }
908 
916 static void quest_list(player *pl, player *who, int showall, const char* name) {
917  quest_player *pq;
918 
919  /* ensure we load data if not loaded yet */
920  pq = get_or_create_quest(who);
921  if (!pq->quests) {
922  draw_ext_info_format(NDI_UNIQUE, 0, pl->ob, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_INFO, "%s didn't start any quest.", name);
923  return;
924  }
925 
926  quest_display(pl, pq, showall, name);
927 }
928 
933 static void quest_help(player *pl) {
934  if (QUERY_FLAG(pl->ob, FLAG_WIZ)) {
935  draw_ext_info(NDI_UNIQUE, 0, pl->ob, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_INFO, "DM Quest commands:");
936  draw_ext_info(NDI_UNIQUE, 0, pl->ob, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_INFO, " - (player name) list: displays quests the player is currently attempting, add 'all' to show completed quests also");
937  draw_ext_info(NDI_UNIQUE, 0, pl->ob, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_INFO, " - (player name) info: displays information about the specified (by number) quest");
938  draw_ext_info(NDI_UNIQUE, 0, pl->ob, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_INFO, " - (player name) set (quest code) (state): set the state of the specified quest");
939  draw_ext_info(NDI_UNIQUE, 0, pl->ob, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_INFO, "Note: (player name) may be a partial name as long as it isn't ambiguous. The player must be online.");
940  } else {
941  draw_ext_info(NDI_UNIQUE, 0, pl->ob, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_INFO, "Quest commands:");
942  draw_ext_info(NDI_UNIQUE, 0, pl->ob, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_INFO, " - list: displays quests you are currently attempting add 'all' to show completed quests also");
943  draw_ext_info(NDI_UNIQUE, 0, pl->ob, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_INFO, " - info: displays information about the specified (by number) quest");
944  }
945 }
946 
954 static quest_state *get_quest_by_number(player *pl, int number) {
957  int questnum = 0;
958 
959  if (number <= 0 || !pq) {
960  return NULL;
961  }
962  /* count through completed quests first */
963  state = pq->quests;
964  while (state) {
965  /* count up the number of completed quests first */
966  if (!(quest_get(state->code)->parent) && (state->state == QC_CAN_RESTART || state->is_complete))
967  if (++questnum == number) return state;
968  state = state->next;
969  }
970  /* then active ones */
971  state = pq->quests;
972  while (state) {
973  /* count up the number of completed quests first */
974  if (!(quest_get(state->code)->parent) && state->state != QC_CAN_RESTART && state->is_complete ==0)
975  if (++questnum == number) return state;
976  state = state->next;
977  }
978  /* Ok, we didn't find our quest, return NULL*/
979  return NULL;
980 }
981 
989 static void quest_info(player *pl, player* who, quest_state *qs, int level) {
990  quest_definition *quest, *child;
993  quest_step_definition *step;
994  const char *prefix;
995 
996  if (!qs) {
997  draw_ext_info(NDI_UNIQUE, 0, pl->ob, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_INFO, "Invalid quest number");
998  return;
999  }
1000  quest = quest_get(qs->code);
1001  if (!quest) {
1002  /* already warned by quest_get */
1003  draw_ext_info(NDI_UNIQUE, 0, pl->ob, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_INFO, "Quest: (internal error)");
1004  return;
1005  }
1006 
1008  if (QUERY_FLAG(pl->ob, FLAG_WIZ)) {
1010  for (step = quest->steps; step != NULL; step = step->next) {
1012  }
1013  }
1015 
1016  step = quest_get_step(quest, qs->state);
1017  if (qs->state == QC_CAN_RESTART || qs->is_complete) {
1018  const char *restart = "";
1019  if (quest->quest_restart)
1020  restart = " (can be replayed)";
1021  draw_ext_info_format(NDI_UNIQUE, 0, pl->ob, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_INFO, "This quest has been completed%s.", restart);
1022  }
1023  prefix = "";
1024  if (qs->state != QC_CAN_RESTART) {
1025  /* ie, if we are in progress or completed for a non-restartable quest */
1026  if (!step) {
1027  /* already warned by quest_get_step */
1028  draw_ext_info_format(NDI_UNIQUE, 0, pl->ob, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_INFO, " \nOutcome: (invalid quest)");
1029  return;
1030  }
1031  if (level > 0) {
1032  prefix = " * ";
1033  } else if (qs->is_complete)
1034  prefix = "Outcome";
1035  else
1036  prefix = "Current Status";
1038  }
1039 
1040  /* ok, now check all of the player's other quests for any children, and print those in order */
1041  state = pq->quests;
1042  while (state) {
1043  child = quest_get(state->code);
1044  if (child->parent == quest)
1045  quest_info(pl, who, state, level+1);
1046  state = state->next;
1047  }
1048  return;
1049 }
1050 
1055 static void free_state(quest_player *pq) {
1056  quest_state *qs = pq->quests, *next;
1057 
1058  while (qs) {
1059  next = qs->next;
1060  free_string(qs->code);
1061  free(qs);
1062  qs = next;
1063  }
1064  pq->quests = NULL;
1065 }
1066 
1067 
1068 /* public functions */
1069 
1078  quest_state *s = get_state(q, quest_code);
1079  quest_definition *quest = quest_get(quest_code);
1080 
1081  if (!s)
1082  return 0;
1083 
1084  if (s->state == QC_CAN_RESTART && quest && quest->quest_restart)
1085  return 0;
1086 
1087  return s->state;
1088 }
1089 
1097  quest_player *pq;
1098  quest_state *q;
1099  quest_definition *quest;
1100 
1101  quest = quest_get(quest_code);
1102  if (!quest) {
1103  LOG(llevError, "quest_start: requested unknown quest %s\n", quest_code);
1104  return;
1105  }
1106  pq = get_or_create_quest(pl);
1107  q = get_or_create_state(pq, quest_code);
1108 
1109  if (state <= 0) {
1110  state = 100;
1111  LOG(llevDebug, "quest_start: negative state %d for %s quest %s\n", state, pl->ob->name, quest_code);
1112  }
1113 
1114  /* if completed already, assume the player can redo it */
1115  if (q->state > 0) {
1116  LOG(llevDebug, "quest_start: warning: player %s has already started quest %s\n", pl->ob->name, quest_code);
1117  }
1118 
1119  draw_ext_info_format(NDI_UNIQUE, 0, pl->ob, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_INFO, "New quest started: %s", quest->quest_title);
1120 
1121  quest_set_state(NULL, pl, quest_code, state, 0);
1122 
1123  /* saving state will be done in quest_set_state(). */
1124 }
1125 
1133  quest_set_state(NULL, pl, quest_code, state, 1);
1134 }
1135 
1144  quest_state *state = get_state(qp, quest_code);
1145 
1146  return (state && state->was_completed);
1147 }
1148 
1154 void command_quest(object *op, const char *params) {
1155  /* who to display information about, used when called in DM mode */
1156  object *who;
1157  const char *name;
1158 
1159  if (!op->contr) {
1160  LOG(llevError, "command_quest called for a non player!\n");
1161  return;
1162  }
1163 
1164  if (!params || *params == '\0') {
1165  quest_help(op->contr);
1166  return;
1167  }
1168 
1169  if (QUERY_FLAG(op, FLAG_WIZ)) {
1170  char* dup = strdup(params);
1171  char* space = strchr(dup, ' ');
1172  player* other;
1173  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN_DM, MSG_TYPE_COMMAND_INFO, "Command 'quest' called in DM mode.");
1174  if (space == NULL) {
1175  free(dup);
1176  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN_DM, MSG_TYPE_COMMAND_FAILURE, "Please specify a player name.");
1177  return;
1178  }
1179  params = params + (space - dup) + 1;
1180  *space = '\0';
1181  other = find_player_partial_name(dup);
1182  if (other == NULL) {
1183  draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN_DM, MSG_TYPE_COMMAND_FAILURE, "%s is not online, or ambiguous name.", dup);
1184  free(dup);
1185  return;
1186  }
1187  free(dup);
1188  who = other->ob;
1189  name = who->name;
1190  } else {
1191  who = op;
1192  name = "You";
1193  }
1194 
1195  if (strcmp(params, "list all") == 0) {
1196  quest_list(op->contr, who->contr, 1, name);
1197  return;
1198  }
1199 
1200  if (strcmp(params, "list") == 0) {
1201  quest_list(op->contr, who->contr, 0, name);
1202  return;
1203  }
1204 
1205  if (strncmp(params, "info ", 5) == 0) {
1206  int number = atoi(params+5);
1207  quest_info(op->contr, who->contr, get_quest_by_number(who->contr, number), 0);
1208  return;
1209  }
1210 
1211  if (QUERY_FLAG(op, FLAG_WIZ) && strncmp(params, "set ", 4) == 0) {
1212  char *dup = strdup(params + 4);
1213  char *space = strrchr(dup, ' ');
1214  int state, number;
1215  quest_state* q;
1216  if (space == NULL) {
1217  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN_DM, MSG_TYPE_COMMAND_FAILURE, "Syntax is: quest (player name) (quest number) (state).");
1218  free(dup);
1219  return;
1220  }
1221  *space = '\0';
1222  number = atoi(dup);
1223  q = get_quest_by_number(who->contr, number);
1224  if (q == NULL) {
1225  draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN_DM, MSG_TYPE_COMMAND_FAILURE, "Invalid quest number %d.", number);
1226  free(dup);
1227  return;
1228  }
1229  state = atoi(space + 1);
1230  quest_set_state(op->contr, who->contr, q->code, state, 0);
1231  free(dup);
1233  return;
1234  }
1235 
1236  quest_help(op->contr);
1237 }
1238 
1245 static void output_quests(quest_definition *parent, int level) {
1246  quest_definition *quest;
1247  quest_step_definition *step;
1248  char prefix[MAX_BUF];
1249  int questcount = 0, stepcount, i;
1250 
1251  /* we only need to set the prefix once,
1252  * all quests that are printed in this call will be at the same level */
1253  prefix[0]='\0';
1254  for (i=0; i<level; i++) {
1255  strncat(prefix, "-", MAX_BUF - 1);
1256  }
1257  prefix[MAX_BUF - 1] = '\0';
1258 
1259  quest = quests;
1260  while (quest) {
1261  if (quest->parent == parent) {
1262  questcount++;
1263  stepcount=0;
1264  step = quest->steps;
1265  while (step) {
1266  stepcount++;
1267  step= step->next;
1268  }
1269  fprintf(logfile, "%s%s - %s - %d steps (%srestartable)\n", prefix, quest->quest_code, quest->quest_title, stepcount, quest->quest_restart?"":"not ");
1270  output_quests(quest, level+1);
1271  }
1272  quest = quest->next;
1273  }
1274 }
1275 
1280 void dump_quests(void) {
1282  output_quests(NULL, 0);
1283  exit(0);
1284 }
1285 
1289 void free_quest(void) {
1291 
1292  while (pq) {
1293  next = pq->next;
1294  free_state(pq);
1295  free_string(pq->player_name);
1296  free(pq);
1297  pq = next;
1298  }
1299  player_states = NULL;
1300 }
1301 
1308  quest_definition *quest = quests, *next_quest;
1309  quest_step_definition *step, *next_step;
1310  quest_condition *condition, *next_condition;
1311 
1312  while (quest != NULL) {
1313  next_quest = quest->next;
1314  free_string(quest->quest_code);
1315  if (quest->quest_description != NULL)
1317  if (quest->quest_title != NULL)
1318  free_string(quest->quest_title);
1319  step = quest->steps;
1320  while (step != NULL) {
1321  next_step = step->next;
1323  condition = step->conditions;
1324  while (condition != NULL) {
1325  next_condition = condition->next;
1326  free_string(condition->quest_code);
1327  free(condition);
1328  condition = next_condition;
1329  }
1330  free(step);
1331  step = next_step;
1332  }
1333  free(quest);
1334  quest = next_quest;
1335  }
1336 
1337  quests = NULL;
1338  quests_loaded = 0;
1339 }
1340 
1347  quest_player *states = NULL;
1348  quest_state *state = NULL;
1349  SockList sl;
1350  size_t size;
1351  quest_definition *quest;
1352  quest_step_definition *step;
1353 
1354  if (pl->socket.notifications < 1)
1355  return;
1356 
1357  /* ensure quest definitions are loaded */
1359 
1360  states = get_or_create_quest(pl);
1361 
1362  SockList_Init(&sl);
1363  SockList_AddString(&sl, "addquest ");
1364  for (state = states->quests; state != NULL; state = state->next) {
1365 
1366  quest = quest_get_by_code(state->code);
1367  if (state->state == -1)
1368  step = NULL;
1369  else
1370  step = quest_get_step(quest, state->state);
1371 
1372  size = 2 + (2 + strlen(quest->quest_title)) + 4 + 1 + (2 + (step != NULL ? strlen(step->step_description) : 0));
1373 
1374  if (SockList_Avail(&sl) < size) {
1375  Send_With_Handling(&pl->socket, &sl);
1376  SockList_Reset(&sl);
1377  SockList_AddString(&sl, "addquest ");
1378  }
1379 
1380  SockList_AddInt(&sl, quest->client_code);
1381  SockList_AddLen16Data(&sl, quest->quest_title, strlen(quest->quest_title));
1382  if (quest->face && !(pl->socket.faces_sent[quest->face]&NS_FACESENT_FACE))
1383  esrv_send_face(&pl->socket, quest->face, 0);
1384  SockList_AddInt(&sl, quest->face);
1385  SockList_AddChar(&sl, quest->quest_restart ? 1 : 0);
1386  SockList_AddInt(&sl, quest->parent ? quest->parent->client_code : 0);
1387  SockList_AddChar(&sl, (step == NULL || step->is_completion_step) ? 1 : 0);
1388  if (step != NULL)
1389  SockList_AddLen16Data(&sl, step->step_description, strlen(step->step_description));
1390  else
1391  SockList_AddShort(&sl, 0);
1392 
1393  state->sent_to_client = 1;
1394  }
1395 
1396  Send_With_Handling(&pl->socket, &sl);
1397  SockList_Term(&sl);
1398 }
1399 
1408  quest_player *qp = get_quest(pl);
1409  if (qp != NULL && qp->quests != NULL) {
1411  }
1412 }
EXTERN FILE * logfile
Used by server/daemon.c.
Definition: global.h:144
void draw_ext_info_format(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *format,...)
Sends message to player(s).
Definition: main.c:315
Error, serious thing.
Definition: logger.h:11
int maxstep
The latest step that triggers the condition, to match, the stages must be between minstep and maxstep...
Definition: quest.c:65
One player.
Definition: player.h:92
sstring step_description
Step description to show player.
Definition: quest.c:73
Information.
Definition: logger.h:12
void quest_first_player_save(player *pl)
Ensure the quest state is correctly saved for a player.
Definition: quest.c:1407
static void output_quests(quest_definition *parent, int level)
Dump all defined quests on the logfile.
Definition: quest.c:1245
void SockList_Reset(SockList *sl)
Resets the length of the stored data for writing.
Definition: lowlevel.c:66
void esrv_send_face(socket_struct *ns, uint16_t face_num, int nocache)
Sends a face to a client if they are in pixmap mode, nothing gets sent in bitmap mode.
Definition: image.c:70
#define NS_FACESENT_FACE
Bitmask for the faces_sent[] array - what portion of the face have we sent?
Definition: newserver.h:149
#define QC_CAN_RESTART
Quest status that indicates a quest was completed and may be restarted.
Definition: quest.c:38
Definition of an in-game quest.
Definition: quest.c:80
struct quest_player quest_player
Information about a player.
void SockList_Init(SockList *sl)
Initializes the SockList instance.
Definition: lowlevel.c:48
void free_quest(void)
Free all quest status structures.
Definition: quest.c:1289
sstring add_refcount(sstring str)
This will increase the refcount of the string str.
Definition: shstr.c:210
sstring quest_code
The quest that triggers the condition.
Definition: quest.c:62
#define MSG_TYPE_COMMAND_FAILURE
Failed result from command.
Definition: newclient.h:511
static void quest_read_player_data(quest_player *pq)
Read quest-data information for a player.
Definition: quest.c:478
uint32_t has_directory
If 0, the player was not yet saved, its directory doesn&#39;t exist.
Definition: player.h:134
void fatal(enum fatal_error err)
fatal() is meant to be called whenever a fatal signal is intercepted.
Definition: utils.c:596
static quest_definition * quest_create_definition(void)
Allocate a quest_definition, will call fatal() if out of memory.
Definition: quest.c:122
struct quest_step_definition quest_step_definition
One step of a quest.
struct quest_player * next
Next player on the list.
Definition: quest.c:54
StringBuffer * stringbuffer_new(void)
Create a new string buffer.
Definition: stringbuffer.c:57
const char * playerdir
Where the player files are.
Definition: global.h:246
void free_string(sstring str)
This will reduce the refcount, and if it has reached 0, str will be freed.
Definition: shstr.c:280
#define QUESTFILE_STEP
In a quest step.
Definition: quest.c:157
#define HUGE_BUF
Used for messages - some can be quite long.
Definition: define.h:37
static quest_condition * quest_create_condition(void)
Allocate a quest_condition, will call fatal() if out of memory.
Definition: quest.c:110
One step of a quest.
Definition: quest.c:71
void SockList_AddShort(SockList *sl, uint16_t data)
Adds a 16 bit value.
Definition: lowlevel.c:108
socket_struct socket
Socket information for this player.
Definition: player.h:94
struct quest_state * quests
Quests done or in progress.
Definition: quest.c:53
void SockList_AddLen16Data(SockList *sl, const void *data, size_t len)
Adds a data block prepended with an 16 bit length field.
Definition: lowlevel.c:183
uint32_t client_code
The code used to communicate with the client, merely a unique index.
Definition: quest.c:86
#define MSG_TYPE_ADMIN_LOADSAVE
load/save operations
Definition: newclient.h:477
void SockList_AddInt(SockList *sl, uint32_t data)
Adds a 32 bit value.
Definition: lowlevel.c:119
sstring code
Quest internal code.
Definition: quest.c:42
int sent_to_client
Whether this state was sent to the client or not.
Definition: quest.c:46
Global type definitions and header inclusions.
static void quest_info(player *pl, player *who, quest_state *qs, int level)
Give details about a quest.
Definition: quest.c:989
void draw_ext_info(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *message)
Sends message to player(s).
Definition: main.c:310
static quest_player * get_quest(player *pl)
Get quest status for a player, not creating it if it doesn&#39;t exist.
Definition: quest.c:637
struct quest_condition quest_condition
One condition to automatically move to a quest step.
static quest_state * get_quest_by_number(player *pl, int number)
returns the quest state which corresponds to a certain number for the given player.
Definition: quest.c:954
static void update_quests(player *pl)
Look through all of the quests for the given player, and see if any need to be updated.
Definition: quest.c:706
static void quest_list(player *pl, player *who, int showall, const char *name)
Display current and completed player quests.
Definition: quest.c:916
uint16_t notifications
Notifications this client wants to get.
Definition: newserver.h:141
void quest_start(player *pl, sstring quest_code, int state)
Start a quest for a player.
Definition: quest.c:1096
struct quest_definition quest_definition
Definition of an in-game quest.
#define MSG_TYPE_ADMIN_DM
DM related admin actions.
Definition: newclient.h:475
Information about a player.
Definition: quest.c:51
static quest_state * get_new_quest_state(void)
Return a new quest_state*, calling fatal() if memory shortage.
Definition: quest.c:467
static int load_quests_from_file(const char *filename)
Loads all of the quests which are found in the given file, any global states for quest loading are pa...
Definition: quest.c:168
#define MSG_TYPE_COMMAND
Responses to commands, eg, who.
Definition: newclient.h:379
One condition to automatically move to a quest step.
Definition: quest.c:61
int was_completed
Whether the quest was completed once or not, indepandently of the state.
Definition: quest.c:44
struct quest_state * next
Next quest on the list.
Definition: quest.c:47
void stringbuffer_append_string(StringBuffer *sb, const char *str)
Append a string to a string buffer instance.
Definition: stringbuffer.c:95
static quest_state * get_state(quest_player *pq, sstring name)
Get the state of a quest for a player, not creating if not existing yet.
Definition: quest.c:593
#define MSG_TYPE_COMMAND_SUCCESS
Successful result from command.
Definition: newclient.h:510
struct quest_step_definition * next
Next step.
Definition: quest.c:75
#define NDI_ALL_DMS
Inform all logged in DMs.
Definition: newclient.h:247
void SockList_Term(SockList *sl)
Frees all resources allocated by a SockList instance.
Definition: lowlevel.c:58
#define snprintf
Definition: win32.h:46
static void quest_write_player_data(const quest_player *pq)
Write quest-data information for a player.
Definition: quest.c:556
void dump_quests(void)
Dump all of the quests, then calls exit() - useful in terms of debugging to make sure that quests are...
Definition: quest.c:1280
char * path_combine_and_normalize(const char *src, const char *dst, char *path, size_t size)
Combines the 2 paths.
Definition: path.c:172
int of_close(OutputFile *of)
Closes an output file.
Definition: output_file.c:61
const char * name
The name of the object, obviously...
Definition: object.h:311
struct quest_definition * next
Next quest in the definition list.
Definition: quest.c:89
sstring quest_code
Quest internal code.
Definition: quest.c:81
void SockList_AddString(SockList *sl, const char *data)
Adds a string without length.
Definition: lowlevel.c:149
static int quests_loaded
Did we already read the &#39;default.quests&#39; file?
Definition: quest.c:92
quest_condition * conditions
The conditions that must be satisfied to trigger the step.
Definition: quest.c:76
void quest_send_initial_states(player *pl)
Send the current quest states for the specified player, if the client supports those notifications...
Definition: quest.c:1346
struct pl * contr
Pointer to the player which control this object.
Definition: object.h:276
static quest_step_definition * quest_get_step(quest_definition *quest, int step)
Get a step for the specified quest.
Definition: quest.c:431
Information about a quest for a player.
Definition: quest.c:41
size_t SockList_Avail(const SockList *sl)
Returns the available bytes in a SockList instance.
Definition: lowlevel.c:238
#define QUERY_FLAG(xyz, p)
Definition: define.h:225
#define QUESTFILE_QUEST
In a quest definition.
Definition: quest.c:155
sstring quest_title
Quest title for player.
Definition: quest.c:82
#define FLAG_WIZ
Object has special privilegies.
Definition: define.h:231
#define QUESTFILE_QUESTDESC
In a quest description.
Definition: quest.c:156
void free_quest_definitions(void)
Free all quest definitions and steps.
Definition: quest.c:1307
static int evaluate_quest_conditions(const quest_condition *condition, player *pl)
Checks whether the conditions for a given step are met.
Definition: quest.c:680
#define MAX_BUF
Used for all kinds of things.
Definition: define.h:35
#define MSG_TYPE_ADMIN
Definition: newclient.h:377
sstring player_name
Player&#39;s name.
Definition: quest.c:52
void quest_set_player_state(player *pl, sstring quest_code, int state)
Set the state of a quest for a player.
Definition: quest.c:1132
static void quest_load_definitions(void)
Load all quest definitions.
Definition: quest.c:412
struct quest_definition * parent
Parent for this quest, NULL if it is a &#39;top-level&#39; quest.
Definition: quest.c:88
void SockList_AddChar(SockList *sl, char c)
Adds an 8 bit value.
Definition: lowlevel.c:98
int minstep
The earliest step in the quest that triggers the condition, -1 means finished, 0 means not started...
Definition: quest.c:63
object * ob
The object representing the player.
Definition: player.h:158
const char * sstring
Strings that should be manipulated through add_string() and free_string().
Definition: global.h:40
unsigned int uint32_t
Definition: win32.h:162
const char * datadir
Read only data files.
Definition: global.h:244
int is_completion_step
Whether this step completes the quest (1) or not (0)
Definition: quest.c:74
#define QUESTFILE_NEXTQUEST
Waiting for next quest definition.
Definition: quest.c:154
int is_complete
Whether the quest is complete in the current playthrough.
Definition: quest.c:45
void command_quest(object *op, const char *params)
Command handler for &#39;quest&#39;.
Definition: quest.c:1154
const char * localdir
Read/write data files.
Definition: global.h:245
static void quest_set_state(player *dm, player *pl, sstring quest_code, int state, int started)
Set the state of a quest for a player.
Definition: quest.c:744
#define QUESTFILE_STEPCOND
In a quest step conditions.
Definition: quest.c:159
Only for debugging purposes.
Definition: logger.h:13
static quest_step_definition * quest_create_step(void)
Allocate a quest_step_definition, will call fatal() if out of memory.
Definition: quest.c:99
int quest_get_player_state(player *pl, sstring quest_code)
Get the quest state for a player.
Definition: quest.c:1076
const char * mapdir
Where the map files are.
Definition: global.h:247
struct Settings settings
Server settings.
Definition: init.c:40
FILE * of_open(OutputFile *of, const char *fname)
Opens an output file.
Definition: output_file.c:30
int quest_restart
If non zero, can be restarted.
Definition: quest.c:84
#define MSG_TYPE_COMMAND_INFO
Generic info: resistances, etc.
Definition: newclient.h:506
static void quest_display(player *pl, quest_player *pq, int showall, const char *name)
Utility function to display a quest list.
Definition: quest.c:843
Functions for creating text output files.
static quest_definition * quest_get(sstring code)
Find a quest from its code.
Definition: quest.c:450
sstring add_string(const char *str)
This will add &#39;str&#39; to the hash table.
Definition: shstr.c:124
static quest_state * get_or_create_state(quest_player *pq, sstring name)
Get the state of a quest for a player, creating it if not existing yet.
Definition: quest.c:611
struct quest_condition * next
The next condition to check.
Definition: quest.c:67
static quest_definition * quests
All known quests.
Definition: quest.c:93
char * strdup(const char *str)
Portable implementation of strdup(3).
Definition: porting.c:200
#define NDI_UNIQUE
Print immediately, don&#39;t buffer.
Definition: newclient.h:245
void LOG(LogLevel logLevel, const char *format,...)
Logs a message to stderr, or to file.
Definition: logger.c:51
int step
Step identifier.
Definition: quest.c:72
quest_step_definition * steps
Quest steps.
Definition: quest.c:87
int quest_was_completed(player *pl, sstring quest_code)
Check if a quest was completed once for a player, without taking account the current state...
Definition: quest.c:1142
static void quest_help(player *pl)
Quest command help.
Definition: quest.c:933
A buffer that will be expanded as content is added to it.
Definition: stringbuffer.c:25
sstring quest_description
Quest longer description.
Definition: quest.c:83
Contains the base information we use to make up a packet we want to send.
Definition: newclient.h:680
static quest_player * player_states
Player quest state.
Definition: quest.c:58
static quest_player * get_or_create_quest(player *pl)
Get quest status for a player, creating it if it doesn&#39;t exist yet.
Definition: quest.c:655
int face
Face associated with this quest.
Definition: quest.c:85
unsigned find_face(const char *name, unsigned error)
This returns an the face number of face &#39;name&#39;.
Definition: image.c:303
player * find_player_partial_name(const char *plname)
Find a player by a partial name.
Definition: player.c:109
#define QUESTFILE_STEPDESC
In a quest step description.
Definition: quest.c:158
static quest_definition * quest_get_by_code(sstring code)
Find a quest from its code.
Definition: quest.c:135
static void free_state(quest_player *pq)
Free quests structures.
Definition: quest.c:1055
uint8_t * faces_sent
This is a bitmap on sent face status.
Definition: newserver.h:106
char * stringbuffer_finish(StringBuffer *sb)
Deallocate the string buffer instance and return the string.
Definition: stringbuffer.c:76
struct quest_state quest_state
Information about a quest for a player.
int state
State for the player.
Definition: quest.c:43
void Send_With_Handling(socket_struct *ns, SockList *sl)
Calls Write_To_Socket to send data to the client.
Definition: lowlevel.c:542