Crossfire Server, Trunk
c_wiz.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 
20 #include "global.h"
21 
22 #include <ctype.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <sys/stat.h>
26 
27 #include "sproto.h"
28 #include "spells.h"
29 #include "treasure.h"
30 #include "skills.h"
31 #include "assets.h"
32 #include "AssetsManager.h"
33 
34 /* Defines for DM item stack **/
35 #define STACK_SIZE 50
37 enum {
42 };
43 
45 
60 static player *get_other_player_from_name(object *op, const char *name) {
61  player *pl;
62 
63  if (!name)
64  return NULL;
65 
66  for (pl = first_player; pl != NULL; pl = pl->next)
67  if (!strncmp(pl->ob->name, name, MAX_NAME))
68  break;
69 
70  if (pl == NULL) {
72  "No such player.");
73  return NULL;
74  }
75 
76  if (pl->ob == op) {
78  "You can't do that to yourself.");
79  return NULL;
80  }
81  if (pl->state != ST_PLAYING) {
83  "That player is in no state for that right now.");
84  return NULL;
85  }
86  return pl;
87 }
88 
95 static void dm_stack_pop(player *pl) {
96  if (!pl->stack_items || !pl->stack_position) {
98  "Empty stack!");
99  return;
100  }
101 
102  pl->stack_position--;
104  "Popped item from stack, %d left.",
105  pl->stack_position);
106 }
107 
120 static object *dm_stack_peek(player *pl) {
121  object *ob;
122 
123  if (!pl->stack_position) {
125  "Empty stack!");
126  return NULL;
127  }
128 
129  ob = object_find_by_tag_global(pl->stack_items[pl->stack_position-1]);
130  if (!ob) {
132  "Stacked item was removed!");
133  dm_stack_pop(pl);
134  return NULL;
135  }
136 
137  return ob;
138 }
139 
150 static void dm_stack_push(player *pl, tag_t item) {
151  if (!pl->stack_items) {
152  pl->stack_items = (tag_t *)malloc(sizeof(tag_t)*STACK_SIZE);
153  memset(pl->stack_items, 0, sizeof(tag_t)*STACK_SIZE);
154  }
155 
156  if (pl->stack_position == STACK_SIZE) {
158  "Item stack full!");
159  return;
160  }
161 
162  pl->stack_items[pl->stack_position] = item;
164  "Item stacked as %d.",
165  pl->stack_position);
166  pl->stack_position++;
167 }
168 
196 static object *get_dm_object(player *pl, const char **params, int *from) {
197  int item_tag, item_position;
198  object *ob;
199 
200  if (!pl)
201  return NULL;
202 
203  if (**params == '\0') {
204  if (from)
205  *from = STACK_FROM_TOP;
206  /* No parameter => get stack item */
207  return dm_stack_peek(pl);
208  }
209 
210  /* Let's clean white spaces */
211  while (**params == ' ')
212  (*params)++;
213 
214  /* Next case: number => item tag */
215  if (sscanf(*params, "%d", &item_tag)) {
216  /* Move parameter to next item */
217  while (isdigit(**params))
218  (*params)++;
219 
220  /* And skip blanks, too */
221  while (**params == ' ')
222  (*params)++;
223 
224  /* Get item */
225  ob = object_find_by_tag_global(item_tag);
226  if (!ob) {
227  if (from)
228  *from = STACK_FROM_NONE;
230  "No such item %d!",
231  item_tag);
232  return NULL;
233  }
234 
235  /* Got one, let's push it on stack */
236  dm_stack_push(pl, item_tag);
237  if (from)
238  *from = STACK_FROM_NUMBER;
239  return ob;
240  }
241 
242  /* Next case: $number => stack item */
243  if (sscanf(*params, "$%d", &item_position)) {
244  /* Move parameter to next item */
245  (*params)++;
246 
247  while (isdigit(**params))
248  (*params)++;
249  while (**params == ' ')
250  (*params)++;
251 
252  if (item_position >= pl->stack_position) {
253  if (from)
254  *from = STACK_FROM_NONE;
256  "No such stack item %d!",
257  item_position);
258  return NULL;
259  }
260 
261  ob = object_find_by_tag_global(pl->stack_items[item_position]);
262  if (!ob) {
263  if (from)
264  *from = STACK_FROM_NONE;
266  "Stack item %d was removed.",
267  item_position);
268  return NULL;
269  }
270 
271  if (from)
272  *from = item_position < pl->stack_position-1 ? STACK_FROM_STACK : STACK_FROM_TOP;
273  return ob;
274  }
275 
276  /* Next case: 'me' => return pl->ob */
277  if (!strncmp(*params, "me", 2)) {
278  if (from)
279  *from = STACK_FROM_NUMBER;
280  dm_stack_push(pl, pl->ob->count);
281 
282  /* Skip to next token */
283  (*params) += 2;
284  while (**params == ' ')
285  (*params)++;
286 
287  return pl->ob;
288  }
289 
290  /* Last case: get stack top */
291  if (from)
292  *from = STACK_FROM_TOP;
293  return dm_stack_peek(pl);
294 }
295 
306 void command_loadtest(object *op, const char *params) {
307  uint32_t x, y;
308  char buf[1024];
309 
311  "loadtest will stress server through teleporting at different map places. "
312  "Use at your own risk. Very long loop used so server may have to be reset. "
313  "type loadtest TRUE to run");
315  "{%s}",
316  params);
317  if (*params == '\0')
318  return;
319  if (strncmp(params, "TRUE", 4))
320  return;
321 
323  "gogogo");
324 
325  for (x = 0; x < settings.worldmaptilesx; x++) {
326  for (y = 0; y < settings.worldmaptilesy; y++) {
327  snprintf(buf, sizeof(buf), "/world/world_%u_%u", x+settings.worldmapstartx, y+settings.worldmapstarty);
328  command_goto(op, buf);
329  }
330  }
331 }
332 
333 static void unhide(object* op) {
334  op->contr->hidden = 0;
335  op->invisible = 1;
336  op->map->players++;
338  "You are no longer hidden from other players");
341  "%s has entered the game.", op->name);
342 }
343 
352 static void do_wizard_hide(object *op, int silent_dm) {
353  if (op->contr->hidden) {
354  unhide(op);
355  if (!silent_dm) {
358  "The Dungeon Master has arrived!");
359  }
360  } else {
361  op->contr->hidden = 1;
363  "Other players will no longer see you.");
364  op->map->players--;
365  if (!silent_dm) {
368  "The Dungeon Master is gone...");
369  }
372  "%s leaves the game.",
373  op->name);
376  "%s left the game.",
377  op->name);
378  }
379 }
380 
389 void command_hide(object *op, const char *params) {
390  (void)params;
391  do_wizard_hide(op, 0);
392 }
393 
403 static object *find_object_both(const char *params) {
404  if (params[0] == '#')
405  return object_find_by_tag_global(atol(params+1));
406  else
408 }
409 
418 void command_setgod(object *op, const char *params) {
419  object *ob;
420  const object *god;
421  char *str;
422 
423  if (*params == '\0' || !(str = const_cast<char *>(strchr(params, ' ')))) {
425  "Usage: set_god player god");
426  return;
427  }
428 
429  /* kill the space, and set string to the next param */
430  *str++ = '\0';
431  if (!(ob = find_object_both(params))) {
433  "Set whose god - can not find object %s?",
434  params);
435  return;
436  }
437 
438  /*
439  * Perhaps this is overly restrictive? Should we perhaps be able
440  * to rebless altars and the like?
441  */
442  if (ob->type != PLAYER) {
444  "%s is not a player - can not change its god",
445  ob->name);
446  return;
447  }
448 
449  god = find_god(str);
450  if (god == NULL) {
452  "No such god %s.",
453  str);
454  return;
455  }
456 
457  become_follower(ob, god);
458 }
459 
468 static void command_kick2(object *op, const char *params) {
469  struct player *pl;
470 
471  for (pl = first_player; pl != NULL; pl = pl->next) {
472  if ((*params == '\0' || !strcmp(pl->ob->name, params)) && pl->ob != op) {
473  object *op = pl->ob;
474  if (!QUERY_FLAG(op, FLAG_REMOVED)) {
476  }
478  "%s is kicked out of the game.",
479  op->name);
480 
481  // Saving/leaving/removing is handled on the next tick in do_server().
482  pl->socket->status = Ns_Dead;
483  }
484  }
485 }
486 
502 void command_banish(object *op, const char *params) {
503  player *pl;
504  FILE *banishfile;
505  char buf[MAX_BUF];
506  time_t now;
507 
508  if (*params == '\0') {
510  "Usage: banish <player>.");
511  return;
512  }
513 
515  if (!pl)
516  return;
517 
518  snprintf(buf, sizeof(buf), "%s/%s", settings.localdir, BANISHFILE);
519 
520  if ((banishfile = fopen(buf, "a")) == NULL) {
521  LOG(llevDebug, "Could not find file banish_file.\n");
523  "Could not find banish_file.");
524  return;
525  }
526 
527  now = time(NULL);
528  /*
529  * Record this as a comment - then we don't have to worry about changing
530  * the parsing code.
531  */
532  fprintf(banishfile, "# %s (%s) banned by %s at %s\n", pl->ob->name, pl->socket->host, op->name, ctime(&now));
533  fprintf(banishfile, "*@%s\n", pl->socket->host);
534  fclose(banishfile);
535 
536  LOG(llevDebug, "! %s banned %s from IP: %s.\n", op->name, pl->ob->name, pl->socket->host);
537 
539  "You banish %s",
540  pl->ob->name);
541 
543  "%s banishes %s from the land!",
544  op->name, pl->ob->name);
545  command_kick2(op, pl->ob->name);
546 }
547 
556 void command_kick(object *op, const char *params) {
558 }
559 
568 void command_overlay_save(object *op, const char *params) {
569  (void)params;
570  if (!op)
571  return;
572 
573  if (save_map(op->map, SAVE_MODE_OVERLAY) < 0)
575  "Overlay save error!");
576  else
578  "Current map has been saved as an overlay.");
579 }
580 
589 void command_overlay_reset(object *op, const char *params) {
590  char filename[MAX_BUF];
591  struct stat stats;
592  (void)params;
593 
595  if (!stat(filename, &stats))
596  if (!unlink(filename))
598  "Overlay successfully removed.");
599  else
601  "Overlay couldn't be removed.");
602  else
604  "No overlay for current map.");
605 }
606 
615 void command_toggle_shout(object *op, const char *params) {
616  player *pl;
617 
618  if (*params == '\0') {
620  "Usage: toggle_shout <player>.");
621  return;
622  }
623 
625  if (!pl)
626  return;
627 
628  if (pl->ob->contr->no_shout == 0) {
629  pl->ob->contr->no_shout = 1;
630 
632  "You have been muzzled by the DM!");
634  "You muzzle %s.",
635  pl->ob->name);
636 
638 
639  return;
640  }
641 
642  pl->ob->contr->no_shout = 0;
644  "You are allowed to shout and chat again.");
646  "You remove %s's muzzle.",
647  pl->ob->name);
648 }
649 
658 void command_shutdown(object *op, const char *params) {
659  if (strlen(params) == 0) {
660  /* Give DM command help and display current shutdown status. */
661  command_help(op, "shutdown");
664  MSG_TYPE_COMMAND_DM, "No shutdown is currently scheduled.");
665  } else if (shutdown_state.type == SHUTDOWN_TIME) {
666  time_t time_left = shutdown_state.time - time(NULL);
668  MSG_TYPE_COMMAND_DM, "Shutdown scheduled in %lu minutes.", time_left/60);
669  } else if (shutdown_state.type == SHUTDOWN_IDLE) {
671  MSG_TYPE_COMMAND_DM, "Shutdown scheduled when there are no active players.");
672  }
673  } else if (strcmp(params, "cancel") == 0) {
676  MSG_TYPE_ADMIN_DM, "Server shutdown cancelled.");
677  LOG(llevInfo, "Server shutdown cancelled by %s.\n", op->name);
679  } else {
681  MSG_TYPE_COMMAND_ERROR, "No shutdown is pending.");
682  }
683  } else if (strncmp(params, "now", 3) == 0) {
684  /* Announce and shut down immediately. */
686  MSG_TYPE_ADMIN_DM, "This server is shutting down now!");
688  shutdown_state.time = time(NULL);
689  LOG(llevInfo, "Server shutdown initiated by %s.\n", op->name);
690  } else if (strcmp(params, "idle") == 0) {
692  MSG_TYPE_ADMIN_DM, "This server will shut down when all players leave.");
694  shutdown_state.time = 0;
696  LOG(llevInfo, "Server idle shutdown scheduled by %s.\n", op->name);
697  } else {
698  /* Schedule (but don't announce) a shutdown. */
699  int minutes = atoi(params);
700 
701  if (minutes > 0 && minutes <= 720) {
704  "Server will shut down in %d minutes.", minutes);
706  shutdown_state.time = time(NULL) + minutes * 60;
707  LOG(llevInfo, "Server shutdown scheduled in %d minutes by %s.\n", minutes, op->name);
708  } else {
711  "Please specify a reasonable time in minutes.");
712  }
713  }
714 }
715 
724 void command_goto(object *op, const char *params) {
725  if (!op)
726  return ;
727 
728  if (*params == '\0') {
730  "Go to what level?");
731  return;
732  }
733 
734  do_goto(op, params, -1, -1);
735 }
736 
745 void command_freeze(object *op, const char *params) {
746  int ticks;
747  player *pl;
748 
749  if (*params == '\0') {
751  "Usage: freeze [ticks] <player>.");
752  return;
753  }
754 
755  ticks = atoi(params);
756  if (ticks) {
757  while ((isdigit(*params) || isspace(*params)) && *params != 0)
758  params++;
759  if (*params == 0) {
761  "Usage: freeze [ticks] <player>.");
762  return;
763  }
764  } else
765  ticks = 100;
766 
768  if (!pl)
769  return;
770 
772  "You have been frozen by the DM!");
773 
775  "You freeze %s for %d ticks",
776  pl->ob->name, ticks);
777 
778  pl->ob->speed_left = -(pl->ob->speed*ticks);
779 }
780 
789 int player_arrest(object *who) {
790  object *dummy;
791  mapstruct *cur;
792  int x, y;
793 
794  if (who->type != PLAYER)
795  return -3;
796 
797  dummy = get_jail_exit(who);
798  if (!dummy) {
799  return -1;
800  }
801  cur = who->map;
802  x = who->x;
803  y = who->y;
804  enter_exit(who, dummy);
806 
807  if (cur == who->map && x == who->x && y == who->y)
808  return -2;
809 
810  return 0;
811 }
812 
821 void command_arrest(object *op, const char *params) {
822  player *pl;
823  int ret;
824 
825  if (!op)
826  return;
827  if (*params == '\0') {
829  "Usage: arrest <player>.");
830  return;
831  }
833  if (!pl)
834  return;
835 
836  ret = player_arrest(pl->ob);
837  if (ret == -1) {
838  /* we have nowhere to send the prisoner....*/
840  "Can't jail player, there is no map to hold them");
841  return;
842  }
843  if (ret == -2) {
844  /* something prevented jailing the player */
846  "Can't jail player, map loading issue or already in jail's position");
847  return;
848 
849  }
850 
852  "You have been arrested.");
854  "Jailed %s",
855  pl->ob->name);
856  LOG(llevInfo, "Player %s arrested by %s\n", pl->ob->name, op->name);
857 }
858 
866 void command_summon(object *op, const char *params) {
867  int i;
868  object *dummy;
869  player *pl;
870 
871  if (!op)
872  return;
873 
874  if (*params == '\0') {
876  "Usage: summon <player>.");
877  return;
878  }
879 
881  if (!pl)
882  return;
883 
884  i = object_find_free_spot(op, op->map, op->x, op->y, 1, 9);
885  if (i == -1) {
887  "Can not find a free spot to place summoned player.");
888  return;
889  }
890 
891  dummy = object_new();
892  EXIT_PATH(dummy) = add_string(op->map->path);
893  EXIT_X(dummy) = op->x+freearr_x[i];
894  EXIT_Y(dummy) = op->y+freearr_y[i];
895  enter_exit(pl->ob, dummy);
898  "You are summoned.");
900  "You summon %s",
901  pl->ob->name);
902 }
903 
912 /* mids 01/16/2002 */
913 void command_teleport(object *op, const char *params) {
914  int i;
915  object *dummy;
916  player *pl;
917 
918  if (!op)
919  return;
920 
921  if (*params == '\0') {
923  "Usage: teleport <player>.");
924  return;
925  }
926 
928  if (!pl) {
930  "No such player or ambiguous name.");
931  return;
932  }
933 
934  i = object_find_free_spot(pl->ob, pl->ob->map, pl->ob->x, pl->ob->y, 1, 9);
935  if (i == -1) {
937  "Can not find a free spot to teleport to.");
938  return;
939  }
940 
941  dummy = object_new();
942  EXIT_PATH(dummy) = add_string(pl->ob->map->path);
943  EXIT_X(dummy) = pl->ob->x+freearr_x[i];
944  EXIT_Y(dummy) = pl->ob->y+freearr_y[i];
945  enter_exit(op, dummy);
947  if (!op->contr->hidden)
949  "You see a portal open.");
951  "You teleport to %s",
952  pl->ob->name);
953 }
954 
979 void command_create(object *op, const char *params) {
980  object *tmp = NULL;
981  uint32_t i;
982  int magic, set_magic = 0, set_nrof = 0, gotquote, gotspace;
983  uint32_t nrof;
984  char *cp, *bp, *bp2, *bp3, *endline, cpy[MAX_BUF];
985  archetype *at, *at_spell = NULL;
986  const artifact *art = NULL;
987 
988  if (!op)
989  return;
990 
991  if (*params == '\0') {
993  "Usage: create [nr] [magic] <archetype> [ of <artifact>] [variable_to_patch setting]");
994  return;
995  }
996  safe_strncpy(cpy, params, sizeof(cpy));
997  bp = cpy;
998 
999  /* We need to know where the line ends */
1000  endline = bp+strlen(bp);
1001 
1002  if (sscanf(bp, "%u ", &nrof)) {
1003  if ((bp = strchr(cpy, ' ')) == NULL) {
1005  "Usage: create [nr] [magic] <archetype> [ of <artifact>] [variable_to_patch setting]");
1006  return;
1007  }
1008  bp++;
1009  set_nrof = 1;
1010  LOG(llevDebug, "%s creates: (%u) %s\n", op->name, nrof, bp);
1011  }
1012  if (sscanf(bp, "%d ", &magic)) {
1013  if ((bp = strchr(bp, ' ')) == NULL) {
1015  "Usage: create [nr] [magic] <archetype> [ of <artifact>] [variable_to_patch setting]");
1016  return;
1017  }
1018  bp++;
1019  set_magic = 1;
1020  LOG(llevDebug, "%s creates: (%d) (%d) %s\n", op->name, nrof, magic, bp);
1021  }
1022  if ((cp = strstr(bp, " of ")) != NULL) {
1023  *cp = '\0';
1024  cp += 4;
1025  }
1026  for (bp2 = bp; *bp2; bp2++) {
1027  if (*bp2 == ' ') {
1028  *bp2 = '\0';
1029  bp2++;
1030  break;
1031  }
1032  }
1033 
1034  if ((at = try_find_archetype(bp)) == NULL) {
1036  "No such archetype.");
1037  return;
1038  }
1039 
1040  if (cp) {
1041  char spell_name[MAX_BUF], *fsp = NULL;
1042 
1043  /*
1044  * Try to find a spell object for this. Note that
1045  * we also set up spell_name which is only
1046  * the first word.
1047  */
1048 
1049  at_spell = try_find_archetype(cp);
1050  if (!at_spell || at_spell->clone.type != SPELL)
1051  at_spell = find_archetype_by_object_name(cp);
1052  if (!at_spell || at_spell->clone.type != SPELL) {
1053  safe_strncpy(spell_name, cp, sizeof(spell_name));
1054  fsp = strchr(spell_name, ' ');
1055  if (fsp) {
1056  *fsp = 0;
1057  fsp++;
1058  at_spell = try_find_archetype(spell_name);
1059 
1060  /* Got a spell, update the first string pointer */
1061  if (at_spell && at_spell->clone.type == SPELL)
1062  bp2 = cp+strlen(spell_name)+1;
1063  else
1064  at_spell = NULL;
1065  } else
1066  at_spell = NULL;
1067  }
1068 
1069  /* OK - we didn't find a spell - presume the 'of'
1070  * in this case means its an artifact.
1071  */
1072  if (!at_spell) {
1073  if (find_artifactlist(at->clone.type) == NULL) {
1075  "No artifact list for type %d\n",
1076  at->clone.type);
1077  } else {
1078  auto items = find_artifactlist(at->clone.type)->items;
1079  auto i = std::find_if(items.cbegin(), items.cend(),
1080  [&] (const auto art) { return !strcmp(art->item->name, cp) && legal_artifact_combination(&at->clone, art); });
1081  art = i == items.cend() ? nullptr : *i;
1082 
1083  if (!art) {
1085  "No such artifact ([%d] of %s)",
1086  at->clone.type, cp);
1087  }
1088  }
1089  LOG(llevDebug, "%s creates: (%d) (%d) (%s) of (%s)\n", op->name, set_nrof ? nrof : 0, set_magic ? magic : 0, bp, cp);
1090  }
1091  } /* if cp */
1092 
1093  /* rods and potions can get their spell from the artifact */
1094  if ((at->clone.type == ROD || at->clone.type == POTION) && !at_spell && (!art || !art->item->other_arch)) {
1096  "Unable to find spell %s for object that needs it, or it is of wrong type",
1097  cp);
1098  return;
1099  }
1100  if ((at->clone.type == WAND || at->clone.type == SCROLL || at->clone.type == SPELLBOOK)
1101  && !at_spell) {
1103  "Unable to find spell %s for object that needs it, or it is of wrong type",
1104  cp);
1105  return;
1106  }
1107 
1108  /*
1109  * Rather than have two different blocks with a lot of similar code,
1110  * just create one object, do all the processing, and then determine
1111  * if that one object should be inserted or if we need to make copies.
1112  */
1113  tmp = object_create_arch(at);
1114  if (settings.real_wiz == FALSE)
1116  if (set_magic)
1117  set_abs_magic(tmp, magic);
1118  if (art)
1120  if (!is_identifiable_type(tmp)) {
1123  }
1124 
1125  /*
1126  * This entire block here tries to find variable pairings,
1127  * eg, 'hp 4' or the like. The mess here is that values
1128  * can be quoted (eg "my cool sword"); So the basic logic
1129  * is we want to find two spaces, but if we got a quote,
1130  * any spaces there don't count.
1131  */
1132  while (*bp2 && bp2 <= endline) {
1133  gotspace = 0;
1134  gotquote = 0;
1135  /* find the first quote */
1136  for (bp3 = bp2; *bp3 && gotspace < 2 && gotquote < 2; bp3++) {
1137  /* Found a quote - now lets find the second one */
1138  if (*bp3 == '"') {
1139  *bp3 = ' ';
1140  bp2 = bp3+1; /* Update start of string */
1141  bp3++;
1142  gotquote++;
1143  while (*bp3) {
1144  if (*bp3 == '"') {
1145  *bp3 = '\0';
1146  gotquote++;
1147  } else
1148  bp3++;
1149  }
1150  } else if (*bp3 == ' ') {
1151  gotspace++;
1152  }
1153  }
1154 
1155  /*
1156  * If we got two spaces, send the second one to null.
1157  * if we've reached the end of the line, increase gotspace -
1158  * this is perfectly valid for the list entry listed.
1159  */
1160  if (gotspace == 2 || gotquote == 2) {
1161  bp3--; /* Undo the extra increment */
1162  *bp3 = '\0';
1163  } else if (*bp3 == '\0')
1164  gotspace++;
1165 
1166  if ((gotquote && gotquote != 2)
1167  || (gotspace != 2 && gotquote != 2)) {
1168  /*
1169  * Unfortunately, we've clobbered lots of values, so printing
1170  * out what we have probably isn't useful. Break out, because
1171  * trying to recover is probably won't get anything useful
1172  * anyways, and we'd be confused about end of line pointers
1173  * anyways.
1174  */
1176  "Malformed create line: %s",
1177  bp2);
1178  break;
1179  }
1180  /* bp2 should still point to the start of this line,
1181  * with bp3 pointing to the end
1182  */
1183  if (set_variable(tmp, bp2) == -1)
1185  "Unknown variable %s",
1186  bp2);
1187  else
1189  "(%s#%d)->%s",
1190  tmp->name, tmp->count, bp2);
1191  bp2 = bp3+1;
1192  }
1193 
1194  if (at->clone.nrof) {
1195  if (at_spell)
1197 
1198  if (set_nrof)
1199  tmp->nrof = nrof;
1200 
1201  if (at->clone.randomitems != NULL && !at_spell) {
1202  create_treasure(at->clone.randomitems, tmp, 0, op->map->difficulty, 0);
1203  if (QUERY_FLAG(tmp, FLAG_MONSTER)) {
1205  }
1206  }
1207 
1208  /* Multipart objects can't be in inventory, put'em on floor. */
1209  if (!tmp->more) {
1211  } else {
1212  object_insert_in_map_at(tmp, op->map, op, 0, op->x, op->y);
1213  }
1214 
1215  /* Let's put this created item on stack so dm can access it easily. */
1216  dm_stack_push(op->contr, tmp->count);
1217 
1218  return;
1219  }
1220 
1221  for (i = 0; i < (set_nrof ? nrof : 1); i++) {
1222  archetype *atmp;
1223  object *prev = NULL, *head = NULL, *dup;
1224 
1225  for (atmp = at; atmp != NULL; atmp = atmp->more) {
1226  dup = arch_to_object(atmp);
1227 
1228  if (at_spell)
1229  object_insert_in_ob(arch_to_object(at_spell), dup);
1230 
1231  /*
1232  * The head is what contains all the important bits,
1233  * so just copying it over should be fine.
1234  */
1235  if (head == NULL) {
1236  head = dup;
1237  object_copy(tmp, dup);
1238  }
1239  if (settings.real_wiz == FALSE)
1240  SET_FLAG(dup, FLAG_WAS_WIZ);
1241  dup->x = op->x+dup->arch->clone.x;
1242  dup->y = op->y+dup->arch->clone.y;
1243  dup->map = op->map;
1244 
1245  if (head != dup) {
1246  dup->head = head;
1247  prev->more = dup;
1248  }
1249  prev = dup;
1250  }
1251 
1252  if (QUERY_FLAG(head, FLAG_ALIVE)) {
1253  object *check = head;
1254  int size_x = 0;
1255  int size_y = 0;
1256 
1257  while (check) {
1258  size_x = MAX(size_x, check->arch->clone.x);
1259  size_y = MAX(size_y, check->arch->clone.y);
1260  check = check->more;
1261  }
1262 
1263  if (out_of_map(op->map, head->x+size_x, head->y+size_y)) {
1264  if (head->x < size_x || head->y < size_y) {
1265  dm_stack_pop(op->contr);
1268  "Object too big to insert in map, or wrong position.");
1270  return;
1271  }
1272 
1273  check = head;
1274  while (check) {
1275  check->x -= size_x;
1276  check->y -= size_y;
1277  check = check->more;
1278  }
1279  }
1280 
1281  object_insert_in_map_at(head, op->map, op, 0, head->x, head->y);
1282  } else
1283  head = object_insert_in_ob(head, op);
1284 
1285  /* Let's put this created item on stack so dm can access it easily. */
1286  /* Wonder if we really want to push all of these, but since
1287  * things like rods have nrof 0, we want to cover those.
1288  */
1289  dm_stack_push(op->contr, head->count);
1290 
1291  if (at->clone.randomitems != NULL && !at_spell) {
1292  create_treasure(at->clone.randomitems, head, 0, op->map->difficulty, 0);
1293  if (QUERY_FLAG(head, FLAG_MONSTER)) {
1295  }
1296  }
1297  }
1298 
1299  /* free the one we used to copy */
1301 }
1302 
1303 /*
1304  * Now follows dm-commands which are also acceptable from sockets
1305  */
1306 
1315 void command_inventory(object *op, const char *params) {
1316  object *tmp;
1317  int i;
1318 
1319  if (*params == '\0') {
1320  inventory(op, NULL);
1321  return;
1322  }
1323 
1324  if (!sscanf(params, "%d", &i) || (tmp = object_find_by_tag_global(i)) == NULL) {
1326  "Inventory of what object (nr)?");
1327  return;
1328  }
1329 
1330  inventory(op, tmp);
1331 }
1332 
1345 void command_skills(object *op, const char *params) {
1346  show_skills(op, *params == '\0' ? NULL : params);
1347 }
1348 
1357 void command_dump(object *op, const char *params) {
1358  object *tmp;
1359  StringBuffer *sb;
1360  char *diff;
1361 
1362  tmp = get_dm_object(op->contr, &params, NULL);
1363  if (!tmp)
1364  return;
1365 
1366  sb = stringbuffer_new();
1367  object_dump(tmp, sb);
1368  diff = stringbuffer_finish(sb);
1370  free(diff);
1373  "Object is marked original");
1374 }
1375 
1385 void command_mon_aggr(object *op, const char *params) {
1386  (void)params;
1387  if (op->enemy || !QUERY_FLAG(op, FLAG_UNAGGRESSIVE)) {
1388  object_set_enemy(op, NULL);
1391  "Aggression turned OFF");
1392  } else {
1396  "Aggression turned ON");
1397  }
1398 }
1399 
1412 void command_possess(object *op, const char *params) {
1413  object *victim;
1414  player *pl;
1415  int i;
1416  char buf[MAX_BUF];
1417 
1418  victim = NULL;
1419  if (*params != '\0') {
1420  if (sscanf(params, "%d", &i))
1422  else if (sscanf(params, "%s", buf))
1424  }
1425  if (victim == NULL) {
1427  "Patch what object (nr)?");
1428  return;
1429  }
1430 
1431  if (victim == op) {
1433  "As insane as you are, I cannot allow you to possess yourself.");
1434  return;
1435  }
1436 
1437  /* make the switch */
1438  pl = op->contr;
1439  victim->contr = pl;
1440  pl->ob = victim;
1441  victim->type = PLAYER;
1443 
1444  /* basic patchup */
1445  /* The use of hard coded values is terrible. Note
1446  * that really, to be fair, this shouldn't get changed at
1447  * all - if you are possessing a kobold, you should have the
1448  * same limitations. As it is, as more body locations are added,
1449  * this will give this player more locations than perhaps
1450  * they should be allowed.
1451  */
1452  for (i = 0; i < NUM_BODY_LOCATIONS; i++)
1453  if (i == 1 || i == 6 || i == 8 || i == 9)
1454  victim->body_info[i] = 2;
1455  else
1456  victim->body_info[i] = 1;
1457 
1458  esrv_new_player(pl, 80); /* just pick a weight, we don't care */
1460 
1461  fix_object(victim);
1462 
1464 }
1465 
1473 void command_patch(object *op, const char *params) {
1474  const char *arg, *arg2;
1475  object *tmp;
1476 
1477  tmp = get_dm_object(op->contr, &params, NULL);
1478  if (!tmp)
1479  /* Player already informed of failure */
1480  return;
1481 
1482  /* params set to first value by get_dm_default */
1483  arg = params;
1484  if (*arg == '\0') {
1486  "Patch what values?");
1487  return;
1488  }
1489 
1490  if ((arg2 = strchr(arg, ' ')))
1491  arg2++;
1492  if (settings.real_wiz == FALSE)
1493  SET_FLAG(tmp, FLAG_WAS_WIZ); /* To avoid cheating */
1494  if (set_variable(tmp, arg) == -1)
1496  "Unknown variable %s",
1497  arg);
1498  else {
1500  "(%s#%d)->%s=%s",
1501  tmp->name, tmp->count, arg, arg2);
1502  }
1503 }
1504 
1505 static void reset_faces_sent(struct socket_struct *socket) {
1506  free(socket->faces_sent);
1507  socket->faces_sent = static_cast<uint8_t *>(calloc(sizeof(socket->faces_sent[0]), get_faces_count()));
1508  socket->faces_sent_len = get_faces_count();
1509 }
1510 
1511 void command_recollect(object *op, const char *params) {
1512  (void)op;
1513  (void)params;
1514  load_assets();
1515 
1516  // To prevent negative speeds from sneaking through, we need to finalize the archetypes.
1517  // Negative speeds on monsters are caught and changed to .005-ish, so we need to make
1518  // sure they're right now rather than later.
1520 
1521  // Clear sent faces for connected sockets so that clients see new faces.
1522  for (int i = 0; i < socket_info.allocated_sockets; i++) {
1523  /*
1524  if (init_sockets[i].status == Ns_Add) {
1525  reset_faces_sent(&init_sockets[i]);
1526  }
1527  */
1528  }
1529 
1530  player *next;
1531  for (player *pl = first_player; pl != NULL; pl = next) {
1532  reset_faces_sent(pl->socket);
1533  next = pl->next;
1534  }
1535 }
1536 
1545 void command_remove(object *op, const char *params) {
1546  object *tmp;
1547  int from;
1548 
1549  tmp = get_dm_object(op->contr, &params, &from);
1550  if (!tmp) {
1552  "Remove what object (nr)?");
1553  return;
1554  }
1555 
1556  if (tmp->type == PLAYER) {
1558  "Unable to remove a player!");
1559  return;
1560  }
1561 
1562  if (QUERY_FLAG(tmp, FLAG_REMOVED)) {
1563  char name[MAX_BUF];
1564 
1567  "%s is already removed!",
1568  name);
1569  return;
1570  }
1571 
1572  if (from != STACK_FROM_STACK)
1573  /* Item is either stack top, or is a number thus is now stack top, let's remove it */
1574  dm_stack_pop(op->contr);
1575 
1576  /* Always work on the head - otherwise object will get in odd state */
1577  tmp = HEAD(tmp);
1578  if (tmp->speed != 0) {
1579  tmp->speed = 0;
1581  }
1582  object_remove(tmp);
1583 }
1584 
1592 void command_free(object *op, const char *params) {
1593  object *tmp;
1594  int from;
1595 
1596  tmp = get_dm_object(op->contr, &params, &from);
1597 
1598  if (!tmp) {
1600  "Free what object (nr)?");
1601  return;
1602  }
1603 
1604  if (from != STACK_FROM_STACK)
1605  /* Item is either stack top, or is a number thus is now stack top, let's remove it */
1606  dm_stack_pop(op->contr);
1607 
1608  tmp = HEAD(tmp);
1609  if (!QUERY_FLAG(tmp, FLAG_REMOVED)) {
1611  "Warning: item was not removed, will do so now.");
1612  object_remove(tmp);
1613  }
1614 
1616 }
1617 
1618 void command_accountpasswd(object *op, const char *params) {
1619  char account_name[MAX_BUF], newpw[MAX_BUF];
1620  // Password may contain spaces, so use %[^\n] format string.
1621  if (sscanf(params, "%s %[^\n]", account_name, newpw) != 2) {
1623  "Usage: accountpasswd ACCOUNT PASSWORD");
1624  return;
1625  }
1626 
1627  int ret = account_change_password(account_name, NULL, newpw);
1628  switch (ret) {
1629  case 0:
1631  "Updated account password.");
1632  return;
1633  case 1:
1635  "Invalid characters in new password.");
1636  return;
1637  case 2:
1639  "Invalid characters in new password.");
1640  return;
1641  default:
1643  "Error changing password.");
1644  return;
1645  }
1646 }
1647 
1656 void command_addexp(object *op, const char *params) {
1657  char buf[MAX_BUF], skill[MAX_BUF];
1658  int i, q;
1659  object *skillob = NULL;
1660  player *pl;
1661 
1662  skill[0] = '\0';
1663  if ((*params == '\0')
1664  || (strlen(params) > MAX_BUF)
1665  || ((q = sscanf(params, "%s %d %[^\r\n]", buf, &i, skill)) < 2)) {
1667  "Usage: addexp player quantity [skill].");
1668  return;
1669  }
1670 
1671  for (pl = first_player; pl != NULL; pl = pl->next)
1672  if (!strncmp(pl->ob->name, buf, MAX_NAME))
1673  break;
1674 
1675  if (pl == NULL) {
1677  "No such player.");
1678  return;
1679  }
1680 
1681  if (q >= 3) {
1682  skillob = find_skill_by_name(pl->ob, skill);
1683  if (!skillob) {
1685  "Unable to find skill %s in %s",
1686  skill, buf);
1687  return;
1688  }
1689 
1690  i = check_exp_adjust(skillob, i);
1691  skillob->stats.exp += i;
1692  calc_perm_exp(skillob);
1693  player_lvl_adj(pl->ob, skillob);
1694  }
1695 
1696  pl->ob->stats.exp += i;
1697  calc_perm_exp(pl->ob);
1698  player_lvl_adj(pl->ob, NULL);
1699 
1700  if (settings.real_wiz == FALSE)
1701  SET_FLAG(pl->ob, FLAG_WAS_WIZ);
1702 }
1703 
1712 void command_speed(object *op, const char *params) {
1713  int i;
1714 
1715  if (*params == '\0' || !sscanf(params, "%d", &i)) {
1717  "Current speed is %d",
1718  tick_duration);
1719  return;
1720  }
1721 
1722  set_tick_duration(i);
1723  reset_sleep();
1725  "The speed is changed to %d.",
1726  i);
1727 }
1728 
1729 /**************************************************************************/
1730 /* Mods made by Tyler Van Gorder, May 10-13, 1992. */
1731 /* CSUChico : tvangod@cscihp.ecst.csuchico.edu */
1732 /**************************************************************************/
1733 
1742 void command_stats(object *op, const char *params) {
1743  player *pl;
1744 
1745  if (*params == '\0') {
1747  "Who?");
1748  return;
1749  }
1750 
1752  if (pl == NULL) {
1754  "No such player.");
1755  return;
1756  }
1757 
1759  "[Fixed]Statistics for %s:", pl->ob->name);
1760 
1762  "[fixed]Str : %-2d H.P. : %-4d MAX : %d",
1763  pl->ob->stats.Str, pl->ob->stats.hp, pl->ob->stats.maxhp);
1764 
1766  "[fixed]Dex : %-2d S.P. : %-4d MAX : %d",
1767  pl->ob->stats.Dex, pl->ob->stats.sp, pl->ob->stats.maxsp);
1768 
1770  "[fixed]Con : %-2d AC : %-4d WC : %d",
1771  pl->ob->stats.Con, pl->ob->stats.ac, pl->ob->stats.wc);
1772 
1774  "[fixed]Int : %-2d Damage : %d",
1775  pl->ob->stats.Int, pl->ob->stats.dam);
1776 
1778  "[fixed]Wis : %-2d EXP : %" FMT64,
1779  pl->ob->stats.Wis, pl->ob->stats.exp);
1780 
1782  "[fixed]Pow : %-2d Grace : %d",
1783  pl->ob->stats.Pow, pl->ob->stats.grace);
1784 
1786  "[fixed]Cha : %-2d Food : %d",
1787  pl->ob->stats.Cha, pl->ob->stats.food);
1788 }
1789 
1799 void command_abil(object *op, const char *params) {
1800  char thing[20], thing2[20];
1801  int iii;
1802  player *pl;
1803 
1804  iii = 0;
1805  thing[0] = '\0';
1806  thing2[0] = '\0';
1807  if (*params == '\0'
1808  || sscanf(params, "%s %s %d", thing, thing2, &iii) != 3
1809  || thing[0] == '\0') {
1811  "Who?");
1812  return;
1813  }
1814 
1815  if (thing2[0] == '\0') {
1817  "You can't change that.");
1818  return;
1819  }
1820 
1821  if (iii < MIN_STAT || iii > settings.max_stat) {
1823  "Illegal range of stat.\n");
1824  return;
1825  }
1826 
1827  for (pl = first_player; pl != NULL; pl = pl->next) {
1828  if (!strcmp(pl->ob->name, thing)) {
1829  if (settings.real_wiz == FALSE)
1830  SET_FLAG(pl->ob, FLAG_WAS_WIZ);
1831  if (!strcmp("str", thing2))
1832  pl->ob->stats.Str = iii, pl->orig_stats.Str = iii;
1833  if (!strcmp("dex", thing2))
1834  pl->ob->stats.Dex = iii, pl->orig_stats.Dex = iii;
1835  if (!strcmp("con", thing2))
1836  pl->ob->stats.Con = iii, pl->orig_stats.Con = iii;
1837  if (!strcmp("wis", thing2))
1838  pl->ob->stats.Wis = iii, pl->orig_stats.Wis = iii;
1839  if (!strcmp("cha", thing2))
1840  pl->ob->stats.Cha = iii, pl->orig_stats.Cha = iii;
1841  if (!strcmp("int", thing2))
1842  pl->ob->stats.Int = iii, pl->orig_stats.Int = iii;
1843  if (!strcmp("pow", thing2))
1844  pl->ob->stats.Pow = iii, pl->orig_stats.Pow = iii;
1846  "%s has been altered.",
1847  pl->ob->name);
1848  fix_object(pl->ob);
1849  return;
1850  }
1851  }
1852 
1854  "No such player.");
1855 }
1856 
1865 void command_reset(object *op, const char *params) {
1866  mapstruct *m;
1867  object *dummy = NULL, *tmp = NULL;
1868  char path[HUGE_BUF];
1869  const char *space, *confirmation = NULL;
1870  int res = 0;
1871 
1872  if (*params == '\0') {
1874  MSG_TYPE_COMMAND_ERROR, "Which map should be reset?");
1875  return;
1876  }
1877 
1878  space = strchr(params, ' ');
1879  if (space != NULL) {
1880  confirmation = params;
1881  params = space + 1;
1882  }
1883 
1884  /* Use the DM's map if the current map was given. */
1885  if (strcmp(params, ".") == 0) {
1886  strlcpy(path, op->map->path, sizeof(path));
1887  } else {
1888  path_combine_and_normalize(op->map->path, params, path, sizeof(path));
1889  }
1890 
1891  m = has_been_loaded(path);
1892  if (m == NULL) {
1894  MSG_TYPE_COMMAND_ERROR, "No such map.");
1895  return;
1896  }
1897 
1898  if (confirmation) {
1899  if (m->unique && (op->map == m)) {
1902  "Cannot reset a unique player map while on it. Use "
1903  "'reset full-reset %s' while standing somewhere else.",
1904  m->path);
1905  return;
1906  }
1907 
1908  if (strncmp("full-reset", confirmation, strlen("full-reset"))) {
1910  MSG_TYPE_COMMAND_ERROR, "Confirm using 'full-reset'.");
1911  return;
1912  }
1913  }
1914 
1915  /* Forbid using reset on our own map when we're in a transport, as
1916  * it has the displeasant effect of crashing the server.
1917  * - gros, July 25th 2006 */
1918  if ((op->contr && op->contr->transport) && (op->map == m)) {
1920  "You need to disembark first.");
1921  return;
1922  }
1923 
1924  strlcpy(path, m->path, sizeof(path));
1925 
1926  sstring reset_group = m->reset_group;
1927  m->reset_group = NULL;
1928 
1929  if (m->in_memory != MAP_SWAPPED) {
1930  if (m->in_memory != MAP_IN_MEMORY) {
1931  LOG(llevError, "Tried to swap out map which was not in memory.\n");
1932  m->reset_group = reset_group;
1933  return;
1934  }
1935 
1936  /*
1937  * Only attempt to remove the player that is doing the reset, and not other
1938  * players or wiz's.
1939  */
1940  if (op->map == m) {
1941  if (strncmp(m->path, "/random/", 8) == 0) {
1942  /* This is not a very satisfying solution - it would be much better
1943  * to recreate a random map with the same seed value as the old one.
1944  * Unfortunately, I think recreating the map would require some
1945  * knowledge about its 'parent', which appears very non-trivial to
1946  * me.
1947  * On the other hand, this should prevent the freeze that this
1948  * situation caused. - gros, 26th July 2006.
1949  */
1951  "You cannot reset a random map when inside it.");
1952  m->reset_group = reset_group;
1953  return;
1954  }
1955 
1956  dummy = object_new();
1957  dummy->map = NULL;
1958  EXIT_X(dummy) = op->x;
1959  EXIT_Y(dummy) = op->y;
1960  EXIT_PATH(dummy) = add_string(op->map->path);
1961  object_remove(op);
1962  op->map = NULL;
1963  tmp = op;
1964  }
1965  res = swap_map(m);
1966  }
1967 
1968  if (res < 0 || m->in_memory != MAP_SWAPPED) {
1969  player *pl;
1970  int playercount = 0;
1971 
1972  /* Need to re-insert player if swap failed for some reason */
1973  if (tmp) {
1974  object_insert_in_map_at(op, m, NULL, 0, op->x, op->y);
1976  }
1977 
1978  if (res < 0 && res != SAVE_ERROR_PLAYER) {
1979  /* no need to warn if player on map, code below checks that. */
1981  "Reset failed, error code: %d.", res);
1982  /* If we somehow (AFAIK this is only possible by DM intervention anyway) get
1983  * on a non-uniquely-loaded unique map (such as by a DM using goto onto a
1984  * unique map template or by creating an exit to a unique map template
1985  * without specifying in that exit that the map is unique), we need to re-insert
1986  * the player without calling enter_exit(), since we trip an assertion failure there.
1987  * If we reach here and tmp is defined, we have already re-inserted the player,
1988  * so we just need to bail.
1989  * -- Neila Hawkins 2023-12-13
1990  */
1991  if (res == SAVE_ERROR_UCREATION) {
1992  m->reset_group = reset_group;
1993  return;
1994  }
1995  }
1996  else {
1998  "Reset failed, couldn't swap map, the following players are on it:");
1999  for (pl = first_player; pl != NULL; pl = pl->next) {
2000  if (pl->ob->map == m && pl->ob != op) {
2002  pl->ob->name);
2003  playercount++;
2004  }
2005  }
2006  if (!playercount)
2008  "hmm, I don't see any other players on this map, something else is the problem.");
2009  m->reset_group = reset_group;
2010  return;
2011  }
2012  }
2013 
2014  FREE_AND_CLEAR_STR_IF(reset_group);
2015 
2016  /* Here, map reset succeeded. */
2017 
2018  if (m && m->in_memory == MAP_SWAPPED) {
2019  if (confirmation) {
2021  LOG(llevDebug, "DM %s fully resetting map %s.\n", op->name, m->path);
2022  } else
2023  LOG(llevDebug, "DM %s resetting map %s.\n", op->name, m->path);
2024 
2025  /* setting this effectively causes an immediate reload */
2026  m->reset_time = 1;
2027  flush_old_maps();
2028  }
2029 
2030  /* Display the appropriate success message. */
2031  if (confirmation) {
2033  MSG_TYPE_COMMAND_DM, "Fully resetting map %s.", path);
2034  } else {
2036  MSG_TYPE_COMMAND_DM, "Resetting map %s.", path);
2037  }
2038 
2039  if (tmp) {
2040  enter_exit(tmp, dummy);
2042  }
2043 
2044  /* Remind the DM how to fully reset the map. */
2045  if (confirmation == NULL) {
2048  "Use 'reset full-reset %s' to fully reset the map.", params);
2049  }
2050 }
2051 
2060 void command_nowiz(object *op, const char *params) { /* 'noadm' is alias */
2061  (void)params;
2065 
2066  if (settings.real_wiz == TRUE)
2068  if (op->contr->hidden) {
2069  unhide(op);
2070  } else
2072  "The Dungeon Master is gone...");
2073 
2074  update_los(op);
2075 }
2076 
2097 static int checkdm(object *op, const char *pl_name, const char *pl_passwd, const char *pl_host) {
2098  FILE *dmfile;
2099  char buf[MAX_BUF];
2100  char line_buf[160], name[160], passwd[160], host[160];
2101 
2102 #ifdef RESTRICTIVE_DM
2103  *pl_name = op->name ? op->name : "*";
2104 #else
2105  (void)op;
2106 #endif
2107 
2108  snprintf(buf, sizeof(buf), "%s/%s", settings.confdir, DMFILE);
2109  if ((dmfile = fopen(buf, "r")) == NULL) {
2110  LOG(llevDebug, "Could not find DM file.\n");
2111  return 0;
2112  }
2113 
2114  while (fgets(line_buf, 160, dmfile) != NULL) {
2115  // Skip empty lines as well as commented ones.
2116  if (line_buf[0] == '#' || line_buf[0] == '\n')
2117  continue;
2118  if (sscanf(line_buf, "%[^:]:%[^:]:%s\n", name, passwd, host) != 3) {
2119  LOG(llevError, "Warning - malformed dm file entry: %s\n", line_buf);
2120  } else if ((!strcmp(name, "*") || (pl_name && !strcmp(pl_name, name)))
2121  && (!strcmp(passwd, "*") || !strcmp(passwd, pl_passwd))
2122  && (!strcmp(host, "*") || !strcmp(host, pl_host))) {
2123  fclose(dmfile);
2124  return (1);
2125  }
2126  }
2127  fclose(dmfile);
2128  return (0);
2129 }
2130 
2145 static int do_wizard_dm(object *op, const char *params, int silent) {
2146  if (!op->contr)
2147  return 0;
2148 
2149  if (QUERY_FLAG(op, FLAG_WIZ)) {
2151  "You are already the Dungeon Master!");
2152  return 0;
2153  }
2154 
2155  if (checkdm(op, op->name, (*params != '\0' ? params : "*"), op->contr->socket->host)) {
2156  SET_FLAG(op, FLAG_WIZ);
2161  "Ok, you are the Dungeon Master!");
2162  /*
2163  * Remove setting flying here - that won't work, because next
2164  * fix_object() is called that will get cleared - proper solution
2165  * is probably something like a wiz_force which gives that and any
2166  * other desired abilities.
2167  */
2168  clear_los(op->contr);
2169 
2170  if (!silent)
2173  "The Dungeon Master has arrived!");
2174 
2175  return 1;
2176  }
2177 
2179  "Sorry Pal, I don't think so.");
2180  return 0;
2181 }
2182 
2194 void command_dm(object *op, const char *params) {
2195  do_wizard_dm(op, params, 0);
2196 }
2197 
2206 void command_invisible(object *op, const char *params) {
2207  (void)params;
2208  if (op) {
2209  op->invisible += 100;
2212  "You turn invisible.");
2213  }
2214 }
2215 
2233 static object *get_spell_by_name(object *op, const char *spell_name) {
2234  archetype *found;
2235  int conflict_found;
2236  size_t spell_name_length;
2237 
2238  /* First check for full name matches. */
2239  conflict_found = 0;
2240  found = NULL;
2241  getManager()->archetypes()->each([&] (auto ar) {
2242  if (ar->clone.type != SPELL)
2243  return;
2244 
2245  if (strncmp(ar->name, "spelldirect_", 12) == 0)
2246  return;
2247 
2248  if (strcmp(ar->clone.name, spell_name) != 0)
2249  return;
2250 
2251  if (found != NULL) {
2252  if (!conflict_found) {
2253  conflict_found = 1;
2255  "More than one archetype matches the spell name %s:",
2256  spell_name);
2258  "- %s",
2259  found->name);
2260  }
2262  "- %s",
2263  ar->name);
2264  return;
2265  }
2266 
2267  found = ar;
2268  });
2269 
2270  /* No match if more more than one archetype matches. */
2271  if (conflict_found)
2272  return NULL;
2273 
2274  /* Return if exactly one archetype matches. */
2275  if (found != NULL)
2276  return arch_to_object(found);
2277 
2278  /* No full match found: now check for partial matches. */
2279  spell_name_length = strlen(spell_name);
2280  conflict_found = 0;
2281  found = NULL;
2282 
2283  getManager()->archetypes()->each([&] (auto ar) {
2284  if (ar->clone.type != SPELL)
2285  return;
2286 
2287  if (strncmp(ar->name, "spelldirect_", 12) == 0)
2288  return;
2289 
2290  if (strncmp(ar->clone.name, spell_name, spell_name_length) != 0)
2291  return;
2292 
2293  if (found != NULL) {
2294  if (!conflict_found) {
2295  conflict_found = 1;
2297  "More than one spell matches %s:",
2298  spell_name);
2300  "- %s",
2301  found->clone.name);
2302  }
2304  "- %s",
2305  ar->clone.name);
2306  return;
2307  }
2308 
2309  found = ar;
2310  });
2311 
2312  /* No match if more more than one archetype matches. */
2313  if (conflict_found)
2314  return NULL;
2315 
2316  /* Return if exactly one archetype matches. */
2317  if (found != NULL)
2318  return arch_to_object(found);
2319 
2320  /* No spell found: just print an error message. */
2322  "The spell %s does not exist.",
2323  spell_name);
2324  return NULL;
2325 }
2326 
2337 static void command_learn_spell_or_prayer(object *op, const char *params, int special_prayer) {
2338  object *tmp;
2339 
2340  if (op->contr == NULL || *params == '\0') {
2342  "Which spell do you want to learn?");
2343  return;
2344  }
2345 
2347  if (tmp == NULL) {
2348  return;
2349  }
2350 
2351  if (check_spell_known(op, tmp->name)) {
2353  "You already know the spell %s.",
2354  tmp->name);
2355  return;
2356  }
2357 
2358  do_learn_spell(op, tmp, special_prayer);
2360 }
2361 
2370 void command_learn_spell(object *op, const char *params) {
2372 }
2373 
2382 void command_learn_special_prayer(object *op, const char *params) {
2384 }
2385 
2395 void command_forget_spell(object *op, const char *params) {
2396  object *spell;
2397 
2398  if (op->contr == NULL || *params == '\0') {
2400  "Which spell do you want to forget?");
2401  return;
2402  }
2403 
2404  spell = lookup_spell_by_name(op, params);
2405  if (spell == NULL) {
2407  "You do not know the spell %s.",
2408  params);
2409  return;
2410  }
2411 
2412  do_forget_spell(op, spell->name);
2413 }
2414 
2423 void command_listplugins(object *op, const char *params) {
2424  (void)params;
2426 }
2427 
2438 void command_loadplugin(object *op, const char *params) {
2439  char buf[MAX_BUF];
2440 
2441  if (*params == '\0') {
2443  "Load which plugin?");
2444  return;
2445  }
2446 
2447  snprintf(buf, sizeof(buf), LIBDIR"/plugins/%s", params);
2448  LOG(llevDebug, "Requested plugin file is %s\n", buf);
2449  if (plugins_init_plugin(buf) == 0) {
2450  LOG(llevInfo, "DM %s loaded plugin %s\n", op->name, params);
2452  "Plugin %s successfully loaded.",
2453  params);
2454  } else
2456  "Could not load plugin %s.",
2457  params);
2458 }
2459 
2470 void command_unloadplugin(object *op, const char *params) {
2471  if (*params == '\0') {
2473  "Remove which plugin?");
2474  return;
2475  }
2476 
2477  if (plugins_remove_plugin(params) == 0) {
2478  LOG(llevInfo, "DM %s unloaded plugin %s\n", op->name, params);
2480  "Plugin %s successfully removed.",
2481  params);
2482  init_signals(); // Restore our signal handlers, some plugins (Python) mess with them
2483  } else
2485  "Could not remove plugin %s.",
2486  params);
2487 }
2488 
2499 void command_dmhide(object *op, const char *params) {
2500  if (!do_wizard_dm(op, params, 1))
2501  return;
2502 
2503  do_wizard_hide(op, 1);
2504 }
2505 
2514 void command_stack_pop(object *op, const char *params) {
2515  (void)params;
2516  dm_stack_pop(op->contr);
2517 }
2518 
2527 void command_stack_push(object *op, const char *params) {
2528  object *ob;
2529  int from;
2530  ob = get_dm_object(op->contr, &params, &from);
2531 
2532  if (ob && from != STACK_FROM_NUMBER)
2533  /* Object was from stack, need to push it again */
2534  dm_stack_push(op->contr, ob->count);
2535 }
2536 
2545 void command_stack_list(object *op, const char *params) {
2546  int item;
2547  object *display;
2548  player *pl = op->contr;
2549  (void)params;
2550 
2552  "Item stack contents:");
2553 
2554  for (item = 0; item < pl->stack_position; item++) {
2555  display = object_find_by_tag_global(pl->stack_items[item]);
2556  if (display)
2558  " %d : %s [%d]",
2559  item, display->name, display->count);
2560  else
2561  /* Item was freed */
2563  " %d : (lost item: %d)",
2564  item, pl->stack_items[item]);
2565  }
2566 }
2567 
2576 void command_stack_clear(object *op, const char *params) {
2577  (void)params;
2578  op->contr->stack_position = 0;
2580  "Item stack cleared.");
2581 }
2582 
2602 void command_diff(object *op, const char *params) {
2603  object *left, *right;
2604  char *diff;
2605  StringBuffer *sb;
2606  int left_from, right_from;
2607 
2608  left = get_dm_object(op->contr, &params, &left_from);
2609  if (!left) {
2611  "Compare to what item?");
2612  return;
2613  }
2614 
2615  if (left_from == STACK_FROM_NUMBER)
2616  /* Item was stacked, remove it else right will be the same... */
2617  dm_stack_pop(op->contr);
2618 
2619  right = get_dm_object(op->contr, &params, &right_from);
2620 
2621  if (!right) {
2623  "Compare what item?");
2624  return;
2625  }
2626 
2628  "Item difference:");
2629 
2630  if (left_from == STACK_FROM_TOP && right_from == STACK_FROM_TOP) {
2631  /*
2632  * Special case: both items were taken from stack top.
2633  * Override the behaviour, taking left as item just below top, if exists.
2634  * See function description for why.
2635  * Besides, if we don't do anything, compare an item to itself, not really useful.
2636  */
2637  if (op->contr->stack_position > 1) {
2638  left = object_find_by_tag_global(op->contr->stack_items[op->contr->stack_position-2]);
2639  if (left)
2641  "(Note: first item taken from undertop)");
2642  else
2643  /* Stupid case: item under top was freed, fallback to stack top */
2644  left = right;
2645  }
2646  }
2647 
2648  sb = stringbuffer_new();
2649  get_ob_diff(sb, left, right);
2650  diff = stringbuffer_finish(sb);
2651  if (*diff == '\0') {
2652  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_DM, "Objects are the same.");
2653  } else {
2655  }
2656  free(diff);
2657 }
2658 
2666 void command_insert_into(object *op, const char *params) {
2667  object *left, *right, *inserted;
2668  int left_from, right_from;
2669  char what[MAX_BUF], where[MAX_BUF];
2670 
2671  left = get_dm_object(op->contr, &params, &left_from);
2672  if (!left) {
2674  "Insert into what object?");
2675  return;
2676  }
2677 
2678  if (left_from == STACK_FROM_NUMBER)
2679  /* Item was stacked, remove it else right will be the same... */
2680  dm_stack_pop(op->contr);
2681 
2682  right = get_dm_object(op->contr, &params, &right_from);
2683 
2684  if (!right) {
2686  "Insert what item?");
2687  return;
2688  }
2689 
2690  if (left_from == STACK_FROM_TOP && right_from == STACK_FROM_TOP) {
2691  /*
2692  * Special case: both items were taken from stack top.
2693  * Override the behaviour, taking left as item just below top, if exists.
2694  * See function description for why.
2695  * Besides, can't insert an item into itself.
2696  */
2697  if (op->contr->stack_position > 1) {
2698  left = object_find_by_tag_global(op->contr->stack_items[op->contr->stack_position-2]);
2699  if (left)
2701  "(Note: item to insert into taken from undertop)");
2702  else
2703  /* Stupid case: item under top was freed, fallback to stack top */
2704  left = right;
2705  }
2706  }
2707 
2708  if (left == right) {
2710  "Can't insert an object into itself!");
2711  return;
2712  }
2713 
2714  if (right->type == PLAYER) {
2716  "Can't insert a player into something!");
2717  return;
2718  }
2719 
2720  if (!QUERY_FLAG(right, FLAG_REMOVED))
2721  object_remove(right);
2722  inserted = object_insert_in_ob(right, left);
2723  if (left->type == PLAYER) {
2724  if (inserted != right)
2725  /* item was merged, so updating name and such. */
2726  esrv_update_item(UPD_WEIGHT|UPD_NAME|UPD_NROF, left, inserted);
2727  }
2728  query_name(inserted, what, MAX_BUF);
2729  query_name(left, where, MAX_BUF);
2731  "Inserted %s in %s",
2732  what, where);
2733 }
2734 
2743 void command_style_map_info(object *op, const char *params) {
2744  extern mapstruct *styles;
2745  mapstruct *mp;
2746  int maps_used = 0, mapmem = 0, objects_used = 0, x, y;
2747  (void)params;
2748 
2749  for (mp = styles; mp != NULL; mp = mp->next) {
2750  maps_used++;
2751  mapmem += map_size(mp) * (sizeof(object *)+sizeof(MapSpace))+sizeof(mapstruct);
2752  for (x = 0; x < MAP_WIDTH(mp); x++) {
2753  for (y = 0; y < MAP_HEIGHT(mp); y++) {
2754  FOR_MAP_PREPARE(mp, x, y, tmp)
2755  objects_used++;
2756  FOR_MAP_FINISH();
2757  }
2758  }
2759  }
2761  "[fixed]Style maps loaded: %d",
2762  maps_used);
2764  "[fixed]Memory used, not");
2766  "[fixed]including objects: %d",
2767  mapmem);
2769  "[fixed]Style objects: %d",
2770  objects_used);
2772  "[fixed]Mem for objects: %lu",
2773  (unsigned long)(objects_used*sizeof(object)));
2774 }
2775 
2776 bool can_follow(object* op, player* other) {
2777  // Only allow follow from same party.
2778  return (other->ob->contr->party != NULL) && (op->contr->party == other->ob->contr->party);
2779 }
2780 
2789 void command_follow(object *op, const char *params) {
2790  player *other;
2791 
2792  if (*params == '\0') {
2793  if (op->contr->followed_player != NULL) {
2794  draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_SUCCESS, "You stop following %s.", op->contr->followed_player);
2795  FREE_AND_CLEAR_STR(op->contr->followed_player);
2796  }
2797  return;
2798  }
2799 
2801  if (!other) {
2802  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_FAILURE, "No such player or ambiguous name.");
2803  return;
2804  }
2805  if (other == op->contr) {
2806  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_FAILURE, "You can't follow yourself.");
2807  return;
2808  }
2809 
2810  // Players trying to 'follow' are subject to additional checks.
2811  if (!QUERY_FLAG(op, FLAG_WIZ)) {
2812  if (!can_follow(op, other)) {
2815  "You can only follow members in the same party.");
2816  return;
2817  }
2818  rv_vector rv;
2819  if (!get_rangevector(op, other->ob, &rv, 0) || rv.distance > 1) {
2820  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_FAILURE, "You need to go to them first!");
2821  return;
2822  }
2824  }
2825 
2826  if (op->contr->followed_player)
2827  FREE_AND_CLEAR_STR(op->contr->followed_player);
2828 
2829  op->contr->followed_player = add_string(other->ob->name);
2830  draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_SUCCESS, "Following %s.", op->contr->followed_player);
2831 }
2832 
2833 void command_purge_quest(object *op, const char * param) {
2834  (void)param;
2835  free_quest();
2836  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, "Purged quest state.");
2837 }
2838 
2839 void command_purge_quest_definitions(object *op, const char * param) {
2840  (void)param;
2842  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, "Purged quests definitions.");
2843 }
2844 
2845 void do_dump(object *who, object *what) {
2846  StringBuffer *sb;
2847  char *diff;
2848 
2849  sb = stringbuffer_new();
2850  object_dump(what, sb);
2851  diff = stringbuffer_finish(sb);
2853  free(diff);
2854 
2855  /* Let's push that item on the dm's stack */
2856  dm_stack_push(who->contr, what->count);
2857 }
2858 
2867 void command_dumpbelow(object *op, const char *params) {
2868  (void)params;
2869  if (op && op->below) {
2870  do_dump(op, op->below);
2871  }
2872 }
2873 
2882 void command_dumpabove(object *op, const char *params) {
2883  (void)params;
2884  if (op && op->above) {
2885  do_dump(op, op->above);
2886  }
2887 }
2888 
2894 void command_settings(object *op, const char *ignored) {
2895  (void)ignored;
2896  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, "Server settings:");
2897 
2899 
2900  if (settings.not_permadeth) {
2901  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, " * death is not permanent");
2902  } else if (settings.resurrection) {
2903  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, " * permanent death, resurrection is enabled");
2904  } else {
2905  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, " * permanent death, resurrection is NOT enabled");
2906  }
2907 
2908  if (settings.set_title) {
2909  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, " * players can set their title");
2910  } else {
2911  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, " * players can't set their title");
2912  }
2913 
2916  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, " * too much equipment can lead to spell failure and ill effects");
2917  } else {
2918  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, " * too much equipment can lead to spell failure but no ill effects");
2919  }
2920  } else {
2921  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, " * too much equipment can't lead to spell failure");
2922  }
2923 
2924  if (settings.casting_time) {
2925  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, " * casting takes time");
2926  } else {
2927  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, " * casting is immediate");
2928  }
2929 
2932 
2934 
2936  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, " * players can't steal from other players");
2937  } else {
2938  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, " * players can steal from other players");
2939  }
2940 
2942  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, " * players can create portals from their apartments");
2943  } else {
2944  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, " * players can't create portals from their apartments");
2945  }
2946 
2948  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, " * players can write spells they are denied");
2949  } else {
2950  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, " * players can't write spells they are denied");
2951  }
2952 }
Settings::casting_time
uint8_t casting_time
Definition: global.h:270
get_other_player_from_name
static player * get_other_player_from_name(object *op, const char *name)
Definition: c_wiz.cpp:60
give.next
def next
Definition: give.py:44
command_overlay_reset
void command_overlay_reset(object *op, const char *params)
Definition: c_wiz.cpp:589
command_possess
void command_possess(object *op, const char *params)
Definition: c_wiz.cpp:1412
STACK_FROM_NONE
@ STACK_FROM_NONE
Definition: c_wiz.cpp:38
living::exp
int64_t exp
Definition: living.h:47
UP_OBJ_FACE
#define UP_OBJ_FACE
Definition: object.h:533
PLAYER
@ PLAYER
Definition: object.h:112
set_magic
static void set_magic(int difficulty, object *op, int max_magic, int flags)
Definition: treasure.cpp:666
FREE_AND_CLEAR_STR_IF
#define FREE_AND_CLEAR_STR_IF(xyz)
Definition: global.h:200
global.h
FREE_OBJ_NO_DESTROY_CALLBACK
#define FREE_OBJ_NO_DESTROY_CALLBACK
Definition: object.h:545
first_player
player * first_player
Definition: init.cpp:106
settings
struct Settings settings
Definition: init.cpp:139
set_abs_magic
void set_abs_magic(object *op, int magic)
Definition: treasure.cpp:618
STACK_SIZE
#define STACK_SIZE
Definition: c_wiz.cpp:35
safe_strncpy
#define safe_strncpy
Definition: compat.h:27
FOR_MAP_FINISH
#define FOR_MAP_FINISH()
Definition: define.h:730
STACK_FROM_NUMBER
@ STACK_FROM_NUMBER
Definition: c_wiz.cpp:41
command_overlay_save
void command_overlay_save(object *op, const char *params)
Definition: c_wiz.cpp:568
NUM_BODY_LOCATIONS
#define NUM_BODY_LOCATIONS
Definition: object.h:15
MSG_TYPE_COMMAND_SUCCESS
#define MSG_TYPE_COMMAND_SUCCESS
Definition: newclient.h:519
command_style_map_info
void command_style_map_info(object *op, const char *params)
Definition: c_wiz.cpp:2743
llevError
@ llevError
Definition: logger.h:11
WAND
@ WAND
Definition: object.h:225
MSG_TYPE_ADMIN_PLAYER
#define MSG_TYPE_ADMIN_PLAYER
Definition: newclient.h:485
LOG
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.cpp:58
SHUTDOWN_IDLE
@ SHUTDOWN_IDLE
Definition: commands.h:44
SET_FLAG
#define SET_FLAG(xyz, p)
Definition: define.h:224
reset_faces_sent
static void reset_faces_sent(struct socket_struct *socket)
Definition: c_wiz.cpp:1505
archetype::more
archetype * more
Definition: object.h:486
command_patch
void command_patch(object *op, const char *params)
Definition: c_wiz.cpp:1473
player
Definition: player.h:105
Settings::resurrection
uint8_t resurrection
Definition: global.h:266
diamondslots.x
x
Definition: diamondslots.py:15
QUERY_FLAG
#define QUERY_FLAG(xyz, p)
Definition: define.h:226
plugins_remove_plugin
int plugins_remove_plugin(const char *id)
Definition: plugins.cpp:454
plugins_init_plugin
int plugins_init_plugin(const char *libfile)
Definition: plugins.cpp:373
Settings::set_title
uint8_t set_title
Definition: global.h:265
AssetsManager.h
do_learn_spell
void do_learn_spell(object *op, object *spell, int special_prayer)
Definition: apply.cpp:484
command_shutdown
void command_shutdown(object *op, const char *params)
Definition: c_wiz.cpp:658
has_been_loaded
mapstruct * has_been_loaded(const char *name)
Definition: map.cpp:79
socket_struct
Definition: newserver.h:89
Socket_Info::allocated_sockets
int allocated_sockets
Definition: newserver.h:144
flush_old_maps
void flush_old_maps(void)
Definition: swap.cpp:291
esrv_new_player
void esrv_new_player(player *pl, uint32_t weight)
Definition: request.cpp:1015
FALSE
#define FALSE
Definition: compat.h:14
Settings::not_permadeth
uint8_t not_permadeth
Definition: global.h:262
banquet.size_x
int size_x
Definition: banquet.py:23
command_speed
void command_speed(object *op, const char *params)
Definition: c_wiz.cpp:1712
Settings::permanent_exp_ratio
uint8_t permanent_exp_ratio
Definition: global.h:258
esrv_send_inventory
void esrv_send_inventory(object *pl, object *op)
Definition: item.cpp:316
do_wizard_dm
static int do_wizard_dm(object *op, const char *params, int silent)
Definition: c_wiz.cpp:2145
command_learn_spell
void command_learn_spell(object *op, const char *params)
Definition: c_wiz.cpp:2370
Settings::datadir
const char * datadir
Definition: global.h:248
stringbuffer_new
StringBuffer * stringbuffer_new(void)
Definition: stringbuffer.cpp:57
UPD_WEIGHT
#define UPD_WEIGHT
Definition: newclient.h:305
if
if(!(yy_init))
Definition: loader.cpp:36428
object_set_enemy
void object_set_enemy(object *op, object *enemy)
Definition: object.cpp:915
artifactlist::items
std::vector< artifact * > items
Definition: artifact.h:28
dm_stack_pop
static void dm_stack_pop(player *pl)
Definition: c_wiz.cpp:95
EXIT_PATH
#define EXIT_PATH(xyz)
Definition: define.h:439
FLAG_OBJ_ORIGINAL
#define FLAG_OBJ_ORIGINAL
Definition: define.h:357
player::ob
object * ob
Definition: player.h:177
give_artifact_abilities
void give_artifact_abilities(object *op, const object *artifact)
Definition: artifact.cpp:230
socket_info
Socket_Info socket_info
Definition: init.cpp:49
object::map
struct mapstruct * map
Definition: object.h:305
command_arrest
void command_arrest(object *op, const char *params)
Definition: c_wiz.cpp:821
Settings::worldmaptilesy
uint32_t worldmaptilesy
Definition: global.h:294
command_teleport
void command_teleport(object *op, const char *params)
Definition: c_wiz.cpp:913
guildjoin.ob
ob
Definition: guildjoin.py:42
command_mon_aggr
void command_mon_aggr(object *op, const char *params)
Definition: c_wiz.cpp:1385
artifact::item
object * item
Definition: artifact.h:15
dm_stack_push
static void dm_stack_push(player *pl, tag_t item)
Definition: c_wiz.cpp:150
check_exp_adjust
int64_t check_exp_adjust(const object *op, int64_t exp)
Definition: living.cpp:2091
Settings::worldmapstartx
uint32_t worldmapstartx
Definition: global.h:291
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
command_purge_quest
void command_purge_quest(object *op, const char *param)
Definition: c_wiz.cpp:2833
calc_perm_exp
void calc_perm_exp(object *op)
Definition: living.cpp:1903
unhide
static void unhide(object *op)
Definition: c_wiz.cpp:333
do_dump
void do_dump(object *who, object *what)
Definition: c_wiz.cpp:2845
object::count
tag_t count
Definition: object.h:307
FLAG_WIZCAST
#define FLAG_WIZCAST
Definition: define.h:289
object_copy
void object_copy(const object *src_ob, object *dest_ob)
Definition: object.cpp:1192
command_invisible
void command_invisible(object *op, const char *params)
Definition: c_wiz.cpp:2206
fix_object
void fix_object(object *op)
Definition: living.cpp:1125
Ice.tmp
int tmp
Definition: Ice.py:207
command_banish
void command_banish(object *op, const char *params)
Definition: c_wiz.cpp:502
NDI_RED
#define NDI_RED
Definition: newclient.h:234
UPD_NROF
#define UPD_NROF
Definition: newclient.h:310
plugins_display_list
void plugins_display_list(object *op)
Definition: plugins.cpp:479
command_addexp
void command_addexp(object *op, const char *params)
Definition: c_wiz.cpp:1656
command_listplugins
void command_listplugins(object *op, const char *params)
Definition: c_wiz.cpp:2423
skills.h
npc_dialog.filename
filename
Definition: npc_dialog.py:99
MSG_TYPE_COMMAND_ERROR
#define MSG_TYPE_COMMAND_ERROR
Definition: newclient.h:518
object_find_by_tag_global
object * object_find_by_tag_global(tag_t i)
Definition: object.cpp:727
create_treasure
void create_treasure(treasurelist *t, object *op, int flag, int difficulty, int tries)
Definition: treasure.cpp:263
buf
StringBuffer * buf
Definition: readable.cpp:1565
set_tick_duration
void set_tick_duration(long t)
Definition: time.cpp:209
getManager
AssetsManager * getManager()
Definition: assets.cpp:305
object_insert_in_ob
object * object_insert_in_ob(object *op, object *where)
Definition: object.cpp:2853
banquet.size_y
int size_y
Definition: banquet.py:24
HUGE_BUF
#define HUGE_BUF
Definition: define.h:37
MAX
#define MAX(x, y)
Definition: compat.h:24
MSG_TYPE_COMMAND
#define MSG_TYPE_COMMAND
Definition: newclient.h:393
find_god
const object * find_god(const char *name)
Definition: holy.cpp:317
NDI_ORANGE
#define NDI_ORANGE
Definition: newclient.h:235
SAVE_MODE_OVERLAY
#define SAVE_MODE_OVERLAY
Definition: map.h:118
Settings::worldmaptilesx
uint32_t worldmaptilesx
Definition: global.h:293
FLAG_ALIVE
#define FLAG_ALIVE
Definition: define.h:230
command_learn_special_prayer
void command_learn_special_prayer(object *op, const char *params)
Definition: c_wiz.cpp:2382
Ns_Dead
@ Ns_Dead
Definition: newserver.h:67
command_remove
void command_remove(object *op, const char *params)
Definition: c_wiz.cpp:1545
map_remove_unique_files
void map_remove_unique_files(const mapstruct *map)
Definition: map.cpp:2668
MSG_TYPE_ADMIN_DM
#define MSG_TYPE_ADMIN_DM
Definition: newclient.h:486
MSG_TYPE_COMMAND_DEBUG
#define MSG_TYPE_COMMAND_DEBUG
Definition: newclient.h:517
ASSETS_QUESTS
#define ASSETS_QUESTS
Definition: assets.h:30
Settings::spell_encumbrance
uint8_t spell_encumbrance
Definition: global.h:268
m
static event_registration m
Definition: citylife.cpp:425
clear_los
void clear_los(player *pl)
Definition: los.cpp:270
autojail.who
who
Definition: autojail.py:3
MAP_IN_MEMORY
#define MAP_IN_MEMORY
Definition: map.h:126
stringbuffer_finish
char * stringbuffer_finish(StringBuffer *sb)
Definition: stringbuffer.cpp:76
object_free_drop_inventory
void object_free_drop_inventory(object *ob)
Definition: object.cpp:1560
object_update
void object_update(object *op, int action)
Definition: object.cpp:1434
shutdown_s::time
time_t time
Definition: commands.h:49
object::contr
struct player * contr
Definition: object.h:284
item.q
q
Definition: item.py:32
FMT64
#define FMT64
Definition: compat.h:16
command_toggle_shout
void command_toggle_shout(object *op, const char *params)
Definition: c_wiz.cpp:615
map_size
uint32_t map_size(mapstruct *m)
Definition: map.cpp:799
command_setgod
void command_setgod(object *op, const char *params)
Definition: c_wiz.cpp:418
FLAG_WAS_WIZ
#define FLAG_WAS_WIZ
Definition: define.h:234
freearr_y
short freearr_y[SIZEOFFREE]
Definition: object.cpp:305
command_create
void command_create(object *op, const char *params)
Definition: c_wiz.cpp:979
Settings::death_penalty_ratio
uint8_t death_penalty_ratio
Definition: global.h:259
command_reset
void command_reset(object *op, const char *params)
Definition: c_wiz.cpp:1865
do_wizard_hide
static void do_wizard_hide(object *op, int silent_dm)
Definition: c_wiz.cpp:352
query_name
void query_name(const object *op, char *buf, size_t size)
Definition: item.cpp:588
POTION
@ POTION
Definition: object.h:116
command_summon
void command_summon(object *op, const char *params)
Definition: c_wiz.cpp:866
Settings::set_friendly_fire
uint16_t set_friendly_fire
Definition: global.h:275
path_combine_and_normalize
char * path_combine_and_normalize(const char *src, const char *dst, char *path, size_t size)
Definition: path.cpp:172
MSG_TYPE_COMMAND_DM
#define MSG_TYPE_COMMAND_DM
Definition: newclient.h:524
command_purge_quest_definitions
void command_purge_quest_definitions(object *op, const char *param)
Definition: c_wiz.cpp:2839
archetype::clone
object clone
Definition: object.h:487
STACK_FROM_TOP
@ STACK_FROM_TOP
Definition: c_wiz.cpp:39
object_dump
void object_dump(const object *op, StringBuffer *sb)
Definition: object.cpp:645
sword_of_souls.victim
victim
Definition: sword_of_souls.py:12
Settings::worldmapstarty
uint32_t worldmapstarty
Definition: global.h:292
add_string
sstring add_string(const char *str)
Definition: shstr.cpp:124
HEAD
#define HEAD(op)
Definition: object.h:607
ROD
@ ROD
Definition: object.h:114
free_quest
void free_quest(void)
Definition: quest.cpp:891
shutdown_s::type
enum shutdown_type type
Definition: commands.h:48
make_face_from_files.str
str
Definition: make_face_from_files.py:30
python_init.path
path
Definition: python_init.py:8
command_dm
void command_dm(object *op, const char *params)
Definition: c_wiz.cpp:2194
out_of_map
int out_of_map(mapstruct *m, int x, int y)
Definition: map.cpp:2289
shutdown_s
Definition: commands.h:47
command_abil
void command_abil(object *op, const char *params)
Definition: c_wiz.cpp:1799
lookup_spell_by_name
object * lookup_spell_by_name(object *op, const char *spname)
Definition: spell_util.cpp:410
command_dumpbelow
void command_dumpbelow(object *op, const char *params)
Definition: c_wiz.cpp:2867
command_diff
void command_diff(object *op, const char *params)
Definition: c_wiz.cpp:2602
object_update_speed
void object_update_speed(object *op)
Definition: object.cpp:1349
object::type
uint8_t type
Definition: object.h:348
command_inventory
void command_inventory(object *op, const char *params)
Definition: c_wiz.cpp:1315
do_goto
void do_goto(object *op, const char *name, int x, int y)
Definition: c_move.cpp:151
command_help
void command_help(object *op, const char *params)
Definition: c_misc.cpp:1772
shutdown_state
struct shutdown_s shutdown_state
Definition: c_wiz.cpp:44
show_skills
void show_skills(object *op, const char *search)
Definition: skill_util.cpp:860
command_skills
void command_skills(object *op, const char *params)
Definition: c_wiz.cpp:1345
object_create_arch
object * object_create_arch(archetype *at)
Definition: arch.cpp:298
player_lvl_adj
void player_lvl_adj(object *who, object *op)
Definition: living.cpp:1819
FLAG_WIZPASS
#define FLAG_WIZPASS
Definition: define.h:314
object_free
void object_free(object *ob, int flags)
Definition: object.cpp:1592
command_dumpabove
void command_dumpabove(object *op, const char *params)
Definition: c_wiz.cpp:2882
Settings::item_power_factor
float item_power_factor
Definition: global.h:303
MAX_NAME
#define MAX_NAME
Definition: define.h:41
DMFILE
#define DMFILE
Definition: config.h:369
command_insert_into
void command_insert_into(object *op, const char *params)
Definition: c_wiz.cpp:2666
FLAG_UNAGGRESSIVE
#define FLAG_UNAGGRESSIVE
Definition: define.h:272
assets_finish_archetypes_for_play
void assets_finish_archetypes_for_play()
Definition: assets.cpp:509
tag_t
uint32_t tag_t
Definition: object.h:14
archetype
Definition: object.h:483
Settings::confdir
const char * confdir
Definition: global.h:247
sproto.h
AssetsCollection::each
void each(std::function< void(T *)> op)
Definition: AssetsCollection.h:158
MapSpace
Definition: map.h:254
MSG_SUBTYPE_NONE
#define MSG_SUBTYPE_NONE
Definition: newclient.h:409
become_follower
int become_follower(object *op, const object *new_god)
Definition: gods.cpp:413
command_goto
void command_goto(object *op, const char *params)
Definition: c_wiz.cpp:724
init_signals
void init_signals()
Definition: init.cpp:1310
Settings::death_penalty_level
uint8_t death_penalty_level
Definition: global.h:260
SHUTDOWN_NONE
@ SHUTDOWN_NONE
Definition: commands.h:42
nlohmann::detail::void
j template void())
Definition: json.hpp:4099
object_insert_in_map_at
object * object_insert_in_map_at(object *op, mapstruct *m, object *originator, int flag, int x, int y)
Definition: object.cpp:2100
object::other_arch
struct archetype * other_arch
Definition: object.h:425
FLAG_MONSTER
#define FLAG_MONSTER
Definition: define.h:245
find_skill_by_name
object * find_skill_by_name(object *who, const char *name)
Definition: skill_util.cpp:211
MAP_WIDTH
#define MAP_WIDTH(m)
Definition: map.h:73
command_kick
void command_kick(object *op, const char *params)
Definition: c_wiz.cpp:556
command_loadtest
void command_loadtest(object *op, const char *params)
Definition: c_wiz.cpp:306
AssetsManager::archetypes
Archetypes * archetypes()
Definition: AssetsManager.h:44
treasure.h
EXIT_X
#define EXIT_X(xyz)
Definition: define.h:441
MAX_BUF
#define MAX_BUF
Definition: define.h:35
strlcpy
size_t strlcpy(char *dst, const char *src, size_t size)
Definition: porting.cpp:222
object_new
object * object_new(void)
Definition: object.cpp:1273
create_overlay_pathname
void create_overlay_pathname(const char *name, char *buf, size_t size)
Definition: map.cpp:125
monster_check_apply_all
void monster_check_apply_all(object *monster)
Definition: monster.cpp:1999
command_hide
void command_hide(object *op, const char *params)
Definition: c_wiz.cpp:389
SAVE_ERROR_UCREATION
#define SAVE_ERROR_UCREATION
Definition: map.h:141
StringBuffer
Definition: stringbuffer.cpp:25
FREE_AND_CLEAR_STR
#define FREE_AND_CLEAR_STR(xyz)
Definition: global.h:198
command_freeze
void command_freeze(object *op, const char *params)
Definition: c_wiz.cpp:745
Settings::spell_failure_effects
uint8_t spell_failure_effects
Definition: global.h:269
is_valid_types_gen.found
found
Definition: is_valid_types_gen.py:39
MSG_TYPE_COMMAND_FAILURE
#define MSG_TYPE_COMMAND_FAILURE
Definition: newclient.h:520
FOR_MAP_PREPARE
#define FOR_MAP_PREPARE(map_, mx_, my_, it_)
Definition: define.h:723
load_assets
void load_assets(void)
Definition: init.cpp:312
ST_PLAYING
#define ST_PLAYING
Definition: define.h:541
command_forget_spell
void command_forget_spell(object *op, const char *params)
Definition: c_wiz.cpp:2395
FLAG_REMOVED
#define FLAG_REMOVED
Definition: define.h:232
Settings::allow_denied_spells_writing
int allow_denied_spells_writing
Definition: global.h:315
command_nowiz
void command_nowiz(object *op, const char *params)
Definition: c_wiz.cpp:2060
FLAG_WIZ
#define FLAG_WIZ
Definition: define.h:231
styles
mapstruct * styles
Definition: style.cpp:122
swap_map
int swap_map(mapstruct *map)
Definition: swap.cpp:136
command_loadplugin
void command_loadplugin(object *op, const char *params)
Definition: c_wiz.cpp:2438
llevInfo
@ llevInfo
Definition: logger.h:12
NDI_UNIQUE
#define NDI_UNIQUE
Definition: newclient.h:251
EVENT_MUZZLE
#define EVENT_MUZZLE
Definition: events.h:52
find_archetype_by_object_name
archetype * find_archetype_by_object_name(const char *name)
Definition: arch.cpp:53
FLAG_FRIENDLY
#define FLAG_FRIENDLY
Definition: define.h:246
spells.h
get_jail_exit
object * get_jail_exit(object *op)
Definition: region.cpp:253
object::name
sstring name
Definition: object.h:319
bigchest.check
check
Definition: bigchest.py:10
command_learn_spell_or_prayer
static void command_learn_spell_or_prayer(object *op, const char *params, int special_prayer)
Definition: c_wiz.cpp:2337
BANISHFILE
#define BANISHFILE
Definition: config.h:520
get_spell_by_name
static object * get_spell_by_name(object *op, const char *spell_name)
Definition: c_wiz.cpp:2233
item
Definition: item.py:1
can_follow
bool can_follow(object *op, player *other)
Definition: c_wiz.cpp:2776
is_identifiable_type
int is_identifiable_type(const object *op)
Definition: item.cpp:1324
mapstruct
Definition: map.h:313
enter_exit
void enter_exit(object *op, object *exit_ob)
Definition: server.cpp:738
object_find_by_name_global
object * object_find_by_name_global(const char *str)
Definition: object.cpp:747
check_spell_known
object * check_spell_known(object *op, const char *name)
Definition: spell_util.cpp:394
find_object_both
static object * find_object_both(const char *params)
Definition: c_wiz.cpp:403
SHUTDOWN_TIME
@ SHUTDOWN_TIME
Definition: commands.h:43
sstring
const typedef char * sstring
Definition: sstring.h:2
command_settings
void command_settings(object *op, const char *ignored)
Definition: c_wiz.cpp:2894
give.op
op
Definition: give.py:33
NDI_ALL
#define NDI_ALL
Definition: newclient.h:252
set_variable
int set_variable(object *op, const char *buf)
Definition: loader.cpp:39047
command_stats
void command_stats(object *op, const char *params)
Definition: c_wiz.cpp:1742
command_dump
void command_dump(object *op, const char *params)
Definition: c_wiz.cpp:1357
object_find_free_spot
int object_find_free_spot(const object *ob, mapstruct *m, int x, int y, int start, int stop)
Definition: object.cpp:3555
command_dmhide
void command_dmhide(object *op, const char *params)
Definition: c_wiz.cpp:2499
esrv_update_item
void esrv_update_item(int flags, object *pl, object *op)
Definition: main.cpp:359
command_unloadplugin
void command_unloadplugin(object *op, const char *params)
Definition: c_wiz.cpp:2470
Settings::max_stat
uint8_t max_stat
Definition: global.h:324
rv_vector
Definition: map.h:368
MAP_SWAPPED
#define MAP_SWAPPED
Definition: map.h:127
roll-o-matic.params
params
Definition: roll-o-matic.py:193
reset_sleep
void reset_sleep(void)
Definition: time.cpp:134
EXIT_Y
#define EXIT_Y(xyz)
Definition: define.h:442
diamondslots.y
y
Definition: diamondslots.py:16
assets.h
python_pickup.where
where
Definition: python_pickup.py:7
CLEAR_FLAG
#define CLEAR_FLAG(xyz, p)
Definition: define.h:225
player_arrest
int player_arrest(object *who)
Definition: c_wiz.cpp:789
socket_struct::faces_sent_len
size_t faces_sent_len
Definition: newserver.h:95
command_follow
void command_follow(object *op, const char *params)
Definition: c_wiz.cpp:2789
get_dm_object
static object * get_dm_object(player *pl, const char **params, int *from)
Definition: c_wiz.cpp:196
MAP_HEIGHT
#define MAP_HEIGHT(m)
Definition: map.h:75
tick_duration
uint32_t tick_duration
Definition: time.cpp:35
NDI_DK_ORANGE
#define NDI_DK_ORANGE
Definition: newclient.h:237
get_ob_diff
void get_ob_diff(StringBuffer *sb, const object *op, const object *op2)
Definition: object.cpp:4982
find_player_partial_name
player * find_player_partial_name(const char *plname)
Definition: player.cpp:114
account_change_password
int account_change_password(const char *account_name, const char *current_password, const char *new_password)
Definition: account.cpp:628
socket_struct::faces_sent
uint8_t * faces_sent
Definition: newserver.h:96
arch_to_object
object * arch_to_object(archetype *at)
Definition: arch.cpp:229
object_give_identified_properties
void object_give_identified_properties(object *op)
Definition: item.cpp:1356
get_rangevector
int get_rangevector(object *op1, const object *op2, rv_vector *retval, int flags)
Definition: map.cpp:2522
player::party
partylist * party
Definition: player.h:203
checkdm
static int checkdm(object *op, const char *pl_name, const char *pl_passwd, const char *pl_host)
Definition: c_wiz.cpp:2097
MSG_TYPE_COMMAND_MAPS
#define MSG_TYPE_COMMAND_MAPS
Definition: newclient.h:509
UPD_NAME
#define UPD_NAME
Definition: newclient.h:307
command_accountpasswd
void command_accountpasswd(object *op, const char *params)
Definition: c_wiz.cpp:1618
object::randomitems
struct treasurelist * randomitems
Definition: object.h:395
Settings::real_wiz
uint8_t real_wiz
Definition: global.h:271
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
MSG_TYPE_COMMUNICATION_PARTY
#define MSG_TYPE_COMMUNICATION_PARTY
Definition: newclient.h:616
object_remove
void object_remove(object *op)
Definition: object.cpp:1833
try_find_archetype
archetype * try_find_archetype(const char *name)
Definition: assets.cpp:270
castle_read.playercount
int playercount
Definition: castle_read.py:62
inventory
void inventory(object *op, object *inv)
Definition: c_object.cpp:2167
do_forget_spell
void do_forget_spell(object *op, const char *spell)
Definition: apply.cpp:525
command_kick2
static void command_kick2(object *op, const char *params)
Definition: c_wiz.cpp:468
do_some_living
void do_some_living(object *op)
Definition: player.cpp:3272
STACK_FROM_STACK
@ STACK_FROM_STACK
Definition: c_wiz.cpp:40
save_map
int save_map(mapstruct *m, int flag)
Definition: map.cpp:1396
SCROLL
@ SCROLL
Definition: object.h:226
shutdown_s::next_warn
int next_warn
Definition: commands.h:51
object::nrof
uint32_t nrof
Definition: object.h:342
command_stack_push
void command_stack_push(object *op, const char *params)
Definition: c_wiz.cpp:2527
mapstruct::next
mapstruct * next
Definition: map.h:314
assets_collect
void assets_collect(const char *datadir, int what)
Definition: assets.cpp:113
Settings::no_player_stealing
uint8_t no_player_stealing
Definition: global.h:310
say.item
dictionary item
Definition: say.py:149
object::stats
living stats
Definition: object.h:378
artifact
Definition: artifact.h:14
command_free
void command_free(object *op, const char *params)
Definition: c_wiz.cpp:1592
object::more
object * more
Definition: object.h:303
MSG_TYPE_COMMUNICATION
#define MSG_TYPE_COMMUNICATION
Definition: newclient.h:399
update_los
void update_los(object *op)
Definition: los.cpp:509
get_faces_count
size_t get_faces_count()
Definition: assets.cpp:293
freearr_x
short freearr_x[SIZEOFFREE]
Definition: object.cpp:299
TRUE
#define TRUE
Definition: compat.h:11
command_recollect
void command_recollect(object *op, const char *params)
Definition: c_wiz.cpp:1511
command_stack_pop
void command_stack_pop(object *op, const char *params)
Definition: c_wiz.cpp:2514
SPELL
@ SPELL
Definition: object.h:219
Settings::create_home_portals
uint8_t create_home_portals
Definition: global.h:311
altar_valkyrie.pl
pl
Definition: altar_valkyrie.py:28
find_artifactlist
artifactlist * find_artifactlist(int type)
Definition: artifact.cpp:574
MSG_TYPE_ADMIN
#define MSG_TYPE_ADMIN
Definition: newclient.h:391
rv_vector::distance
unsigned int distance
Definition: map.h:369
SPELLBOOK
@ SPELLBOOK
Definition: object.h:208
EVENT_KICK
#define EVENT_KICK
Definition: events.h:43
SAVE_ERROR_PLAYER
#define SAVE_ERROR_PLAYER
Definition: map.h:148
dm_stack_peek
static object * dm_stack_peek(player *pl)
Definition: c_wiz.cpp:120
altar_valkyrie.res
int res
Definition: altar_valkyrie.py:74
NDI_LT_GREEN
#define NDI_LT_GREEN
Definition: newclient.h:239
events_execute_global_event
void events_execute_global_event(int eventcode,...)
Definition: events.cpp:32
llevDebug
@ llevDebug
Definition: logger.h:13
FLAG_IDENTIFIED
#define FLAG_IDENTIFIED
Definition: define.h:261
command_stack_clear
void command_stack_clear(object *op, const char *params)
Definition: c_wiz.cpp:2576
give.name
name
Definition: give.py:27
command_stack_list
void command_stack_list(object *op, const char *params)
Definition: c_wiz.cpp:2545
Settings::localdir
const char * localdir
Definition: global.h:249