Crossfire Server  1.75.0
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 
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
407  return object_find_by_name_global(params);
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)) {
475  events_execute_global_event(EVENT_KICK, op, *params == '\0' ? NULL : params);
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 
514  pl = get_other_player_from_name(op, params);
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) {
557  command_kick2(op, 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 
594  create_overlay_pathname(op->map->path, filename, MAX_BUF);
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 
624  pl = get_other_player_from_name(op, params);
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 
767  pl = get_other_player_from_name(op, params);
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  }
832  pl = get_other_player_from_name(op, params);
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 
880  pl = get_other_player_from_name(op, params);
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 
907 void command_swap(object *op, const char *params) {
908  if (*params == '\0') {
910  return;
911  }
912 
913  char path[HUGE_BUF];
914  path_combine_and_normalize(op->map->path, params, path, sizeof(path));
915  mapstruct *m = has_been_loaded(path);
916  if (m == NULL || m->in_memory != MAP_IN_MEMORY) {
917  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR, "That map isn't in memory.");
918  return;
919  }
920  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_SUCCESS, "Marked map ready for swapping.");
921  m->timeout = 1; // not zero but one, see check_active_maps()
922 }
923 
932 /* mids 01/16/2002 */
933 void command_teleport(object *op, const char *params) {
934  int i;
935  object *dummy;
936  player *pl;
937 
938  if (!op)
939  return;
940 
941  if (*params == '\0') {
943  "Usage: teleport <player>.");
944  return;
945  }
946 
947  pl = find_player_partial_name(params);
948  if (!pl) {
950  "No such player or ambiguous name.");
951  return;
952  }
953 
954  i = object_find_free_spot(pl->ob, pl->ob->map, pl->ob->x, pl->ob->y, 1, 9);
955  if (i == -1) {
957  "Can not find a free spot to teleport to.");
958  return;
959  }
960 
961  dummy = object_new();
962  EXIT_PATH(dummy) = add_string(pl->ob->map->path);
963  EXIT_X(dummy) = pl->ob->x+freearr_x[i];
964  EXIT_Y(dummy) = pl->ob->y+freearr_y[i];
965  enter_exit(op, dummy);
967  if (!op->contr->hidden)
969  "You see a portal open.");
971  "You teleport to %s",
972  pl->ob->name);
973 }
974 
999 void command_create(object *op, const char *params) {
1000  object *tmp = NULL;
1001  uint32_t i;
1002  int magic, set_magic = 0, set_nrof = 0, gotquote, gotspace;
1003  uint32_t nrof;
1004  char *cp, *bp, *bp2, *bp3, *endline, cpy[MAX_BUF];
1005  archetype *at, *at_spell = NULL;
1006  const artifact *art = NULL;
1007 
1008  if (!op)
1009  return;
1010 
1011  if (*params == '\0') {
1013  "Usage: create [nr] [magic] <archetype> [ of <artifact>] [variable_to_patch setting]");
1014  return;
1015  }
1016  safe_strncpy(cpy, params, sizeof(cpy));
1017  bp = cpy;
1018 
1019  /* We need to know where the line ends */
1020  endline = bp+strlen(bp);
1021 
1022  if (sscanf(bp, "%u ", &nrof)) {
1023  if ((bp = strchr(cpy, ' ')) == NULL) {
1025  "Usage: create [nr] [magic] <archetype> [ of <artifact>] [variable_to_patch setting]");
1026  return;
1027  }
1028  bp++;
1029  set_nrof = 1;
1030  LOG(llevDebug, "%s creates: (%u) %s\n", op->name, nrof, bp);
1031  }
1032  if (sscanf(bp, "%d ", &magic)) {
1033  if ((bp = strchr(bp, ' ')) == NULL) {
1035  "Usage: create [nr] [magic] <archetype> [ of <artifact>] [variable_to_patch setting]");
1036  return;
1037  }
1038  bp++;
1039  set_magic = 1;
1040  LOG(llevDebug, "%s creates: (%d) (%d) %s\n", op->name, nrof, magic, bp);
1041  }
1042  if ((cp = strstr(bp, " of ")) != NULL) {
1043  *cp = '\0';
1044  cp += 4;
1045  }
1046  for (bp2 = bp; *bp2; bp2++) {
1047  if (*bp2 == ' ') {
1048  *bp2 = '\0';
1049  bp2++;
1050  break;
1051  }
1052  }
1053 
1054  if ((at = try_find_archetype(bp)) == NULL) {
1056  "No such archetype.");
1057  return;
1058  }
1059 
1060  if (cp) {
1061  char spell_name[MAX_BUF], *fsp = NULL;
1062 
1063  /*
1064  * Try to find a spell object for this. Note that
1065  * we also set up spell_name which is only
1066  * the first word.
1067  */
1068 
1069  at_spell = try_find_archetype(cp);
1070  if (!at_spell || at_spell->clone.type != SPELL)
1071  at_spell = find_archetype_by_object_name(cp);
1072  if (!at_spell || at_spell->clone.type != SPELL) {
1073  safe_strncpy(spell_name, cp, sizeof(spell_name));
1074  fsp = strchr(spell_name, ' ');
1075  if (fsp) {
1076  *fsp = 0;
1077  fsp++;
1078  at_spell = try_find_archetype(spell_name);
1079 
1080  /* Got a spell, update the first string pointer */
1081  if (at_spell && at_spell->clone.type == SPELL)
1082  bp2 = cp+strlen(spell_name)+1;
1083  else
1084  at_spell = NULL;
1085  } else
1086  at_spell = NULL;
1087  }
1088 
1089  /* OK - we didn't find a spell - presume the 'of'
1090  * in this case means its an artifact.
1091  */
1092  if (!at_spell) {
1093  if (find_artifactlist(at->clone.type) == NULL) {
1095  "No artifact list for type %d\n",
1096  at->clone.type);
1097  } else {
1098  auto items = find_artifactlist(at->clone.type)->items;
1099  auto i = std::find_if(items.cbegin(), items.cend(),
1100  [&] (const auto art) { return !strcmp(art->item->name, cp) && legal_artifact_combination(&at->clone, art); });
1101  art = i == items.cend() ? nullptr : *i;
1102 
1103  if (!art) {
1105  "No such artifact ([%d] of %s)",
1106  at->clone.type, cp);
1107  }
1108  }
1109  LOG(llevDebug, "%s creates: (%d) (%d) (%s) of (%s)\n", op->name, set_nrof ? nrof : 0, set_magic ? magic : 0, bp, cp);
1110  }
1111  } /* if cp */
1112 
1113  /* rods and potions can get their spell from the artifact */
1114  if ((at->clone.type == ROD || at->clone.type == POTION) && !at_spell && (!art || !art->item->other_arch)) {
1116  "Unable to find spell %s for object that needs it, or it is of wrong type",
1117  cp);
1118  return;
1119  }
1120  if ((at->clone.type == WAND || at->clone.type == SCROLL || at->clone.type == SPELLBOOK)
1121  && !at_spell) {
1123  "Unable to find spell %s for object that needs it, or it is of wrong type",
1124  cp);
1125  return;
1126  }
1127 
1128  /*
1129  * Rather than have two different blocks with a lot of similar code,
1130  * just create one object, do all the processing, and then determine
1131  * if that one object should be inserted or if we need to make copies.
1132  */
1133  tmp = object_create_arch(at);
1134  if (settings.real_wiz == FALSE)
1135  SET_FLAG(tmp, FLAG_WAS_WIZ);
1136  if (set_magic)
1137  set_abs_magic(tmp, magic);
1138  if (art)
1139  give_artifact_abilities(tmp, art->item);
1140  if (!is_identifiable_type(tmp)) {
1141  SET_FLAG(tmp, FLAG_IDENTIFIED);
1143  }
1144 
1145  /*
1146  * This entire block here tries to find variable pairings,
1147  * eg, 'hp 4' or the like. The mess here is that values
1148  * can be quoted (eg "my cool sword"); So the basic logic
1149  * is we want to find two spaces, but if we got a quote,
1150  * any spaces there don't count.
1151  */
1152  while (*bp2 && bp2 <= endline) {
1153  gotspace = 0;
1154  gotquote = 0;
1155  /* find the first quote */
1156  for (bp3 = bp2; *bp3 && gotspace < 2 && gotquote < 2; bp3++) {
1157  /* Found a quote - now lets find the second one */
1158  if (*bp3 == '"') {
1159  *bp3 = ' ';
1160  bp2 = bp3+1; /* Update start of string */
1161  bp3++;
1162  gotquote++;
1163  while (*bp3) {
1164  if (*bp3 == '"') {
1165  *bp3 = '\0';
1166  gotquote++;
1167  } else
1168  bp3++;
1169  }
1170  } else if (*bp3 == ' ') {
1171  gotspace++;
1172  }
1173  }
1174 
1175  /*
1176  * If we got two spaces, send the second one to null.
1177  * if we've reached the end of the line, increase gotspace -
1178  * this is perfectly valid for the list entry listed.
1179  */
1180  if (gotspace == 2 || gotquote == 2) {
1181  bp3--; /* Undo the extra increment */
1182  *bp3 = '\0';
1183  } else if (*bp3 == '\0')
1184  gotspace++;
1185 
1186  if ((gotquote && gotquote != 2)
1187  || (gotspace != 2 && gotquote != 2)) {
1188  /*
1189  * Unfortunately, we've clobbered lots of values, so printing
1190  * out what we have probably isn't useful. Break out, because
1191  * trying to recover is probably won't get anything useful
1192  * anyways, and we'd be confused about end of line pointers
1193  * anyways.
1194  */
1196  "Malformed create line: %s",
1197  bp2);
1198  break;
1199  }
1200  /* bp2 should still point to the start of this line,
1201  * with bp3 pointing to the end
1202  */
1203  if (set_variable(tmp, bp2) == -1)
1205  "Unknown variable %s",
1206  bp2);
1207  else
1209  "(%s#%d)->%s",
1210  tmp->name, tmp->count, bp2);
1211  bp2 = bp3+1;
1212  }
1213 
1214  if (at->clone.nrof) {
1215  if (at_spell)
1216  object_insert_in_ob(arch_to_object(at_spell), tmp);
1217 
1218  if (set_nrof)
1219  tmp->nrof = nrof;
1220 
1221  if (at->clone.randomitems != NULL && !at_spell) {
1222  create_treasure(at->clone.randomitems, tmp, 0, op->map->difficulty, 0);
1223  if (QUERY_FLAG(tmp, FLAG_MONSTER)) {
1225  }
1226  }
1227 
1228  /* Multipart objects can't be in inventory, put'em on floor. */
1229  if (!tmp->more) {
1230  tmp = object_insert_in_ob(tmp, op);
1231  } else {
1232  object_insert_in_map_at(tmp, op->map, op, 0, op->x, op->y);
1233  }
1234 
1235  /* Let's put this created item on stack so dm can access it easily. */
1236  dm_stack_push(op->contr, tmp->count);
1237 
1238  return;
1239  }
1240 
1241  for (i = 0; i < (set_nrof ? nrof : 1); i++) {
1242  archetype *atmp;
1243  object *prev = NULL, *head = NULL, *dup;
1244 
1245  for (atmp = at; atmp != NULL; atmp = atmp->more) {
1246  dup = arch_to_object(atmp);
1247 
1248  if (at_spell)
1249  object_insert_in_ob(arch_to_object(at_spell), dup);
1250 
1251  /*
1252  * The head is what contains all the important bits,
1253  * so just copying it over should be fine.
1254  */
1255  if (head == NULL) {
1256  head = dup;
1257  object_copy(tmp, dup);
1258  }
1259  if (settings.real_wiz == FALSE)
1260  SET_FLAG(dup, FLAG_WAS_WIZ);
1261  dup->x = op->x+dup->arch->clone.x;
1262  dup->y = op->y+dup->arch->clone.y;
1263  dup->map = op->map;
1264 
1265  if (head != dup) {
1266  dup->head = head;
1267  prev->more = dup;
1268  }
1269  prev = dup;
1270  }
1271 
1272  if (QUERY_FLAG(head, FLAG_ALIVE)) {
1273  object *check = head;
1274  int size_x = 0;
1275  int size_y = 0;
1276 
1277  while (check) {
1278  size_x = MAX(size_x, check->arch->clone.x);
1279  size_y = MAX(size_y, check->arch->clone.y);
1280  check = check->more;
1281  }
1282 
1283  if (out_of_map(op->map, head->x+size_x, head->y+size_y)) {
1284  if (head->x < size_x || head->y < size_y) {
1285  dm_stack_pop(op->contr);
1288  "Object too big to insert in map, or wrong position.");
1290  return;
1291  }
1292 
1293  check = head;
1294  while (check) {
1295  check->x -= size_x;
1296  check->y -= size_y;
1297  check = check->more;
1298  }
1299  }
1300 
1301  object_insert_in_map_at(head, op->map, op, 0, head->x, head->y);
1302  } else
1303  head = object_insert_in_ob(head, op);
1304 
1305  /* Let's put this created item on stack so dm can access it easily. */
1306  /* Wonder if we really want to push all of these, but since
1307  * things like rods have nrof 0, we want to cover those.
1308  */
1309  dm_stack_push(op->contr, head->count);
1310 
1311  if (at->clone.randomitems != NULL && !at_spell) {
1312  create_treasure(at->clone.randomitems, head, 0, op->map->difficulty, 0);
1313  if (QUERY_FLAG(head, FLAG_MONSTER)) {
1315  }
1316  }
1317  }
1318 
1319  /* free the one we used to copy */
1321 }
1322 
1323 /*
1324  * Now follows dm-commands which are also acceptable from sockets
1325  */
1326 
1335 void command_inventory(object *op, const char *params) {
1336  object *tmp;
1337  int i;
1338 
1339  if (*params == '\0') {
1340  inventory(op, NULL);
1341  return;
1342  }
1343 
1344  if (!sscanf(params, "%d", &i) || (tmp = object_find_by_tag_global(i)) == NULL) {
1346  "Inventory of what object (nr)?");
1347  return;
1348  }
1349 
1350  inventory(op, tmp);
1351 }
1352 
1365 void command_skills(object *op, const char *params) {
1366  show_skills(op, *params == '\0' ? NULL : params);
1367 }
1368 
1377 void command_dump(object *op, const char *params) {
1378  object *tmp;
1379  StringBuffer *sb;
1380  char *diff;
1381 
1382  tmp = get_dm_object(op->contr, &params, NULL);
1383  if (!tmp)
1384  return;
1385 
1386  sb = stringbuffer_new();
1387  object_dump(tmp, sb);
1388  diff = stringbuffer_finish(sb);
1390  free(diff);
1391  if (QUERY_FLAG(tmp, FLAG_OBJ_ORIGINAL))
1393  "Object is marked original");
1394 }
1395 
1405 void command_mon_aggr(object *op, const char *params) {
1406  (void)params;
1407  if (op->enemy || !QUERY_FLAG(op, FLAG_UNAGGRESSIVE)) {
1408  object_set_enemy(op, NULL);
1411  "Aggression turned OFF");
1412  } else {
1416  "Aggression turned ON");
1417  }
1418 }
1419 
1432 void command_possess(object *op, const char *params) {
1433  object *victim;
1434  player *pl;
1435  int i;
1436  char buf[MAX_BUF];
1437 
1438  victim = NULL;
1439  if (*params != '\0') {
1440  if (sscanf(params, "%d", &i))
1441  victim = object_find_by_tag_global(i);
1442  else if (sscanf(params, "%s", buf))
1443  victim = object_find_by_name_global(buf);
1444  }
1445  if (victim == NULL) {
1447  "Patch what object (nr)?");
1448  return;
1449  }
1450 
1451  if (victim == op) {
1453  "As insane as you are, I cannot allow you to possess yourself.");
1454  return;
1455  }
1456 
1457  /* make the switch */
1458  pl = op->contr;
1459  victim->contr = pl;
1460  pl->ob = victim;
1461  victim->type = PLAYER;
1462  SET_FLAG(victim, FLAG_WIZ);
1463 
1464  /* basic patchup */
1465  /* The use of hard coded values is terrible. Note
1466  * that really, to be fair, this shouldn't get changed at
1467  * all - if you are possessing a kobold, you should have the
1468  * same limitations. As it is, as more body locations are added,
1469  * this will give this player more locations than perhaps
1470  * they should be allowed.
1471  */
1472  for (i = 0; i < NUM_BODY_LOCATIONS; i++)
1473  if (i == 1 || i == 6 || i == 8 || i == 9)
1474  victim->body_info[i] = 2;
1475  else
1476  victim->body_info[i] = 1;
1477 
1478  esrv_new_player(pl, 80); /* just pick a weight, we don't care */
1479  esrv_send_inventory(victim, victim);
1480 
1481  fix_object(victim);
1482 
1483  do_some_living(victim);
1484 }
1485 
1493 void command_patch(object *op, const char *params) {
1494  const char *arg, *arg2;
1495  object *tmp;
1496 
1497  tmp = get_dm_object(op->contr, &params, NULL);
1498  if (!tmp)
1499  /* Player already informed of failure */
1500  return;
1501 
1502  /* params set to first value by get_dm_default */
1503  arg = params;
1504  if (*arg == '\0') {
1506  "Patch what values?");
1507  return;
1508  }
1509 
1510  if ((arg2 = strchr(arg, ' ')))
1511  arg2++;
1512  if (settings.real_wiz == FALSE)
1513  SET_FLAG(tmp, FLAG_WAS_WIZ); /* To avoid cheating */
1514  if (set_variable(tmp, arg) == -1)
1516  "Unknown variable %s",
1517  arg);
1518  else {
1520  "(%s#%d)->%s=%s",
1521  tmp->name, tmp->count, arg, arg2);
1522  }
1523 }
1524 
1525 static void reset_faces_sent(struct socket_struct *socket) {
1526  free(socket->faces_sent);
1527  socket->faces_sent = static_cast<uint8_t *>(calloc(sizeof(socket->faces_sent[0]), get_faces_count()));
1528  socket->faces_sent_len = get_faces_count();
1529 }
1530 
1531 void command_recollect(object *op, const char *params) {
1532  (void)op;
1533  (void)params;
1534  load_assets();
1535 
1536  // To prevent negative speeds from sneaking through, we need to finalize the archetypes.
1537  // Negative speeds on monsters are caught and changed to .005-ish, so we need to make
1538  // sure they're right now rather than later.
1540 
1541  // Clear sent faces for connected sockets so that clients see new faces.
1542  for (int i = 0; i < socket_info.allocated_sockets; i++) {
1543  /*
1544  if (init_sockets[i].status == Ns_Add) {
1545  reset_faces_sent(&init_sockets[i]);
1546  }
1547  */
1548  }
1549 
1550  player *next;
1551  for (player *pl = first_player; pl != NULL; pl = next) {
1552  reset_faces_sent(pl->socket);
1553  next = pl->next;
1554  }
1555 }
1556 
1565 void command_remove(object *op, const char *params) {
1566  object *tmp;
1567  int from;
1568 
1569  tmp = get_dm_object(op->contr, &params, &from);
1570  if (!tmp) {
1572  "Remove what object (nr)?");
1573  return;
1574  }
1575 
1576  if (tmp->type == PLAYER) {
1578  "Unable to remove a player!");
1579  return;
1580  }
1581 
1582  if (QUERY_FLAG(tmp, FLAG_REMOVED)) {
1583  char name[MAX_BUF];
1584 
1585  query_name(tmp, name, MAX_BUF);
1587  "%s is already removed!",
1588  name);
1589  return;
1590  }
1591 
1592  if (from != STACK_FROM_STACK)
1593  /* Item is either stack top, or is a number thus is now stack top, let's remove it */
1594  dm_stack_pop(op->contr);
1595 
1596  /* Always work on the head - otherwise object will get in odd state */
1597  tmp = HEAD(tmp);
1598  if (tmp->speed != 0) {
1599  tmp->speed = 0;
1600  object_update_speed(tmp);
1601  }
1602  object_remove(tmp);
1603 }
1604 
1612 void command_free(object *op, const char *params) {
1613  object *tmp;
1614  int from;
1615 
1616  tmp = get_dm_object(op->contr, &params, &from);
1617 
1618  if (!tmp) {
1620  "Free what object (nr)?");
1621  return;
1622  }
1623 
1624  if (from != STACK_FROM_STACK)
1625  /* Item is either stack top, or is a number thus is now stack top, let's remove it */
1626  dm_stack_pop(op->contr);
1627 
1628  tmp = HEAD(tmp);
1629  if (!QUERY_FLAG(tmp, FLAG_REMOVED)) {
1631  "Warning: item was not removed, will do so now.");
1632  object_remove(tmp);
1633  }
1634 
1636 }
1637 
1638 void command_accountpasswd(object *op, const char *params) {
1639  char account_name[MAX_BUF], newpw[MAX_BUF];
1640  // Password may contain spaces, so use %[^\n] format string.
1641  if (sscanf(params, "%s %[^\n]", account_name, newpw) != 2) {
1643  "Usage: accountpasswd ACCOUNT PASSWORD");
1644  return;
1645  }
1646 
1647  int ret = account_change_password(account_name, NULL, newpw);
1648  switch (ret) {
1649  case 0:
1651  "Updated account password.");
1652  return;
1653  case 1:
1655  "Invalid characters in new password.");
1656  return;
1657  case 2:
1659  "Invalid characters in new password.");
1660  return;
1661  default:
1663  "Error changing password.");
1664  return;
1665  }
1666 }
1667 
1676 void command_addexp(object *op, const char *params) {
1677  char buf[MAX_BUF], skill[MAX_BUF];
1678  int i, q;
1679  object *skillob = NULL;
1680  player *pl;
1681 
1682  skill[0] = '\0';
1683  if ((*params == '\0')
1684  || (strlen(params) > MAX_BUF)
1685  || ((q = sscanf(params, "%s %d %[^\r\n]", buf, &i, skill)) < 2)) {
1687  "Usage: addexp player quantity [skill].");
1688  return;
1689  }
1690 
1691  for (pl = first_player; pl != NULL; pl = pl->next)
1692  if (!strncmp(pl->ob->name, buf, MAX_NAME))
1693  break;
1694 
1695  if (pl == NULL) {
1697  "No such player.");
1698  return;
1699  }
1700 
1701  if (q >= 3) {
1702  skillob = find_skill_by_name(pl->ob, skill);
1703  if (!skillob) {
1705  "Unable to find skill %s in %s",
1706  skill, buf);
1707  return;
1708  }
1709 
1710  i = check_exp_adjust(skillob, i);
1711  skillob->stats.exp += i;
1712  calc_perm_exp(skillob);
1713  player_lvl_adj(pl->ob, skillob);
1714  }
1715 
1716  pl->ob->stats.exp += i;
1717  calc_perm_exp(pl->ob);
1718  player_lvl_adj(pl->ob, NULL);
1719 
1720  if (settings.real_wiz == FALSE)
1721  SET_FLAG(pl->ob, FLAG_WAS_WIZ);
1722 }
1723 
1732 void command_speed(object *op, const char *params) {
1733  int i;
1734 
1735  if (*params == '\0' || !sscanf(params, "%d", &i)) {
1737  "Current speed is %d",
1738  tick_duration);
1739  return;
1740  }
1741 
1742  set_tick_duration(i);
1743  reset_sleep();
1745  "The speed is changed to %d.",
1746  i);
1747 }
1748 
1749 /**************************************************************************/
1750 /* Mods made by Tyler Van Gorder, May 10-13, 1992. */
1751 /* CSUChico : tvangod@cscihp.ecst.csuchico.edu */
1752 /**************************************************************************/
1753 
1762 void command_stats(object *op, const char *params) {
1763  player *pl;
1764 
1765  if (*params == '\0') {
1767  "Who?");
1768  return;
1769  }
1770 
1771  pl = find_player_partial_name(params);
1772  if (pl == NULL) {
1774  "No such player.");
1775  return;
1776  }
1777 
1779  "[Fixed]Statistics for %s:", pl->ob->name);
1780 
1782  "[fixed]Str : %-2d H.P. : %-4d MAX : %d",
1783  pl->ob->stats.Str, pl->ob->stats.hp, pl->ob->stats.maxhp);
1784 
1786  "[fixed]Dex : %-2d S.P. : %-4d MAX : %d",
1787  pl->ob->stats.Dex, pl->ob->stats.sp, pl->ob->stats.maxsp);
1788 
1790  "[fixed]Con : %-2d AC : %-4d WC : %d",
1791  pl->ob->stats.Con, pl->ob->stats.ac, pl->ob->stats.wc);
1792 
1794  "[fixed]Int : %-2d Damage : %d",
1795  pl->ob->stats.Int, pl->ob->stats.dam);
1796 
1798  "[fixed]Wis : %-2d EXP : %" FMT64,
1799  pl->ob->stats.Wis, pl->ob->stats.exp);
1800 
1802  "[fixed]Pow : %-2d Grace : %d",
1803  pl->ob->stats.Pow, pl->ob->stats.grace);
1804 
1806  "[fixed]Cha : %-2d Food : %d",
1807  pl->ob->stats.Cha, pl->ob->stats.food);
1808 }
1809 
1819 void command_abil(object *op, const char *params) {
1820  char thing[20], thing2[20];
1821  int iii;
1822  player *pl;
1823 
1824  iii = 0;
1825  thing[0] = '\0';
1826  thing2[0] = '\0';
1827  if (*params == '\0'
1828  || sscanf(params, "%s %s %d", thing, thing2, &iii) != 3
1829  || thing[0] == '\0') {
1831  "Who?");
1832  return;
1833  }
1834 
1835  if (thing2[0] == '\0') {
1837  "You can't change that.");
1838  return;
1839  }
1840 
1841  if (iii < MIN_STAT || iii > settings.max_stat) {
1843  "Illegal range of stat.\n");
1844  return;
1845  }
1846 
1847  for (pl = first_player; pl != NULL; pl = pl->next) {
1848  if (!strcmp(pl->ob->name, thing)) {
1849  if (settings.real_wiz == FALSE)
1850  SET_FLAG(pl->ob, FLAG_WAS_WIZ);
1851  if (!strcmp("str", thing2))
1852  pl->ob->stats.Str = iii, pl->orig_stats.Str = iii;
1853  if (!strcmp("dex", thing2))
1854  pl->ob->stats.Dex = iii, pl->orig_stats.Dex = iii;
1855  if (!strcmp("con", thing2))
1856  pl->ob->stats.Con = iii, pl->orig_stats.Con = iii;
1857  if (!strcmp("wis", thing2))
1858  pl->ob->stats.Wis = iii, pl->orig_stats.Wis = iii;
1859  if (!strcmp("cha", thing2))
1860  pl->ob->stats.Cha = iii, pl->orig_stats.Cha = iii;
1861  if (!strcmp("int", thing2))
1862  pl->ob->stats.Int = iii, pl->orig_stats.Int = iii;
1863  if (!strcmp("pow", thing2))
1864  pl->ob->stats.Pow = iii, pl->orig_stats.Pow = iii;
1866  "%s has been altered.",
1867  pl->ob->name);
1868  fix_object(pl->ob);
1869  return;
1870  }
1871  }
1872 
1874  "No such player.");
1875 }
1876 
1885 void command_reset(object *op, const char *params) {
1886  mapstruct *m;
1887  object *dummy = NULL, *tmp = NULL;
1888  char path[HUGE_BUF];
1889  const char *space, *confirmation = NULL;
1890  int res = 0;
1891 
1892  if (*params == '\0') {
1894  MSG_TYPE_COMMAND_ERROR, "Which map should be reset?");
1895  return;
1896  }
1897 
1898  space = strchr(params, ' ');
1899  if (space != NULL) {
1900  confirmation = params;
1901  params = space + 1;
1902  }
1903 
1904  /* Use the DM's map if the current map was given. */
1905  if (strcmp(params, ".") == 0) {
1906  strlcpy(path, op->map->path, sizeof(path));
1907  } else {
1908  path_combine_and_normalize(op->map->path, params, path, sizeof(path));
1909  }
1910 
1911  m = has_been_loaded(path);
1912  if (m == NULL) {
1914  MSG_TYPE_COMMAND_ERROR, "No such map.");
1915  return;
1916  }
1917 
1918  if (confirmation) {
1919  if (m->unique && (op->map == m)) {
1922  "Cannot reset a unique player map while on it. Use "
1923  "'reset full-reset %s' while standing somewhere else.",
1924  m->path);
1925  return;
1926  }
1927 
1928  if (strncmp("full-reset", confirmation, strlen("full-reset"))) {
1930  MSG_TYPE_COMMAND_ERROR, "Confirm using 'full-reset'.");
1931  return;
1932  }
1933  }
1934 
1935  /* Forbid using reset on our own map when we're in a transport, as
1936  * it has the displeasant effect of crashing the server.
1937  * - gros, July 25th 2006 */
1938  if ((op->contr && op->contr->transport) && (op->map == m)) {
1940  "You need to disembark first.");
1941  return;
1942  }
1943 
1944  strlcpy(path, m->path, sizeof(path));
1945 
1946  sstring reset_group = m->reset_group;
1947  m->reset_group = NULL;
1948 
1949  if (m->in_memory != MAP_SWAPPED) {
1950  if (m->in_memory != MAP_IN_MEMORY) {
1951  LOG(llevError, "Tried to swap out map which was not in memory.\n");
1952  m->reset_group = reset_group;
1953  return;
1954  }
1955 
1956  /*
1957  * Only attempt to remove the player that is doing the reset, and not other
1958  * players or wiz's.
1959  */
1960  if (op->map == m) {
1961  if (strncmp(m->path, "/random/", 8) == 0) {
1962  /* This is not a very satisfying solution - it would be much better
1963  * to recreate a random map with the same seed value as the old one.
1964  * Unfortunately, I think recreating the map would require some
1965  * knowledge about its 'parent', which appears very non-trivial to
1966  * me.
1967  * On the other hand, this should prevent the freeze that this
1968  * situation caused. - gros, 26th July 2006.
1969  */
1971  "You cannot reset a random map when inside it.");
1972  m->reset_group = reset_group;
1973  return;
1974  }
1975 
1976  dummy = object_new();
1977  dummy->map = NULL;
1978  EXIT_X(dummy) = op->x;
1979  EXIT_Y(dummy) = op->y;
1980  EXIT_PATH(dummy) = add_string(op->map->path);
1981  object_remove(op);
1982  op->map = NULL;
1983  tmp = op;
1984  }
1985  res = swap_map(m);
1986  }
1987 
1988  if (res < 0 || m->in_memory != MAP_SWAPPED) {
1989  player *pl;
1990  int playercount = 0;
1991 
1992  /* Need to re-insert player if swap failed for some reason */
1993  if (tmp) {
1994  object_insert_in_map_at(op, m, NULL, 0, op->x, op->y);
1996  }
1997 
1998  if (res < 0 && res != SAVE_ERROR_PLAYER) {
1999  /* no need to warn if player on map, code below checks that. */
2001  "Reset failed, error code: %d.", res);
2002  /* If we somehow (AFAIK this is only possible by DM intervention anyway) get
2003  * on a non-uniquely-loaded unique map (such as by a DM using goto onto a
2004  * unique map template or by creating an exit to a unique map template
2005  * without specifying in that exit that the map is unique), we need to re-insert
2006  * the player without calling enter_exit(), since we trip an assertion failure there.
2007  * If we reach here and tmp is defined, we have already re-inserted the player,
2008  * so we just need to bail.
2009  * -- Neila Hawkins 2023-12-13
2010  */
2011  if (res == SAVE_ERROR_UCREATION) {
2012  m->reset_group = reset_group;
2013  return;
2014  }
2015  }
2016  else {
2018  "Reset failed, couldn't swap map, the following players are on it:");
2019  for (pl = first_player; pl != NULL; pl = pl->next) {
2020  if (pl->ob->map == m && pl->ob != op) {
2022  pl->ob->name);
2023  playercount++;
2024  }
2025  }
2026  if (!playercount)
2028  "hmm, I don't see any other players on this map, something else is the problem.");
2029  m->reset_group = reset_group;
2030  return;
2031  }
2032  }
2033 
2034  FREE_AND_CLEAR_STR_IF(reset_group);
2035 
2036  /* Here, map reset succeeded. */
2037 
2038  if (m && m->in_memory == MAP_SWAPPED) {
2039  if (confirmation) {
2041  LOG(llevDebug, "DM %s fully resetting map %s.\n", op->name, m->path);
2042  } else
2043  LOG(llevDebug, "DM %s resetting map %s.\n", op->name, m->path);
2044 
2045  /* setting this effectively causes an immediate reload */
2046  m->reset_time = 1;
2047  flush_old_maps();
2048  }
2049 
2050  /* Display the appropriate success message. */
2051  if (confirmation) {
2053  MSG_TYPE_COMMAND_DM, "Fully resetting map %s.", path);
2054  } else {
2056  MSG_TYPE_COMMAND_DM, "Resetting map %s.", path);
2057  }
2058 
2059  if (tmp) {
2060  enter_exit(tmp, dummy);
2062  }
2063 
2064  /* Remind the DM how to fully reset the map. */
2065  if (confirmation == NULL) {
2068  "Use 'reset full-reset %s' to fully reset the map.", params);
2069  }
2070 }
2071 
2080 void command_nowiz(object *op, const char *params) { /* 'noadm' is alias */
2081  (void)params;
2082  CLEAR_FLAG(op, FLAG_WIZ);
2083  CLEAR_FLAG(op, FLAG_WIZPASS);
2084  CLEAR_FLAG(op, FLAG_WIZCAST);
2085 
2086  if (settings.real_wiz == TRUE)
2087  CLEAR_FLAG(op, FLAG_WAS_WIZ);
2088  if (op->contr->hidden) {
2089  unhide(op);
2090  } else
2092  "The Dungeon Master is gone...");
2093 
2094  update_los(op);
2095 }
2096 
2117 static int checkdm(object *op, const char *pl_name, const char *pl_passwd, const char *pl_host) {
2118  FILE *dmfile;
2119  char buf[MAX_BUF];
2120  char line_buf[160], name[160], passwd[160], host[160];
2121 
2122 #ifdef RESTRICTIVE_DM
2123  *pl_name = op->name ? op->name : "*";
2124 #else
2125  (void)op;
2126 #endif
2127 
2128  snprintf(buf, sizeof(buf), "%s/%s", settings.confdir, DMFILE);
2129  if ((dmfile = fopen(buf, "r")) == NULL) {
2130  LOG(llevDebug, "Could not find DM file.\n");
2131  return 0;
2132  }
2133 
2134  while (fgets(line_buf, 160, dmfile) != NULL) {
2135  // Skip empty lines as well as commented ones.
2136  if (line_buf[0] == '#' || line_buf[0] == '\n')
2137  continue;
2138  if (sscanf(line_buf, "%[^:]:%[^:]:%s\n", name, passwd, host) != 3) {
2139  LOG(llevError, "Warning - malformed dm file entry: %s\n", line_buf);
2140  } else if ((!strcmp(name, "*") || (pl_name && !strcmp(pl_name, name)))
2141  && (!strcmp(passwd, "*") || !strcmp(passwd, pl_passwd))
2142  && (!strcmp(host, "*") || !strcmp(host, pl_host))) {
2143  fclose(dmfile);
2144  return (1);
2145  }
2146  }
2147  fclose(dmfile);
2148  return (0);
2149 }
2150 
2165 static int do_wizard_dm(object *op, const char *params, int silent) {
2166  if (!op->contr)
2167  return 0;
2168 
2169  if (QUERY_FLAG(op, FLAG_WIZ)) {
2171  "You are already the Dungeon Master!");
2172  return 0;
2173  }
2174 
2175  if (checkdm(op, op->name, (*params != '\0' ? params : "*"), op->contr->socket->host)) {
2176  SET_FLAG(op, FLAG_WIZ);
2177  SET_FLAG(op, FLAG_WAS_WIZ);
2178  SET_FLAG(op, FLAG_WIZPASS);
2179  SET_FLAG(op, FLAG_WIZCAST);
2181  "Ok, you are the Dungeon Master!");
2182  /*
2183  * Remove setting flying here - that won't work, because next
2184  * fix_object() is called that will get cleared - proper solution
2185  * is probably something like a wiz_force which gives that and any
2186  * other desired abilities.
2187  */
2188  clear_los(op->contr);
2189 
2190  if (!silent)
2193  "The Dungeon Master has arrived!");
2194 
2195  return 1;
2196  }
2197 
2199  "Sorry Pal, I don't think so.");
2200  return 0;
2201 }
2202 
2214 void command_dm(object *op, const char *params) {
2215  do_wizard_dm(op, params, 0);
2216 }
2217 
2226 void command_invisible(object *op, const char *params) {
2227  (void)params;
2228  if (op) {
2229  op->invisible += 100;
2232  "You turn invisible.");
2233  }
2234 }
2235 
2253 static object *get_spell_by_name(object *op, const char *spell_name) {
2254  archetype *found;
2255  int conflict_found;
2256  size_t spell_name_length;
2257 
2258  /* First check for full name matches. */
2259  conflict_found = 0;
2260  found = NULL;
2261  getManager()->archetypes()->each([&] (auto ar) {
2262  if (ar->clone.type != SPELL)
2263  return;
2264 
2265  if (strncmp(ar->name, "spelldirect_", 12) == 0)
2266  return;
2267 
2268  if (strcmp(ar->clone.name, spell_name) != 0)
2269  return;
2270 
2271  if (found != NULL) {
2272  if (!conflict_found) {
2273  conflict_found = 1;
2275  "More than one archetype matches the spell name %s:",
2276  spell_name);
2278  "- %s",
2279  found->name);
2280  }
2282  "- %s",
2283  ar->name);
2284  return;
2285  }
2286 
2287  found = ar;
2288  });
2289 
2290  /* No match if more more than one archetype matches. */
2291  if (conflict_found)
2292  return NULL;
2293 
2294  /* Return if exactly one archetype matches. */
2295  if (found != NULL)
2296  return arch_to_object(found);
2297 
2298  /* No full match found: now check for partial matches. */
2299  spell_name_length = strlen(spell_name);
2300  conflict_found = 0;
2301  found = NULL;
2302 
2303  getManager()->archetypes()->each([&] (auto ar) {
2304  if (ar->clone.type != SPELL)
2305  return;
2306 
2307  if (strncmp(ar->name, "spelldirect_", 12) == 0)
2308  return;
2309 
2310  if (strncmp(ar->clone.name, spell_name, spell_name_length) != 0)
2311  return;
2312 
2313  if (found != NULL) {
2314  if (!conflict_found) {
2315  conflict_found = 1;
2317  "More than one spell matches %s:",
2318  spell_name);
2320  "- %s",
2321  found->clone.name);
2322  }
2324  "- %s",
2325  ar->clone.name);
2326  return;
2327  }
2328 
2329  found = ar;
2330  });
2331 
2332  /* No match if more more than one archetype matches. */
2333  if (conflict_found)
2334  return NULL;
2335 
2336  /* Return if exactly one archetype matches. */
2337  if (found != NULL)
2338  return arch_to_object(found);
2339 
2340  /* No spell found: just print an error message. */
2342  "The spell %s does not exist.",
2343  spell_name);
2344  return NULL;
2345 }
2346 
2357 static void command_learn_spell_or_prayer(object *op, const char *params, int special_prayer) {
2358  object *tmp;
2359 
2360  if (op->contr == NULL || *params == '\0') {
2362  "Which spell do you want to learn?");
2363  return;
2364  }
2365 
2366  tmp = get_spell_by_name(op, params);
2367  if (tmp == NULL) {
2368  return;
2369  }
2370 
2371  if (check_spell_known(op, tmp->name)) {
2373  "You already know the spell %s.",
2374  tmp->name);
2375  return;
2376  }
2377 
2378  do_learn_spell(op, tmp, special_prayer);
2380 }
2381 
2390 void command_learn_spell(object *op, const char *params) {
2391  command_learn_spell_or_prayer(op, params, 0);
2392 }
2393 
2402 void command_learn_special_prayer(object *op, const char *params) {
2403  command_learn_spell_or_prayer(op, params, 1);
2404 }
2405 
2415 void command_forget_spell(object *op, const char *params) {
2416  object *spell;
2417 
2418  if (op->contr == NULL || *params == '\0') {
2420  "Which spell do you want to forget?");
2421  return;
2422  }
2423 
2424  spell = lookup_spell_by_name(op, params);
2425  if (spell == NULL) {
2427  "You do not know the spell %s.",
2428  params);
2429  return;
2430  }
2431 
2432  do_forget_spell(op, spell->name);
2433 }
2434 
2443 void command_listplugins(object *op, const char *params) {
2444  (void)params;
2446 }
2447 
2458 void command_loadplugin(object *op, const char *params) {
2459  char buf[MAX_BUF];
2460 
2461  if (*params == '\0') {
2463  "Load which plugin?");
2464  return;
2465  }
2466 
2467  snprintf(buf, sizeof(buf), LIBDIR"/plugins/%s", params);
2468  LOG(llevDebug, "Requested plugin file is %s\n", buf);
2469  if (plugins_init_plugin(buf) == 0) {
2470  LOG(llevInfo, "DM %s loaded plugin %s\n", op->name, params);
2472  "Plugin %s successfully loaded.",
2473  params);
2474  } else
2476  "Could not load plugin %s.",
2477  params);
2478 }
2479 
2490 void command_unloadplugin(object *op, const char *params) {
2491  if (*params == '\0') {
2493  "Remove which plugin?");
2494  return;
2495  }
2496 
2497  if (plugins_remove_plugin(params) == 0) {
2498  LOG(llevInfo, "DM %s unloaded plugin %s\n", op->name, params);
2500  "Plugin %s successfully removed.",
2501  params);
2502  init_signals(); // Restore our signal handlers, some plugins (Python) mess with them
2503  } else
2505  "Could not remove plugin %s.",
2506  params);
2507 }
2508 
2519 void command_dmhide(object *op, const char *params) {
2520  if (!do_wizard_dm(op, params, 1))
2521  return;
2522 
2523  do_wizard_hide(op, 1);
2524 }
2525 
2534 void command_stack_pop(object *op, const char *params) {
2535  (void)params;
2536  dm_stack_pop(op->contr);
2537 }
2538 
2547 void command_stack_push(object *op, const char *params) {
2548  object *ob;
2549  int from;
2550  ob = get_dm_object(op->contr, &params, &from);
2551 
2552  if (ob && from != STACK_FROM_NUMBER)
2553  /* Object was from stack, need to push it again */
2554  dm_stack_push(op->contr, ob->count);
2555 }
2556 
2565 void command_stack_list(object *op, const char *params) {
2566  int item;
2567  object *display;
2568  player *pl = op->contr;
2569  (void)params;
2570 
2572  "Item stack contents:");
2573 
2574  for (item = 0; item < pl->stack_position; item++) {
2575  display = object_find_by_tag_global(pl->stack_items[item]);
2576  if (display)
2578  " %d : %s [%d]",
2579  item, display->name, display->count);
2580  else
2581  /* Item was freed */
2583  " %d : (lost item: %d)",
2584  item, pl->stack_items[item]);
2585  }
2586 }
2587 
2596 void command_stack_clear(object *op, const char *params) {
2597  (void)params;
2598  op->contr->stack_position = 0;
2600  "Item stack cleared.");
2601 }
2602 
2622 void command_diff(object *op, const char *params) {
2623  object *left, *right;
2624  char *diff;
2625  StringBuffer *sb;
2626  int left_from, right_from;
2627 
2628  left = get_dm_object(op->contr, &params, &left_from);
2629  if (!left) {
2631  "Compare to what item?");
2632  return;
2633  }
2634 
2635  if (left_from == STACK_FROM_NUMBER)
2636  /* Item was stacked, remove it else right will be the same... */
2637  dm_stack_pop(op->contr);
2638 
2639  right = get_dm_object(op->contr, &params, &right_from);
2640 
2641  if (!right) {
2643  "Compare what item?");
2644  return;
2645  }
2646 
2648  "Item difference:");
2649 
2650  if (left_from == STACK_FROM_TOP && right_from == STACK_FROM_TOP) {
2651  /*
2652  * Special case: both items were taken from stack top.
2653  * Override the behaviour, taking left as item just below top, if exists.
2654  * See function description for why.
2655  * Besides, if we don't do anything, compare an item to itself, not really useful.
2656  */
2657  if (op->contr->stack_position > 1) {
2659  if (left)
2661  "(Note: first item taken from undertop)");
2662  else
2663  /* Stupid case: item under top was freed, fallback to stack top */
2664  left = right;
2665  }
2666  }
2667 
2668  sb = stringbuffer_new();
2669  get_ob_diff(sb, left, right);
2670  diff = stringbuffer_finish(sb);
2671  if (*diff == '\0') {
2672  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_DM, "Objects are the same.");
2673  } else {
2675  }
2676  free(diff);
2677 }
2678 
2686 void command_insert_into(object *op, const char *params) {
2687  object *left, *right, *inserted;
2688  int left_from, right_from;
2689  char what[MAX_BUF], where[MAX_BUF];
2690 
2691  left = get_dm_object(op->contr, &params, &left_from);
2692  if (!left) {
2694  "Insert into what object?");
2695  return;
2696  }
2697 
2698  if (left_from == STACK_FROM_NUMBER)
2699  /* Item was stacked, remove it else right will be the same... */
2700  dm_stack_pop(op->contr);
2701 
2702  right = get_dm_object(op->contr, &params, &right_from);
2703 
2704  if (!right) {
2706  "Insert what item?");
2707  return;
2708  }
2709 
2710  if (left_from == STACK_FROM_TOP && right_from == STACK_FROM_TOP) {
2711  /*
2712  * Special case: both items were taken from stack top.
2713  * Override the behaviour, taking left as item just below top, if exists.
2714  * See function description for why.
2715  * Besides, can't insert an item into itself.
2716  */
2717  if (op->contr->stack_position > 1) {
2719  if (left)
2721  "(Note: item to insert into taken from undertop)");
2722  else
2723  /* Stupid case: item under top was freed, fallback to stack top */
2724  left = right;
2725  }
2726  }
2727 
2728  if (left == right) {
2730  "Can't insert an object into itself!");
2731  return;
2732  }
2733 
2734  if (right->type == PLAYER) {
2736  "Can't insert a player into something!");
2737  return;
2738  }
2739 
2740  if (!QUERY_FLAG(right, FLAG_REMOVED))
2741  object_remove(right);
2742  inserted = object_insert_in_ob(right, left);
2743  if (left->type == PLAYER) {
2744  if (inserted != right)
2745  /* item was merged, so updating name and such. */
2746  esrv_update_item(UPD_WEIGHT|UPD_NAME|UPD_NROF, left, inserted);
2747  }
2748  query_name(inserted, what, MAX_BUF);
2749  query_name(left, where, MAX_BUF);
2751  "Inserted %s in %s",
2752  what, where);
2753 }
2754 
2763 void command_style_map_info(object *op, const char *params) {
2764  extern mapstruct *styles;
2765  mapstruct *mp;
2766  int maps_used = 0, mapmem = 0, objects_used = 0, x, y;
2767  (void)params;
2768 
2769  for (mp = styles; mp != NULL; mp = mp->next) {
2770  maps_used++;
2771  mapmem += map_size(mp) * (sizeof(object *)+sizeof(MapSpace))+sizeof(mapstruct);
2772  for (x = 0; x < MAP_WIDTH(mp); x++) {
2773  for (y = 0; y < MAP_HEIGHT(mp); y++) {
2774  FOR_MAP_PREPARE(mp, x, y, tmp)
2775  objects_used++;
2776  FOR_MAP_FINISH();
2777  }
2778  }
2779  }
2781  "[fixed]Style maps loaded: %d",
2782  maps_used);
2784  "[fixed]Memory used, not");
2786  "[fixed]including objects: %d",
2787  mapmem);
2789  "[fixed]Style objects: %d",
2790  objects_used);
2792  "[fixed]Mem for objects: %lu",
2793  (unsigned long)(objects_used*sizeof(object)));
2794 }
2795 
2796 bool can_follow(object* op, player* other) {
2797  // Only allow follow from same party.
2798  return (other->ob->contr->party != NULL) && (op->contr->party == other->ob->contr->party);
2799 }
2800 
2809 void command_follow(object *op, const char *params) {
2810  player *other;
2811 
2812  if (*params == '\0') {
2813  if (op->contr->followed_player != NULL) {
2816  }
2817  return;
2818  }
2819 
2820  other = find_player_partial_name(params);
2821  if (!other) {
2822  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_FAILURE, "No such player or ambiguous name.");
2823  return;
2824  }
2825  if (other == op->contr) {
2826  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_FAILURE, "You can't follow yourself.");
2827  return;
2828  }
2829 
2830  // Players trying to 'follow' are subject to additional checks.
2831  if (!QUERY_FLAG(op, FLAG_WIZ)) {
2832  if (!can_follow(op, other)) {
2835  "You can only follow members in the same party.");
2836  return;
2837  }
2838  rv_vector rv;
2839  if (!get_rangevector(op, other->ob, &rv, 0) || rv.distance > 1) {
2840  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_FAILURE, "You need to go to them first!");
2841  return;
2842  }
2844  }
2845 
2846  if (op->contr->followed_player)
2848 
2849  op->contr->followed_player = add_string(other->ob->name);
2851 }
2852 
2853 void command_purge_quest(object *op, const char * param) {
2854  (void)param;
2855  free_quest();
2856  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, "Purged quest state.");
2857 }
2858 
2859 void command_purge_quest_definitions(object *op, const char * param) {
2860  (void)param;
2862  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, "Purged quests definitions.");
2863 }
2864 
2865 void do_dump(object *who, object *what) {
2866  StringBuffer *sb;
2867  char *diff;
2868 
2869  sb = stringbuffer_new();
2870  object_dump(what, sb);
2871  diff = stringbuffer_finish(sb);
2873  free(diff);
2874 
2875  /* Let's push that item on the dm's stack */
2876  dm_stack_push(who->contr, what->count);
2877 }
2878 
2887 void command_dumpbelow(object *op, const char *params) {
2888  (void)params;
2889  if (op && op->below) {
2890  do_dump(op, op->below);
2891  }
2892 }
2893 
2902 void command_dumpabove(object *op, const char *params) {
2903  (void)params;
2904  if (op && op->above) {
2905  do_dump(op, op->above);
2906  }
2907 }
2908 
2914 void command_settings(object *op, const char *ignored) {
2915  (void)ignored;
2916  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, "Server settings:");
2917 
2919 
2920  if (settings.not_permadeth) {
2921  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, " * death is not permanent");
2922  } else if (settings.resurrection) {
2923  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, " * permanent death, resurrection is enabled");
2924  } else {
2925  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, " * permanent death, resurrection is NOT enabled");
2926  }
2927 
2928  if (settings.set_title) {
2929  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, " * players can set their title");
2930  } else {
2931  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, " * players can't set their title");
2932  }
2933 
2936  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");
2937  } else {
2938  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");
2939  }
2940  } else {
2941  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, " * too much equipment can't lead to spell failure");
2942  }
2943 
2944  if (settings.casting_time) {
2945  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, " * casting takes time");
2946  } else {
2947  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, " * casting is immediate");
2948  }
2949 
2952 
2954 
2956  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, " * players can't steal from other players");
2957  } else {
2958  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, " * players can steal from other players");
2959  }
2960 
2962  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, " * players can create portals from their apartments");
2963  } else {
2964  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, " * players can't create portals from their apartments");
2965  }
2966 
2968  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, " * players can write spells they are denied");
2969  } else {
2970  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, " * players can't write spells they are denied");
2971  }
2972 }
void command_addexp(object *op, const char *params)
This adds exp to a player.
Definition: c_wiz.cpp:1676
#define MSG_TYPE_COMMAND_MAPS
Definition: newclient.h:541
Error, serious thing.
Definition: logger.h:11
void init_signals()
Setup our signal handlers.
Definition: init.cpp:1331
uint8_t not_permadeth
If true, death is non-permament.
Definition: global.h:263
void command_invisible(object *op, const char *params)
Wizard wants to become invisible.
Definition: c_wiz.cpp:2226
object * lookup_spell_by_name(object *op, const char *spname)
Look at object &#39;op&#39; and see if they know the spell spname.
Definition: spell_util.cpp:410
#define NUM_BODY_LOCATIONS
Number of body locations.
Definition: object.h:15
void command_banish(object *op, const char *params)
Add player&#39;s IP to ban_file and kick them off the server.
Definition: c_wiz.cpp:502
int stack_position
Current stack position, 0 for no item.
Definition: player.h:221
living orig_stats
Permanent real stats of player.
Definition: player.h:169
#define BANISHFILE
Definition: config.h:520
void show_skills(object *op, const char *search)
Displays a player&#39;s skill list, and some other non skill related info (god, max weapon improvements...
Definition: skill_util.cpp:884
#define UP_OBJ_FACE
Only thing that changed was the face.
Definition: object.h:533
uint8_t create_home_portals
If 1, can create portals in unique maps (apartments)
Definition: global.h:312
char * stringbuffer_finish(StringBuffer *sb)
Deallocate the string buffer instance and return the string.
void command_purge_quest(object *op, const char *param)
Definition: c_wiz.cpp:2853
Spell-related defines: spellpath, subtypes, ...
Information.
Definition: logger.h:12
uint8_t max_stat
Maximum stat value - 255 should be sufficient.
Definition: global.h:325
void enter_exit(object *op, object *exit_ob)
Tries to move &#39;op&#39; to exit_ob.
Definition: server.cpp:727
This is used by get_rangevector to determine where the other creature is.
Definition: map.h:375
struct archetype * arch
Pointer to archetype.
Definition: object.h:424
uint32_t worldmaptilesx
Number of tiles wide the worldmap is.
Definition: global.h:294
const object * find_god(const char *name)
Returns a god&#39;s object from its name.
Definition: holy.cpp:317
void command_learn_special_prayer(object *op, const char *params)
Wizard wants to learn a god-given spell.
Definition: c_wiz.cpp:2402
object * check_spell_known(object *op, const char *name)
Checks to see if player knows the spell.
Definition: spell_util.cpp:394
void load_assets(void)
Definition: assets.cpp:551
void command_teleport(object *op, const char *params)
Teleport next to target player.
Definition: c_wiz.cpp:933
uint32_t hidden
If True, player (DM) is hidden from view.
Definition: player.h:149
void command_mon_aggr(object *op, const char *params)
When DM is possessing a monster, flip aggression on and off, to allow better motion.
Definition: c_wiz.cpp:1405
uint8_t spell_encumbrance
Encumbrance effects spells.
Definition: global.h:269
int16_t players
How many players are on this level right now.
Definition: map.h:339
void LOG(LogLevel logLevel, const char *format,...)
Logs a message to stderr, or to file.
Definition: logger.cpp:58
void do_forget_spell(object *op, const char *spell)
Erases spell from player&#39;s inventory.
Definition: apply.cpp:187
#define NDI_ALL
Inform all players of this message.
Definition: newclient.h:271
See Scroll.
Definition: object.h:226
void do_dump(object *who, object *what)
Definition: c_wiz.cpp:2865
void calc_perm_exp(object *op)
Ensure that the permanent experience requirements in an exp object are met.
Definition: living.cpp:1914
#define MSG_TYPE_COMMAND_FAILURE
Failed result from command.
Definition: newclient.h:552
void command_stack_pop(object *op, const char *params)
Pop the stack top.
Definition: c_wiz.cpp:2534
uint8_t death_penalty_level
How many levels worth of exp may be lost on one death.
Definition: global.h:261
void do_some_living(object *op)
Regenerate hp/sp/gr, decreases food.
Definition: player.cpp:3298
int save_map(mapstruct *m, int flag)
Saves a map to file.
Definition: map.cpp:1404
void draw_ext_info_format(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *format,...) PRINTF_ARGS(6
int16_t grace
Grace.
Definition: living.h:44
void command_create(object *op, const char *params)
Wizard wants to create an object.
Definition: c_wiz.cpp:999
#define NDI_ORANGE
Definition: newclient.h:250
#define FLAG_FRIENDLY
Will help players.
Definition: define.h:233
void fix_object(object *op)
Updates all abilities given by applied objects in the inventory of the given object.
Definition: living.cpp:1132
int account_change_password(const char *account_name, const char *current_password, const char *new_password)
Change an account password.
Definition: account.cpp:627
void object_remove(object *op)
This function removes the object op from the linked list of objects which it is currently tied to...
Definition: object.cpp:1818
void command_summon(object *op, const char *params)
Summons player near DM.
Definition: c_wiz.cpp:866
#define DMFILE
File containing valid names that can be dm, one on each line.
Definition: config.h:369
void command_listplugins(object *op, const char *params)
Lists all plugins currently loaded with their IDs and full names.
Definition: c_wiz.cpp:2443
player * first_player
First player.
Definition: init.cpp:106
Item is a number (may be top)
Definition: c_wiz.cpp:41
void command_recollect(object *op, const char *params)
Definition: c_wiz.cpp:1531
object * below
Pointer to the object stacked below this one.
Definition: object.h:295
int object_find_free_spot(const object *ob, mapstruct *m, int x, int y, int start, int stop)
object_find_free_spot(object, map, x, y, start, stop) will search for a spot at the given map and coo...
Definition: object.cpp:3544
uint32_t count
Any numbers typed before a command.
Definition: player.h:124
uint32_t worldmapstarty
Starting y tile for the worldmap.
Definition: global.h:293
#define HUGE_BUF
Used for messages - some can be quite long.
Definition: define.h:37
void esrv_update_item(int flags, object *pl, object *op)
Updates object *op for player *pl.
Definition: main.cpp:359
See Spellbook.
Definition: object.h:208
partylist * party
Party this player is part of.
Definition: player.h:205
object * more
Pointer to the rest of a large body of objects.
Definition: object.h:303
sstring add_string(const char *str)
Share a string.
Definition: shstr.cpp:137
#define MAP_HEIGHT(m)
Map height.
Definition: map.h:78
Socket structure, represents a client-server connection.
Definition: newserver.h:93
#define FREE_AND_CLEAR_STR_IF(xyz)
Definition: global.h:202
object * above
Pointer to the object stacked above this one.
Definition: object.h:296
void esrv_send_inventory(object *pl, object *op)
Sends inventory of a container.
Definition: item.cpp:316
void command_overlay_reset(object *op, const char *params)
Removes the overlay for op&#39;s current map.
Definition: c_wiz.cpp:589
See Rod.
Definition: object.h:114
int16_t y
Position in the map for this object.
Definition: object.h:335
void command_inventory(object *op, const char *params)
Shows the inventory or some item.
Definition: c_wiz.cpp:1335
void player_lvl_adj(object *who, object *op)
For the new exp system.
Definition: living.cpp:1830
void command_swap(object *op, const char *params)
Mark a map as ready for swapping.
Definition: c_wiz.cpp:907
#define FREE_OBJ_NO_DESTROY_CALLBACK
Do not run the destroy callback.
Definition: object.h:547
uint32_t reset_time
Server time when map gets reset, seconds since epoch.
Definition: map.h:327
void command_learn_spell(object *op, const char *params)
Wizard wants to learn a regular spell.
Definition: c_wiz.cpp:2390
StringBuffer * stringbuffer_new(void)
Create a new string buffer.
enum Sock_Status status
Definition: newserver.h:94
#define TRUE
Definition: compat.h:11
artifactlist * find_artifactlist(int type)
Finds the artifact list for a certain item type.
Definition: artifact.cpp:570
void create_overlay_pathname(const char *name, char *buf, size_t size)
Same as create_pathname(), but for the overlay maps.
Definition: map.cpp:125
void command_insert_into(object *op, const char *params)
Puts an object into another.
Definition: c_wiz.cpp:2686
#define EVENT_KICK
A player was Kicked by a DM.
Definition: events.h:56
#define FALSE
Definition: compat.h:14
#define MAX(x, y)
Definition: compat.h:24
uint8_t death_penalty_ratio
Hhow much exp should be lost at death.
Definition: global.h:260
int16_t x
Definition: object.h:335
Global type definitions and header inclusions.
#define safe_strncpy
Definition: compat.h:27
void free_quest(void)
Free all quest status structures.
Definition: quest.cpp:911
struct player * contr
Pointer to the player which control this object.
Definition: object.h:284
int8_t Con
Use
Definition: living.h:36
uint32_t worldmaptilesy
Number of tiles high the worldmap is.
Definition: global.h:295
static void do_wizard_hide(object *op, int silent_dm)
Actually hides or unhides specified player (obviously a DM).
Definition: c_wiz.cpp:352
int swap_map(mapstruct *map)
Swaps a map to disk.
Definition: swap.cpp:136
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.cpp:308
#define ST_PLAYING
Usual state.
Definition: define.h:562
void command_dm(object *op, const char *params)
Actual command to perhaps become dm.
Definition: c_wiz.cpp:2214
#define NDI_DK_ORANGE
DarkOrange2.
Definition: newclient.h:252
char * host
Which host it is connected from (ip address).
Definition: newserver.h:104
See Wand & Staff.
Definition: object.h:225
uint8_t casting_time
It takes awhile to cast a spell.
Definition: global.h:271
archetype * try_find_archetype(const char *name)
Definition: assets.cpp:274
#define FLAG_REMOVED
Object is not in any map or invenory.
Definition: define.h:219
Item was not found.
Definition: c_wiz.cpp:38
void events_execute_global_event(int eventcode,...)
Execute a global event.
Definition: events.cpp:30
object * transport
Transport the player is in.
Definition: player.h:216
AssetsManager * getManager()
Definition: assets.cpp:309
size_t faces_sent_len
This is the number of elements allocated in faces_sent[].
Definition: newserver.h:99
#define MSG_TYPE_ADMIN_DM
DM related admin actions.
Definition: newclient.h:516
void assets_collect(const char *datadir, int what)
Collect all assets from the specified directory and all its subdirectories.
Definition: assets.cpp:113
#define MAP_IN_MEMORY
Map is fully loaded.
Definition: map.h:129
void command_dumpbelow(object *op, const char *params)
Player wants to dump object below her.
Definition: c_wiz.cpp:2887
void esrv_new_player(player *pl, uint32_t weight)
Tells the client that here is a player it should start using.
Definition: request.cpp:1008
int set_variable(object *op, const char *buf)
int16_t sp
Spell points.
Definition: living.h:42
#define NDI_RED
Definition: newclient.h:249
int is_identifiable_type(const object *op)
Return true if this item&#39;s type is one that cares about whether or not it&#39;s been identified – e...
Definition: item.cpp:1333
void flush_old_maps(void)
Reset maps that need to, remove their swap file.
Definition: swap.cpp:291
void object_free(object *ob, int flags)
Frees everything allocated by an object, removes it from the list of used objects, and puts it on the list of free objects.
Definition: object.cpp:1577
player * next
Pointer to next player, NULL if this is last.
Definition: player.h:108
int legal_artifact_combination(const object *op, const artifact *art)
Checks if op can be combined with art.
Definition: artifact.cpp:252
#define MSG_TYPE_COMMAND
Responses to commands, eg, who.
Definition: newclient.h:420
sstring reset_group
For reset purpose, all maps in the same group reset at the same time.
Definition: map.h:332
std::vector< artifact * > items
Artifacts for this type.
Definition: artifact.h:28
tag_t * stack_items
Item stack for patch/dump/...
Definition: player.h:219
#define FLAG_ALIVE
Object can fight (or be fought)
Definition: define.h:217
Socket_Info socket_info
Socket information.
Definition: init.cpp:52
void command_skills(object *op, const char *params)
Player is asking for her skills.
Definition: c_wiz.cpp:1365
static int do_wizard_dm(object *op, const char *params, int silent)
Actually changes a player to wizard.
Definition: c_wiz.cpp:2165
static void dm_stack_push(player *pl, tag_t item)
Push specified item on player stack.
Definition: c_wiz.cpp:150
void create_treasure(treasurelist *t, object *op, int flag, int difficulty, int tries)
This calls the appropriate treasure creation function.
Definition: treasure.cpp:287
#define FLAG_OBJ_ORIGINAL
NEVER SET THIS.
Definition: define.h:352
The archetype structure is a set of rules on how to generate and manipulate objects which point to ar...
Definition: object.h:483
#define MAP_SWAPPED
Map spaces have been saved to disk.
Definition: map.h:130
static void dm_stack_pop(player *pl)
Remove an item from the wizard&#39;s item stack.
Definition: c_wiz.cpp:95
sstring name
More definite name, like "generate_kobold".
Definition: object.h:484
uint32_t unique
If set, this is a per player unique map.
Definition: map.h:333
#define MSG_TYPE_COMMAND_SUCCESS
Successful result from command.
Definition: newclient.h:551
#define MSG_TYPE_COMMAND_ERROR
Bad syntax/can&#39;t use command.
Definition: newclient.h:550
#define ASSETS_QUESTS
Definition: assets.h:30
int8_t Dex
Use
Definition: living.h:36
Defines and variables used by the artifact generation routines.
float speed
Frequency of object &#39;moves&#39; relative to server tick rate.
Definition: object.h:337
void set_tick_duration(long t)
Sets the tick duration.
Definition: time.cpp:209
object * object_find_by_name_global(const char *str)
Finds an object by name.
Definition: object.cpp:732
object * arch_to_object(archetype *at)
Creates and returns a new object which is a copy of the given archetype.
Definition: arch.cpp:227
char path[HUGE_BUF]
Filename of the map.
Definition: map.h:360
#define SET_FLAG(xyz, p)
Definition: define.h:384
void command_loadplugin(object *op, const char *params)
Loads the given plugin.
Definition: c_wiz.cpp:2458
#define FLAG_UNAGGRESSIVE
Monster doesn&#39;t attack players.
Definition: define.h:259
#define QUERY_FLAG(xyz, p)
Definition: define.h:386
#define MSG_TYPE_ADMIN_PLAYER
Player coming/going/death.
Definition: newclient.h:515
int8_t Wis
Use
Definition: living.h:36
void command_hide(object *op, const char *params)
Wizard &#39;hide&#39; command.
Definition: c_wiz.cpp:389
void monster_check_apply_all(object *monster)
Calls monster_check_apply() for all inventory objects.
Definition: monster.cpp:2001
void command_settings(object *op, const char *ignored)
Wizard wants to know some server settings, so display.
Definition: c_wiz.cpp:2914
int plugins_init_plugin(const char *libfile)
Try to load the specified plugin.
Definition: plugins.cpp:374
void give_artifact_abilities(object *op, const object *artifact)
Fixes the given object, giving it the abilities and titles it should have due to the second artifact-...
Definition: artifact.cpp:230
void object_give_identified_properties(object *op)
Ensure op has all its "identified" properties set.
Definition: item.cpp:1365
void query_name(const object *op, char *buf, size_t size)
Describes an item.
Definition: item.cpp:594
void command_setgod(object *op, const char *params)
Sets the god for some objects.
Definition: c_wiz.cpp:418
static void command_learn_spell_or_prayer(object *op, const char *params, int special_prayer)
Wizards wants to learn a spell.
Definition: c_wiz.cpp:2357
static void set_magic(int difficulty, object *op, int max_magic, int flags)
Sets a random magical bonus in the given object based upon the given difficulty, and the given max po...
Definition: treasure.cpp:690
void object_free_drop_inventory(object *ob)
Frees everything allocated by an object, removes it from the list of used objects, and puts it on the list of free objects.
Definition: object.cpp:1545
#define FLAG_IDENTIFIED
Item is identifiable (e.g.
Definition: define.h:248
short freearr_x[SIZEOFFREE]
X offset when searching around a spot.
Definition: object.cpp:299
socket_struct * socket
Socket information for this player.
Definition: player.h:109
void command_remove(object *op, const char *params)
Remove an object from its position.
Definition: c_wiz.cpp:1565
#define FMT64
Definition: compat.h:16
void set_abs_magic(object *op, int magic)
Sets magical bonus in an object, and recalculates the effect on the armour variable, and the effect on speed of armour.
Definition: treasure.cpp:642
This is a game-map.
Definition: map.h:320
void object_dump(const object *op, StringBuffer *sb)
Dumps an object.
Definition: object.cpp:630
void command_reset(object *op, const char *params)
Resets a map.
Definition: c_wiz.cpp:1885
#define MSG_TYPE_COMMUNICATION
Communication between players.
Definition: newclient.h:427
Archetypes * archetypes()
Get archetypes.
Definition: AssetsManager.h:44
#define EXIT_PATH(xyz)
Definition: define.h:439
int out_of_map(mapstruct *m, int x, int y)
Return 1 if coordinates X and Y are out of the map M, taking into account tiling. ...
Definition: map.cpp:2323
uint8_t state
Input state of the player (name, password, etc).
Definition: player.h:133
object * ob
The object representing the player.
Definition: player.h:179
Item is stack top.
Definition: c_wiz.cpp:39
#define EXIT_X(xyz)
Definition: define.h:441
uint8_t real_wiz
Use mud-like wizards.
Definition: global.h:272
void do_learn_spell(object *op, object *spell, int special_prayer)
Actually makes op learn spell.
Definition: apply.cpp:146
See Potion.
Definition: object.h:116
size_t get_faces_count()
Definition: assets.cpp:297
int plugins_remove_plugin(const char *id)
Unload the specified plugin.
Definition: plugins.cpp:455
struct Settings settings
Global settings.
Definition: init.cpp:139
uint32_t map_size(mapstruct *m)
Calculate map size without intermediate sign extension.
Definition: map.cpp:808
#define NDI_LT_GREEN
DarkSeaGreen, which is actually paler than seagreen - also background color.
Definition: newclient.h:254
object * object_new(void)
Grabs an object from the list of unused objects, makes sure it is initialised, and returns it...
Definition: object.cpp:1258
char * path_combine_and_normalize(const char *src, const char *dst, char *path, size_t size)
Combines the 2 paths.
Definition: path.cpp:172
#define FREE_AND_CLEAR_STR(xyz)
Release the shared string, and set it to NULL.
Definition: global.h:200
static object * get_spell_by_name(object *op, const char *spell_name)
Returns spell object (from archetypes) by name.
Definition: c_wiz.cpp:2253
#define UPD_WEIGHT
Definition: newclient.h:332
uint32_t tag_t
Object tag, unique during the whole game.
Definition: object.h:14
int16_t dam
How much damage this object does when hitting.
Definition: living.h:46
See Spell.
Definition: object.h:219
enum shutdown_type type
Definition: commands.h:48
Item is somewhere in stack.
Definition: c_wiz.cpp:40
int allocated_sockets
Number of allocated items in init_sockets.
Definition: newserver.h:148
struct shutdown_s shutdown_state
Definition: c_wiz.cpp:44
#define HEAD(op)
Returns the head part of an object.
Definition: object.h:609
#define FLAG_WIZ
Object has special privilegies.
Definition: define.h:218
void update_los(object *op)
Recalculates the array which specifies what is visible for the given player-object.
Definition: los.cpp:509
void command_toggle_shout(object *op, const char *params)
A simple toggle for the no_shout field.
Definition: c_wiz.cpp:615
#define MSG_TYPE_COMMAND_DEBUG
Various debug type commands.
Definition: newclient.h:549
living stats
Str, Con, Dex, etc.
Definition: object.h:378
#define EXIT_Y(xyz)
Definition: define.h:442
void plugins_display_list(object *op)
Displays a list of loaded plugins (keystrings and description) in the game log window.
Definition: plugins.cpp:480
#define MAX_BUF
Used for all kinds of things.
Definition: define.h:35
void command_purge_quest_definitions(object *op, const char *param)
Definition: c_wiz.cpp:2859
int16_t invisible
How much longer the object will be invis.
Definition: object.h:370
#define MSG_TYPE_ADMIN
Definition: newclient.h:418
static void command_kick2(object *op, const char *params)
Kicks a player from the server.
Definition: c_wiz.cpp:468
uint32_t tick_duration
Gloabal variables:
Definition: time.cpp:35
size_t strlcpy(char *dst, const char *src, size_t size)
Portable implementation of strlcpy(3).
Definition: porting.cpp:222
float speed_left
How much speed is left to spend this round.
Definition: object.h:338
void object_copy(const object *src_ob, object *dest_ob)
Copy object first frees everything allocated by the second object, and then copies the contents of th...
Definition: object.cpp:1177
struct mapstruct * map
Pointer to the map in which this object is present.
Definition: object.h:305
Skill-related defines, including subtypes.
void assets_finish_archetypes_for_play()
Definition: assets.cpp:513
void command_help(object *op, const char *params)
Player is asking for some help.
Definition: c_misc.cpp:1770
object * object_find_by_tag_global(tag_t i)
Returns the object which has the count-variable equal to the argument.
Definition: object.cpp:712
const char * confdir
Configuration files.
Definition: global.h:248
object * get_jail_exit(object *op)
Returns an object which is an exit through which the player represented by op should be sent in order...
Definition: region.cpp:252
void command_goto(object *op, const char *params)
Wizard teleports to a map.
Definition: c_wiz.cpp:724
void command_dumpabove(object *op, const char *params)
Player wants to dump object above her.
Definition: c_wiz.cpp:2902
uint32_t in_memory
Combination of IN_MEMORY_xxx flags.
Definition: map.h:340
short freearr_y[SIZEOFFREE]
Y offset when searching around a spot.
Definition: object.cpp:305
void inventory(object *op, object *inv)
Prints object&#39;s inventory.
Definition: c_object.cpp:2117
object * object_create_arch(archetype *at)
Create a full object using the given archetype.
Definition: arch.cpp:296
#define FOR_MAP_FINISH()
Finishes FOR_MAP_PREPARE().
Definition: define.h:753
void command_abil(object *op, const char *params)
Changes an object&#39;s statistics.
Definition: c_wiz.cpp:1819
void command_diff(object *op, const char *params)
Get a diff of specified items.
Definition: c_wiz.cpp:2622
#define SAVE_ERROR_UCREATION
Couldn&#39;t create the file for unique objects.
Definition: map.h:144
uint8_t permanent_exp_ratio
How much exp should be &#39;permenant&#39; and unable to be lost.
Definition: global.h:259
void command_kick(object *op, const char *params)
Kicks a player from the server.
Definition: c_wiz.cpp:556
See Player.
Definition: object.h:112
const char * datadir
Read only data files.
Definition: global.h:249
struct archetype * other_arch
Pointer used for various things - mostly used for what this objects turns into or what this object cr...
Definition: object.h:425
struct treasurelist * randomitems
Items to be generated.
Definition: object.h:395
int8_t body_info[NUM_BODY_LOCATIONS]
Body info as loaded from the file.
Definition: object.h:382
void clear_los(player *pl)
Clears/initialises the los-array associated to the player controlling the object. ...
Definition: los.cpp:270
void command_stack_push(object *op, const char *params)
Push specified item on stack.
Definition: c_wiz.cpp:2547
mapstruct * styles
Loaded styles maps cache, to avoid having to load all the time.
Definition: style.cpp:122
static event_registration m
Definition: citylife.cpp:424
uint16_t set_friendly_fire
Percent of damage done by peaceful player vs player damage.
Definition: global.h:276
This structure contains all information related to one map square.
Definition: map.h:261
#define UPD_NROF
Definition: newclient.h:337
int become_follower(object *op, const object *new_god)
This function is called whenever a player has switched to a new god.
Definition: gods.cpp:414
const char * localdir
Read/write data files.
Definition: global.h:250
#define FLAG_WIZCAST
The wizard can cast spells in no-magic area.
Definition: define.h:277
static object * dm_stack_peek(player *pl)
Get current stack top item for player.
Definition: c_wiz.cpp:120
void command_possess(object *op, const char *params)
DM can possess a monster.
Definition: c_wiz.cpp:1432
sstring name
The name of the object, obviously...
Definition: object.h:319
time_t time
When using SHUTDOWN_TIME, time of shutdown.
Definition: commands.h:49
#define MAP_WIDTH(m)
Map width.
Definition: map.h:76
Only for debugging purposes.
Definition: logger.h:13
uint32_t nrof
Number of objects.
Definition: object.h:342
uint8_t no_player_stealing
If 1, can not steal from other players.
Definition: global.h:311
uint32_t no_shout
if True, player is *not *able to use shout command.
Definition: player.h:150
int8_t Cha
Use
Definition: living.h:36
unsigned int distance
Distance, in squares.
Definition: map.h:376
void reset_sleep(void)
Initialise all variables used in the timing routines.
Definition: time.cpp:134
void object_set_enemy(object *op, object *enemy)
Sets the enemy of an object.
Definition: object.cpp:900
void command_free(object *op, const char *params)
Totally free an object.
Definition: c_wiz.cpp:1612
#define CLEAR_FLAG(xyz, p)
Definition: define.h:385
#define STACK_SIZE
Stack size, static.
Definition: c_wiz.cpp:35
uint8_t type
PLAYER, BULLET, etc.
Definition: object.h:348
int8_t ac
Armor Class, lower AC increases probability of not getting hit.
Definition: living.h:38
void command_overlay_save(object *op, const char *params)
Saves the op&#39;s map as an overlay - objects are persisted.
Definition: c_wiz.cpp:568
void get_ob_diff(StringBuffer *sb, const object *op, const object *op2)
Returns a pointer to a static string which contains all variables which are different in the two give...
Definition: object.cpp:4971
int8_t Pow
Use
Definition: living.h:36
void object_update_speed(object *op)
Updates the speed of an object.
Definition: object.cpp:1334
void command_loadtest(object *op, const char *params)
This command will stress server.
Definition: c_wiz.cpp:306
static player * get_other_player_from_name(object *op, const char *name)
Enough of the DM functions seem to need this that I broke it out to a separate function.
Definition: c_wiz.cpp:60
#define UPD_NAME
Definition: newclient.h:334
void map_remove_unique_files(const mapstruct *map)
Remove files containing the map&#39;s unique items.
Definition: map.cpp:2668
int next_warn
Definition: commands.h:51
bool can_follow(object *op, player *other)
Definition: c_wiz.cpp:2796
int get_rangevector(object *op1, const object *op2, rv_vector *retval, int flags)
From map.c This is used by get_player to determine where the other creature is.
Definition: map.cpp:2522
static void reset_faces_sent(struct socket_struct *socket)
Definition: c_wiz.cpp:1525
void command_freeze(object *op, const char *params)
Freezes a player for a specified tick count, 100 by default.
Definition: c_wiz.cpp:745
int64_t check_exp_adjust(const object *op, int64_t exp)
Returns the maximum experience the object can gain or lose.
Definition: living.cpp:2102
void command_stats(object *op, const char *params)
Displays the statistics of a player.
Definition: c_wiz.cpp:1762
void command_dump(object *op, const char *params)
Dumps the difference between an object and its archetype.
Definition: c_wiz.cpp:1377
archetype * find_archetype_by_object_name(const char *name)
This function retrieves an archetype given the name that appears during the game (for example...
Definition: arch.cpp:51
int64_t exp
Experience.
Definition: living.h:47
int16_t maxsp
Max spell points.
Definition: living.h:43
#define FLAG_MONSTER
Will attack players.
Definition: define.h:232
uint8_t set_title
Players can set thier title.
Definition: global.h:266
#define NDI_UNIQUE
Print immediately, don&#39;t buffer.
Definition: newclient.h:270
void command_nowiz(object *op, const char *params)
Steps down from wizard mode.
Definition: c_wiz.cpp:2080
#define MSG_SUBTYPE_NONE
Definition: newclient.h:439
C function wrappers to interact with assets.
mapstruct * has_been_loaded(const char *name)
Checks whether map has been loaded.
Definition: map.cpp:79
One player.
Definition: player.h:107
void command_follow(object *op, const char *params)
Follow a player, or stop following a player.
Definition: c_wiz.cpp:2809
archetype * more
Next part of a linked object.
Definition: object.h:486
#define FLAG_WAS_WIZ
Player was once a wiz.
Definition: define.h:221
#define MAX_NAME
Definition: define.h:41
#define FOR_MAP_PREPARE(map_, mx_, my_, it_)
Constructs a loop iterating over all objects of a map tile.
Definition: define.h:746
#define EVENT_MUZZLE
A player was Muzzled (no_shout set).
Definition: events.h:65
void command_stack_clear(object *op, const char *params)
Empty DM item stack.
Definition: c_wiz.cpp:2596
int32_t food
How much food in stomach.
Definition: living.h:48
StringBuffer * buf
Definition: readable.cpp:1563
uint32_t worldmapstartx
Starting x tile for the worldmap.
Definition: global.h:292
void command_stack_list(object *op, const char *params)
Displays stack contents.
Definition: c_wiz.cpp:2565
A buffer that will be expanded as content is added to it.
int16_t maxhp
Max hit points.
Definition: living.h:41
uint16_t difficulty
What level the player should be to play here.
Definition: map.h:338
void command_forget_spell(object *op, const char *params)
Command for players to forget a spell.
Definition: c_wiz.cpp:2415
void command_unloadplugin(object *op, const char *params)
Unloads the given plugin.
Definition: c_wiz.cpp:2490
int allow_denied_spells_writing
If set, players can write spells they can&#39;t cast.
Definition: global.h:316
const char * sstring
Definition: sstring.h:2
mapstruct * next
Next map, linked list.
Definition: map.h:321
object * object_insert_in_ob(object *op, object *where)
This function inserts the object op in the linked list inside the object environment.
Definition: object.cpp:2842
object * object_insert_in_map_at(object *op, mapstruct *m, object *originator, int flag, int x, int y)
Same as object_insert_in_map() except it handle separate coordinates and do a clean job preparing mul...
Definition: object.cpp:2085
int8_t Int
Use
Definition: living.h:36
int8_t wc
Weapon Class, lower WC increases probability of hitting.
Definition: living.h:37
void command_shutdown(object *op, const char *params)
Totally shutdowns the server.
Definition: c_wiz.cpp:658
static object * find_object_both(const char *params)
This finds and returns the object which matches the name or object number (specified via num #whateve...
Definition: c_wiz.cpp:403
void object_update(object *op, int action)
object_update() updates the array which represents the map.
Definition: object.cpp:1419
tag_t count
Unique object number for this object.
Definition: object.h:307
#define FLAG_WIZPASS
The wizard can go through walls.
Definition: define.h:302
#define SAVE_ERROR_PLAYER
Player on map to save.
Definition: map.h:151
void do_goto(object *op, const char *name, int x, int y)
Definition: c_move.cpp:151
uint8_t spell_failure_effects
Nasty backlash to spell failures.
Definition: global.h:270
int32_t timeout
Swapout is set to this.
Definition: map.h:337
This is one artifact, ie one special item.
Definition: artifact.h:14
void command_dmhide(object *op, const char *params)
A players wants to become DM and hide.
Definition: c_wiz.cpp:2519
player * find_player_partial_name(const char *plname)
Find a player by a partial name.
Definition: player.cpp:114
static void unhide(object *op)
Definition: c_wiz.cpp:333
static int checkdm(object *op, const char *pl_name, const char *pl_passwd, const char *pl_host)
object *op is trying to become dm.
Definition: c_wiz.cpp:2117
object * find_skill_by_name(object *who, const char *name)
This returns the skill pointer of the given name (the one that accumulates exp, has the level...
Definition: skill_util.cpp:209
void command_style_map_info(object *op, const char *params)
Displays information about styles loaded for random maps.
Definition: c_wiz.cpp:2763
uint8_t * faces_sent
This is a bitmap on sent face status.
Definition: newserver.h:100
float item_power_factor
See note in setings file.
Definition: global.h:304
object clone
An object from which to do object_copy()
Definition: object.h:487
#define SAVE_MODE_OVERLAY
Map is persisted as an overlay.
Definition: map.h:121
void command_accountpasswd(object *op, const char *params)
Definition: c_wiz.cpp:1638
void command_arrest(object *op, const char *params)
Wizard jails player.
Definition: c_wiz.cpp:821
int player_arrest(object *who)
Put a player into jail, taking into account cursed exits and player&#39;s region.
Definition: c_wiz.cpp:789
int8_t Str
Use
Definition: living.h:36
uint8_t resurrection
Ressurection possible w/ permadeth on.
Definition: global.h:267
static object * get_dm_object(player *pl, const char **params, int *from)
Checks &#39;params&#39; for object code.
Definition: c_wiz.cpp:196
void command_speed(object *op, const char *params)
Changes the server speed.
Definition: c_wiz.cpp:1732
#define MSG_TYPE_COMMAND_DM
DM related commands.
Definition: newclient.h:556
void command_patch(object *op, const char *params)
Wizard wants to altar an object.
Definition: c_wiz.cpp:1493
object * item
Special values of the artifact.
Definition: artifact.h:15
int16_t hp
Hit Points.
Definition: living.h:40
sstring followed_player
Player the DM is following.
Definition: player.h:220
object * enemy
Monster/player to follow even if not closest.
Definition: object.h:391
void each(std::function< void(T *)> op)
Apply a function to each asset.
#define MSG_TYPE_COMMUNICATION_PARTY
Party message.
Definition: newclient.h:663