Crossfire Server, Trunk
c_wiz.c
Go to the documentation of this file.
1 /*
2  * Crossfire -- cooperative multi-player graphical RPG and adventure game
3  *
4  * Copyright (c) 1999-2014 Mark Wedel and the Crossfire Development Team
5  * Copyright (c) 1992 Frank Tore Johansen
6  *
7  * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are
8  * welcome to redistribute it under certain conditions. For details, please
9  * see COPYING and LICENSE.
10  *
11  * The authors can be reached via e-mail at <crossfire@metalforge.org>.
12  */
13 
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 
32 /* Defines for DM item stack **/
33 #define STACK_SIZE 50
35 enum {
40 };
41 
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 = 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;
473  int removed = 0;
474 
475  op = pl->ob;
476  if (!QUERY_FLAG(op, FLAG_REMOVED)) {
478  object_remove(op);
479  removed = 1;
480  }
481  op->direction = 0;
483  "%s is kicked out of the game.",
484  op->name);
485  strcpy(op->contr->killer, "left");
486  hiscore_check(op, 0); /* Always check score */
487 
488  /*
489  * not sure how the player would be freed, but did see
490  * a crash here - if that is the case, don't save the
491  * the player.
492  */
493  if (!removed && !QUERY_FLAG(op, FLAG_FREED)) {
494  (void)save_player(op, 0);
495  if (op->map)
496  op->map->players--;
497  }
498 #if MAP_MAXTIMEOUT
499  if (op->map)
500  op->map->timeout = MAP_TIMEOUT(op->map);
501 #endif
502  pl->socket.status = Ns_Dead;
503  }
504  }
505 }
506 
522 void command_banish(object *op, const char *params) {
523  player *pl;
524  FILE *banishfile;
525  char buf[MAX_BUF];
526  time_t now;
527 
528  if (*params == '\0') {
530  "Usage: banish <player>.");
531  return;
532  }
533 
535  if (!pl)
536  return;
537 
538  snprintf(buf, sizeof(buf), "%s/%s", settings.localdir, BANISHFILE);
539 
540  if ((banishfile = fopen(buf, "a")) == NULL) {
541  LOG(llevDebug, "Could not find file banish_file.\n");
543  "Could not find banish_file.");
544  return;
545  }
546 
547  now = time(NULL);
548  /*
549  * Record this as a comment - then we don't have to worry about changing
550  * the parsing code.
551  */
552  fprintf(banishfile, "# %s (%s) banned by %s at %s\n", pl->ob->name, pl->socket.host, op->name, ctime(&now));
553  fprintf(banishfile, "*@%s\n", pl->socket.host);
554  fclose(banishfile);
555 
556  LOG(llevDebug, "! %s banned %s from IP: %s.\n", op->name, pl->ob->name, pl->socket.host);
557 
559  "You banish %s",
560  pl->ob->name);
561 
563  "%s banishes %s from the land!",
564  op->name, pl->ob->name);
565  command_kick2(op, pl->ob->name);
566 }
567 
576 void command_kick(object *op, const char *params) {
578 }
579 
588 void command_overlay_save(object *op, const char *params) {
589  (void)params;
590  if (!op)
591  return;
592 
593  if (save_map(op->map, SAVE_MODE_OVERLAY) < 0)
595  "Overlay save error!");
596  else
598  "Current map has been saved as an overlay.");
599 }
600 
609 void command_overlay_reset(object *op, const char *params) {
610  char filename[MAX_BUF];
611  struct stat stats;
612  (void)params;
613 
615  if (!stat(filename, &stats))
616  if (!unlink(filename))
618  "Overlay successfully removed.");
619  else
621  "Overlay couldn't be removed.");
622  else
624  "No overlay for current map.");
625 }
626 
635 void command_toggle_shout(object *op, const char *params) {
636  player *pl;
637 
638  if (*params == '\0') {
640  "Usage: toggle_shout <player>.");
641  return;
642  }
643 
645  if (!pl)
646  return;
647 
648  if (pl->ob->contr->no_shout == 0) {
649  pl->ob->contr->no_shout = 1;
650 
652  "You have been muzzled by the DM!");
654  "You muzzle %s.",
655  pl->ob->name);
656 
658 
659  return;
660  }
661 
662  pl->ob->contr->no_shout = 0;
664  "You are allowed to shout and chat again.");
666  "You remove %s's muzzle.",
667  pl->ob->name);
668 }
669 
678 void command_shutdown(object *op, const char *params) {
679  if (strlen(params) == 0) {
680  /* Give DM command help and display current shutdown status. */
681  command_help(op, "shutdown");
682 
683  if (cmd_shutdown_time != 0) {
685  MSG_TYPE_COMMAND_DM, "Server is shutting down soon.");
686  }
687  } else if (strcmp(params, "cancel") == 0) {
688  /* Tell everyone that the server is no longer shutting down. */
689  if (cmd_shutdown_time != 0) {
691  MSG_TYPE_ADMIN_DM, "Server shutdown cancelled.");
692  cmd_shutdown_time = 0;
693  LOG(llevInfo, "Server shutdown cancelled by %s.\n", op->name);
694  } else {
696  MSG_TYPE_COMMAND_ERROR, "No shutdown is pending.");
697  }
698  } else if (strncmp(params, "now", 3) == 0) {
699  /* Announce and shut down immediately. */
701  MSG_TYPE_ADMIN_DM, "Server is shutting down now!");
702  cmd_shutdown_time = time(NULL);
703  LOG(llevInfo, "Server shutdown initiated by %s.\n", op->name);
704  } else {
705  /* Schedule (but don't announce) a shutdown. */
706  int minutes = atoi(params);
707 
708  if (minutes > 0 && minutes <= 720) {
711  "Server will shut down in %d minutes.", minutes);
712  cmd_shutdown_time = time(NULL) + minutes * 60;
713  LOG(llevInfo, "Server shutdown initiated by %s in %d minutes.\n", op->name, minutes);
714  } else {
717  "Please specify a reasonable time in minutes.");
718  }
719  }
720 }
721 
730 void command_goto(object *op, const char *params) {
731  if (!op)
732  return ;
733 
734  if (*params == '\0') {
736  "Go to what level?");
737  return;
738  }
739 
740  do_goto(op, params, -1, -1);
741 }
742 
751 void command_freeze(object *op, const char *params) {
752  int ticks;
753  player *pl;
754 
755  if (*params == '\0') {
757  "Usage: freeze [ticks] <player>.");
758  return;
759  }
760 
761  ticks = atoi(params);
762  if (ticks) {
763  while ((isdigit(*params) || isspace(*params)) && *params != 0)
764  params++;
765  if (*params == 0) {
767  "Usage: freeze [ticks] <player>.");
768  return;
769  }
770  } else
771  ticks = 100;
772 
774  if (!pl)
775  return;
776 
778  "You have been frozen by the DM!");
779 
781  "You freeze %s for %d ticks",
782  pl->ob->name, ticks);
783 
784  pl->ob->speed_left = -(pl->ob->speed*ticks);
785 }
786 
795 int player_arrest(object *who) {
796  object *dummy;
797  mapstruct *cur;
798  int x, y;
799 
800  if (who->type != PLAYER)
801  return -3;
802 
803  dummy = get_jail_exit(who);
804  if (!dummy) {
805  return -1;
806  }
807  cur = who->map;
808  x = who->x;
809  y = who->y;
810  enter_exit(who, dummy);
811  object_free(dummy, FREE_OBJ_NO_DESTROY_CALLBACK);
812 
813  if (cur == who->map && x == who->x && y == who->y)
814  return -2;
815 
816  return 0;
817 }
818 
827 void command_arrest(object *op, const char *params) {
828  player *pl;
829  int ret;
830 
831  if (!op)
832  return;
833  if (*params == '\0') {
835  "Usage: arrest <player>.");
836  return;
837  }
839  if (!pl)
840  return;
841 
842  ret = player_arrest(pl->ob);
843  if (ret == -1) {
844  /* we have nowhere to send the prisoner....*/
846  "Can't jail player, there is no map to hold them");
847  return;
848  }
849  if (ret == -2) {
850  /* something prevented jailing the player */
852  "Can't jail player, map loading issue or already in jail's position");
853  return;
854 
855  }
856 
858  "You have been arrested.");
860  "Jailed %s",
861  pl->ob->name);
862  LOG(llevInfo, "Player %s arrested by %s\n", pl->ob->name, op->name);
863 }
864 
872 void command_summon(object *op, const char *params) {
873  int i;
874  object *dummy;
875  player *pl;
876 
877  if (!op)
878  return;
879 
880  if (*params == '\0') {
882  "Usage: summon <player>.");
883  return;
884  }
885 
887  if (!pl)
888  return;
889 
890  i = object_find_free_spot(op, op->map, op->x, op->y, 1, 9);
891  if (i == -1) {
893  "Can not find a free spot to place summoned player.");
894  return;
895  }
896 
897  dummy = object_new();
898  EXIT_PATH(dummy) = add_string(op->map->path);
899  EXIT_X(dummy) = op->x+freearr_x[i];
900  EXIT_Y(dummy) = op->y+freearr_y[i];
901  enter_exit(pl->ob, dummy);
902  object_free(dummy, FREE_OBJ_NO_DESTROY_CALLBACK);
904  "You are summoned.");
906  "You summon %s",
907  pl->ob->name);
908 }
909 
918 /* mids 01/16/2002 */
919 void command_teleport(object *op, const char *params) {
920  int i;
921  object *dummy;
922  player *pl;
923 
924  if (!op)
925  return;
926 
927  if (*params == '\0') {
929  "Usage: teleport <player>.");
930  return;
931  }
932 
934  if (!pl) {
936  "No such player or ambiguous name.");
937  return;
938  }
939 
940  i = object_find_free_spot(pl->ob, pl->ob->map, pl->ob->x, pl->ob->y, 1, 9);
941  if (i == -1) {
943  "Can not find a free spot to teleport to.");
944  return;
945  }
946 
947  dummy = object_new();
948  EXIT_PATH(dummy) = add_string(pl->ob->map->path);
949  EXIT_X(dummy) = pl->ob->x+freearr_x[i];
950  EXIT_Y(dummy) = pl->ob->y+freearr_y[i];
951  enter_exit(op, dummy);
952  object_free(dummy, FREE_OBJ_NO_DESTROY_CALLBACK);
953  if (!op->contr->hidden)
955  "You see a portal open.");
957  "You teleport to %s",
958  pl->ob->name);
959 }
960 
985 void command_create(object *op, const char *params) {
986  object *tmp = NULL;
987  uint32_t i;
988  int magic, set_magic = 0, set_nrof = 0, gotquote, gotspace;
989  uint32_t nrof;
990  char *cp, *bp, *bp2, *bp3, *endline, cpy[MAX_BUF];
991  archetype *at, *at_spell = NULL;
992  const artifact *art = NULL;
993 
994  if (!op)
995  return;
996 
997  if (*params == '\0') {
999  "Usage: create [nr] [magic] <archetype> [ of <artifact>] [variable_to_patch setting]");
1000  return;
1001  }
1002  safe_strncpy(cpy, params, sizeof(cpy));
1003  bp = cpy;
1004 
1005  /* We need to know where the line ends */
1006  endline = bp+strlen(bp);
1007 
1008  if (sscanf(bp, "%u ", &nrof)) {
1009  if ((bp = strchr(cpy, ' ')) == NULL) {
1011  "Usage: create [nr] [magic] <archetype> [ of <artifact>] [variable_to_patch setting]");
1012  return;
1013  }
1014  bp++;
1015  set_nrof = 1;
1016  LOG(llevDebug, "%s creates: (%u) %s\n", op->name, nrof, bp);
1017  }
1018  if (sscanf(bp, "%d ", &magic)) {
1019  if ((bp = strchr(bp, ' ')) == NULL) {
1021  "Usage: create [nr] [magic] <archetype> [ of <artifact>] [variable_to_patch setting]");
1022  return;
1023  }
1024  bp++;
1025  set_magic = 1;
1026  LOG(llevDebug, "%s creates: (%d) (%d) %s\n", op->name, nrof, magic, bp);
1027  }
1028  if ((cp = strstr(bp, " of ")) != NULL) {
1029  *cp = '\0';
1030  cp += 4;
1031  }
1032  for (bp2 = bp; *bp2; bp2++) {
1033  if (*bp2 == ' ') {
1034  *bp2 = '\0';
1035  bp2++;
1036  break;
1037  }
1038  }
1039 
1040  if ((at = try_find_archetype(bp)) == NULL) {
1042  "No such archetype.");
1043  return;
1044  }
1045 
1046  if (cp) {
1047  char spell_name[MAX_BUF], *fsp = NULL;
1048 
1049  /*
1050  * Try to find a spell object for this. Note that
1051  * we also set up spell_name which is only
1052  * the first word.
1053  */
1054 
1055  at_spell = try_find_archetype(cp);
1056  if (!at_spell || at_spell->clone.type != SPELL)
1057  at_spell = find_archetype_by_object_name(cp);
1058  if (!at_spell || at_spell->clone.type != SPELL) {
1059  safe_strncpy(spell_name, cp, sizeof(spell_name));
1060  fsp = strchr(spell_name, ' ');
1061  if (fsp) {
1062  *fsp = 0;
1063  fsp++;
1064  at_spell = try_find_archetype(spell_name);
1065 
1066  /* Got a spell, update the first string pointer */
1067  if (at_spell && at_spell->clone.type == SPELL)
1068  bp2 = cp+strlen(spell_name)+1;
1069  else
1070  at_spell = NULL;
1071  } else
1072  at_spell = NULL;
1073  }
1074 
1075  /* OK - we didn't find a spell - presume the 'of'
1076  * in this case means its an artifact.
1077  */
1078  if (!at_spell) {
1079  if (find_artifactlist(at->clone.type) == NULL) {
1081  "No artifact list for type %d\n",
1082  at->clone.type);
1083  } else {
1084  art = find_artifactlist(at->clone.type)->items;
1085 
1086  do {
1087  if (!strcmp(art->item->name, cp) && legal_artifact_combination(&at->clone, art))
1088  break;
1089  art = art->next;
1090  } while (art != NULL);
1091  if (!art) {
1093  "No such artifact ([%d] of %s)",
1094  at->clone.type, cp);
1095  }
1096  }
1097  LOG(llevDebug, "%s creates: (%d) (%d) (%s) of (%s)\n", op->name, set_nrof ? nrof : 0, set_magic ? magic : 0, bp, cp);
1098  }
1099  } /* if cp */
1100 
1101  /* rods and potions can get their spell from the artifact */
1102  if ((at->clone.type == ROD || at->clone.type == POTION) && !at_spell && (!art || !art->item->other_arch)) {
1104  "Unable to find spell %s for object that needs it, or it is of wrong type",
1105  cp);
1106  return;
1107  }
1108  if ((at->clone.type == WAND || at->clone.type == SCROLL || at->clone.type == SPELLBOOK)
1109  && !at_spell) {
1111  "Unable to find spell %s for object that needs it, or it is of wrong type",
1112  cp);
1113  return;
1114  }
1115 
1116  /*
1117  * Rather than have two different blocks with a lot of similar code,
1118  * just create one object, do all the processing, and then determine
1119  * if that one object should be inserted or if we need to make copies.
1120  */
1121  tmp = object_create_arch(at);
1122  if (settings.real_wiz == FALSE)
1124  if (set_magic)
1125  set_abs_magic(tmp, magic);
1126  if (art)
1128  if (!is_identifiable_type(tmp)) {
1131  }
1132 
1133  /*
1134  * This entire block here tries to find variable pairings,
1135  * eg, 'hp 4' or the like. The mess here is that values
1136  * can be quoted (eg "my cool sword"); So the basic logic
1137  * is we want to find two spaces, but if we got a quote,
1138  * any spaces there don't count.
1139  */
1140  while (*bp2 && bp2 <= endline) {
1141  gotspace = 0;
1142  gotquote = 0;
1143  /* find the first quote */
1144  for (bp3 = bp2; *bp3 && gotspace < 2 && gotquote < 2; bp3++) {
1145  /* Found a quote - now lets find the second one */
1146  if (*bp3 == '"') {
1147  *bp3 = ' ';
1148  bp2 = bp3+1; /* Update start of string */
1149  bp3++;
1150  gotquote++;
1151  while (*bp3) {
1152  if (*bp3 == '"') {
1153  *bp3 = '\0';
1154  gotquote++;
1155  } else
1156  bp3++;
1157  }
1158  } else if (*bp3 == ' ') {
1159  gotspace++;
1160  }
1161  }
1162 
1163  /*
1164  * If we got two spaces, send the second one to null.
1165  * if we've reached the end of the line, increase gotspace -
1166  * this is perfectly valid for the list entry listed.
1167  */
1168  if (gotspace == 2 || gotquote == 2) {
1169  bp3--; /* Undo the extra increment */
1170  *bp3 = '\0';
1171  } else if (*bp3 == '\0')
1172  gotspace++;
1173 
1174  if ((gotquote && gotquote != 2)
1175  || (gotspace != 2 && gotquote != 2)) {
1176  /*
1177  * Unfortunately, we've clobbered lots of values, so printing
1178  * out what we have probably isn't useful. Break out, because
1179  * trying to recover is probably won't get anything useful
1180  * anyways, and we'd be confused about end of line pointers
1181  * anyways.
1182  */
1184  "Malformed create line: %s",
1185  bp2);
1186  break;
1187  }
1188  /* bp2 should still point to the start of this line,
1189  * with bp3 pointing to the end
1190  */
1191  if (set_variable(tmp, bp2) == -1)
1193  "Unknown variable %s",
1194  bp2);
1195  else
1197  "(%s#%d)->%s",
1198  tmp->name, tmp->count, bp2);
1199  bp2 = bp3+1;
1200  }
1201 
1202  if (at->clone.nrof) {
1203  if (at_spell)
1205 
1206  if (set_nrof)
1207  tmp->nrof = nrof;
1208 
1209  if (at->clone.randomitems != NULL && !at_spell) {
1210  create_treasure(at->clone.randomitems, tmp, 0, op->map->difficulty, 0);
1211  if (QUERY_FLAG(tmp, FLAG_MONSTER)) {
1213  }
1214  }
1215 
1216  /* Multipart objects can't be in inventory, put'em on floor. */
1217  if (!tmp->more) {
1219  } else {
1220  object_insert_in_map_at(tmp, op->map, op, 0, op->x, op->y);
1221  }
1222 
1223  /* Let's put this created item on stack so dm can access it easily. */
1224  dm_stack_push(op->contr, tmp->count);
1225 
1226  return;
1227  }
1228 
1229  for (i = 0; i < (set_nrof ? nrof : 1); i++) {
1230  archetype *atmp;
1231  object *prev = NULL, *head = NULL, *dup;
1232 
1233  for (atmp = at; atmp != NULL; atmp = atmp->more) {
1234  dup = arch_to_object(atmp);
1235 
1236  if (at_spell)
1237  object_insert_in_ob(arch_to_object(at_spell), dup);
1238 
1239  /*
1240  * The head is what contains all the important bits,
1241  * so just copying it over should be fine.
1242  */
1243  if (head == NULL) {
1244  head = dup;
1245  object_copy(tmp, dup);
1246  }
1247  if (settings.real_wiz == FALSE)
1248  SET_FLAG(dup, FLAG_WAS_WIZ);
1249  dup->x = op->x+dup->arch->clone.x;
1250  dup->y = op->y+dup->arch->clone.y;
1251  dup->map = op->map;
1252 
1253  if (head != dup) {
1254  dup->head = head;
1255  prev->more = dup;
1256  }
1257  prev = dup;
1258  }
1259 
1260  if (QUERY_FLAG(head, FLAG_ALIVE)) {
1261  object *check = head;
1262  int size_x = 0;
1263  int size_y = 0;
1264 
1265  while (check) {
1266  size_x = MAX(size_x, check->arch->clone.x);
1267  size_y = MAX(size_y, check->arch->clone.y);
1268  check = check->more;
1269  }
1270 
1271  if (out_of_map(op->map, head->x+size_x, head->y+size_y)) {
1272  if (head->x < size_x || head->y < size_y) {
1273  dm_stack_pop(op->contr);
1274  object_free(head, FREE_OBJ_NO_DESTROY_CALLBACK);
1276  "Object too big to insert in map, or wrong position.");
1277  object_free(tmp, FREE_OBJ_NO_DESTROY_CALLBACK);
1278  return;
1279  }
1280 
1281  check = head;
1282  while (check) {
1283  check->x -= size_x;
1284  check->y -= size_y;
1285  check = check->more;
1286  }
1287  }
1288 
1289  object_insert_in_map_at(head, op->map, op, 0, head->x, head->y);
1290  } else
1291  head = object_insert_in_ob(head, op);
1292 
1293  /* Let's put this created item on stack so dm can access it easily. */
1294  /* Wonder if we really want to push all of these, but since
1295  * things like rods have nrof 0, we want to cover those.
1296  */
1297  dm_stack_push(op->contr, head->count);
1298 
1299  if (at->clone.randomitems != NULL && !at_spell) {
1300  create_treasure(at->clone.randomitems, head, 0, op->map->difficulty, 0);
1301  if (QUERY_FLAG(head, FLAG_MONSTER)) {
1303  }
1304  }
1305  }
1306 
1307  /* free the one we used to copy */
1308  object_free(tmp, FREE_OBJ_NO_DESTROY_CALLBACK);
1309 }
1310 
1311 /*
1312  * Now follows dm-commands which are also acceptable from sockets
1313  */
1314 
1323 void command_inventory(object *op, const char *params) {
1324  object *tmp;
1325  int i;
1326 
1327  if (*params == '\0') {
1328  inventory(op, NULL);
1329  return;
1330  }
1331 
1332  if (!sscanf(params, "%d", &i) || (tmp = object_find_by_tag_global(i)) == NULL) {
1334  "Inventory of what object (nr)?");
1335  return;
1336  }
1337 
1338  inventory(op, tmp);
1339 }
1340 
1353 void command_skills(object *op, const char *params) {
1354  show_skills(op, *params == '\0' ? NULL : params);
1355 }
1356 
1365 void command_dump(object *op, const char *params) {
1366  object *tmp;
1367  StringBuffer *sb;
1368  char *diff;
1369 
1370  tmp = get_dm_object(op->contr, &params, NULL);
1371  if (!tmp)
1372  return;
1373 
1374  sb = stringbuffer_new();
1375  object_dump(tmp, sb);
1376  diff = stringbuffer_finish(sb);
1378  free(diff);
1381  "Object is marked original");
1382 }
1383 
1393 void command_mon_aggr(object *op, const char *params) {
1394  (void)params;
1395  if (op->enemy || !QUERY_FLAG(op, FLAG_UNAGGRESSIVE)) {
1396  object_set_enemy(op, NULL);
1399  "Aggression turned OFF");
1400  } else {
1404  "Aggression turned ON");
1405  }
1406 }
1407 
1420 void command_possess(object *op, const char *params) {
1421  object *victim;
1422  player *pl;
1423  int i;
1424  char buf[MAX_BUF];
1425 
1426  victim = NULL;
1427  if (*params != '\0') {
1428  if (sscanf(params, "%d", &i))
1430  else if (sscanf(params, "%s", buf))
1432  }
1433  if (victim == NULL) {
1435  "Patch what object (nr)?");
1436  return;
1437  }
1438 
1439  if (victim == op) {
1441  "As insane as you are, I cannot allow you to possess yourself.");
1442  return;
1443  }
1444 
1445  /* make the switch */
1446  pl = op->contr;
1447  victim->contr = pl;
1448  pl->ob = victim;
1449  victim->type = PLAYER;
1451 
1452  /* basic patchup */
1453  /* The use of hard coded values is terrible. Note
1454  * that really, to be fair, this shouldn't get changed at
1455  * all - if you are possessing a kobold, you should have the
1456  * same limitations. As it is, as more body locations are added,
1457  * this will give this player more locations than perhaps
1458  * they should be allowed.
1459  */
1460  for (i = 0; i < NUM_BODY_LOCATIONS; i++)
1461  if (i == 1 || i == 6 || i == 8 || i == 9)
1462  victim->body_info[i] = 2;
1463  else
1464  victim->body_info[i] = 1;
1465 
1466  esrv_new_player(pl, 80); /* just pick a weight, we don't care */
1468 
1469  fix_object(victim);
1470 
1472 }
1473 
1481 void command_patch(object *op, const char *params) {
1482  const char *arg, *arg2;
1483  object *tmp;
1484 
1485  tmp = get_dm_object(op->contr, &params, NULL);
1486  if (!tmp)
1487  /* Player already informed of failure */
1488  return;
1489 
1490  /* params set to first value by get_dm_default */
1491  arg = params;
1492  if (*arg == '\0') {
1494  "Patch what values?");
1495  return;
1496  }
1497 
1498  if ((arg2 = strchr(arg, ' ')))
1499  arg2++;
1500  if (settings.real_wiz == FALSE)
1501  SET_FLAG(tmp, FLAG_WAS_WIZ); /* To avoid cheating */
1502  if (set_variable(tmp, arg) == -1)
1504  "Unknown variable %s",
1505  arg);
1506  else {
1508  "(%s#%d)->%s=%s",
1509  tmp->name, tmp->count, arg, arg2);
1510  }
1511 }
1512 
1521 void command_remove(object *op, const char *params) {
1522  object *tmp;
1523  int from;
1524 
1525  tmp = get_dm_object(op->contr, &params, &from);
1526  if (!tmp) {
1528  "Remove what object (nr)?");
1529  return;
1530  }
1531 
1532  if (tmp->type == PLAYER) {
1534  "Unable to remove a player!");
1535  return;
1536  }
1537 
1538  if (QUERY_FLAG(tmp, FLAG_REMOVED)) {
1539  char name[MAX_BUF];
1540 
1543  "%s is already removed!",
1544  name);
1545  return;
1546  }
1547 
1548  if (from != STACK_FROM_STACK)
1549  /* Item is either stack top, or is a number thus is now stack top, let's remove it */
1550  dm_stack_pop(op->contr);
1551 
1552  /* Always work on the head - otherwise object will get in odd state */
1553  tmp = HEAD(tmp);
1554  if (tmp->speed != 0) {
1555  tmp->speed = 0;
1557  }
1558  object_remove(tmp);
1559 }
1560 
1568 void command_free(object *op, const char *params) {
1569  object *tmp;
1570  int from;
1571 
1572  tmp = get_dm_object(op->contr, &params, &from);
1573 
1574  if (!tmp) {
1576  "Free what object (nr)?");
1577  return;
1578  }
1579 
1580  if (from != STACK_FROM_STACK)
1581  /* Item is either stack top, or is a number thus is now stack top, let's remove it */
1582  dm_stack_pop(op->contr);
1583 
1584  tmp = HEAD(tmp);
1585  if (!QUERY_FLAG(tmp, FLAG_REMOVED)) {
1587  "Warning: item was not removed, will do so now.");
1588  object_remove(tmp);
1589  }
1590 
1592 }
1593 
1594 void command_accountpasswd(object *op, const char *params) {
1595  char account_name[MAX_BUF], newpw[MAX_BUF];
1596  // Password may contain spaces, so use %[^\n] format string.
1597  if (sscanf(params, "%s %[^\n]", account_name, newpw) != 2) {
1599  "Usage: accountpasswd ACCOUNT PASSWORD");
1600  return;
1601  }
1602 
1603  int ret = account_change_password(account_name, NULL, newpw);
1604  switch (ret) {
1605  case 0:
1607  "Updated account password.");
1608  return;
1609  case 1:
1611  "Invalid characters in new password.");
1612  return;
1613  case 2:
1615  "Invalid characters in new password.");
1616  return;
1617  default:
1619  "Error changing password.");
1620  return;
1621  }
1622 }
1623 
1632 void command_addexp(object *op, const char *params) {
1633  char buf[MAX_BUF], skill[MAX_BUF];
1634  int i, q;
1635  object *skillob = NULL;
1636  player *pl;
1637 
1638  skill[0] = '\0';
1639  if ((*params == '\0')
1640  || (strlen(params) > MAX_BUF)
1641  || ((q = sscanf(params, "%s %d %[^\r\n]", buf, &i, skill)) < 2)) {
1643  "Usage: addexp player quantity [skill].");
1644  return;
1645  }
1646 
1647  for (pl = first_player; pl != NULL; pl = pl->next)
1648  if (!strncmp(pl->ob->name, buf, MAX_NAME))
1649  break;
1650 
1651  if (pl == NULL) {
1653  "No such player.");
1654  return;
1655  }
1656 
1657  if (q >= 3) {
1658  skillob = find_skill_by_name(pl->ob, skill);
1659  if (!skillob) {
1661  "Unable to find skill %s in %s",
1662  skill, buf);
1663  return;
1664  }
1665 
1666  i = check_exp_adjust(skillob, i);
1667  skillob->stats.exp += i;
1668  calc_perm_exp(skillob);
1669  player_lvl_adj(pl->ob, skillob);
1670  }
1671 
1672  pl->ob->stats.exp += i;
1673  calc_perm_exp(pl->ob);
1674  player_lvl_adj(pl->ob, NULL);
1675 
1676  if (settings.real_wiz == FALSE)
1678 }
1679 
1688 void command_speed(object *op, const char *params) {
1689  int i;
1690 
1691  if (*params == '\0' || !sscanf(params, "%d", &i)) {
1693  "Current speed is %d",
1694  max_time);
1695  return;
1696  }
1697 
1698  set_max_time(i);
1699  reset_sleep();
1701  "The speed is changed to %d.",
1702  i);
1703 }
1704 
1705 /**************************************************************************/
1706 /* Mods made by Tyler Van Gorder, May 10-13, 1992. */
1707 /* CSUChico : tvangod@cscihp.ecst.csuchico.edu */
1708 /**************************************************************************/
1709 
1718 void command_stats(object *op, const char *params) {
1719  player *pl;
1720 
1721  if (*params == '\0') {
1723  "Who?");
1724  return;
1725  }
1726 
1728  if (pl == NULL) {
1730  "No such player.");
1731  return;
1732  }
1733 
1735  "[Fixed]Statistics for %s:", pl->ob->name);
1736 
1738  "[fixed]Str : %-2d H.P. : %-4d MAX : %d",
1739  pl->ob->stats.Str, pl->ob->stats.hp, pl->ob->stats.maxhp);
1740 
1742  "[fixed]Dex : %-2d S.P. : %-4d MAX : %d",
1743  pl->ob->stats.Dex, pl->ob->stats.sp, pl->ob->stats.maxsp);
1744 
1746  "[fixed]Con : %-2d AC : %-4d WC : %d",
1747  pl->ob->stats.Con, pl->ob->stats.ac, pl->ob->stats.wc);
1748 
1750  "[fixed]Int : %-2d Damage : %d",
1751  pl->ob->stats.Int, pl->ob->stats.dam);
1752 
1754  "[fixed]Wis : %-2d EXP : %"FMT64,
1755  pl->ob->stats.Wis, pl->ob->stats.exp);
1756 
1758  "[fixed]Pow : %-2d Grace : %d",
1759  pl->ob->stats.Pow, pl->ob->stats.grace);
1760 
1762  "[fixed]Cha : %-2d Food : %d",
1763  pl->ob->stats.Cha, pl->ob->stats.food);
1764 }
1765 
1775 void command_abil(object *op, const char *params) {
1776  char thing[20], thing2[20];
1777  int iii;
1778  player *pl;
1779 
1780  iii = 0;
1781  thing[0] = '\0';
1782  thing2[0] = '\0';
1783  if (*params == '\0'
1784  || sscanf(params, "%s %s %d", thing, thing2, &iii) != 3
1785  || thing[0] == '\0') {
1787  "Who?");
1788  return;
1789  }
1790 
1791  if (thing2[0] == '\0') {
1793  "You can't change that.");
1794  return;
1795  }
1796 
1797  if (iii < MIN_STAT || iii > settings.max_stat) {
1799  "Illegal range of stat.\n");
1800  return;
1801  }
1802 
1803  for (pl = first_player; pl != NULL; pl = pl->next) {
1804  if (!strcmp(pl->ob->name, thing)) {
1805  if (settings.real_wiz == FALSE)
1807  if (!strcmp("str", thing2))
1808  pl->ob->stats.Str = iii, pl->orig_stats.Str = iii;
1809  if (!strcmp("dex", thing2))
1810  pl->ob->stats.Dex = iii, pl->orig_stats.Dex = iii;
1811  if (!strcmp("con", thing2))
1812  pl->ob->stats.Con = iii, pl->orig_stats.Con = iii;
1813  if (!strcmp("wis", thing2))
1814  pl->ob->stats.Wis = iii, pl->orig_stats.Wis = iii;
1815  if (!strcmp("cha", thing2))
1816  pl->ob->stats.Cha = iii, pl->orig_stats.Cha = iii;
1817  if (!strcmp("int", thing2))
1818  pl->ob->stats.Int = iii, pl->orig_stats.Int = iii;
1819  if (!strcmp("pow", thing2))
1820  pl->ob->stats.Pow = iii, pl->orig_stats.Pow = iii;
1822  "%s has been altered.",
1823  pl->ob->name);
1824  fix_object(pl->ob);
1825  return;
1826  }
1827  }
1828 
1830  "No such player.");
1831 }
1832 
1841 void command_reset(object *op, const char *params) {
1842  mapstruct *m;
1843  object *dummy = NULL, *tmp = NULL;
1844  char path[HUGE_BUF];
1845  const char *space, *confirmation = NULL;
1846  int res = 0;
1847 
1848  if (*params == '\0') {
1850  MSG_TYPE_COMMAND_ERROR, "Which map should be reset?");
1851  return;
1852  }
1853 
1854  space = strchr(params, ' ');
1855  if (space != NULL) {
1856  confirmation = params;
1857  params = space + 1;
1858  }
1859 
1860  /* Use the DM's map if the current map was given. */
1861  if (strcmp(params, ".") == 0) {
1862  strlcpy(path, op->map->path, sizeof(path));
1863  } else {
1864  path_combine_and_normalize(op->map->path, params, path, sizeof(path));
1865  }
1866 
1867  m = has_been_loaded(path);
1868  if (m == NULL) {
1870  MSG_TYPE_COMMAND_ERROR, "No such map.");
1871  return;
1872  }
1873 
1874  if (confirmation) {
1875  if (m->unique && (op->map == m)) {
1878  "Cannot reset a unique player map while on it. Use "
1879  "'reset full-reset %s' while standing somewhere else.",
1880  m->path);
1881  return;
1882  }
1883 
1884  if (strncmp("full-reset", confirmation, strlen("full-reset"))) {
1886  MSG_TYPE_COMMAND_ERROR, "Confirm using 'full-reset'.");
1887  return;
1888  }
1889  }
1890 
1891  /* Forbid using reset on our own map when we're in a transport, as
1892  * it has the displeasant effect of crashing the server.
1893  * - gros, July 25th 2006 */
1894  if ((op->contr && op->contr->transport) && (op->map == m)) {
1896  "You need to disembark first.");
1897  return;
1898  }
1899 
1900  strlcpy(path, m->path, sizeof(path));
1901 
1902  if (m->in_memory != MAP_SWAPPED) {
1903  if (m->in_memory != MAP_IN_MEMORY) {
1904  LOG(llevError, "Tried to swap out map which was not in memory.\n");
1905  return;
1906  }
1907 
1908  /*
1909  * Only attempt to remove the player that is doing the reset, and not other
1910  * players or wiz's.
1911  */
1912  if (op->map == m) {
1913  if (strncmp(m->path, "/random/", 8) == 0) {
1914  /* This is not a very satisfying solution - it would be much better
1915  * to recreate a random map with the same seed value as the old one.
1916  * Unfortunately, I think recreating the map would require some
1917  * knowledge about its 'parent', which appears very non-trivial to
1918  * me.
1919  * On the other hand, this should prevent the freeze that this
1920  * situation caused. - gros, 26th July 2006.
1921  */
1923  "You cannot reset a random map when inside it.");
1924  return;
1925  }
1926 
1927  dummy = object_new();
1928  dummy->map = NULL;
1929  EXIT_X(dummy) = op->x;
1930  EXIT_Y(dummy) = op->y;
1931  EXIT_PATH(dummy) = add_string(op->map->path);
1932  object_remove(op);
1933  op->map = NULL;
1934  tmp = op;
1935  }
1936  res = swap_map(m);
1937  }
1938 
1939  if (res < 0 || m->in_memory != MAP_SWAPPED) {
1940  player *pl;
1941  int playercount = 0;
1942 
1943  /* Need to re-insert player if swap failed for some reason */
1944  if (tmp) {
1945  object_insert_in_map_at(op, m, NULL, 0, op->x, op->y);
1946  object_free(dummy, FREE_OBJ_NO_DESTROY_CALLBACK);
1947  }
1948 
1949  if (res < 0 && res != SAVE_ERROR_PLAYER)
1950  /* no need to warn if player on map, code below checks that. */
1952  "Reset failed, error code: %d.", res);
1953  else {
1955  "Reset failed, couldn't swap map, the following players are on it:");
1956  for (pl = first_player; pl != NULL; pl = pl->next) {
1957  if (pl->ob->map == m && pl->ob != op) {
1959  pl->ob->name);
1960  playercount++;
1961  }
1962  }
1963  if (!playercount)
1965  "hmm, I don't see any other players on this map, something else is the problem.");
1966  return;
1967  }
1968  }
1969 
1970  /* Here, map reset succeeded. */
1971 
1972  if (m && m->in_memory == MAP_SWAPPED) {
1973  if (confirmation) {
1975  LOG(llevDebug, "DM %s fully resetting map %s.\n", op->name, m->path);
1976  } else
1977  LOG(llevDebug, "DM %s resetting map %s.\n", op->name, m->path);
1978 
1979  /* setting this effectively causes an immediate reload */
1980  m->reset_time = 1;
1981  flush_old_maps();
1982  }
1983 
1984  /* Display the appropriate success message. */
1985  if (confirmation) {
1987  MSG_TYPE_COMMAND_DM, "Fully resetting map %s.", path);
1988  } else {
1990  MSG_TYPE_COMMAND_DM, "Resetting map %s.", path);
1991  }
1992 
1993  if (tmp) {
1994  enter_exit(tmp, dummy);
1995  object_free(dummy, FREE_OBJ_NO_DESTROY_CALLBACK);
1996  }
1997 
1998  /* Remind the DM how to fully reset the map. */
1999  if (confirmation == NULL) {
2002  "Use 'reset full-reset %s' to fully reset the map.", params);
2003  }
2004 }
2005 
2014 void command_nowiz(object *op, const char *params) { /* 'noadm' is alias */
2015  (void)params;
2019 
2020  if (settings.real_wiz == TRUE)
2022  if (op->contr->hidden) {
2023  unhide(op);
2024  } else
2026  "The Dungeon Master is gone..");
2027 
2028  update_los(op);
2029 }
2030 
2051 static int checkdm(object *op, const char *pl_name, const char *pl_passwd, const char *pl_host) {
2052  FILE *dmfile;
2053  char buf[MAX_BUF];
2054  char line_buf[160], name[160], passwd[160], host[160];
2055 
2056 #ifdef RESTRICTIVE_DM
2057  *pl_name = op->name ? op->name : "*";
2058 #else
2059  (void)op;
2060 #endif
2061 
2062  snprintf(buf, sizeof(buf), "%s/%s", settings.confdir, DMFILE);
2063  if ((dmfile = fopen(buf, "r")) == NULL) {
2064  LOG(llevDebug, "Could not find DM file.\n");
2065  return 0;
2066  }
2067 
2068  while (fgets(line_buf, 160, dmfile) != NULL) {
2069  // Skip empty lines as well as commented ones.
2070  if (line_buf[0] == '#' || line_buf[0] == '\n')
2071  continue;
2072  if (sscanf(line_buf, "%[^:]:%[^:]:%s\n", name, passwd, host) != 3) {
2073  LOG(llevError, "Warning - malformed dm file entry: %s\n", line_buf);
2074  } else if ((!strcmp(name, "*") || (pl_name && !strcmp(pl_name, name)))
2075  && (!strcmp(passwd, "*") || !strcmp(passwd, pl_passwd))
2076  && (!strcmp(host, "*") || !strcmp(host, pl_host))) {
2077  fclose(dmfile);
2078  return (1);
2079  }
2080  }
2081  fclose(dmfile);
2082  return (0);
2083 }
2084 
2099 static int do_wizard_dm(object *op, const char *params, int silent) {
2100  if (!op->contr)
2101  return 0;
2102 
2103  if (QUERY_FLAG(op, FLAG_WIZ)) {
2105  "You are already the Dungeon Master!");
2106  return 0;
2107  }
2108 
2109  if (checkdm(op, op->name, (*params != '\0' ? params : "*"), op->contr->socket.host)) {
2110  SET_FLAG(op, FLAG_WIZ);
2115  "Ok, you are the Dungeon Master!");
2116  /*
2117  * Remove setting flying here - that won't work, because next
2118  * fix_object() is called that will get cleared - proper solution
2119  * is probably something like a wiz_force which gives that and any
2120  * other desired abilities.
2121  */
2122  clear_los(op->contr);
2123 
2124  if (!silent)
2127  "The Dungeon Master has arrived!");
2128 
2129  return 1;
2130  }
2131 
2133  "Sorry Pal, I don't think so.");
2134  return 0;
2135 }
2136 
2148 void command_dm(object *op, const char *params) {
2149  do_wizard_dm(op, params, 0);
2150 }
2151 
2160 void command_invisible(object *op, const char *params) {
2161  (void)params;
2162  if (op) {
2163  op->invisible += 100;
2164  object_update(op, UP_OBJ_FACE);
2166  "You turn invisible.");
2167  }
2168 }
2169 
2187 static object *get_spell_by_name(object *op, const char *spell_name) {
2188  archetype *ar;
2189  archetype *found;
2190  int conflict_found;
2191  size_t spell_name_length;
2192 
2193  /* First check for full name matches. */
2194  conflict_found = 0;
2195  found = NULL;
2196  for (ar = get_next_archetype(NULL); ar != NULL; ar = get_next_archetype(ar)) {
2197  if (ar->clone.type != SPELL)
2198  continue;
2199 
2200  if (strncmp(ar->name, "spelldirect_", 12) == 0)
2201  continue;
2202 
2203  if (strcmp(ar->clone.name, spell_name) != 0)
2204  continue;
2205 
2206  if (found != NULL) {
2207  if (!conflict_found) {
2208  conflict_found = 1;
2210  "More than one archetype matches the spell name %s:",
2211  spell_name);
2213  "- %s",
2214  found->name);
2215  }
2217  "- %s",
2218  ar->name);
2219  continue;
2220  }
2221 
2222  found = ar;
2223  }
2224 
2225  /* No match if more more than one archetype matches. */
2226  if (conflict_found)
2227  return NULL;
2228 
2229  /* Return if exactly one archetype matches. */
2230  if (found != NULL)
2231  return arch_to_object(found);
2232 
2233  /* No full match found: now check for partial matches. */
2234  spell_name_length = strlen(spell_name);
2235  conflict_found = 0;
2236  found = NULL;
2237 
2238  for (ar = get_next_archetype(NULL); ar != NULL; ar = get_next_archetype(ar)) {
2239  if (ar->clone.type != SPELL)
2240  continue;
2241 
2242  if (strncmp(ar->name, "spelldirect_", 12) == 0)
2243  continue;
2244 
2245  if (strncmp(ar->clone.name, spell_name, spell_name_length) != 0)
2246  continue;
2247 
2248  if (found != NULL) {
2249  if (!conflict_found) {
2250  conflict_found = 1;
2252  "More than one spell matches %s:",
2253  spell_name);
2255  "- %s",
2256  found->clone.name);
2257  }
2259  "- %s",
2260  ar->clone.name);
2261  continue;
2262  }
2263 
2264  found = ar;
2265  }
2266 
2267  /* No match if more more than one archetype matches. */
2268  if (conflict_found)
2269  return NULL;
2270 
2271  /* Return if exactly one archetype matches. */
2272  if (found != NULL)
2273  return arch_to_object(found);
2274 
2275  /* No spell found: just print an error message. */
2277  "The spell %s does not exist.",
2278  spell_name);
2279  return NULL;
2280 }
2281 
2292 static void command_learn_spell_or_prayer(object *op, const char *params, int special_prayer) {
2293  object *tmp;
2294 
2295  if (op->contr == NULL || *params == '\0') {
2297  "Which spell do you want to learn?");
2298  return;
2299  }
2300 
2302  if (tmp == NULL) {
2303  return;
2304  }
2305 
2306  if (check_spell_known(op, tmp->name)) {
2308  "You already know the spell %s.",
2309  tmp->name);
2310  return;
2311  }
2312 
2313  do_learn_spell(op, tmp, special_prayer);
2314  object_free(tmp, FREE_OBJ_NO_DESTROY_CALLBACK);
2315 }
2316 
2325 void command_learn_spell(object *op, const char *params) {
2327 }
2328 
2337 void command_learn_special_prayer(object *op, const char *params) {
2339 }
2340 
2350 void command_forget_spell(object *op, const char *params) {
2351  object *spell;
2352 
2353  if (op->contr == NULL || *params == '\0') {
2355  "Which spell do you want to forget?");
2356  return;
2357  }
2358 
2359  spell = lookup_spell_by_name(op, params);
2360  if (spell == NULL) {
2362  "You do not know the spell %s.",
2363  params);
2364  return;
2365  }
2366 
2367  do_forget_spell(op, spell->name);
2368 }
2369 
2378 void command_listplugins(object *op, const char *params) {
2379  (void)params;
2381 }
2382 
2393 void command_loadplugin(object *op, const char *params) {
2394  char buf[MAX_BUF];
2395 
2396  if (*params == '\0') {
2398  "Load which plugin?");
2399  return;
2400  }
2401 
2402  snprintf(buf, sizeof(buf), LIBDIR"/plugins/%s", params);
2403  LOG(llevDebug, "Requested plugin file is %s\n", buf);
2404  if (plugins_init_plugin(buf) == 0) {
2405  LOG(llevInfo, "DM %s loaded plugin %s\n", op->name, params);
2407  "Plugin %s successfully loaded.",
2408  params);
2409  } else
2411  "Could not load plugin %s.",
2412  params);
2413 }
2414 
2425 void command_unloadplugin(object *op, const char *params) {
2426  if (*params == '\0') {
2428  "Remove which plugin?");
2429  return;
2430  }
2431 
2432  if (plugins_remove_plugin(params) == 0) {
2433  LOG(llevInfo, "DM %s unloaded plugin %s\n", op->name, params);
2435  "Plugin %s successfully removed.",
2436  params);
2437  init_signals(); // Restore our signal handlers, some plugins (Python) mess with them
2438  } else
2440  "Could not remove plugin %s.",
2441  params);
2442 }
2443 
2454 void command_dmhide(object *op, const char *params) {
2455  if (!do_wizard_dm(op, params, 1))
2456  return;
2457 
2458  do_wizard_hide(op, 1);
2459 }
2460 
2469 void command_stack_pop(object *op, const char *params) {
2470  (void)params;
2471  dm_stack_pop(op->contr);
2472 }
2473 
2482 void command_stack_push(object *op, const char *params) {
2483  object *ob;
2484  int from;
2485  ob = get_dm_object(op->contr, &params, &from);
2486 
2487  if (ob && from != STACK_FROM_NUMBER)
2488  /* Object was from stack, need to push it again */
2489  dm_stack_push(op->contr, ob->count);
2490 }
2491 
2500 void command_stack_list(object *op, const char *params) {
2501  int item;
2502  object *display;
2503  player *pl = op->contr;
2504  (void)params;
2505 
2507  "Item stack contents:");
2508 
2509  for (item = 0; item < pl->stack_position; item++) {
2511  if (display)
2513  " %d : %s [%d]",
2514  item, display->name, display->count);
2515  else
2516  /* Item was freed */
2518  " %d : (lost item: %d)",
2519  item, pl->stack_items[item]);
2520  }
2521 }
2522 
2531 void command_stack_clear(object *op, const char *params) {
2532  (void)params;
2533  op->contr->stack_position = 0;
2535  "Item stack cleared.");
2536 }
2537 
2557 void command_diff(object *op, const char *params) {
2558  object *left, *right;
2559  char *diff;
2560  StringBuffer *sb;
2561  int left_from, right_from;
2562 
2563  left = get_dm_object(op->contr, &params, &left_from);
2564  if (!left) {
2566  "Compare to what item?");
2567  return;
2568  }
2569 
2570  if (left_from == STACK_FROM_NUMBER)
2571  /* Item was stacked, remove it else right will be the same... */
2572  dm_stack_pop(op->contr);
2573 
2574  right = get_dm_object(op->contr, &params, &right_from);
2575 
2576  if (!right) {
2578  "Compare what item?");
2579  return;
2580  }
2581 
2583  "Item difference:");
2584 
2585  if (left_from == STACK_FROM_TOP && right_from == STACK_FROM_TOP) {
2586  /*
2587  * Special case: both items were taken from stack top.
2588  * Override the behaviour, taking left as item just below top, if exists.
2589  * See function description for why.
2590  * Besides, if we don't do anything, compare an item to itself, not really useful.
2591  */
2592  if (op->contr->stack_position > 1) {
2593  left = object_find_by_tag_global(op->contr->stack_items[op->contr->stack_position-2]);
2594  if (left)
2596  "(Note: first item taken from undertop)");
2597  else
2598  /* Stupid case: item under top was freed, fallback to stack top */
2599  left = right;
2600  }
2601  }
2602 
2603  sb = stringbuffer_new();
2604  get_ob_diff(sb, left, right);
2605  diff = stringbuffer_finish(sb);
2606  if (*diff == '\0') {
2607  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_DM, "Objects are the same.");
2608  } else {
2610  }
2611  free(diff);
2612 }
2613 
2621 void command_insert_into(object *op, const char *params) {
2622  object *left, *right, *inserted;
2623  int left_from, right_from;
2624  char what[MAX_BUF], where[MAX_BUF];
2625 
2626  left = get_dm_object(op->contr, &params, &left_from);
2627  if (!left) {
2629  "Insert into what object?");
2630  return;
2631  }
2632 
2633  if (left_from == STACK_FROM_NUMBER)
2634  /* Item was stacked, remove it else right will be the same... */
2635  dm_stack_pop(op->contr);
2636 
2637  right = get_dm_object(op->contr, &params, &right_from);
2638 
2639  if (!right) {
2641  "Insert what item?");
2642  return;
2643  }
2644 
2645  if (left_from == STACK_FROM_TOP && right_from == STACK_FROM_TOP) {
2646  /*
2647  * Special case: both items were taken from stack top.
2648  * Override the behaviour, taking left as item just below top, if exists.
2649  * See function description for why.
2650  * Besides, can't insert an item into itself.
2651  */
2652  if (op->contr->stack_position > 1) {
2653  left = object_find_by_tag_global(op->contr->stack_items[op->contr->stack_position-2]);
2654  if (left)
2656  "(Note: item to insert into taken from undertop)");
2657  else
2658  /* Stupid case: item under top was freed, fallback to stack top */
2659  left = right;
2660  }
2661  }
2662 
2663  if (left == right) {
2665  "Can't insert an object into itself!");
2666  return;
2667  }
2668 
2669  if (right->type == PLAYER) {
2671  "Can't insert a player into something!");
2672  return;
2673  }
2674 
2675  if (!QUERY_FLAG(right, FLAG_REMOVED))
2676  object_remove(right);
2677  inserted = object_insert_in_ob(right, left);
2678  if (left->type == PLAYER) {
2679  if (inserted != right)
2680  /* item was merged, so updating name and such. */
2681  esrv_update_item(UPD_WEIGHT|UPD_NAME|UPD_NROF, left, inserted);
2682  }
2683  query_name(inserted, what, MAX_BUF);
2684  query_name(left, where, MAX_BUF);
2686  "Inserted %s in %s",
2687  what, where);
2688 }
2689 
2698 void command_style_map_info(object *op, const char *params) {
2699  extern mapstruct *styles;
2700  mapstruct *mp;
2701  int maps_used = 0, mapmem = 0, objects_used = 0, x, y;
2702  (void)params;
2703 
2704  for (mp = styles; mp != NULL; mp = mp->next) {
2705  maps_used++;
2706  mapmem += map_size(mp) * (sizeof(object *)+sizeof(MapSpace))+sizeof(mapstruct);
2707  for (x = 0; x < MAP_WIDTH(mp); x++) {
2708  for (y = 0; y < MAP_HEIGHT(mp); y++) {
2709  FOR_MAP_PREPARE(mp, x, y, tmp)
2710  objects_used++;
2711  FOR_MAP_FINISH();
2712  }
2713  }
2714  }
2716  "[fixed]Style maps loaded: %d",
2717  maps_used);
2719  "[fixed]Memory used, not");
2721  "[fixed]including objects: %d",
2722  mapmem);
2724  "[fixed]Style objects: %d",
2725  objects_used);
2727  "[fixed]Mem for objects: %lu",
2728  (unsigned long)(objects_used*sizeof(object)));
2729 }
2730 
2731 bool can_follow(object* op, player* other) {
2732  // Only allow follow from same party.
2733  return (other->ob->contr->party != NULL) && (op->contr->party == other->ob->contr->party);
2734 }
2735 
2744 void command_follow(object *op, const char *params) {
2745  player *other;
2746 
2747  if (*params == '\0') {
2748  if (op->contr->followed_player != NULL) {
2749  draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_SUCCESS, "You stop following %s.", op->contr->followed_player);
2750  FREE_AND_CLEAR_STR(op->contr->followed_player);
2751  }
2752  return;
2753  }
2754 
2756  if (!other) {
2757  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_FAILURE, "No such player or ambiguous name.");
2758  return;
2759  }
2760  if (other == op->contr) {
2761  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_FAILURE, "You can't follow yourself.");
2762  return;
2763  }
2764 
2765  // Players trying to 'follow' are subject to additional checks.
2766  if (!QUERY_FLAG(op, FLAG_WIZ)) {
2767  if (!can_follow(op, other)) {
2770  "You can only follow members in the same party.");
2771  return;
2772  }
2773  rv_vector rv;
2774  if (!get_rangevector(op, other->ob, &rv, 0) || rv.distance > 1) {
2775  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_FAILURE, "You need to go to them first!");
2776  return;
2777  }
2779  }
2780 
2781  if (op->contr->followed_player)
2782  FREE_AND_CLEAR_STR(op->contr->followed_player);
2783 
2784  op->contr->followed_player = add_string(other->ob->name);
2785  draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_SUCCESS, "Following %s.", op->contr->followed_player);
2786 }
2787 
2788 void command_purge_quest(object *op, const char * param) {
2789  (void)param;
2790  free_quest();
2791  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, "Purged quest state.");
2792 }
2793 
2794 void command_purge_quest_definitions(object *op, const char * param) {
2795  (void)param;
2797  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, "Purged quests definitions.");
2798 }
2799 
2800 static void do_dump(object *who, object *what) {
2801  StringBuffer *sb;
2802  char *diff;
2803 
2804  sb = stringbuffer_new();
2805  object_dump(what, sb);
2806  diff = stringbuffer_finish(sb);
2808  free(diff);
2809 
2810  /* Let's push that item on the dm's stack */
2811  dm_stack_push(who->contr, what->count);
2812 }
2813 
2822 void command_dumpbelow(object *op, const char *params) {
2823  (void)params;
2824  if (op && op->below) {
2825  do_dump(op, op->below);
2826  }
2827 }
2828 
2837 void command_dumpabove(object *op, const char *params) {
2838  (void)params;
2839  if (op && op->above) {
2840  do_dump(op, op->above);
2841  }
2842 }
2843 
2849 void command_settings(object *op, const char *ignored) {
2850  (void)ignored;
2851  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, "Server settings:");
2852 
2854 
2855  if (settings.not_permadeth) {
2856  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, " * death is not permanent");
2857  } else if (settings.resurrection) {
2858  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, " * permanent death, resurrection is enabled");
2859  } else {
2860  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, " * permanent death, resurrection is NOT enabled");
2861  }
2862 
2863  if (settings.set_title) {
2864  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, " * players can set their title");
2865  } else {
2866  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, " * players can't set their title");
2867  }
2868 
2871  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");
2872  } else {
2873  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");
2874  }
2875  } else {
2876  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, " * too much equipment can't lead to spell failure");
2877  }
2878 
2879  if (settings.casting_time) {
2880  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, " * casting takes time");
2881  } else {
2882  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, " * casting is immediate");
2883  }
2884 
2887 
2889 
2891  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, " * players can't steal from other players");
2892  } else {
2893  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, " * players can steal from other players");
2894  }
2895 
2897  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, " * players can create portals from their apartments");
2898  } else {
2899  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, " * players can't create portals from their apartments");
2900  }
2901 
2903  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, " * players can write spells they are denied");
2904  } else {
2905  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, " * players can't write spells they are denied");
2906  }
2907 }
Settings::casting_time
uint8_t casting_time
Definition: global.h:265
global.h
STACK_FROM_NONE
@ STACK_FROM_NONE
Definition: c_wiz.c:36
command_stack_clear
void command_stack_clear(object *op, const char *params)
Definition: c_wiz.c:2531
object_free
void object_free(object *ob, int flags)
Definition: object.c:1573
add_string
sstring add_string(const char *str)
Definition: shstr.c:124
command_invisible
void command_invisible(object *op, const char *params)
Definition: c_wiz.c:2160
spell_arrow.archetype
archetype
Definition: spell_arrow.py:11
object_remove
void object_remove(object *op)
Definition: object.c:1814
safe_strncpy
#define safe_strncpy
Definition: compat.h:27
FOR_MAP_FINISH
#define FOR_MAP_FINISH()
Definition: define.h:728
stringbuffer_new
StringBuffer * stringbuffer_new(void)
Definition: stringbuffer.c:57
object_set_enemy
void object_set_enemy(object *op, object *enemy)
Definition: object.c:902
MSG_TYPE_COMMAND_SUCCESS
#define MSG_TYPE_COMMAND_SUCCESS
Definition: newclient.h:530
command_stack_push
void command_stack_push(object *op, const char *params)
Definition: c_wiz.c:2482
llevError
@ llevError
Definition: logger.h:11
give_artifact_abilities
void give_artifact_abilities(object *op, const object *artifact)
Definition: artifact.c:194
MSG_TYPE_ADMIN_PLAYER
#define MSG_TYPE_ADMIN_PLAYER
Definition: newclient.h:496
SET_FLAG
#define SET_FLAG(xyz, p)
Definition: define.h:224
Settings::resurrection
uint8_t resurrection
Definition: global.h:261
object_update
void object_update(object *op, int action)
Definition: object.c:1415
diamondslots.x
x
Definition: diamondslots.py:15
QUERY_FLAG
#define QUERY_FLAG(xyz, p)
Definition: define.h:226
checkdm
static int checkdm(object *op, const char *pl_name, const char *pl_passwd, const char *pl_host)
Definition: c_wiz.c:2051
plugins_remove_plugin
int plugins_remove_plugin(const char *id)
Definition: plugins.c:457
plugins_init_plugin
int plugins_init_plugin(const char *libfile)
Definition: plugins.c:366
get_next_archetype
archetype * get_next_archetype(archetype *current)
Definition: assets.cpp:262
Settings::set_title
uint8_t set_title
Definition: global.h:260
do_learn_spell
void do_learn_spell(object *op, object *spell, int special_prayer)
Definition: apply.c:484
flush_old_maps
void flush_old_maps(void)
Definition: swap.c:247
out_of_map
int out_of_map(mapstruct *m, int x, int y)
Definition: map.c:2302
esrv_new_player
void esrv_new_player(player *pl, uint32_t weight)
Definition: request.c:942
liv::Str
int8_t Str
Definition: living.h:36
cmd_shutdown_time
int cmd_shutdown_time
Definition: c_wiz.c:43
FALSE
#define FALSE
Definition: compat.h:14
Settings::not_permadeth
uint8_t not_permadeth
Definition: global.h:257
banquet.size_x
int size_x
Definition: banquet.py:23
Settings::permanent_exp_ratio
uint8_t permanent_exp_ratio
Definition: global.h:253
object_new
object * object_new(void)
Definition: object.c:1236
esrv_send_inventory
void esrv_send_inventory(object *pl, object *op)
Definition: item.c:312
command_purge_quest_definitions
void command_purge_quest_definitions(object *op, const char *param)
Definition: c_wiz.c:2794
manor.params
params
Definition: manor.py:295
UPD_WEIGHT
#define UPD_WEIGHT
Definition: newclient.h:316
set_max_time
void set_max_time(long t)
Definition: time.c:203
pl::socket
socket_struct socket
Definition: player.h:94
pl
Definition: player.h:92
EXIT_PATH
#define EXIT_PATH(xyz)
Definition: define.h:439
FLAG_OBJ_ORIGINAL
#define FLAG_OBJ_ORIGINAL
Definition: define.h:357
get_ob_diff
void get_ob_diff(StringBuffer *sb, const object *op, const object *op2)
Definition: object.c:4960
Settings::worldmaptilesy
uint32_t worldmaptilesy
Definition: global.h:289
guildjoin.ob
ob
Definition: guildjoin.py:42
python_event.path
path
Definition: python_event.py:11
command_remove
void command_remove(object *op, const char *params)
Definition: c_wiz.c:1521
Settings::worldmapstartx
uint32_t worldmapstartx
Definition: global.h:286
find_object_both
static object * find_object_both(const char *params)
Definition: c_wiz.c:402
command_skills
void command_skills(object *op, const char *params)
Definition: c_wiz.c:1353
command_learn_spell_or_prayer
static void command_learn_spell_or_prayer(object *op, const char *params, int special_prayer)
Definition: c_wiz.c:2292
pl::ob
object * ob
Definition: player.h:162
FLAG_WIZCAST
#define FLAG_WIZCAST
Definition: define.h:289
path_combine_and_normalize
char * path_combine_and_normalize(const char *src, const char *dst, char *path, size_t size)
Definition: path.c:172
artifactliststruct::items
struct artifactstruct * items
Definition: artifact.h:30
Ice.tmp
int tmp
Definition: Ice.py:207
can_follow
bool can_follow(object *op, player *other)
Definition: c_wiz.c:2731
NDI_RED
#define NDI_RED
Definition: newclient.h:245
command_addexp
void command_addexp(object *op, const char *params)
Definition: c_wiz.c:1632
max_time
uint32_t max_time
Definition: time.c:35
get_other_player_from_name
static player * get_other_player_from_name(object *op, const char *name)
Definition: c_wiz.c:59
command_toggle_shout
void command_toggle_shout(object *op, const char *params)
Definition: c_wiz.c:635
UPD_NROF
#define UPD_NROF
Definition: newclient.h:321
plugins_display_list
void plugins_display_list(object *op)
Definition: plugins.c:506
get_rangevector
int get_rangevector(object *op1, const object *op2, rv_vector *retval, int flags)
Definition: map.c:2535
command_kick2
static void command_kick2(object *op, const char *params)
Definition: c_wiz.c:467
skills.h
npc_dialog.filename
filename
Definition: npc_dialog.py:99
MSG_TYPE_COMMAND_ERROR
#define MSG_TYPE_COMMAND_ERROR
Definition: newclient.h:529
create_treasure
void create_treasure(treasurelist *t, object *op, int flag, int difficulty, int tries)
Definition: treasure.c:242
set_variable
int set_variable(object *op, const char *buf)
Definition: loader.c:5269
command_forget_spell
void command_forget_spell(object *op, const char *params)
Definition: c_wiz.c:2350
hiscore_check
void hiscore_check(object *op, int quiet)
Definition: hiscore.c:348
command_listplugins
void command_listplugins(object *op, const char *params)
Definition: c_wiz.c:2378
command_dm
void command_dm(object *op, const char *params)
Definition: c_wiz.c:2148
banquet.size_y
int size_y
Definition: banquet.py:24
HUGE_BUF
#define HUGE_BUF
Definition: define.h:37
find_artifactlist
const artifactlist * find_artifactlist(int type)
Definition: artifact.c:647
do_dump
static void do_dump(object *who, object *what)
Definition: c_wiz.c:2800
MAX
#define MAX(x, y)
Definition: compat.h:24
MSG_TYPE_COMMAND
#define MSG_TYPE_COMMAND
Definition: newclient.h:404
command_teleport
void command_teleport(object *op, const char *params)
Definition: c_wiz.c:919
freearr_x
short freearr_x[SIZEOFFREE]
Definition: object.c:288
freearr_y
short freearr_y[SIZEOFFREE]
Definition: object.c:294
reset_sleep
void reset_sleep(void)
Definition: time.c:130
NDI_ORANGE
#define NDI_ORANGE
Definition: newclient.h:246
reputation_trigger_connect.check
def check()
Definition: reputation_trigger_connect.py:18
SAVE_MODE_OVERLAY
#define SAVE_MODE_OVERLAY
Definition: map.h:123
dm_stack_pop
static void dm_stack_pop(player *pl)
Definition: c_wiz.c:94
Settings::worldmaptilesx
uint32_t worldmaptilesx
Definition: global.h:288
settings
struct Settings settings
Definition: init.c:39
FLAG_ALIVE
#define FLAG_ALIVE
Definition: define.h:230
command_loadtest
void command_loadtest(object *op, const char *params)
Definition: c_wiz.c:305
Ns_Dead
@ Ns_Dead
Definition: newserver.h:67
calc_perm_exp
void calc_perm_exp(object *op)
Definition: living.c:1903
command_style_map_info
void command_style_map_info(object *op, const char *params)
Definition: c_wiz.c:2698
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
command_setgod
void command_setgod(object *op, const char *params)
Definition: c_wiz.c:417
Settings::spell_encumbrance
uint8_t spell_encumbrance
Definition: global.h:263
m
static event_registration m
Definition: citylife.cpp:410
autojail.who
who
Definition: autojail.py:3
MAP_IN_MEMORY
#define MAP_IN_MEMORY
Definition: map.h:131
item.q
q
Definition: item.py:32
pl::next
struct pl * next
Definition: player.h:93
FMT64
#define FMT64
Definition: compat.h:16
STACK_FROM_NUMBER
@ STACK_FROM_NUMBER
Definition: c_wiz.c:39
command_unloadplugin
void command_unloadplugin(object *op, const char *params)
Definition: c_wiz.c:2425
FLAG_WAS_WIZ
#define FLAG_WAS_WIZ
Definition: define.h:234
command_dumpbelow
void command_dumpbelow(object *op, const char *params)
Definition: c_wiz.c:2822
command_hide
void command_hide(object *op, const char *params)
Definition: c_wiz.c:388
command_patch
void command_patch(object *op, const char *params)
Definition: c_wiz.c:1481
pl::state
uint8_t state
Definition: player.h:118
is_identifiable_type
int is_identifiable_type(const object *op)
Definition: item.c:1301
Settings::death_penalty_ratio
uint8_t death_penalty_ratio
Definition: global.h:254
object_copy
void object_copy(const object *src_ob, object *dest_ob)
Definition: object.c:1047
query_name
void query_name(const object *op, char *buf, size_t size)
Definition: item.c:584
Settings::set_friendly_fire
uint16_t set_friendly_fire
Definition: global.h:270
command_overlay_save
void command_overlay_save(object *op, const char *params)
Definition: c_wiz.c:588
object_dump
void object_dump(const object *op, StringBuffer *sb)
Definition: object.c:638
MSG_TYPE_COMMAND_DM
#define MSG_TYPE_COMMAND_DM
Definition: newclient.h:535
command_kick
void command_kick(object *op, const char *params)
Definition: c_wiz.c:576
artifactstruct::next
struct artifactstruct * next
Definition: artifact.h:18
Settings::worldmapstarty
uint32_t worldmapstarty
Definition: global.h:287
liv::Cha
int8_t Cha
Definition: living.h:36
free_quest
void free_quest(void)
Definition: quest.c:1280
make_face_from_files.str
str
Definition: make_face_from_files.py:24
FLAG_FREED
#define FLAG_FREED
Definition: define.h:233
socket_struct::host
char * host
Definition: newserver.h:100
lookup_spell_by_name
object * lookup_spell_by_name(object *op, const char *spname)
Definition: spell_util.c:409
command_accountpasswd
void command_accountpasswd(object *op, const char *params)
Definition: c_wiz.c:1594
get_jail_exit
object * get_jail_exit(object *op)
Definition: region.c:260
first_player
EXTERN player * first_player
Definition: global.h:115
do_goto
void do_goto(object *op, const char *name, int x, int y)
Definition: c_move.c:151
command_help
void command_help(object *op, const char *params)
Definition: c_misc.c:1766
fix_object
void fix_object(object *op)
Definition: living.c:1126
command_follow
void command_follow(object *op, const char *params)
Definition: c_wiz.c:2744
show_skills
void show_skills(object *op, const char *search)
Definition: skill_util.c:851
object_create_arch
object * object_create_arch(archetype *at)
Definition: arch.cpp:301
styles
mapstruct * styles
Definition: style.c:122
stringbuffer_finish
char * stringbuffer_finish(StringBuffer *sb)
Definition: stringbuffer.c:76
FLAG_WIZPASS
#define FLAG_WIZPASS
Definition: define.h:314
Settings::item_power_factor
float item_power_factor
Definition: global.h:298
command_create
void command_create(object *op, const char *params)
Definition: c_wiz.c:985
MAX_NAME
#define MAX_NAME
Definition: define.h:41
command_stack_pop
void command_stack_pop(object *op, const char *params)
Definition: c_wiz.c:2469
command_possess
void command_possess(object *op, const char *params)
Definition: c_wiz.c:1420
DMFILE
#define DMFILE
Definition: config.h:361
FLAG_UNAGGRESSIVE
#define FLAG_UNAGGRESSIVE
Definition: define.h:272
object_give_identified_properties
void object_give_identified_properties(object *op)
Definition: item.c:1333
liv::Con
int8_t Con
Definition: living.h:36
command_settings
void command_settings(object *op, const char *ignored)
Definition: c_wiz.c:2849
command_nowiz
void command_nowiz(object *op, const char *params)
Definition: c_wiz.c:2014
Settings::confdir
const char * confdir
Definition: global.h:242
sproto.h
command_arrest
void command_arrest(object *op, const char *params)
Definition: c_wiz.c:827
MapSpace
Definition: map.h:257
set_magic
static void set_magic(int difficulty, object *op, int max_magic, int flags)
Definition: treasure.c:639
mapdef
Definition: map.h:324
command_loadplugin
void command_loadplugin(object *op, const char *params)
Definition: c_wiz.c:2393
MSG_SUBTYPE_NONE
#define MSG_SUBTYPE_NONE
Definition: newclient.h:420
become_follower
int become_follower(object *op, const object *new_god)
Definition: gods.c:477
liv::Int
int8_t Int
Definition: living.h:36
init_signals
void init_signals()
Definition: init.c:1332
Settings::death_penalty_level
uint8_t death_penalty_level
Definition: global.h:255
command_speed
void command_speed(object *op, const char *params)
Definition: c_wiz.c:1688
create_overlay_pathname
void create_overlay_pathname(const char *name, char *buf, size_t size)
Definition: map.c:134
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.c:202
MAP_WIDTH
#define MAP_WIDTH(m)
Definition: map.h:78
strlcpy
size_t strlcpy(char *dst, const char *src, size_t size)
Definition: porting.c:220
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
clear_los
void clear_los(player *pl)
Definition: los.c:252
monster_check_apply_all
void monster_check_apply_all(object *monster)
Definition: monster.c:1827
StringBuffer
Definition: stringbuffer.c:25
FREE_AND_CLEAR_STR
#define FREE_AND_CLEAR_STR(xyz)
Definition: global.h:196
free_quest_definitions
void free_quest_definitions(void)
Definition: quest.c:1298
save_map
int save_map(mapstruct *m, int flag)
Definition: map.c:1416
Settings::spell_failure_effects
uint8_t spell_failure_effects
Definition: global.h:264
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:721
ST_PLAYING
#define ST_PLAYING
Definition: define.h:541
command_insert_into
void command_insert_into(object *op, const char *params)
Definition: c_wiz.c:2621
FLAG_REMOVED
#define FLAG_REMOVED
Definition: define.h:232
Settings::allow_denied_spells_writing
int allow_denied_spells_writing
Definition: global.h:310
player_lvl_adj
void player_lvl_adj(object *who, object *op)
Definition: living.c:1819
FLAG_WIZ
#define FLAG_WIZ
Definition: define.h:231
swap_map
int swap_map(mapstruct *map)
Definition: swap.c:135
llevInfo
@ llevInfo
Definition: logger.h:12
command_stats
void command_stats(object *op, const char *params)
Definition: c_wiz.c:1718
command_inventory
void command_inventory(object *op, const char *params)
Definition: c_wiz.c:1323
NDI_UNIQUE
#define NDI_UNIQUE
Definition: newclient.h:262
EVENT_MUZZLE
#define EVENT_MUZZLE
Definition: events.h:50
command_freeze
void command_freeze(object *op, const char *params)
Definition: c_wiz.c:751
object_find_by_tag_global
object * object_find_by_tag_global(tag_t i)
Definition: object.c:714
find_archetype_by_object_name
archetype * find_archetype_by_object_name(const char *name)
Definition: arch.cpp:55
command_diff
void command_diff(object *op, const char *params)
Definition: c_wiz.c:2557
FLAG_FRIENDLY
#define FLAG_FRIENDLY
Definition: define.h:246
spells.h
command_goto
void command_goto(object *op, const char *params)
Definition: c_wiz.c:730
STACK_FROM_TOP
@ STACK_FROM_TOP
Definition: c_wiz.c:37
BANISHFILE
#define BANISHFILE
Definition: config.h:512
command_reset
void command_reset(object *op, const char *params)
Definition: c_wiz.c:1841
liv::Dex
int8_t Dex
Definition: living.h:36
check_exp_adjust
int64_t check_exp_adjust(const object *op, int64_t exp)
Definition: living.c:2091
item
Definition: item.py:1
reputation.victim
victim
Definition: reputation.py:14
LOG
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.c:51
enter_exit
void enter_exit(object *op, object *exit_ob)
Definition: server.c:721
command_mon_aggr
void command_mon_aggr(object *op, const char *params)
Definition: c_wiz.c:1393
check_spell_known
object * check_spell_known(object *op, const char *name)
Definition: spell_util.c:393
liv::Wis
int8_t Wis
Definition: living.h:36
give.op
op
Definition: give.py:33
object_find_free_spot
int object_find_free_spot(const object *ob, mapstruct *m, int x, int y, int start, int stop)
Definition: object.c:3517
NDI_ALL
#define NDI_ALL
Definition: newclient.h:263
socket_struct::status
enum Sock_Status status
Definition: newserver.h:90
esrv_update_item
void esrv_update_item(int flags, object *pl, object *op)
Definition: main.c:360
do_wizard_hide
static void do_wizard_hide(object *op, int silent_dm)
Definition: c_wiz.c:351
Settings::max_stat
uint8_t max_stat
Definition: global.h:319
rv_vector
Definition: map.h:379
MAP_SWAPPED
#define MAP_SWAPPED
Definition: map.h:132
EXIT_Y
#define EXIT_Y(xyz)
Definition: define.h:442
pl::stack_position
int stack_position
Definition: player.h:204
guild_entry.found
int found
Definition: guild_entry.py:46
diamondslots.y
y
Definition: diamondslots.py:16
python_pickup.where
where
Definition: python_pickup.py:7
CLEAR_FLAG
#define CLEAR_FLAG(xyz, p)
Definition: define.h:225
command_learn_spell
void command_learn_spell(object *op, const char *params)
Definition: c_wiz.c:2325
buf
StringBuffer * buf
Definition: readable.c:1606
MAP_HEIGHT
#define MAP_HEIGHT(m)
Definition: map.h:80
object_insert_in_ob
object * object_insert_in_ob(object *op, object *where)
Definition: object.c:2828
NDI_DK_ORANGE
#define NDI_DK_ORANGE
Definition: newclient.h:248
find_player_partial_name
player * find_player_partial_name(const char *plname)
Definition: player.c:111
account_change_password
int account_change_password(const char *account_name, const char *current_password, const char *new_password)
Definition: account.c:685
object_update_speed
void object_update_speed(object *op)
Definition: object.c:1311
object_find_by_name_global
object * object_find_by_name_global(const char *str)
Definition: object.c:734
arch_to_object
object * arch_to_object(archetype *at)
Definition: arch.cpp:232
map_size
uint32_t map_size(mapstruct *m)
Definition: map.c:823
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
get_dm_object
static object * get_dm_object(player *pl, const char **params, int *from)
Definition: c_wiz.c:195
save_player
int save_player(object *op, int flag)
Definition: login.c:230
command_shutdown
void command_shutdown(object *op, const char *params)
Definition: c_wiz.c:678
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.c:2075
Settings::real_wiz
uint8_t real_wiz
Definition: global.h:266
dm_stack_push
static void dm_stack_push(player *pl, tag_t item)
Definition: c_wiz.c:149
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.c:309
object_free_drop_inventory
void object_free_drop_inventory(object *ob)
Definition: object.c:1541
MSG_TYPE_COMMUNICATION_PARTY
#define MSG_TYPE_COMMUNICATION_PARTY
Definition: newclient.h:627
try_find_archetype
archetype * try_find_archetype(const char *name)
Definition: assets.cpp:270
dm_stack_peek
static object * dm_stack_peek(player *pl)
Definition: c_wiz.c:119
castle_read.playercount
int playercount
Definition: castle_read.py:62
inventory
void inventory(object *op, object *inv)
Definition: c_object.c:2016
do_wizard_dm
static int do_wizard_dm(object *op, const char *params, int silent)
Definition: c_wiz.c:2099
do_forget_spell
void do_forget_spell(object *op, const char *spell)
Definition: apply.c:525
do_some_living
void do_some_living(object *op)
Definition: player.c:3236
command_free
void command_free(object *op, const char *params)
Definition: c_wiz.c:1568
set_abs_magic
void set_abs_magic(object *op, int magic)
Definition: treasure.c:591
command_banish
void command_banish(object *op, const char *params)
Definition: c_wiz.c:522
Settings::no_player_stealing
uint8_t no_player_stealing
Definition: global.h:305
say.item
dictionary item
Definition: say.py:149
command_learn_special_prayer
void command_learn_special_prayer(object *op, const char *params)
Definition: c_wiz.c:2337
command_dumpabove
void command_dumpabove(object *op, const char *params)
Definition: c_wiz.c:2837
MSG_TYPE_COMMUNICATION
#define MSG_TYPE_COMMUNICATION
Definition: newclient.h:410
command_dump
void command_dump(object *op, const char *params)
Definition: c_wiz.c:1365
pl::stack_items
tag_t * stack_items
Definition: player.h:202
command_overlay_reset
void command_overlay_reset(object *op, const char *params)
Definition: c_wiz.c:609
MAP_TIMEOUT
#define MAP_TIMEOUT(m)
Definition: map.h:66
TRUE
#define TRUE
Definition: compat.h:11
find_god
const object * find_god(const char *name)
Definition: gods.c:80
legal_artifact_combination
int legal_artifact_combination(const object *op, const artifact *art)
Definition: artifact.c:216
command_stack_list
void command_stack_list(object *op, const char *params)
Definition: c_wiz.c:2500
Settings::create_home_portals
uint8_t create_home_portals
Definition: global.h:306
unhide
static void unhide(object *op)
Definition: c_wiz.c:332
command_abil
void command_abil(object *op, const char *params)
Definition: c_wiz.c:1775
altar_valkyrie.pl
pl
Definition: altar_valkyrie.py:28
STACK_SIZE
#define STACK_SIZE
Definition: c_wiz.c:33
get_spell_by_name
static object * get_spell_by_name(object *op, const char *spell_name)
Definition: c_wiz.c:2187
command_dmhide
void command_dmhide(object *op, const char *params)
Definition: c_wiz.c:2454
mapdef::next
struct mapdef * next
Definition: map.h:325
MSG_TYPE_ADMIN
#define MSG_TYPE_ADMIN
Definition: newclient.h:402
rv_vector::distance
unsigned int distance
Definition: map.h:380
STACK_FROM_STACK
@ STACK_FROM_STACK
Definition: c_wiz.c:38
command_purge_quest
void command_purge_quest(object *op, const char *param)
Definition: c_wiz.c:2788
EVENT_KICK
#define EVENT_KICK
Definition: events.h:42
SAVE_ERROR_PLAYER
#define SAVE_ERROR_PLAYER
Definition: map.h:153
altar_valkyrie.res
int res
Definition: altar_valkyrie.py:74
liv::Pow
int8_t Pow
Definition: living.h:36
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,...)
Definition: main.c:319
NDI_LT_GREEN
#define NDI_LT_GREEN
Definition: newclient.h:250
update_los
void update_los(object *op)
Definition: los.c:459
events_execute_global_event
void events_execute_global_event(int eventcode,...)
Definition: events.cpp:27
llevDebug
@ llevDebug
Definition: logger.h:13
player_arrest
int player_arrest(object *who)
Definition: c_wiz.c:795
pl::orig_stats
living orig_stats
Definition: player.h:152
command_summon
void command_summon(object *op, const char *params)
Definition: c_wiz.c:872
FLAG_IDENTIFIED
#define FLAG_IDENTIFIED
Definition: define.h:261
give.name
name
Definition: give.py:27
has_been_loaded
mapstruct * has_been_loaded(const char *name)
Definition: map.c:88
map_remove_unique_files
void map_remove_unique_files(const mapstruct *map)
Definition: map.c:2687
Settings::localdir
const char * localdir
Definition: global.h:244