Crossfire Server, Trunk
c_wiz.cpp
Go to the documentation of this file.
1 /*
2  * Crossfire -- cooperative multi-player graphical RPG and adventure game
3  *
4  * Copyright (c) 1999-2014 Mark Wedel and the Crossfire Development Team
5  * Copyright (c) 1992 Frank Tore Johansen
6  *
7  * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are
8  * welcome to redistribute it under certain conditions. For details, please
9  * see COPYING and LICENSE.
10  *
11  * The authors can be reached via e-mail at <crossfire@metalforge.org>.
12  */
13 
20 #include "global.h"
21 
22 #include <ctype.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <sys/stat.h>
26 
27 #include "sproto.h"
28 #include "spells.h"
29 #include "treasure.h"
30 #include "skills.h"
31 #include "assets.h"
32 
33 /* Defines for DM item stack **/
34 #define STACK_SIZE 50
36 enum {
41 };
42 
44 
59 static player *get_other_player_from_name(object *op, const char *name) {
60  player *pl;
61 
62  if (!name)
63  return NULL;
64 
65  for (pl = first_player; pl != NULL; pl = pl->next)
66  if (!strncmp(pl->ob->name, name, MAX_NAME))
67  break;
68 
69  if (pl == NULL) {
71  "No such player.");
72  return NULL;
73  }
74 
75  if (pl->ob == op) {
77  "You can't do that to yourself.");
78  return NULL;
79  }
80  if (pl->state != ST_PLAYING) {
82  "That player is in no state for that right now.");
83  return NULL;
84  }
85  return pl;
86 }
87 
94 static void dm_stack_pop(player *pl) {
95  if (!pl->stack_items || !pl->stack_position) {
97  "Empty stack!");
98  return;
99  }
100 
101  pl->stack_position--;
103  "Popped item from stack, %d left.",
104  pl->stack_position);
105 }
106 
119 static object *dm_stack_peek(player *pl) {
120  object *ob;
121 
122  if (!pl->stack_position) {
124  "Empty stack!");
125  return NULL;
126  }
127 
129  if (!ob) {
131  "Stacked item was removed!");
132  dm_stack_pop(pl);
133  return NULL;
134  }
135 
136  return ob;
137 }
138 
149 static void dm_stack_push(player *pl, tag_t item) {
150  if (!pl->stack_items) {
151  pl->stack_items = (tag_t *)malloc(sizeof(tag_t)*STACK_SIZE);
152  memset(pl->stack_items, 0, sizeof(tag_t)*STACK_SIZE);
153  }
154 
155  if (pl->stack_position == STACK_SIZE) {
157  "Item stack full!");
158  return;
159  }
160 
163  "Item stacked as %d.",
164  pl->stack_position);
165  pl->stack_position++;
166 }
167 
195 static object *get_dm_object(player *pl, const char **params, int *from) {
196  int item_tag, item_position;
197  object *ob;
198 
199  if (!pl)
200  return NULL;
201 
202  if (**params == '\0') {
203  if (from)
204  *from = STACK_FROM_TOP;
205  /* No parameter => get stack item */
206  return dm_stack_peek(pl);
207  }
208 
209  /* Let's clean white spaces */
210  while (**params == ' ')
211  (*params)++;
212 
213  /* Next case: number => item tag */
214  if (sscanf(*params, "%d", &item_tag)) {
215  /* Move parameter to next item */
216  while (isdigit(**params))
217  (*params)++;
218 
219  /* And skip blanks, too */
220  while (**params == ' ')
221  (*params)++;
222 
223  /* Get item */
224  ob = object_find_by_tag_global(item_tag);
225  if (!ob) {
226  if (from)
227  *from = STACK_FROM_NONE;
229  "No such item %d!",
230  item_tag);
231  return NULL;
232  }
233 
234  /* Got one, let's push it on stack */
235  dm_stack_push(pl, item_tag);
236  if (from)
237  *from = STACK_FROM_NUMBER;
238  return ob;
239  }
240 
241  /* Next case: $number => stack item */
242  if (sscanf(*params, "$%d", &item_position)) {
243  /* Move parameter to next item */
244  (*params)++;
245 
246  while (isdigit(**params))
247  (*params)++;
248  while (**params == ' ')
249  (*params)++;
250 
251  if (item_position >= pl->stack_position) {
252  if (from)
253  *from = STACK_FROM_NONE;
255  "No such stack item %d!",
256  item_position);
257  return NULL;
258  }
259 
260  ob = object_find_by_tag_global(pl->stack_items[item_position]);
261  if (!ob) {
262  if (from)
263  *from = STACK_FROM_NONE;
265  "Stack item %d was removed.",
266  item_position);
267  return NULL;
268  }
269 
270  if (from)
271  *from = item_position < pl->stack_position-1 ? STACK_FROM_STACK : STACK_FROM_TOP;
272  return ob;
273  }
274 
275  /* Next case: 'me' => return pl->ob */
276  if (!strncmp(*params, "me", 2)) {
277  if (from)
278  *from = STACK_FROM_NUMBER;
279  dm_stack_push(pl, pl->ob->count);
280 
281  /* Skip to next token */
282  (*params) += 2;
283  while (**params == ' ')
284  (*params)++;
285 
286  return pl->ob;
287  }
288 
289  /* Last case: get stack top */
290  if (from)
291  *from = STACK_FROM_TOP;
292  return dm_stack_peek(pl);
293 }
294 
305 void command_loadtest(object *op, const char *params) {
306  uint32_t x, y;
307  char buf[1024];
308 
310  "loadtest will stress server through teleporting at different map places. "
311  "Use at your own risk. Very long loop used so server may have to be reset. "
312  "type loadtest TRUE to run");
314  "{%s}",
315  params);
316  if (*params == '\0')
317  return;
318  if (strncmp(params, "TRUE", 4))
319  return;
320 
322  "gogogo");
323 
324  for (x = 0; x < settings.worldmaptilesx; x++) {
325  for (y = 0; y < settings.worldmaptilesy; y++) {
326  snprintf(buf, sizeof(buf), "/world/world_%u_%u", x+settings.worldmapstartx, y+settings.worldmapstarty);
327  command_goto(op, buf);
328  }
329  }
330 }
331 
332 static void unhide(object* op) {
333  op->contr->hidden = 0;
334  op->invisible = 1;
335  op->map->players++;
337  "You are no longer hidden from other players");
340  "%s has entered the game.", op->name);
341 }
342 
351 static void do_wizard_hide(object *op, int silent_dm) {
352  if (op->contr->hidden) {
353  unhide(op);
354  if (!silent_dm) {
357  "The Dungeon Master has arrived!");
358  }
359  } else {
360  op->contr->hidden = 1;
362  "Other players will no longer see you.");
363  op->map->players--;
364  if (!silent_dm) {
367  "The Dungeon Master is gone...");
368  }
371  "%s leaves the game.",
372  op->name);
375  "%s left the game.",
376  op->name);
377  }
378 }
379 
388 void command_hide(object *op, const char *params) {
389  (void)params;
390  do_wizard_hide(op, 0);
391 }
392 
402 static object *find_object_both(const char *params) {
403  if (params[0] == '#')
404  return object_find_by_tag_global(atol(params+1));
405  else
407 }
408 
417 void command_setgod(object *op, const char *params) {
418  object *ob;
419  const object *god;
420  char *str;
421 
422  if (*params == '\0' || !(str = const_cast<char *>(strchr(params, ' ')))) {
424  "Usage: set_god player god");
425  return;
426  }
427 
428  /* kill the space, and set string to the next param */
429  *str++ = '\0';
430  if (!(ob = find_object_both(params))) {
432  "Set whose god - can not find object %s?",
433  params);
434  return;
435  }
436 
437  /*
438  * Perhaps this is overly restrictive? Should we perhaps be able
439  * to rebless altars and the like?
440  */
441  if (ob->type != PLAYER) {
443  "%s is not a player - can not change its god",
444  ob->name);
445  return;
446  }
447 
448  god = find_god(str);
449  if (god == NULL) {
451  "No such god %s.",
452  str);
453  return;
454  }
455 
456  become_follower(ob, god);
457 }
458 
467 static void command_kick2(object *op, const char *params) {
468  struct pl *pl;
469 
470  for (pl = first_player; pl != NULL; pl = pl->next) {
471  if ((*params == '\0' || !strcmp(pl->ob->name, params)) && pl->ob != op) {
472  object *op = pl->ob;
473  if (!QUERY_FLAG(op, FLAG_REMOVED)) {
475  }
477  "%s is kicked out of the game.",
478  op->name);
479 
480  // Saving/leaving/removing is handled on the next tick in do_server().
481  pl->socket->status = Ns_Dead;
482  }
483  }
484 }
485 
501 void command_banish(object *op, const char *params) {
502  player *pl;
503  FILE *banishfile;
504  char buf[MAX_BUF];
505  time_t now;
506 
507  if (*params == '\0') {
509  "Usage: banish <player>.");
510  return;
511  }
512 
514  if (!pl)
515  return;
516 
517  snprintf(buf, sizeof(buf), "%s/%s", settings.localdir, BANISHFILE);
518 
519  if ((banishfile = fopen(buf, "a")) == NULL) {
520  LOG(llevDebug, "Could not find file banish_file.\n");
522  "Could not find banish_file.");
523  return;
524  }
525 
526  now = time(NULL);
527  /*
528  * Record this as a comment - then we don't have to worry about changing
529  * the parsing code.
530  */
531  fprintf(banishfile, "# %s (%s) banned by %s at %s\n", pl->ob->name, pl->socket->host, op->name, ctime(&now));
532  fprintf(banishfile, "*@%s\n", pl->socket->host);
533  fclose(banishfile);
534 
535  LOG(llevDebug, "! %s banned %s from IP: %s.\n", op->name, pl->ob->name, pl->socket->host);
536 
538  "You banish %s",
539  pl->ob->name);
540 
542  "%s banishes %s from the land!",
543  op->name, pl->ob->name);
544  command_kick2(op, pl->ob->name);
545 }
546 
555 void command_kick(object *op, const char *params) {
557 }
558 
567 void command_overlay_save(object *op, const char *params) {
568  (void)params;
569  if (!op)
570  return;
571 
572  if (save_map(op->map, SAVE_MODE_OVERLAY) < 0)
574  "Overlay save error!");
575  else
577  "Current map has been saved as an overlay.");
578 }
579 
588 void command_overlay_reset(object *op, const char *params) {
589  char filename[MAX_BUF];
590  struct stat stats;
591  (void)params;
592 
594  if (!stat(filename, &stats))
595  if (!unlink(filename))
597  "Overlay successfully removed.");
598  else
600  "Overlay couldn't be removed.");
601  else
603  "No overlay for current map.");
604 }
605 
614 void command_toggle_shout(object *op, const char *params) {
615  player *pl;
616 
617  if (*params == '\0') {
619  "Usage: toggle_shout <player>.");
620  return;
621  }
622 
624  if (!pl)
625  return;
626 
627  if (pl->ob->contr->no_shout == 0) {
628  pl->ob->contr->no_shout = 1;
629 
631  "You have been muzzled by the DM!");
633  "You muzzle %s.",
634  pl->ob->name);
635 
637 
638  return;
639  }
640 
641  pl->ob->contr->no_shout = 0;
643  "You are allowed to shout and chat again.");
645  "You remove %s's muzzle.",
646  pl->ob->name);
647 }
648 
657 void command_shutdown(object *op, const char *params) {
658  if (strlen(params) == 0) {
659  /* Give DM command help and display current shutdown status. */
660  command_help(op, "shutdown");
663  MSG_TYPE_COMMAND_DM, "No shutdown is currently scheduled.");
664  } else if (shutdown_state.type == SHUTDOWN_TIME) {
665  time_t time_left = shutdown_state.time - time(NULL);
667  MSG_TYPE_COMMAND_DM, "Shutdown scheduled in %lu minutes.", time_left/60);
668  } else if (shutdown_state.type == SHUTDOWN_IDLE) {
670  MSG_TYPE_COMMAND_DM, "Shutdown scheduled when there are no active players.");
671  }
672  } else if (strcmp(params, "cancel") == 0) {
675  MSG_TYPE_ADMIN_DM, "Server shutdown cancelled.");
676  LOG(llevInfo, "Server shutdown cancelled by %s.\n", op->name);
678  } else {
680  MSG_TYPE_COMMAND_ERROR, "No shutdown is pending.");
681  }
682  } else if (strncmp(params, "now", 3) == 0) {
683  /* Announce and shut down immediately. */
685  MSG_TYPE_ADMIN_DM, "This server is shutting down now!");
687  shutdown_state.time = time(NULL);
688  LOG(llevInfo, "Server shutdown initiated by %s.\n", op->name);
689  } else if (strcmp(params, "idle") == 0) {
691  MSG_TYPE_ADMIN_DM, "This server will shut down when all players leave.");
693  shutdown_state.time = 0;
695  LOG(llevInfo, "Server idle shutdown scheduled by %s.\n", op->name);
696  } else {
697  /* Schedule (but don't announce) a shutdown. */
698  int minutes = atoi(params);
699 
700  if (minutes > 0 && minutes <= 720) {
703  "Server will shut down in %d minutes.", minutes);
705  shutdown_state.time = time(NULL) + minutes * 60;
706  LOG(llevInfo, "Server shutdown scheduled in %d minutes by %s.\n", minutes, op->name);
707  } else {
710  "Please specify a reasonable time in minutes.");
711  }
712  }
713 }
714 
723 void command_goto(object *op, const char *params) {
724  if (!op)
725  return ;
726 
727  if (*params == '\0') {
729  "Go to what level?");
730  return;
731  }
732 
733  do_goto(op, params, -1, -1);
734 }
735 
744 void command_freeze(object *op, const char *params) {
745  int ticks;
746  player *pl;
747 
748  if (*params == '\0') {
750  "Usage: freeze [ticks] <player>.");
751  return;
752  }
753 
754  ticks = atoi(params);
755  if (ticks) {
756  while ((isdigit(*params) || isspace(*params)) && *params != 0)
757  params++;
758  if (*params == 0) {
760  "Usage: freeze [ticks] <player>.");
761  return;
762  }
763  } else
764  ticks = 100;
765 
767  if (!pl)
768  return;
769 
771  "You have been frozen by the DM!");
772 
774  "You freeze %s for %d ticks",
775  pl->ob->name, ticks);
776 
777  pl->ob->speed_left = -(pl->ob->speed*ticks);
778 }
779 
788 int player_arrest(object *who) {
789  object *dummy;
790  mapstruct *cur;
791  int x, y;
792 
793  if (who->type != PLAYER)
794  return -3;
795 
796  dummy = get_jail_exit(who);
797  if (!dummy) {
798  return -1;
799  }
800  cur = who->map;
801  x = who->x;
802  y = who->y;
803  enter_exit(who, dummy);
805 
806  if (cur == who->map && x == who->x && y == who->y)
807  return -2;
808 
809  return 0;
810 }
811 
820 void command_arrest(object *op, const char *params) {
821  player *pl;
822  int ret;
823 
824  if (!op)
825  return;
826  if (*params == '\0') {
828  "Usage: arrest <player>.");
829  return;
830  }
832  if (!pl)
833  return;
834 
835  ret = player_arrest(pl->ob);
836  if (ret == -1) {
837  /* we have nowhere to send the prisoner....*/
839  "Can't jail player, there is no map to hold them");
840  return;
841  }
842  if (ret == -2) {
843  /* something prevented jailing the player */
845  "Can't jail player, map loading issue or already in jail's position");
846  return;
847 
848  }
849 
851  "You have been arrested.");
853  "Jailed %s",
854  pl->ob->name);
855  LOG(llevInfo, "Player %s arrested by %s\n", pl->ob->name, op->name);
856 }
857 
865 void command_summon(object *op, const char *params) {
866  int i;
867  object *dummy;
868  player *pl;
869 
870  if (!op)
871  return;
872 
873  if (*params == '\0') {
875  "Usage: summon <player>.");
876  return;
877  }
878 
880  if (!pl)
881  return;
882 
883  i = object_find_free_spot(op, op->map, op->x, op->y, 1, 9);
884  if (i == -1) {
886  "Can not find a free spot to place summoned player.");
887  return;
888  }
889 
890  dummy = object_new();
891  EXIT_PATH(dummy) = add_string(op->map->path);
892  EXIT_X(dummy) = op->x+freearr_x[i];
893  EXIT_Y(dummy) = op->y+freearr_y[i];
894  enter_exit(pl->ob, dummy);
897  "You are summoned.");
899  "You summon %s",
900  pl->ob->name);
901 }
902 
911 /* mids 01/16/2002 */
912 void command_teleport(object *op, const char *params) {
913  int i;
914  object *dummy;
915  player *pl;
916 
917  if (!op)
918  return;
919 
920  if (*params == '\0') {
922  "Usage: teleport <player>.");
923  return;
924  }
925 
927  if (!pl) {
929  "No such player or ambiguous name.");
930  return;
931  }
932 
933  i = object_find_free_spot(pl->ob, pl->ob->map, pl->ob->x, pl->ob->y, 1, 9);
934  if (i == -1) {
936  "Can not find a free spot to teleport to.");
937  return;
938  }
939 
940  dummy = object_new();
941  EXIT_PATH(dummy) = add_string(pl->ob->map->path);
942  EXIT_X(dummy) = pl->ob->x+freearr_x[i];
943  EXIT_Y(dummy) = pl->ob->y+freearr_y[i];
944  enter_exit(op, dummy);
946  if (!op->contr->hidden)
948  "You see a portal open.");
950  "You teleport to %s",
951  pl->ob->name);
952 }
953 
978 void command_create(object *op, const char *params) {
979  object *tmp = NULL;
980  uint32_t i;
981  int magic, set_magic = 0, set_nrof = 0, gotquote, gotspace;
982  uint32_t nrof;
983  char *cp, *bp, *bp2, *bp3, *endline, cpy[MAX_BUF];
984  archetype *at, *at_spell = NULL;
985  const artifact *art = NULL;
986 
987  if (!op)
988  return;
989 
990  if (*params == '\0') {
992  "Usage: create [nr] [magic] <archetype> [ of <artifact>] [variable_to_patch setting]");
993  return;
994  }
995  safe_strncpy(cpy, params, sizeof(cpy));
996  bp = cpy;
997 
998  /* We need to know where the line ends */
999  endline = bp+strlen(bp);
1000 
1001  if (sscanf(bp, "%u ", &nrof)) {
1002  if ((bp = strchr(cpy, ' ')) == NULL) {
1004  "Usage: create [nr] [magic] <archetype> [ of <artifact>] [variable_to_patch setting]");
1005  return;
1006  }
1007  bp++;
1008  set_nrof = 1;
1009  LOG(llevDebug, "%s creates: (%u) %s\n", op->name, nrof, bp);
1010  }
1011  if (sscanf(bp, "%d ", &magic)) {
1012  if ((bp = strchr(bp, ' ')) == NULL) {
1014  "Usage: create [nr] [magic] <archetype> [ of <artifact>] [variable_to_patch setting]");
1015  return;
1016  }
1017  bp++;
1018  set_magic = 1;
1019  LOG(llevDebug, "%s creates: (%d) (%d) %s\n", op->name, nrof, magic, bp);
1020  }
1021  if ((cp = strstr(bp, " of ")) != NULL) {
1022  *cp = '\0';
1023  cp += 4;
1024  }
1025  for (bp2 = bp; *bp2; bp2++) {
1026  if (*bp2 == ' ') {
1027  *bp2 = '\0';
1028  bp2++;
1029  break;
1030  }
1031  }
1032 
1033  if ((at = try_find_archetype(bp)) == NULL) {
1035  "No such archetype.");
1036  return;
1037  }
1038 
1039  if (cp) {
1040  char spell_name[MAX_BUF], *fsp = NULL;
1041 
1042  /*
1043  * Try to find a spell object for this. Note that
1044  * we also set up spell_name which is only
1045  * the first word.
1046  */
1047 
1048  at_spell = try_find_archetype(cp);
1049  if (!at_spell || at_spell->clone.type != SPELL)
1050  at_spell = find_archetype_by_object_name(cp);
1051  if (!at_spell || at_spell->clone.type != SPELL) {
1052  safe_strncpy(spell_name, cp, sizeof(spell_name));
1053  fsp = strchr(spell_name, ' ');
1054  if (fsp) {
1055  *fsp = 0;
1056  fsp++;
1057  at_spell = try_find_archetype(spell_name);
1058 
1059  /* Got a spell, update the first string pointer */
1060  if (at_spell && at_spell->clone.type == SPELL)
1061  bp2 = cp+strlen(spell_name)+1;
1062  else
1063  at_spell = NULL;
1064  } else
1065  at_spell = NULL;
1066  }
1067 
1068  /* OK - we didn't find a spell - presume the 'of'
1069  * in this case means its an artifact.
1070  */
1071  if (!at_spell) {
1072  if (find_artifactlist(at->clone.type) == NULL) {
1074  "No artifact list for type %d\n",
1075  at->clone.type);
1076  } else {
1077  art = find_artifactlist(at->clone.type)->items;
1078 
1079  do {
1080  if (!strcmp(art->item->name, cp) && legal_artifact_combination(&at->clone, art))
1081  break;
1082  art = art->next;
1083  } while (art != NULL);
1084  if (!art) {
1086  "No such artifact ([%d] of %s)",
1087  at->clone.type, cp);
1088  }
1089  }
1090  LOG(llevDebug, "%s creates: (%d) (%d) (%s) of (%s)\n", op->name, set_nrof ? nrof : 0, set_magic ? magic : 0, bp, cp);
1091  }
1092  } /* if cp */
1093 
1094  /* rods and potions can get their spell from the artifact */
1095  if ((at->clone.type == ROD || at->clone.type == POTION) && !at_spell && (!art || !art->item->other_arch)) {
1097  "Unable to find spell %s for object that needs it, or it is of wrong type",
1098  cp);
1099  return;
1100  }
1101  if ((at->clone.type == WAND || at->clone.type == SCROLL || at->clone.type == SPELLBOOK)
1102  && !at_spell) {
1104  "Unable to find spell %s for object that needs it, or it is of wrong type",
1105  cp);
1106  return;
1107  }
1108 
1109  /*
1110  * Rather than have two different blocks with a lot of similar code,
1111  * just create one object, do all the processing, and then determine
1112  * if that one object should be inserted or if we need to make copies.
1113  */
1114  tmp = object_create_arch(at);
1115  if (settings.real_wiz == FALSE)
1117  if (set_magic)
1118  set_abs_magic(tmp, magic);
1119  if (art)
1121  if (!is_identifiable_type(tmp)) {
1124  }
1125 
1126  /*
1127  * This entire block here tries to find variable pairings,
1128  * eg, 'hp 4' or the like. The mess here is that values
1129  * can be quoted (eg "my cool sword"); So the basic logic
1130  * is we want to find two spaces, but if we got a quote,
1131  * any spaces there don't count.
1132  */
1133  while (*bp2 && bp2 <= endline) {
1134  gotspace = 0;
1135  gotquote = 0;
1136  /* find the first quote */
1137  for (bp3 = bp2; *bp3 && gotspace < 2 && gotquote < 2; bp3++) {
1138  /* Found a quote - now lets find the second one */
1139  if (*bp3 == '"') {
1140  *bp3 = ' ';
1141  bp2 = bp3+1; /* Update start of string */
1142  bp3++;
1143  gotquote++;
1144  while (*bp3) {
1145  if (*bp3 == '"') {
1146  *bp3 = '\0';
1147  gotquote++;
1148  } else
1149  bp3++;
1150  }
1151  } else if (*bp3 == ' ') {
1152  gotspace++;
1153  }
1154  }
1155 
1156  /*
1157  * If we got two spaces, send the second one to null.
1158  * if we've reached the end of the line, increase gotspace -
1159  * this is perfectly valid for the list entry listed.
1160  */
1161  if (gotspace == 2 || gotquote == 2) {
1162  bp3--; /* Undo the extra increment */
1163  *bp3 = '\0';
1164  } else if (*bp3 == '\0')
1165  gotspace++;
1166 
1167  if ((gotquote && gotquote != 2)
1168  || (gotspace != 2 && gotquote != 2)) {
1169  /*
1170  * Unfortunately, we've clobbered lots of values, so printing
1171  * out what we have probably isn't useful. Break out, because
1172  * trying to recover is probably won't get anything useful
1173  * anyways, and we'd be confused about end of line pointers
1174  * anyways.
1175  */
1177  "Malformed create line: %s",
1178  bp2);
1179  break;
1180  }
1181  /* bp2 should still point to the start of this line,
1182  * with bp3 pointing to the end
1183  */
1184  if (set_variable(tmp, bp2) == -1)
1186  "Unknown variable %s",
1187  bp2);
1188  else
1190  "(%s#%d)->%s",
1191  tmp->name, tmp->count, bp2);
1192  bp2 = bp3+1;
1193  }
1194 
1195  if (at->clone.nrof) {
1196  if (at_spell)
1198 
1199  if (set_nrof)
1200  tmp->nrof = nrof;
1201 
1202  if (at->clone.randomitems != NULL && !at_spell) {
1203  create_treasure(at->clone.randomitems, tmp, 0, op->map->difficulty, 0);
1204  if (QUERY_FLAG(tmp, FLAG_MONSTER)) {
1206  }
1207  }
1208 
1209  /* Multipart objects can't be in inventory, put'em on floor. */
1210  if (!tmp->more) {
1212  } else {
1213  object_insert_in_map_at(tmp, op->map, op, 0, op->x, op->y);
1214  }
1215 
1216  /* Let's put this created item on stack so dm can access it easily. */
1217  dm_stack_push(op->contr, tmp->count);
1218 
1219  return;
1220  }
1221 
1222  for (i = 0; i < (set_nrof ? nrof : 1); i++) {
1223  archetype *atmp;
1224  object *prev = NULL, *head = NULL, *dup;
1225 
1226  for (atmp = at; atmp != NULL; atmp = atmp->more) {
1227  dup = arch_to_object(atmp);
1228 
1229  if (at_spell)
1230  object_insert_in_ob(arch_to_object(at_spell), dup);
1231 
1232  /*
1233  * The head is what contains all the important bits,
1234  * so just copying it over should be fine.
1235  */
1236  if (head == NULL) {
1237  head = dup;
1238  object_copy(tmp, dup);
1239  }
1240  if (settings.real_wiz == FALSE)
1241  SET_FLAG(dup, FLAG_WAS_WIZ);
1242  dup->x = op->x+dup->arch->clone.x;
1243  dup->y = op->y+dup->arch->clone.y;
1244  dup->map = op->map;
1245 
1246  if (head != dup) {
1247  dup->head = head;
1248  prev->more = dup;
1249  }
1250  prev = dup;
1251  }
1252 
1253  if (QUERY_FLAG(head, FLAG_ALIVE)) {
1254  object *check = head;
1255  int size_x = 0;
1256  int size_y = 0;
1257 
1258  while (check) {
1259  size_x = MAX(size_x, check->arch->clone.x);
1260  size_y = MAX(size_y, check->arch->clone.y);
1261  check = check->more;
1262  }
1263 
1264  if (out_of_map(op->map, head->x+size_x, head->y+size_y)) {
1265  if (head->x < size_x || head->y < size_y) {
1266  dm_stack_pop(op->contr);
1269  "Object too big to insert in map, or wrong position.");
1271  return;
1272  }
1273 
1274  check = head;
1275  while (check) {
1276  check->x -= size_x;
1277  check->y -= size_y;
1278  check = check->more;
1279  }
1280  }
1281 
1282  object_insert_in_map_at(head, op->map, op, 0, head->x, head->y);
1283  } else
1284  head = object_insert_in_ob(head, op);
1285 
1286  /* Let's put this created item on stack so dm can access it easily. */
1287  /* Wonder if we really want to push all of these, but since
1288  * things like rods have nrof 0, we want to cover those.
1289  */
1290  dm_stack_push(op->contr, head->count);
1291 
1292  if (at->clone.randomitems != NULL && !at_spell) {
1293  create_treasure(at->clone.randomitems, head, 0, op->map->difficulty, 0);
1294  if (QUERY_FLAG(head, FLAG_MONSTER)) {
1296  }
1297  }
1298  }
1299 
1300  /* free the one we used to copy */
1302 }
1303 
1304 /*
1305  * Now follows dm-commands which are also acceptable from sockets
1306  */
1307 
1316 void command_inventory(object *op, const char *params) {
1317  object *tmp;
1318  int i;
1319 
1320  if (*params == '\0') {
1321  inventory(op, NULL);
1322  return;
1323  }
1324 
1325  if (!sscanf(params, "%d", &i) || (tmp = object_find_by_tag_global(i)) == NULL) {
1327  "Inventory of what object (nr)?");
1328  return;
1329  }
1330 
1331  inventory(op, tmp);
1332 }
1333 
1346 void command_skills(object *op, const char *params) {
1347  show_skills(op, *params == '\0' ? NULL : params);
1348 }
1349 
1358 void command_dump(object *op, const char *params) {
1359  object *tmp;
1360  StringBuffer *sb;
1361  char *diff;
1362 
1363  tmp = get_dm_object(op->contr, &params, NULL);
1364  if (!tmp)
1365  return;
1366 
1367  sb = stringbuffer_new();
1368  object_dump(tmp, sb);
1369  diff = stringbuffer_finish(sb);
1371  free(diff);
1374  "Object is marked original");
1375 }
1376 
1386 void command_mon_aggr(object *op, const char *params) {
1387  (void)params;
1388  if (op->enemy || !QUERY_FLAG(op, FLAG_UNAGGRESSIVE)) {
1389  object_set_enemy(op, NULL);
1392  "Aggression turned OFF");
1393  } else {
1397  "Aggression turned ON");
1398  }
1399 }
1400 
1413 void command_possess(object *op, const char *params) {
1414  object *victim;
1415  player *pl;
1416  int i;
1417  char buf[MAX_BUF];
1418 
1419  victim = NULL;
1420  if (*params != '\0') {
1421  if (sscanf(params, "%d", &i))
1423  else if (sscanf(params, "%s", buf))
1425  }
1426  if (victim == NULL) {
1428  "Patch what object (nr)?");
1429  return;
1430  }
1431 
1432  if (victim == op) {
1434  "As insane as you are, I cannot allow you to possess yourself.");
1435  return;
1436  }
1437 
1438  /* make the switch */
1439  pl = op->contr;
1440  victim->contr = pl;
1441  pl->ob = victim;
1442  victim->type = PLAYER;
1444 
1445  /* basic patchup */
1446  /* The use of hard coded values is terrible. Note
1447  * that really, to be fair, this shouldn't get changed at
1448  * all - if you are possessing a kobold, you should have the
1449  * same limitations. As it is, as more body locations are added,
1450  * this will give this player more locations than perhaps
1451  * they should be allowed.
1452  */
1453  for (i = 0; i < NUM_BODY_LOCATIONS; i++)
1454  if (i == 1 || i == 6 || i == 8 || i == 9)
1455  victim->body_info[i] = 2;
1456  else
1457  victim->body_info[i] = 1;
1458 
1459  esrv_new_player(pl, 80); /* just pick a weight, we don't care */
1461 
1462  fix_object(victim);
1463 
1465 }
1466 
1474 void command_patch(object *op, const char *params) {
1475  const char *arg, *arg2;
1476  object *tmp;
1477 
1478  tmp = get_dm_object(op->contr, &params, NULL);
1479  if (!tmp)
1480  /* Player already informed of failure */
1481  return;
1482 
1483  /* params set to first value by get_dm_default */
1484  arg = params;
1485  if (*arg == '\0') {
1487  "Patch what values?");
1488  return;
1489  }
1490 
1491  if ((arg2 = strchr(arg, ' ')))
1492  arg2++;
1493  if (settings.real_wiz == FALSE)
1494  SET_FLAG(tmp, FLAG_WAS_WIZ); /* To avoid cheating */
1495  if (set_variable(tmp, arg) == -1)
1497  "Unknown variable %s",
1498  arg);
1499  else {
1501  "(%s#%d)->%s=%s",
1502  tmp->name, tmp->count, arg, arg2);
1503  }
1504 }
1505 
1506 static void reset_faces_sent(struct socket_struct *socket) {
1507  free(socket->faces_sent);
1508  socket->faces_sent = static_cast<uint8_t *>(calloc(sizeof(socket->faces_sent[0]), get_faces_count()));
1509  socket->faces_sent_len = get_faces_count();
1510 }
1511 
1512 void command_recollect(object *op, const char *params) {
1513  (void)op;
1514  (void)params;
1515  load_assets();
1516 
1517  // Clear sent faces for connected sockets so that clients see new faces.
1518  for (int i = 0; i < socket_info.allocated_sockets; i++) {
1519  /*
1520  if (init_sockets[i].status == Ns_Add) {
1521  reset_faces_sent(&init_sockets[i]);
1522  }
1523  */
1524  }
1525 
1526  player *next;
1527  for (player *pl = first_player; pl != NULL; pl = next) {
1529  next = pl->next;
1530  }
1531 }
1532 
1541 void command_remove(object *op, const char *params) {
1542  object *tmp;
1543  int from;
1544 
1545  tmp = get_dm_object(op->contr, &params, &from);
1546  if (!tmp) {
1548  "Remove what object (nr)?");
1549  return;
1550  }
1551 
1552  if (tmp->type == PLAYER) {
1554  "Unable to remove a player!");
1555  return;
1556  }
1557 
1558  if (QUERY_FLAG(tmp, FLAG_REMOVED)) {
1559  char name[MAX_BUF];
1560 
1563  "%s is already removed!",
1564  name);
1565  return;
1566  }
1567 
1568  if (from != STACK_FROM_STACK)
1569  /* Item is either stack top, or is a number thus is now stack top, let's remove it */
1570  dm_stack_pop(op->contr);
1571 
1572  /* Always work on the head - otherwise object will get in odd state */
1573  tmp = HEAD(tmp);
1574  if (tmp->speed != 0) {
1575  tmp->speed = 0;
1577  }
1578  object_remove(tmp);
1579 }
1580 
1588 void command_free(object *op, const char *params) {
1589  object *tmp;
1590  int from;
1591 
1592  tmp = get_dm_object(op->contr, &params, &from);
1593 
1594  if (!tmp) {
1596  "Free what object (nr)?");
1597  return;
1598  }
1599 
1600  if (from != STACK_FROM_STACK)
1601  /* Item is either stack top, or is a number thus is now stack top, let's remove it */
1602  dm_stack_pop(op->contr);
1603 
1604  tmp = HEAD(tmp);
1605  if (!QUERY_FLAG(tmp, FLAG_REMOVED)) {
1607  "Warning: item was not removed, will do so now.");
1608  object_remove(tmp);
1609  }
1610 
1612 }
1613 
1614 void command_accountpasswd(object *op, const char *params) {
1615  char account_name[MAX_BUF], newpw[MAX_BUF];
1616  // Password may contain spaces, so use %[^\n] format string.
1617  if (sscanf(params, "%s %[^\n]", account_name, newpw) != 2) {
1619  "Usage: accountpasswd ACCOUNT PASSWORD");
1620  return;
1621  }
1622 
1623  int ret = account_change_password(account_name, NULL, newpw);
1624  switch (ret) {
1625  case 0:
1627  "Updated account password.");
1628  return;
1629  case 1:
1631  "Invalid characters in new password.");
1632  return;
1633  case 2:
1635  "Invalid characters in new password.");
1636  return;
1637  default:
1639  "Error changing password.");
1640  return;
1641  }
1642 }
1643 
1652 void command_addexp(object *op, const char *params) {
1653  char buf[MAX_BUF], skill[MAX_BUF];
1654  int i, q;
1655  object *skillob = NULL;
1656  player *pl;
1657 
1658  skill[0] = '\0';
1659  if ((*params == '\0')
1660  || (strlen(params) > MAX_BUF)
1661  || ((q = sscanf(params, "%s %d %[^\r\n]", buf, &i, skill)) < 2)) {
1663  "Usage: addexp player quantity [skill].");
1664  return;
1665  }
1666 
1667  for (pl = first_player; pl != NULL; pl = pl->next)
1668  if (!strncmp(pl->ob->name, buf, MAX_NAME))
1669  break;
1670 
1671  if (pl == NULL) {
1673  "No such player.");
1674  return;
1675  }
1676 
1677  if (q >= 3) {
1678  skillob = find_skill_by_name(pl->ob, skill);
1679  if (!skillob) {
1681  "Unable to find skill %s in %s",
1682  skill, buf);
1683  return;
1684  }
1685 
1686  i = check_exp_adjust(skillob, i);
1687  skillob->stats.exp += i;
1688  calc_perm_exp(skillob);
1689  player_lvl_adj(pl->ob, skillob);
1690  }
1691 
1692  pl->ob->stats.exp += i;
1693  calc_perm_exp(pl->ob);
1694  player_lvl_adj(pl->ob, NULL);
1695 
1696  if (settings.real_wiz == FALSE)
1698 }
1699 
1708 void command_speed(object *op, const char *params) {
1709  int i;
1710 
1711  if (*params == '\0' || !sscanf(params, "%d", &i)) {
1713  "Current speed is %d",
1714  tick_duration);
1715  return;
1716  }
1717 
1718  set_tick_duration(i);
1719  reset_sleep();
1721  "The speed is changed to %d.",
1722  i);
1723 }
1724 
1725 /**************************************************************************/
1726 /* Mods made by Tyler Van Gorder, May 10-13, 1992. */
1727 /* CSUChico : tvangod@cscihp.ecst.csuchico.edu */
1728 /**************************************************************************/
1729 
1738 void command_stats(object *op, const char *params) {
1739  player *pl;
1740 
1741  if (*params == '\0') {
1743  "Who?");
1744  return;
1745  }
1746 
1748  if (pl == NULL) {
1750  "No such player.");
1751  return;
1752  }
1753 
1755  "[Fixed]Statistics for %s:", pl->ob->name);
1756 
1758  "[fixed]Str : %-2d H.P. : %-4d MAX : %d",
1759  pl->ob->stats.Str, pl->ob->stats.hp, pl->ob->stats.maxhp);
1760 
1762  "[fixed]Dex : %-2d S.P. : %-4d MAX : %d",
1763  pl->ob->stats.Dex, pl->ob->stats.sp, pl->ob->stats.maxsp);
1764 
1766  "[fixed]Con : %-2d AC : %-4d WC : %d",
1767  pl->ob->stats.Con, pl->ob->stats.ac, pl->ob->stats.wc);
1768 
1770  "[fixed]Int : %-2d Damage : %d",
1771  pl->ob->stats.Int, pl->ob->stats.dam);
1772 
1774  "[fixed]Wis : %-2d EXP : %" FMT64,
1775  pl->ob->stats.Wis, pl->ob->stats.exp);
1776 
1778  "[fixed]Pow : %-2d Grace : %d",
1779  pl->ob->stats.Pow, pl->ob->stats.grace);
1780 
1782  "[fixed]Cha : %-2d Food : %d",
1783  pl->ob->stats.Cha, pl->ob->stats.food);
1784 }
1785 
1795 void command_abil(object *op, const char *params) {
1796  char thing[20], thing2[20];
1797  int iii;
1798  player *pl;
1799 
1800  iii = 0;
1801  thing[0] = '\0';
1802  thing2[0] = '\0';
1803  if (*params == '\0'
1804  || sscanf(params, "%s %s %d", thing, thing2, &iii) != 3
1805  || thing[0] == '\0') {
1807  "Who?");
1808  return;
1809  }
1810 
1811  if (thing2[0] == '\0') {
1813  "You can't change that.");
1814  return;
1815  }
1816 
1817  if (iii < MIN_STAT || iii > settings.max_stat) {
1819  "Illegal range of stat.\n");
1820  return;
1821  }
1822 
1823  for (pl = first_player; pl != NULL; pl = pl->next) {
1824  if (!strcmp(pl->ob->name, thing)) {
1825  if (settings.real_wiz == FALSE)
1827  if (!strcmp("str", thing2))
1828  pl->ob->stats.Str = iii, pl->orig_stats.Str = iii;
1829  if (!strcmp("dex", thing2))
1830  pl->ob->stats.Dex = iii, pl->orig_stats.Dex = iii;
1831  if (!strcmp("con", thing2))
1832  pl->ob->stats.Con = iii, pl->orig_stats.Con = iii;
1833  if (!strcmp("wis", thing2))
1834  pl->ob->stats.Wis = iii, pl->orig_stats.Wis = iii;
1835  if (!strcmp("cha", thing2))
1836  pl->ob->stats.Cha = iii, pl->orig_stats.Cha = iii;
1837  if (!strcmp("int", thing2))
1838  pl->ob->stats.Int = iii, pl->orig_stats.Int = iii;
1839  if (!strcmp("pow", thing2))
1840  pl->ob->stats.Pow = iii, pl->orig_stats.Pow = iii;
1842  "%s has been altered.",
1843  pl->ob->name);
1844  fix_object(pl->ob);
1845  return;
1846  }
1847  }
1848 
1850  "No such player.");
1851 }
1852 
1861 void command_reset(object *op, const char *params) {
1862  mapstruct *m;
1863  object *dummy = NULL, *tmp = NULL;
1864  char path[HUGE_BUF];
1865  const char *space, *confirmation = NULL;
1866  int res = 0;
1867 
1868  if (*params == '\0') {
1870  MSG_TYPE_COMMAND_ERROR, "Which map should be reset?");
1871  return;
1872  }
1873 
1874  space = strchr(params, ' ');
1875  if (space != NULL) {
1876  confirmation = params;
1877  params = space + 1;
1878  }
1879 
1880  /* Use the DM's map if the current map was given. */
1881  if (strcmp(params, ".") == 0) {
1882  strlcpy(path, op->map->path, sizeof(path));
1883  } else {
1884  path_combine_and_normalize(op->map->path, params, path, sizeof(path));
1885  }
1886 
1887  m = has_been_loaded(path);
1888  if (m == NULL) {
1890  MSG_TYPE_COMMAND_ERROR, "No such map.");
1891  return;
1892  }
1893 
1894  if (confirmation) {
1895  if (m->unique && (op->map == m)) {
1898  "Cannot reset a unique player map while on it. Use "
1899  "'reset full-reset %s' while standing somewhere else.",
1900  m->path);
1901  return;
1902  }
1903 
1904  if (strncmp("full-reset", confirmation, strlen("full-reset"))) {
1906  MSG_TYPE_COMMAND_ERROR, "Confirm using 'full-reset'.");
1907  return;
1908  }
1909  }
1910 
1911  /* Forbid using reset on our own map when we're in a transport, as
1912  * it has the displeasant effect of crashing the server.
1913  * - gros, July 25th 2006 */
1914  if ((op->contr && op->contr->transport) && (op->map == m)) {
1916  "You need to disembark first.");
1917  return;
1918  }
1919 
1920  strlcpy(path, m->path, sizeof(path));
1921 
1922  sstring reset_group = m->reset_group;
1923  m->reset_group = NULL;
1924 
1925  if (m->in_memory != MAP_SWAPPED) {
1926  if (m->in_memory != MAP_IN_MEMORY) {
1927  LOG(llevError, "Tried to swap out map which was not in memory.\n");
1928  m->reset_group = reset_group;
1929  return;
1930  }
1931 
1932  /*
1933  * Only attempt to remove the player that is doing the reset, and not other
1934  * players or wiz's.
1935  */
1936  if (op->map == m) {
1937  if (strncmp(m->path, "/random/", 8) == 0) {
1938  /* This is not a very satisfying solution - it would be much better
1939  * to recreate a random map with the same seed value as the old one.
1940  * Unfortunately, I think recreating the map would require some
1941  * knowledge about its 'parent', which appears very non-trivial to
1942  * me.
1943  * On the other hand, this should prevent the freeze that this
1944  * situation caused. - gros, 26th July 2006.
1945  */
1947  "You cannot reset a random map when inside it.");
1948  m->reset_group = reset_group;
1949  return;
1950  }
1951 
1952  dummy = object_new();
1953  dummy->map = NULL;
1954  EXIT_X(dummy) = op->x;
1955  EXIT_Y(dummy) = op->y;
1956  EXIT_PATH(dummy) = add_string(op->map->path);
1957  object_remove(op);
1958  op->map = NULL;
1959  tmp = op;
1960  }
1961  res = swap_map(m);
1962  }
1963 
1964  if (res < 0 || m->in_memory != MAP_SWAPPED) {
1965  player *pl;
1966  int playercount = 0;
1967 
1968  /* Need to re-insert player if swap failed for some reason */
1969  if (tmp) {
1970  object_insert_in_map_at(op, m, NULL, 0, op->x, op->y);
1972  }
1973 
1974  if (res < 0 && res != SAVE_ERROR_PLAYER)
1975  /* no need to warn if player on map, code below checks that. */
1977  "Reset failed, error code: %d.", res);
1978  else {
1980  "Reset failed, couldn't swap map, the following players are on it:");
1981  for (pl = first_player; pl != NULL; pl = pl->next) {
1982  if (pl->ob->map == m && pl->ob != op) {
1984  pl->ob->name);
1985  playercount++;
1986  }
1987  }
1988  if (!playercount)
1990  "hmm, I don't see any other players on this map, something else is the problem.");
1991  m->reset_group = reset_group;
1992  return;
1993  }
1994  }
1995 
1996  FREE_AND_CLEAR_STR_IF(reset_group);
1997 
1998  /* Here, map reset succeeded. */
1999 
2000  if (m && m->in_memory == MAP_SWAPPED) {
2001  if (confirmation) {
2003  LOG(llevDebug, "DM %s fully resetting map %s.\n", op->name, m->path);
2004  } else
2005  LOG(llevDebug, "DM %s resetting map %s.\n", op->name, m->path);
2006 
2007  /* setting this effectively causes an immediate reload */
2008  m->reset_time = 1;
2009  flush_old_maps();
2010  }
2011 
2012  /* Display the appropriate success message. */
2013  if (confirmation) {
2015  MSG_TYPE_COMMAND_DM, "Fully resetting map %s.", path);
2016  } else {
2018  MSG_TYPE_COMMAND_DM, "Resetting map %s.", path);
2019  }
2020 
2021  if (tmp) {
2022  enter_exit(tmp, dummy);
2024  }
2025 
2026  /* Remind the DM how to fully reset the map. */
2027  if (confirmation == NULL) {
2030  "Use 'reset full-reset %s' to fully reset the map.", params);
2031  }
2032 }
2033 
2042 void command_nowiz(object *op, const char *params) { /* 'noadm' is alias */
2043  (void)params;
2047 
2048  if (settings.real_wiz == TRUE)
2050  if (op->contr->hidden) {
2051  unhide(op);
2052  } else
2054  "The Dungeon Master is gone...");
2055 
2056  update_los(op);
2057 }
2058 
2079 static int checkdm(object *op, const char *pl_name, const char *pl_passwd, const char *pl_host) {
2080  FILE *dmfile;
2081  char buf[MAX_BUF];
2082  char line_buf[160], name[160], passwd[160], host[160];
2083 
2084 #ifdef RESTRICTIVE_DM
2085  *pl_name = op->name ? op->name : "*";
2086 #else
2087  (void)op;
2088 #endif
2089 
2090  snprintf(buf, sizeof(buf), "%s/%s", settings.confdir, DMFILE);
2091  if ((dmfile = fopen(buf, "r")) == NULL) {
2092  LOG(llevDebug, "Could not find DM file.\n");
2093  return 0;
2094  }
2095 
2096  while (fgets(line_buf, 160, dmfile) != NULL) {
2097  // Skip empty lines as well as commented ones.
2098  if (line_buf[0] == '#' || line_buf[0] == '\n')
2099  continue;
2100  if (sscanf(line_buf, "%[^:]:%[^:]:%s\n", name, passwd, host) != 3) {
2101  LOG(llevError, "Warning - malformed dm file entry: %s\n", line_buf);
2102  } else if ((!strcmp(name, "*") || (pl_name && !strcmp(pl_name, name)))
2103  && (!strcmp(passwd, "*") || !strcmp(passwd, pl_passwd))
2104  && (!strcmp(host, "*") || !strcmp(host, pl_host))) {
2105  fclose(dmfile);
2106  return (1);
2107  }
2108  }
2109  fclose(dmfile);
2110  return (0);
2111 }
2112 
2127 static int do_wizard_dm(object *op, const char *params, int silent) {
2128  if (!op->contr)
2129  return 0;
2130 
2131  if (QUERY_FLAG(op, FLAG_WIZ)) {
2133  "You are already the Dungeon Master!");
2134  return 0;
2135  }
2136 
2137  if (checkdm(op, op->name, (*params != '\0' ? params : "*"), op->contr->socket->host)) {
2138  SET_FLAG(op, FLAG_WIZ);
2143  "Ok, you are the Dungeon Master!");
2144  /*
2145  * Remove setting flying here - that won't work, because next
2146  * fix_object() is called that will get cleared - proper solution
2147  * is probably something like a wiz_force which gives that and any
2148  * other desired abilities.
2149  */
2150  clear_los(op->contr);
2151 
2152  if (!silent)
2155  "The Dungeon Master has arrived!");
2156 
2157  return 1;
2158  }
2159 
2161  "Sorry Pal, I don't think so.");
2162  return 0;
2163 }
2164 
2176 void command_dm(object *op, const char *params) {
2177  do_wizard_dm(op, params, 0);
2178 }
2179 
2188 void command_invisible(object *op, const char *params) {
2189  (void)params;
2190  if (op) {
2191  op->invisible += 100;
2194  "You turn invisible.");
2195  }
2196 }
2197 
2215 static object *get_spell_by_name(object *op, const char *spell_name) {
2216  archetype *ar;
2217  archetype *found;
2218  int conflict_found;
2219  size_t spell_name_length;
2220 
2221  /* First check for full name matches. */
2222  conflict_found = 0;
2223  found = NULL;
2224  for (ar = get_next_archetype(NULL); ar != NULL; ar = get_next_archetype(ar)) {
2225  if (ar->clone.type != SPELL)
2226  continue;
2227 
2228  if (strncmp(ar->name, "spelldirect_", 12) == 0)
2229  continue;
2230 
2231  if (strcmp(ar->clone.name, spell_name) != 0)
2232  continue;
2233 
2234  if (found != NULL) {
2235  if (!conflict_found) {
2236  conflict_found = 1;
2238  "More than one archetype matches the spell name %s:",
2239  spell_name);
2241  "- %s",
2242  found->name);
2243  }
2245  "- %s",
2246  ar->name);
2247  continue;
2248  }
2249 
2250  found = ar;
2251  }
2252 
2253  /* No match if more more than one archetype matches. */
2254  if (conflict_found)
2255  return NULL;
2256 
2257  /* Return if exactly one archetype matches. */
2258  if (found != NULL)
2259  return arch_to_object(found);
2260 
2261  /* No full match found: now check for partial matches. */
2262  spell_name_length = strlen(spell_name);
2263  conflict_found = 0;
2264  found = NULL;
2265 
2266  for (ar = get_next_archetype(NULL); ar != NULL; ar = get_next_archetype(ar)) {
2267  if (ar->clone.type != SPELL)
2268  continue;
2269 
2270  if (strncmp(ar->name, "spelldirect_", 12) == 0)
2271  continue;
2272 
2273  if (strncmp(ar->clone.name, spell_name, spell_name_length) != 0)
2274  continue;
2275 
2276  if (found != NULL) {
2277  if (!conflict_found) {
2278  conflict_found = 1;
2280  "More than one spell matches %s:",
2281  spell_name);
2283  "- %s",
2284  found->clone.name);
2285  }
2287  "- %s",
2288  ar->clone.name);
2289  continue;
2290  }
2291 
2292  found = ar;
2293  }
2294 
2295  /* No match if more more than one archetype matches. */
2296  if (conflict_found)
2297  return NULL;
2298 
2299  /* Return if exactly one archetype matches. */
2300  if (found != NULL)
2301  return arch_to_object(found);
2302 
2303  /* No spell found: just print an error message. */
2305  "The spell %s does not exist.",
2306  spell_name);
2307  return NULL;
2308 }
2309 
2320 static void command_learn_spell_or_prayer(object *op, const char *params, int special_prayer) {
2321  object *tmp;
2322 
2323  if (op->contr == NULL || *params == '\0') {
2325  "Which spell do you want to learn?");
2326  return;
2327  }
2328 
2330  if (tmp == NULL) {
2331  return;
2332  }
2333 
2334  if (check_spell_known(op, tmp->name)) {
2336  "You already know the spell %s.",
2337  tmp->name);
2338  return;
2339  }
2340 
2341  do_learn_spell(op, tmp, special_prayer);
2343 }
2344 
2353 void command_learn_spell(object *op, const char *params) {
2355 }
2356 
2365 void command_learn_special_prayer(object *op, const char *params) {
2367 }
2368 
2378 void command_forget_spell(object *op, const char *params) {
2379  object *spell;
2380 
2381  if (op->contr == NULL || *params == '\0') {
2383  "Which spell do you want to forget?");
2384  return;
2385  }
2386 
2387  spell = lookup_spell_by_name(op, params);
2388  if (spell == NULL) {
2390  "You do not know the spell %s.",
2391  params);
2392  return;
2393  }
2394 
2395  do_forget_spell(op, spell->name);
2396 }
2397 
2406 void command_listplugins(object *op, const char *params) {
2407  (void)params;
2409 }
2410 
2421 void command_loadplugin(object *op, const char *params) {
2422  char buf[MAX_BUF];
2423 
2424  if (*params == '\0') {
2426  "Load which plugin?");
2427  return;
2428  }
2429 
2430  snprintf(buf, sizeof(buf), LIBDIR"/plugins/%s", params);
2431  LOG(llevDebug, "Requested plugin file is %s\n", buf);
2432  if (plugins_init_plugin(buf) == 0) {
2433  LOG(llevInfo, "DM %s loaded plugin %s\n", op->name, params);
2435  "Plugin %s successfully loaded.",
2436  params);
2437  } else
2439  "Could not load plugin %s.",
2440  params);
2441 }
2442 
2453 void command_unloadplugin(object *op, const char *params) {
2454  if (*params == '\0') {
2456  "Remove which plugin?");
2457  return;
2458  }
2459 
2460  if (plugins_remove_plugin(params) == 0) {
2461  LOG(llevInfo, "DM %s unloaded plugin %s\n", op->name, params);
2463  "Plugin %s successfully removed.",
2464  params);
2465  init_signals(); // Restore our signal handlers, some plugins (Python) mess with them
2466  } else
2468  "Could not remove plugin %s.",
2469  params);
2470 }
2471 
2482 void command_dmhide(object *op, const char *params) {
2483  if (!do_wizard_dm(op, params, 1))
2484  return;
2485 
2486  do_wizard_hide(op, 1);
2487 }
2488 
2497 void command_stack_pop(object *op, const char *params) {
2498  (void)params;
2499  dm_stack_pop(op->contr);
2500 }
2501 
2510 void command_stack_push(object *op, const char *params) {
2511  object *ob;
2512  int from;
2513  ob = get_dm_object(op->contr, &params, &from);
2514 
2515  if (ob && from != STACK_FROM_NUMBER)
2516  /* Object was from stack, need to push it again */
2517  dm_stack_push(op->contr, ob->count);
2518 }
2519 
2528 void command_stack_list(object *op, const char *params) {
2529  int item;
2530  object *display;
2531  player *pl = op->contr;
2532  (void)params;
2533 
2535  "Item stack contents:");
2536 
2537  for (item = 0; item < pl->stack_position; item++) {
2539  if (display)
2541  " %d : %s [%d]",
2542  item, display->name, display->count);
2543  else
2544  /* Item was freed */
2546  " %d : (lost item: %d)",
2547  item, pl->stack_items[item]);
2548  }
2549 }
2550 
2559 void command_stack_clear(object *op, const char *params) {
2560  (void)params;
2561  op->contr->stack_position = 0;
2563  "Item stack cleared.");
2564 }
2565 
2585 void command_diff(object *op, const char *params) {
2586  object *left, *right;
2587  char *diff;
2588  StringBuffer *sb;
2589  int left_from, right_from;
2590 
2591  left = get_dm_object(op->contr, &params, &left_from);
2592  if (!left) {
2594  "Compare to what item?");
2595  return;
2596  }
2597 
2598  if (left_from == STACK_FROM_NUMBER)
2599  /* Item was stacked, remove it else right will be the same... */
2600  dm_stack_pop(op->contr);
2601 
2602  right = get_dm_object(op->contr, &params, &right_from);
2603 
2604  if (!right) {
2606  "Compare what item?");
2607  return;
2608  }
2609 
2611  "Item difference:");
2612 
2613  if (left_from == STACK_FROM_TOP && right_from == STACK_FROM_TOP) {
2614  /*
2615  * Special case: both items were taken from stack top.
2616  * Override the behaviour, taking left as item just below top, if exists.
2617  * See function description for why.
2618  * Besides, if we don't do anything, compare an item to itself, not really useful.
2619  */
2620  if (op->contr->stack_position > 1) {
2621  left = object_find_by_tag_global(op->contr->stack_items[op->contr->stack_position-2]);
2622  if (left)
2624  "(Note: first item taken from undertop)");
2625  else
2626  /* Stupid case: item under top was freed, fallback to stack top */
2627  left = right;
2628  }
2629  }
2630 
2631  sb = stringbuffer_new();
2632  get_ob_diff(sb, left, right);
2633  diff = stringbuffer_finish(sb);
2634  if (*diff == '\0') {
2635  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_DM, "Objects are the same.");
2636  } else {
2638  }
2639  free(diff);
2640 }
2641 
2649 void command_insert_into(object *op, const char *params) {
2650  object *left, *right, *inserted;
2651  int left_from, right_from;
2652  char what[MAX_BUF], where[MAX_BUF];
2653 
2654  left = get_dm_object(op->contr, &params, &left_from);
2655  if (!left) {
2657  "Insert into what object?");
2658  return;
2659  }
2660 
2661  if (left_from == STACK_FROM_NUMBER)
2662  /* Item was stacked, remove it else right will be the same... */
2663  dm_stack_pop(op->contr);
2664 
2665  right = get_dm_object(op->contr, &params, &right_from);
2666 
2667  if (!right) {
2669  "Insert what item?");
2670  return;
2671  }
2672 
2673  if (left_from == STACK_FROM_TOP && right_from == STACK_FROM_TOP) {
2674  /*
2675  * Special case: both items were taken from stack top.
2676  * Override the behaviour, taking left as item just below top, if exists.
2677  * See function description for why.
2678  * Besides, can't insert an item into itself.
2679  */
2680  if (op->contr->stack_position > 1) {
2681  left = object_find_by_tag_global(op->contr->stack_items[op->contr->stack_position-2]);
2682  if (left)
2684  "(Note: item to insert into taken from undertop)");
2685  else
2686  /* Stupid case: item under top was freed, fallback to stack top */
2687  left = right;
2688  }
2689  }
2690 
2691  if (left == right) {
2693  "Can't insert an object into itself!");
2694  return;
2695  }
2696 
2697  if (right->type == PLAYER) {
2699  "Can't insert a player into something!");
2700  return;
2701  }
2702 
2703  if (!QUERY_FLAG(right, FLAG_REMOVED))
2704  object_remove(right);
2705  inserted = object_insert_in_ob(right, left);
2706  if (left->type == PLAYER) {
2707  if (inserted != right)
2708  /* item was merged, so updating name and such. */
2709  esrv_update_item(UPD_WEIGHT|UPD_NAME|UPD_NROF, left, inserted);
2710  }
2711  query_name(inserted, what, MAX_BUF);
2712  query_name(left, where, MAX_BUF);
2714  "Inserted %s in %s",
2715  what, where);
2716 }
2717 
2726 void command_style_map_info(object *op, const char *params) {
2727  extern mapstruct *styles;
2728  mapstruct *mp;
2729  int maps_used = 0, mapmem = 0, objects_used = 0, x, y;
2730  (void)params;
2731 
2732  for (mp = styles; mp != NULL; mp = mp->next) {
2733  maps_used++;
2734  mapmem += map_size(mp) * (sizeof(object *)+sizeof(MapSpace))+sizeof(mapstruct);
2735  for (x = 0; x < MAP_WIDTH(mp); x++) {
2736  for (y = 0; y < MAP_HEIGHT(mp); y++) {
2737  FOR_MAP_PREPARE(mp, x, y, tmp)
2738  objects_used++;
2739  FOR_MAP_FINISH();
2740  }
2741  }
2742  }
2744  "[fixed]Style maps loaded: %d",
2745  maps_used);
2747  "[fixed]Memory used, not");
2749  "[fixed]including objects: %d",
2750  mapmem);
2752  "[fixed]Style objects: %d",
2753  objects_used);
2755  "[fixed]Mem for objects: %lu",
2756  (unsigned long)(objects_used*sizeof(object)));
2757 }
2758 
2759 bool can_follow(object* op, player* other) {
2760  // Only allow follow from same party.
2761  return (other->ob->contr->party != NULL) && (op->contr->party == other->ob->contr->party);
2762 }
2763 
2772 void command_follow(object *op, const char *params) {
2773  player *other;
2774 
2775  if (*params == '\0') {
2776  if (op->contr->followed_player != NULL) {
2777  draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_SUCCESS, "You stop following %s.", op->contr->followed_player);
2778  FREE_AND_CLEAR_STR(op->contr->followed_player);
2779  }
2780  return;
2781  }
2782 
2784  if (!other) {
2785  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_FAILURE, "No such player or ambiguous name.");
2786  return;
2787  }
2788  if (other == op->contr) {
2789  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_FAILURE, "You can't follow yourself.");
2790  return;
2791  }
2792 
2793  // Players trying to 'follow' are subject to additional checks.
2794  if (!QUERY_FLAG(op, FLAG_WIZ)) {
2795  if (!can_follow(op, other)) {
2798  "You can only follow members in the same party.");
2799  return;
2800  }
2801  rv_vector rv;
2802  if (!get_rangevector(op, other->ob, &rv, 0) || rv.distance > 1) {
2803  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_FAILURE, "You need to go to them first!");
2804  return;
2805  }
2807  }
2808 
2809  if (op->contr->followed_player)
2810  FREE_AND_CLEAR_STR(op->contr->followed_player);
2811 
2812  op->contr->followed_player = add_string(other->ob->name);
2813  draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_SUCCESS, "Following %s.", op->contr->followed_player);
2814 }
2815 
2816 void command_purge_quest(object *op, const char * param) {
2817  (void)param;
2818  free_quest();
2819  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, "Purged quest state.");
2820 }
2821 
2822 void command_purge_quest_definitions(object *op, const char * param) {
2823  (void)param;
2825  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, "Purged quests definitions.");
2826 }
2827 
2828 void do_dump(object *who, object *what) {
2829  StringBuffer *sb;
2830  char *diff;
2831 
2832  sb = stringbuffer_new();
2833  object_dump(what, sb);
2834  diff = stringbuffer_finish(sb);
2836  free(diff);
2837 
2838  /* Let's push that item on the dm's stack */
2839  dm_stack_push(who->contr, what->count);
2840 }
2841 
2850 void command_dumpbelow(object *op, const char *params) {
2851  (void)params;
2852  if (op && op->below) {
2853  do_dump(op, op->below);
2854  }
2855 }
2856 
2865 void command_dumpabove(object *op, const char *params) {
2866  (void)params;
2867  if (op && op->above) {
2868  do_dump(op, op->above);
2869  }
2870 }
2871 
2877 void command_settings(object *op, const char *ignored) {
2878  (void)ignored;
2879  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, "Server settings:");
2880 
2882 
2883  if (settings.not_permadeth) {
2884  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, " * death is not permanent");
2885  } else if (settings.resurrection) {
2886  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, " * permanent death, resurrection is enabled");
2887  } else {
2888  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, " * permanent death, resurrection is NOT enabled");
2889  }
2890 
2891  if (settings.set_title) {
2892  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, " * players can set their title");
2893  } else {
2894  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, " * players can't set their title");
2895  }
2896 
2899  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");
2900  } else {
2901  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");
2902  }
2903  } else {
2904  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, " * too much equipment can't lead to spell failure");
2905  }
2906 
2907  if (settings.casting_time) {
2908  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, " * casting takes time");
2909  } else {
2910  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, " * casting is immediate");
2911  }
2912 
2915 
2917 
2919  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, " * players can't steal from other players");
2920  } else {
2921  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, " * players can steal from other players");
2922  }
2923 
2925  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, " * players can create portals from their apartments");
2926  } else {
2927  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, " * players can't create portals from their apartments");
2928  }
2929 
2931  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, " * players can write spells they are denied");
2932  } else {
2933  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, " * players can't write spells they are denied");
2934  }
2935 }
Settings::casting_time
uint8_t casting_time
Definition: global.h:270
get_other_player_from_name
static player * get_other_player_from_name(object *op, const char *name)
Definition: c_wiz.cpp:59
give.next
def next
Definition: give.py:44
command_overlay_reset
void command_overlay_reset(object *op, const char *params)
Definition: c_wiz.cpp:588
command_possess
void command_possess(object *op, const char *params)
Definition: c_wiz.cpp:1413
STACK_FROM_NONE
@ STACK_FROM_NONE
Definition: c_wiz.cpp:37
UP_OBJ_FACE
#define UP_OBJ_FACE
Definition: object.h:522
PLAYER
@ PLAYER
Definition: object.h:110
set_magic
static void set_magic(int difficulty, object *op, int max_magic, int flags)
Definition: treasure.cpp:653
FREE_AND_CLEAR_STR_IF
#define FREE_AND_CLEAR_STR_IF(xyz)
Definition: global.h:200
global.h
FREE_OBJ_NO_DESTROY_CALLBACK
#define FREE_OBJ_NO_DESTROY_CALLBACK
Definition: object.h:534
first_player
player * first_player
Definition: init.cpp:106
settings
struct Settings settings
Definition: init.cpp:139
set_abs_magic
void set_abs_magic(object *op, int magic)
Definition: treasure.cpp:605
liv::dam
int16_t dam
Definition: living.h:46
STACK_SIZE
#define STACK_SIZE
Definition: c_wiz.cpp:34
safe_strncpy
#define safe_strncpy
Definition: compat.h:27
FOR_MAP_FINISH
#define FOR_MAP_FINISH()
Definition: define.h:730
STACK_FROM_NUMBER
@ STACK_FROM_NUMBER
Definition: c_wiz.cpp:40
command_overlay_save
void command_overlay_save(object *op, const char *params)
Definition: c_wiz.cpp:567
NUM_BODY_LOCATIONS
#define NUM_BODY_LOCATIONS
Definition: object.h:13
MSG_TYPE_COMMAND_SUCCESS
#define MSG_TYPE_COMMAND_SUCCESS
Definition: newclient.h:530
command_style_map_info
void command_style_map_info(object *op, const char *params)
Definition: c_wiz.cpp:2726
llevError
@ llevError
Definition: logger.h:11
WAND
@ WAND
Definition: object.h:223
MSG_TYPE_ADMIN_PLAYER
#define MSG_TYPE_ADMIN_PLAYER
Definition: newclient.h:496
LOG
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.cpp:51
SHUTDOWN_IDLE
@ SHUTDOWN_IDLE
Definition: commands.h:44
SET_FLAG
#define SET_FLAG(xyz, p)
Definition: define.h:224
reset_faces_sent
static void reset_faces_sent(struct socket_struct *socket)
Definition: c_wiz.cpp:1506
command_patch
void command_patch(object *op, const char *params)
Definition: c_wiz.cpp:1474
Settings::resurrection
uint8_t resurrection
Definition: global.h:266
diamondslots.x
x
Definition: diamondslots.py:15
obj::count
tag_t count
Definition: object.h:305
obj::map
struct mapdef * map
Definition: object.h:303
QUERY_FLAG
#define QUERY_FLAG(xyz, p)
Definition: define.h:226
plugins_remove_plugin
int plugins_remove_plugin(const char *id)
Definition: plugins.cpp:457
plugins_init_plugin
int plugins_init_plugin(const char *libfile)
Definition: plugins.cpp:366
get_next_archetype
archetype * get_next_archetype(archetype *current)
Definition: assets.cpp:266
Settings::set_title
uint8_t set_title
Definition: global.h:265
liv::wc
int8_t wc
Definition: living.h:37
do_learn_spell
void do_learn_spell(object *op, object *spell, int special_prayer)
Definition: apply.cpp:484
command_shutdown
void command_shutdown(object *op, const char *params)
Definition: c_wiz.cpp:657
has_been_loaded
mapstruct * has_been_loaded(const char *name)
Definition: map.cpp:78
socket_struct
Definition: newserver.h:89
Socket_Info::allocated_sockets
int allocated_sockets
Definition: newserver.h:144
flush_old_maps
void flush_old_maps(void)
Definition: swap.cpp:289
esrv_new_player
void esrv_new_player(player *pl, uint32_t weight)
Definition: request.cpp:943
liv::Str
int8_t Str
Definition: living.h:36
FALSE
#define FALSE
Definition: compat.h:14
Settings::not_permadeth
uint8_t not_permadeth
Definition: global.h:262
banquet.size_x
int size_x
Definition: banquet.py:23
command_speed
void command_speed(object *op, const char *params)
Definition: c_wiz.cpp:1708
Settings::permanent_exp_ratio
uint8_t permanent_exp_ratio
Definition: global.h:258
esrv_send_inventory
void esrv_send_inventory(object *pl, object *op)
Definition: item.cpp:316
do_wizard_dm
static int do_wizard_dm(object *op, const char *params, int silent)
Definition: c_wiz.cpp:2127
command_learn_spell
void command_learn_spell(object *op, const char *params)
Definition: c_wiz.cpp:2353
Settings::datadir
const char * datadir
Definition: global.h:248
stringbuffer_new
StringBuffer * stringbuffer_new(void)
Definition: stringbuffer.cpp:57
UPD_WEIGHT
#define UPD_WEIGHT
Definition: newclient.h:316
liv::maxhp
int16_t maxhp
Definition: living.h:41
object_set_enemy
void object_set_enemy(object *op, object *enemy)
Definition: object.cpp:915
pl
Definition: player.h:105
dm_stack_pop
static void dm_stack_pop(player *pl)
Definition: c_wiz.cpp:94
EXIT_PATH
#define EXIT_PATH(xyz)
Definition: define.h:439
FLAG_OBJ_ORIGINAL
#define FLAG_OBJ_ORIGINAL
Definition: define.h:357
give_artifact_abilities
void give_artifact_abilities(object *op, const object *artifact)
Definition: artifact.cpp:238
socket_info
Socket_Info socket_info
Definition: init.cpp:49
command_arrest
void command_arrest(object *op, const char *params)
Definition: c_wiz.cpp:820
Settings::worldmaptilesy
uint32_t worldmaptilesy
Definition: global.h:294
command_teleport
void command_teleport(object *op, const char *params)
Definition: c_wiz.cpp:912
guildjoin.ob
ob
Definition: guildjoin.py:42
command_mon_aggr
void command_mon_aggr(object *op, const char *params)
Definition: c_wiz.cpp:1386
liv::hp
int16_t hp
Definition: living.h:40
dm_stack_push
static void dm_stack_push(player *pl, tag_t item)
Definition: c_wiz.cpp:149
check_exp_adjust
int64_t check_exp_adjust(const object *op, int64_t exp)
Definition: living.cpp:2089
Settings::worldmapstartx
uint32_t worldmapstartx
Definition: global.h:291
draw_ext_info_format
void draw_ext_info_format(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *format,...) PRINTF_ARGS(6
command_purge_quest
void command_purge_quest(object *op, const char *param)
Definition: c_wiz.cpp:2816
calc_perm_exp
void calc_perm_exp(object *op)
Definition: living.cpp:1901
unhide
static void unhide(object *op)
Definition: c_wiz.cpp:332
pl::ob
object * ob
Definition: player.h:176
do_dump
void do_dump(object *who, object *what)
Definition: c_wiz.cpp:2828
FLAG_WIZCAST
#define FLAG_WIZCAST
Definition: define.h:289
object_copy
void object_copy(const object *src_ob, object *dest_ob)
Definition: object.cpp:1192
command_invisible
void command_invisible(object *op, const char *params)
Definition: c_wiz.cpp:2188
artifactliststruct::items
struct artifactstruct * items
Definition: artifact.h:30
fix_object
void fix_object(object *op)
Definition: living.cpp:1125
Ice.tmp
int tmp
Definition: Ice.py:207
command_banish
void command_banish(object *op, const char *params)
Definition: c_wiz.cpp:501
NDI_RED
#define NDI_RED
Definition: newclient.h:245
UPD_NROF
#define UPD_NROF
Definition: newclient.h:321
plugins_display_list
void plugins_display_list(object *op)
Definition: plugins.cpp:506
command_addexp
void command_addexp(object *op, const char *params)
Definition: c_wiz.cpp:1652
command_listplugins
void command_listplugins(object *op, const char *params)
Definition: c_wiz.cpp:2406
skills.h
npc_dialog.filename
filename
Definition: npc_dialog.py:99
MSG_TYPE_COMMAND_ERROR
#define MSG_TYPE_COMMAND_ERROR
Definition: newclient.h:529
object_find_by_tag_global
object * object_find_by_tag_global(tag_t i)
Definition: object.cpp:727
create_treasure
void create_treasure(treasurelist *t, object *op, int flag, int difficulty, int tries)
Definition: treasure.cpp:256
set_variable
int set_variable(object *op, const char *buf)
Definition: loader.c:5306
buf
StringBuffer * buf
Definition: readable.cpp:1611
obj::randomitems
struct treasureliststruct * randomitems
Definition: object.h:393
set_tick_duration
void set_tick_duration(long t)
Definition: time.cpp:205
object_insert_in_ob
object * object_insert_in_ob(object *op, object *where)
Definition: object.cpp:2851
banquet.size_y
int size_y
Definition: banquet.py:24
HUGE_BUF
#define HUGE_BUF
Definition: define.h:37
MAX
#define MAX(x, y)
Definition: compat.h:24
MSG_TYPE_COMMAND
#define MSG_TYPE_COMMAND
Definition: newclient.h:404
obj::nrof
uint32_t nrof
Definition: object.h:340
find_god
const object * find_god(const char *name)
Definition: holy.cpp:319
NDI_ORANGE
#define NDI_ORANGE
Definition: newclient.h:246
SAVE_MODE_OVERLAY
#define SAVE_MODE_OVERLAY
Definition: map.h:123
Settings::worldmaptilesx
uint32_t worldmaptilesx
Definition: global.h:293
archt
Definition: object.h:472
FLAG_ALIVE
#define FLAG_ALIVE
Definition: define.h:230
command_learn_special_prayer
void command_learn_special_prayer(object *op, const char *params)
Definition: c_wiz.cpp:2365
Ns_Dead
@ Ns_Dead
Definition: newserver.h:67
command_remove
void command_remove(object *op, const char *params)
Definition: c_wiz.cpp:1541
map_remove_unique_files
void map_remove_unique_files(const mapstruct *map)
Definition: map.cpp:2705
MSG_TYPE_ADMIN_DM
#define MSG_TYPE_ADMIN_DM
Definition: newclient.h:497
MSG_TYPE_COMMAND_DEBUG
#define MSG_TYPE_COMMAND_DEBUG
Definition: newclient.h:528
ASSETS_QUESTS
#define ASSETS_QUESTS
Definition: assets.h:30
Settings::spell_encumbrance
uint8_t spell_encumbrance
Definition: global.h:268
m
static event_registration m
Definition: citylife.cpp:425
liv::maxsp
int16_t maxsp
Definition: living.h:43
clear_los
void clear_los(player *pl)
Definition: los.cpp:252
autojail.who
who
Definition: autojail.py:3
MAP_IN_MEMORY
#define MAP_IN_MEMORY
Definition: map.h:131
stringbuffer_finish
char * stringbuffer_finish(StringBuffer *sb)
Definition: stringbuffer.cpp:76
liv::exp
int64_t exp
Definition: living.h:47
object_free_drop_inventory
void object_free_drop_inventory(object *ob)
Definition: object.cpp:1560
object_update
void object_update(object *op, int action)
Definition: object.cpp:1434
shutdown_s::time
time_t time
Definition: commands.h:49
item.q
q
Definition: item.py:32
pl::next
struct pl * next
Definition: player.h:106
FMT64
#define FMT64
Definition: compat.h:16
command_toggle_shout
void command_toggle_shout(object *op, const char *params)
Definition: c_wiz.cpp:614
map_size
uint32_t map_size(mapstruct *m)
Definition: map.cpp:825
command_setgod
void command_setgod(object *op, const char *params)
Definition: c_wiz.cpp:417
FLAG_WAS_WIZ
#define FLAG_WAS_WIZ
Definition: define.h:234
obj::name
sstring name
Definition: object.h:317
pl::state
uint8_t state
Definition: player.h:131
freearr_y
short freearr_y[SIZEOFFREE]
Definition: object.cpp:305
command_create
void command_create(object *op, const char *params)
Definition: c_wiz.cpp:978
Settings::death_penalty_ratio
uint8_t death_penalty_ratio
Definition: global.h:259
command_reset
void command_reset(object *op, const char *params)
Definition: c_wiz.cpp:1861
do_wizard_hide
static void do_wizard_hide(object *op, int silent_dm)
Definition: c_wiz.cpp:351
query_name
void query_name(const object *op, char *buf, size_t size)
Definition: item.cpp:585
POTION
@ POTION
Definition: object.h:114
command_summon
void command_summon(object *op, const char *params)
Definition: c_wiz.cpp:865
Settings::set_friendly_fire
uint16_t set_friendly_fire
Definition: global.h:275
path_combine_and_normalize
char * path_combine_and_normalize(const char *src, const char *dst, char *path, size_t size)
Definition: path.cpp:172
MSG_TYPE_COMMAND_DM
#define MSG_TYPE_COMMAND_DM
Definition: newclient.h:535
command_purge_quest_definitions
void command_purge_quest_definitions(object *op, const char *param)
Definition: c_wiz.cpp:2822
STACK_FROM_TOP
@ STACK_FROM_TOP
Definition: c_wiz.cpp:38
artifactstruct::next
struct artifactstruct * next
Definition: artifact.h:18
object_dump
void object_dump(const object *op, StringBuffer *sb)
Definition: object.cpp:645
Settings::worldmapstarty
uint32_t worldmapstarty
Definition: global.h:292
add_string
sstring add_string(const char *str)
Definition: shstr.cpp:124
liv::Cha
int8_t Cha
Definition: living.h:36
HEAD
#define HEAD(op)
Definition: object.h:596
ROD
@ ROD
Definition: object.h:112
free_quest
void free_quest(void)
Definition: quest.cpp:910
shutdown_s::type
enum shutdown_type type
Definition: commands.h:48
make_face_from_files.str
str
Definition: make_face_from_files.py:24
obj::speed_left
float speed_left
Definition: object.h:336
python_init.path
path
Definition: python_init.py:8
command_dm
void command_dm(object *op, const char *params)
Definition: c_wiz.cpp:2176
out_of_map
int out_of_map(mapstruct *m, int x, int y)
Definition: map.cpp:2320
socket_struct::host
char * host
Definition: newserver.h:100
shutdown_s
Definition: commands.h:47
command_abil
void command_abil(object *op, const char *params)
Definition: c_wiz.cpp:1795
lookup_spell_by_name
object * lookup_spell_by_name(object *op, const char *spname)
Definition: spell_util.cpp:409
command_dumpbelow
void command_dumpbelow(object *op, const char *params)
Definition: c_wiz.cpp:2850
command_diff
void command_diff(object *op, const char *params)
Definition: c_wiz.cpp:2585
object_update_speed
void object_update_speed(object *op)
Definition: object.cpp:1349
pl::no_shout
uint32_t no_shout
Definition: player.h:148
obj::x
int16_t x
Definition: object.h:333
command_inventory
void command_inventory(object *op, const char *params)
Definition: c_wiz.cpp:1316
do_goto
void do_goto(object *op, const char *name, int x, int y)
Definition: c_move.cpp:151
command_help
void command_help(object *op, const char *params)
Definition: c_misc.cpp:1773
shutdown_state
struct shutdown_s shutdown_state
Definition: c_wiz.cpp:43
show_skills
void show_skills(object *op, const char *search)
Definition: skill_util.cpp:851
command_skills
void command_skills(object *op, const char *params)
Definition: c_wiz.cpp:1346
object_create_arch
object * object_create_arch(archetype *at)
Definition: arch.cpp:299
player_lvl_adj
void player_lvl_adj(object *who, object *op)
Definition: living.cpp:1817
FLAG_WIZPASS
#define FLAG_WIZPASS
Definition: define.h:314
object_free
void object_free(object *ob, int flags)
Definition: object.cpp:1592
command_dumpabove
void command_dumpabove(object *op, const char *params)
Definition: c_wiz.cpp:2865
Settings::item_power_factor
float item_power_factor
Definition: global.h:303
obj::other_arch
struct archt * other_arch
Definition: object.h:421
MAX_NAME
#define MAX_NAME
Definition: define.h:41
archt::more
struct archt * more
Definition: object.h:475
DMFILE
#define DMFILE
Definition: config.h:361
command_insert_into
void command_insert_into(object *op, const char *params)
Definition: c_wiz.cpp:2649
sstring
const typedef char * sstring
Definition: global.h:43
FLAG_UNAGGRESSIVE
#define FLAG_UNAGGRESSIVE
Definition: define.h:272
obj::speed
float speed
Definition: object.h:335
tag_t
uint32_t tag_t
Definition: object.h:12
liv::Con
int8_t Con
Definition: living.h:36
Settings::confdir
const char * confdir
Definition: global.h:247
sproto.h
liv::food
int32_t food
Definition: living.h:48
MapSpace
Definition: map.h:257
mapdef
Definition: map.h:317
MSG_SUBTYPE_NONE
#define MSG_SUBTYPE_NONE
Definition: newclient.h:420
become_follower
int become_follower(object *op, const object *new_god)
Definition: gods.cpp:413
command_goto
void command_goto(object *op, const char *params)
Definition: c_wiz.cpp:723
liv::Int
int8_t Int
Definition: living.h:36
init_signals
void init_signals()
Definition: init.cpp:1329
Settings::death_penalty_level
uint8_t death_penalty_level
Definition: global.h:260
SHUTDOWN_NONE
@ SHUTDOWN_NONE
Definition: commands.h:42
nlohmann::detail::void
j template void())
Definition: json.hpp:4099
object_insert_in_map_at
object * object_insert_in_map_at(object *op, mapstruct *m, object *originator, int flag, int x, int y)
Definition: object.cpp:2098
FLAG_MONSTER
#define FLAG_MONSTER
Definition: define.h:245
find_skill_by_name
object * find_skill_by_name(object *who, const char *name)
Definition: skill_util.cpp:202
MAP_WIDTH
#define MAP_WIDTH(m)
Definition: map.h:78
command_kick
void command_kick(object *op, const char *params)
Definition: c_wiz.cpp:555
command_loadtest
void command_loadtest(object *op, const char *params)
Definition: c_wiz.cpp:305
treasure.h
EXIT_X
#define EXIT_X(xyz)
Definition: define.h:441
MAX_BUF
#define MAX_BUF
Definition: define.h:35
artifactstruct
Definition: artifact.h:14
strlcpy
size_t strlcpy(char *dst, const char *src, size_t size)
Definition: porting.cpp:222
object_new
object * object_new(void)
Definition: object.cpp:1273
create_overlay_pathname
void create_overlay_pathname(const char *name, char *buf, size_t size)
Definition: map.cpp:124
monster_check_apply_all
void monster_check_apply_all(object *monster)
Definition: monster.cpp:1997
command_hide
void command_hide(object *op, const char *params)
Definition: c_wiz.cpp:388
StringBuffer
Definition: stringbuffer.cpp:25
FREE_AND_CLEAR_STR
#define FREE_AND_CLEAR_STR(xyz)
Definition: global.h:198
command_freeze
void command_freeze(object *op, const char *params)
Definition: c_wiz.cpp:744
Settings::spell_failure_effects
uint8_t spell_failure_effects
Definition: global.h:269
is_valid_types_gen.found
found
Definition: is_valid_types_gen.py:39
MSG_TYPE_COMMAND_FAILURE
#define MSG_TYPE_COMMAND_FAILURE
Definition: newclient.h:531
FOR_MAP_PREPARE
#define FOR_MAP_PREPARE(map_, mx_, my_, it_)
Definition: define.h:723
load_assets
void load_assets(void)
Definition: init.cpp:311
obj::y
int16_t y
Definition: object.h:333
ST_PLAYING
#define ST_PLAYING
Definition: define.h:541
command_forget_spell
void command_forget_spell(object *op, const char *params)
Definition: c_wiz.cpp:2378
FLAG_REMOVED
#define FLAG_REMOVED
Definition: define.h:232
Settings::allow_denied_spells_writing
int allow_denied_spells_writing
Definition: global.h:315
command_nowiz
void command_nowiz(object *op, const char *params)
Definition: c_wiz.cpp:2042
FLAG_WIZ
#define FLAG_WIZ
Definition: define.h:231
styles
mapstruct * styles
Definition: style.cpp:122
swap_map
int swap_map(mapstruct *map)
Definition: swap.cpp:135
command_loadplugin
void command_loadplugin(object *op, const char *params)
Definition: c_wiz.cpp:2421
llevInfo
@ llevInfo
Definition: logger.h:12
obj::type
uint8_t type
Definition: object.h:346
NDI_UNIQUE
#define NDI_UNIQUE
Definition: newclient.h:262
EVENT_MUZZLE
#define EVENT_MUZZLE
Definition: events.h:52
find_archetype_by_object_name
archetype * find_archetype_by_object_name(const char *name)
Definition: arch.cpp:53
FLAG_FRIENDLY
#define FLAG_FRIENDLY
Definition: define.h:246
spells.h
get_jail_exit
object * get_jail_exit(object *op)
Definition: region.cpp:257
obj::stats
living stats
Definition: object.h:376
bigchest.check
check
Definition: bigchest.py:10
archt::clone
object clone
Definition: object.h:476
obj::contr
struct pl * contr
Definition: object.h:282
command_learn_spell_or_prayer
static void command_learn_spell_or_prayer(object *op, const char *params, int special_prayer)
Definition: c_wiz.cpp:2320
BANISHFILE
#define BANISHFILE
Definition: config.h:512
get_spell_by_name
static object * get_spell_by_name(object *op, const char *spell_name)
Definition: c_wiz.cpp:2215
liv::Dex
int8_t Dex
Definition: living.h:36
item
Definition: item.py:1
reputation.victim
victim
Definition: reputation.py:14
can_follow
bool can_follow(object *op, player *other)
Definition: c_wiz.cpp:2759
is_identifiable_type
int is_identifiable_type(const object *op)
Definition: item.cpp:1312
enter_exit
void enter_exit(object *op, object *exit_ob)
Definition: server.cpp:732
object_find_by_name_global
object * object_find_by_name_global(const char *str)
Definition: object.cpp:747
check_spell_known
object * check_spell_known(object *op, const char *name)
Definition: spell_util.cpp:393
liv::Wis
int8_t Wis
Definition: living.h:36
find_object_both
static object * find_object_both(const char *params)
Definition: c_wiz.cpp:402
SHUTDOWN_TIME
@ SHUTDOWN_TIME
Definition: commands.h:43
liv::grace
int16_t grace
Definition: living.h:44
command_settings
void command_settings(object *op, const char *ignored)
Definition: c_wiz.cpp:2877
give.op
op
Definition: give.py:33
NDI_ALL
#define NDI_ALL
Definition: newclient.h:263
socket_struct::status
enum Sock_Status status
Definition: newserver.h:90
command_stats
void command_stats(object *op, const char *params)
Definition: c_wiz.cpp:1738
command_dump
void command_dump(object *op, const char *params)
Definition: c_wiz.cpp:1358
object_find_free_spot
int object_find_free_spot(const object *ob, mapstruct *m, int x, int y, int start, int stop)
Definition: object.cpp:3552
command_dmhide
void command_dmhide(object *op, const char *params)
Definition: c_wiz.cpp:2482
esrv_update_item
void esrv_update_item(int flags, object *pl, object *op)
Definition: main.cpp:359
command_unloadplugin
void command_unloadplugin(object *op, const char *params)
Definition: c_wiz.cpp:2453
Settings::max_stat
uint8_t max_stat
Definition: global.h:324
rv_vector
Definition: map.h:373
MAP_SWAPPED
#define MAP_SWAPPED
Definition: map.h:132
roll-o-matic.params
params
Definition: roll-o-matic.py:193
reset_sleep
void reset_sleep(void)
Definition: time.cpp:132
EXIT_Y
#define EXIT_Y(xyz)
Definition: define.h:442
pl::stack_position
int stack_position
Definition: player.h:218
diamondslots.y
y
Definition: diamondslots.py:16
assets.h
python_pickup.where
where
Definition: python_pickup.py:7
CLEAR_FLAG
#define CLEAR_FLAG(xyz, p)
Definition: define.h:225
player_arrest
int player_arrest(object *who)
Definition: c_wiz.cpp:788
socket_struct::faces_sent_len
size_t faces_sent_len
Definition: newserver.h:95
command_follow
void command_follow(object *op, const char *params)
Definition: c_wiz.cpp:2772
get_dm_object
static object * get_dm_object(player *pl, const char **params, int *from)
Definition: c_wiz.cpp:195
MAP_HEIGHT
#define MAP_HEIGHT(m)
Definition: map.h:80
tick_duration
uint32_t tick_duration
Definition: time.cpp:35
NDI_DK_ORANGE
#define NDI_DK_ORANGE
Definition: newclient.h:248
get_ob_diff
void get_ob_diff(StringBuffer *sb, const object *op, const object *op2)
Definition: object.cpp:4979
find_player_partial_name
player * find_player_partial_name(const char *plname)
Definition: player.cpp:112
account_change_password
int account_change_password(const char *account_name, const char *current_password, const char *new_password)
Definition: account.cpp:652
obj::more
struct obj * more
Definition: object.h:301
socket_struct::faces_sent
uint8_t * faces_sent
Definition: newserver.h:96
arch_to_object
object * arch_to_object(archetype *at)
Definition: arch.cpp:230
object_give_identified_properties
void object_give_identified_properties(object *op)
Definition: item.cpp:1344
get_rangevector
int get_rangevector(object *op1, const object *op2, rv_vector *retval, int flags)
Definition: map.cpp:2553
checkdm
static int checkdm(object *op, const char *pl_name, const char *pl_passwd, const char *pl_host)
Definition: c_wiz.cpp:2079
MSG_TYPE_COMMAND_MAPS
#define MSG_TYPE_COMMAND_MAPS
Definition: newclient.h:520
artifactstruct::item
object * item
Definition: artifact.h:15
UPD_NAME
#define UPD_NAME
Definition: newclient.h:318
command_accountpasswd
void command_accountpasswd(object *op, const char *params)
Definition: c_wiz.cpp:1614
liv::ac
int8_t ac
Definition: living.h:38
Settings::real_wiz
uint8_t real_wiz
Definition: global.h:271
draw_ext_info
void draw_ext_info(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *message)
Definition: main.cpp:308
MSG_TYPE_COMMUNICATION_PARTY
#define MSG_TYPE_COMMUNICATION_PARTY
Definition: newclient.h:627
object_remove
void object_remove(object *op)
Definition: object.cpp:1833
try_find_archetype
archetype * try_find_archetype(const char *name)
Definition: assets.cpp:274
castle_read.playercount
int playercount
Definition: castle_read.py:62
inventory
void inventory(object *op, object *inv)
Definition: c_object.cpp:2019
do_forget_spell
void do_forget_spell(object *op, const char *spell)
Definition: apply.cpp:525
command_kick2
static void command_kick2(object *op, const char *params)
Definition: c_wiz.cpp:467
do_some_living
void do_some_living(object *op)
Definition: player.cpp:3240
STACK_FROM_STACK
@ STACK_FROM_STACK
Definition: c_wiz.cpp:39
archt::name
sstring name
Definition: object.h:473
save_map
int save_map(mapstruct *m, int flag)
Definition: map.cpp:1428
SCROLL
@ SCROLL
Definition: object.h:224
shutdown_s::next_warn
int next_warn
Definition: commands.h:51
command_stack_push
void command_stack_push(object *op, const char *params)
Definition: c_wiz.cpp:2510
assets_collect
void assets_collect(const char *datadir, int what)
Definition: assets.cpp:115
Settings::no_player_stealing
uint8_t no_player_stealing
Definition: global.h:310
say.item
dictionary item
Definition: say.py:149
command_free
void command_free(object *op, const char *params)
Definition: c_wiz.cpp:1588
MSG_TYPE_COMMUNICATION
#define MSG_TYPE_COMMUNICATION
Definition: newclient.h:410
pl::stack_items
tag_t * stack_items
Definition: player.h:216
update_los
void update_los(object *op)
Definition: los.cpp:459
get_faces_count
size_t get_faces_count()
Definition: assets.cpp:297
freearr_x
short freearr_x[SIZEOFFREE]
Definition: object.cpp:299
mapdef::path
char path[HUGE_BUF]
Definition: map.h:358
pl::party
partylist * party
Definition: player.h:202
TRUE
#define TRUE
Definition: compat.h:11
command_recollect
void command_recollect(object *op, const char *params)
Definition: c_wiz.cpp:1512
command_stack_pop
void command_stack_pop(object *op, const char *params)
Definition: c_wiz.cpp:2497
SPELL
@ SPELL
Definition: object.h:217
liv::sp
int16_t sp
Definition: living.h:42
Settings::create_home_portals
uint8_t create_home_portals
Definition: global.h:311
pl::socket
socket_struct * socket
Definition: player.h:107
altar_valkyrie.pl
pl
Definition: altar_valkyrie.py:28
find_artifactlist
artifactlist * find_artifactlist(int type)
Definition: artifact.cpp:575
mapdef::next
struct mapdef * next
Definition: map.h:318
MSG_TYPE_ADMIN
#define MSG_TYPE_ADMIN
Definition: newclient.h:402
rv_vector::distance
unsigned int distance
Definition: map.h:374
SPELLBOOK
@ SPELLBOOK
Definition: object.h:206
EVENT_KICK
#define EVENT_KICK
Definition: events.h:43
SAVE_ERROR_PLAYER
#define SAVE_ERROR_PLAYER
Definition: map.h:153
dm_stack_peek
static object * dm_stack_peek(player *pl)
Definition: c_wiz.cpp:119
altar_valkyrie.res
int res
Definition: altar_valkyrie.py:74
liv::Pow
int8_t Pow
Definition: living.h:36
NDI_LT_GREEN
#define NDI_LT_GREEN
Definition: newclient.h:250
events_execute_global_event
void events_execute_global_event(int eventcode,...)
Definition: events.cpp:27
llevDebug
@ llevDebug
Definition: logger.h:13
pl::orig_stats
living orig_stats
Definition: player.h:166
FLAG_IDENTIFIED
#define FLAG_IDENTIFIED
Definition: define.h:261
command_stack_clear
void command_stack_clear(object *op, const char *params)
Definition: c_wiz.cpp:2559
give.name
name
Definition: give.py:27
legal_artifact_combination
int legal_artifact_combination(const object *op, const artifact *art)
Definition: artifact.cpp:260
command_stack_list
void command_stack_list(object *op, const char *params)
Definition: c_wiz.cpp:2528
Settings::localdir
const char * localdir
Definition: global.h:249