Crossfire Server, Trunk  R21017
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 
161  pl->stack_items[pl->stack_position] = item;
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  do_wizard_hide(op, 0);
390 }
391 
401 static object *find_object_both(const char *params) {
402  if (params[0] == '#')
403  return object_find_by_tag_global(atol(params+1));
404  else
405  return object_find_by_name_global(params);
406 }
407 
416 void command_setgod(object *op, const char *params) {
417  object *ob;
418  const object *god;
419  char *str;
420 
421  if (*params == '\0' || !(str = strchr(params, ' '))) {
423  "Usage: set_god player god");
424  return;
425  }
426 
427  /* kill the space, and set string to the next param */
428  *str++ = '\0';
429  if (!(ob = find_object_both(params))) {
431  "Set whose god - can not find object %s?",
432  params);
433  return;
434  }
435 
436  /*
437  * Perhaps this is overly restrictive? Should we perhaps be able
438  * to rebless altars and the like?
439  */
440  if (ob->type != PLAYER) {
442  "%s is not a player - can not change its god",
443  ob->name);
444  return;
445  }
446 
447  god = find_god(str);
448  if (god == NULL) {
450  "No such god %s.",
451  str);
452  return;
453  }
454 
455  become_follower(ob, god);
456 }
457 
466 static void command_kick2(object *op, const char *params) {
467  struct pl *pl;
468 
469  for (pl = first_player; pl != NULL; pl = pl->next) {
470  if ((*params == '\0' || !strcmp(pl->ob->name, params)) && pl->ob != op) {
471  object *op;
472  int removed = 0;
473 
474  op = pl->ob;
475  if (!QUERY_FLAG(op, FLAG_REMOVED)) {
476  /* Avion : Here we handle the KICK global event */
477  execute_global_event(EVENT_KICK, op, *params == '\0' ? NULL : params);
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 
534  pl = get_other_player_from_name(op, params);
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) {
577  command_kick2(op, params);
578 }
579 
588 void command_overlay_save(object *op, const char *params) {
589  if (!op)
590  return;
591 
592  if (save_map(op->map, SAVE_MODE_OVERLAY) < 0)
594  "Overlay save error!");
595  else
597  "Current map has been saved as an overlay.");
598 }
599 
608 void command_overlay_reset(object *op, const char *params) {
609  char filename[MAX_BUF];
610  struct stat stats;
611 
612  create_overlay_pathname(op->map->path, filename, MAX_BUF);
613  if (!stat(filename, &stats))
614  if (!unlink(filename))
616  "Overlay successfully removed.");
617  else
619  "Overlay couldn't be removed.");
620  else
622  "No overlay for current map.");
623 }
624 
633 void command_toggle_shout(object *op, const char *params) {
634  player *pl;
635 
636  if (*params == '\0') {
638  "Usage: toggle_shout <player>.");
639  return;
640  }
641 
642  pl = get_other_player_from_name(op, params);
643  if (!pl)
644  return;
645 
646  if (pl->ob->contr->no_shout == 0) {
647  pl->ob->contr->no_shout = 1;
648 
650  "You have been muzzled by the DM!");
652  "You muzzle %s.",
653  pl->ob->name);
654 
655  /* Avion : Here we handle the MUZZLE global event */
656  execute_global_event(EVENT_MUZZLE, pl->ob, params);
657 
658  return;
659  }
660 
661  pl->ob->contr->no_shout = 0;
663  "You are allowed to shout and chat again.");
665  "You remove %s's muzzle.",
666  pl->ob->name);
667 }
668 
677 void command_shutdown(object *op, const char *params) {
678  if (strlen(params) == 0) {
679  /* Give DM command help and display current shutdown status. */
680  command_help(op, "shutdown");
681 
682  if (cmd_shutdown_time != 0) {
684  MSG_TYPE_COMMAND_DM, "Server is shutting down soon.");
685  }
686  } else if (strcmp(params, "cancel") == 0) {
687  /* Tell everyone that the server is no longer shutting down. */
688  if (cmd_shutdown_time != 0) {
690  MSG_TYPE_ADMIN_DM, "Server shutdown cancelled.");
691  cmd_shutdown_time = 0;
692  LOG(llevInfo, "Server shutdown cancelled by %s.\n", op->name);
693  } else {
695  MSG_TYPE_COMMAND_ERROR, "No shutdown is pending.");
696  }
697  } else if (strncmp(params, "now", 3) == 0) {
698  /* Announce and shut down immediately. */
700  MSG_TYPE_ADMIN_DM, "Server is shutting down now!");
701  cmd_shutdown_time = time(NULL);
702  LOG(llevInfo, "Server shutdown initiated by %s.\n", op->name);
703  } else {
704  /* Schedule (but don't announce) a shutdown. */
705  int minutes = atoi(params);
706 
707  if (minutes > 0 && minutes <= 720) {
710  "Server will shut down in %d minutes.", minutes);
711  cmd_shutdown_time = time(NULL) + minutes * 60;
712  LOG(llevInfo, "Server shutdown initiated by %s in %d minutes.\n", op->name, minutes);
713  } else {
716  "Please specify a reasonable time in minutes.");
717  }
718  }
719 }
720 
729 void command_goto(object *op, const char *params) {
730  if (!op)
731  return ;
732 
733  if (*params == '\0') {
735  "Go to what level?");
736  return;
737  }
738 
739  do_goto(op, params, -1, -1);
741  "Difficulty: %d.",
742  op->map->difficulty);
743 }
744 
753 void command_freeze(object *op, const char *params) {
754  int ticks;
755  player *pl;
756 
757  if (*params == '\0') {
759  "Usage: freeze [ticks] <player>.");
760  return;
761  }
762 
763  ticks = atoi(params);
764  if (ticks) {
765  while ((isdigit(*params) || isspace(*params)) && *params != 0)
766  params++;
767  if (*params == 0) {
769  "Usage: freeze [ticks] <player>.");
770  return;
771  }
772  } else
773  ticks = 100;
774 
775  pl = get_other_player_from_name(op, params);
776  if (!pl)
777  return;
778 
780  "You have been frozen by the DM!");
781 
783  "You freeze %s for %d ticks",
784  pl->ob->name, ticks);
785 
786  pl->ob->speed_left = -(pl->ob->speed*ticks);
787 }
788 
797 int player_arrest(object *who) {
798  object *dummy;
799  mapstruct *cur;
800  int x, y;
801 
802  if (who->type != PLAYER)
803  return -3;
804 
805  dummy = get_jail_exit(who);
806  if (!dummy) {
807  return -1;
808  }
809  cur = who->map;
810  x = who->x;
811  y = who->y;
812  enter_exit(who, dummy);
814 
815  if (cur == who->map && x == who->x && y == who->y)
816  return -2;
817 
818  return 0;
819 }
820 
829 void command_arrest(object *op, const char *params) {
830  player *pl;
831  int ret;
832 
833  if (!op)
834  return;
835  if (*params == '\0') {
837  "Usage: arrest <player>.");
838  return;
839  }
840  pl = get_other_player_from_name(op, params);
841  if (!pl)
842  return;
843 
844  ret = player_arrest(pl->ob);
845  if (ret == -1) {
846  /* we have nowhere to send the prisoner....*/
848  "Can't jail player, there is no map to hold them");
849  return;
850  }
851  if (ret == -2) {
852  /* something prevented jailing the player */
854  "Can't jail player, map loading issue or already in jail's position");
855  return;
856 
857  }
858 
860  "You have been arrested.");
862  "Jailed %s",
863  pl->ob->name);
864  LOG(llevInfo, "Player %s arrested by %s\n", pl->ob->name, op->name);
865 }
866 
874 void command_summon(object *op, const char *params) {
875  int i;
876  object *dummy;
877  player *pl;
878 
879  if (!op)
880  return;
881 
882  if (*params == '\0') {
884  "Usage: summon <player>.");
885  return;
886  }
887 
888  pl = get_other_player_from_name(op, params);
889  if (!pl)
890  return;
891 
892  i = object_find_free_spot(op, op->map, op->x, op->y, 1, 9);
893  if (i == -1) {
895  "Can not find a free spot to place summoned player.");
896  return;
897  }
898 
899  dummy = object_new();
900  EXIT_PATH(dummy) = add_string(op->map->path);
901  EXIT_X(dummy) = op->x+freearr_x[i];
902  EXIT_Y(dummy) = op->y+freearr_y[i];
903  enter_exit(pl->ob, dummy);
906  "You are summoned.");
908  "You summon %s",
909  pl->ob->name);
910 }
911 
920 /* mids 01/16/2002 */
921 void command_teleport(object *op, const char *params) {
922  int i;
923  object *dummy;
924  player *pl;
925 
926  if (!op)
927  return;
928 
929  if (*params == '\0') {
931  "Usage: teleport <player>.");
932  return;
933  }
934 
935  pl = find_player_partial_name(params);
936  if (!pl) {
938  "No such player or ambiguous name.");
939  return;
940  }
941 
942  i = object_find_free_spot(pl->ob, pl->ob->map, pl->ob->x, pl->ob->y, 1, 9);
943  if (i == -1) {
945  "Can not find a free spot to teleport to.");
946  return;
947  }
948 
949  dummy = object_new();
950  EXIT_PATH(dummy) = add_string(pl->ob->map->path);
951  EXIT_X(dummy) = pl->ob->x+freearr_x[i];
952  EXIT_Y(dummy) = pl->ob->y+freearr_y[i];
953  enter_exit(op, dummy);
955  if (!op->contr->hidden)
957  "You see a portal open.");
959  "You teleport to %s",
960  pl->ob->name);
961 }
962 
987 void command_create(object *op, const char *params) {
988  object *tmp = NULL;
989  uint32_t i;
990  int magic, set_magic = 0, set_nrof = 0, gotquote, gotspace;
991  uint32_t nrof;
992  char *cp, *bp, *bp2, *bp3, *endline, cpy[MAX_BUF];
993  archetype *at, *at_spell = NULL;
994  const artifact *art = NULL;
995 
996  if (!op)
997  return;
998 
999  if (*params == '\0') {
1001  "Usage: create [nr] [magic] <archetype> [ of <artifact>] [variable_to_patch setting]");
1002  return;
1003  }
1004  safe_strncpy(cpy, params, sizeof(cpy));
1005  bp = cpy;
1006 
1007  /* We need to know where the line ends */
1008  endline = bp+strlen(bp);
1009 
1010  if (sscanf(bp, "%u ", &nrof)) {
1011  if ((bp = strchr(cpy, ' ')) == NULL) {
1013  "Usage: create [nr] [magic] <archetype> [ of <artifact>] [variable_to_patch setting]");
1014  return;
1015  }
1016  bp++;
1017  set_nrof = 1;
1018  LOG(llevDebug, "%s creates: (%u) %s\n", op->name, nrof, bp);
1019  }
1020  if (sscanf(bp, "%d ", &magic)) {
1021  if ((bp = strchr(bp, ' ')) == NULL) {
1023  "Usage: create [nr] [magic] <archetype> [ of <artifact>] [variable_to_patch setting]");
1024  return;
1025  }
1026  bp++;
1027  set_magic = 1;
1028  LOG(llevDebug, "%s creates: (%d) (%d) %s\n", op->name, nrof, magic, bp);
1029  }
1030  if ((cp = strstr(bp, " of ")) != NULL) {
1031  *cp = '\0';
1032  cp += 4;
1033  }
1034  for (bp2 = bp; *bp2; bp2++) {
1035  if (*bp2 == ' ') {
1036  *bp2 = '\0';
1037  bp2++;
1038  break;
1039  }
1040  }
1041 
1042  if ((at = try_find_archetype(bp)) == NULL) {
1044  "No such archetype.");
1045  return;
1046  }
1047 
1048  if (cp) {
1049  char spell_name[MAX_BUF], *fsp = NULL;
1050 
1051  /*
1052  * Try to find a spell object for this. Note that
1053  * we also set up spell_name which is only
1054  * the first word.
1055  */
1056 
1057  at_spell = try_find_archetype(cp);
1058  if (!at_spell || at_spell->clone.type != SPELL)
1059  at_spell = find_archetype_by_object_name(cp);
1060  if (!at_spell || at_spell->clone.type != SPELL) {
1061  safe_strncpy(spell_name, cp, sizeof(spell_name));
1062  fsp = strchr(spell_name, ' ');
1063  if (fsp) {
1064  *fsp = 0;
1065  fsp++;
1066  at_spell = try_find_archetype(spell_name);
1067 
1068  /* Got a spell, update the first string pointer */
1069  if (at_spell && at_spell->clone.type == SPELL)
1070  bp2 = cp+strlen(spell_name)+1;
1071  else
1072  at_spell = NULL;
1073  } else
1074  at_spell = NULL;
1075  }
1076 
1077  /* OK - we didn't find a spell - presume the 'of'
1078  * in this case means its an artifact.
1079  */
1080  if (!at_spell) {
1081  if (find_artifactlist(at->clone.type) == NULL) {
1083  "No artifact list for type %d\n",
1084  at->clone.type);
1085  } else {
1086  art = find_artifactlist(at->clone.type)->items;
1087 
1088  do {
1089  if (!strcmp(art->item->name, cp) && legal_artifact_combination(&at->clone, art))
1090  break;
1091  art = art->next;
1092  } while (art != NULL);
1093  if (!art) {
1095  "No such artifact ([%d] of %s)",
1096  at->clone.type, cp);
1097  }
1098  }
1099  LOG(llevDebug, "%s creates: (%d) (%d) (%s) of (%s)\n", op->name, set_nrof ? nrof : 0, set_magic ? magic : 0, bp, cp);
1100  }
1101  } /* if cp */
1102 
1103  /* rods and potions can get their spell from the artifact */
1104  if ((at->clone.type == ROD || at->clone.type == POTION) && !at_spell && (!art || !art->item->other_arch)) {
1106  "Unable to find spell %s for object that needs it, or it is of wrong type",
1107  cp);
1108  return;
1109  }
1110  if ((at->clone.type == WAND || at->clone.type == SCROLL || at->clone.type == SPELLBOOK)
1111  && !at_spell) {
1113  "Unable to find spell %s for object that needs it, or it is of wrong type",
1114  cp);
1115  return;
1116  }
1117 
1118  /*
1119  * Rather than have two different blocks with a lot of similar code,
1120  * just create one object, do all the processing, and then determine
1121  * if that one object should be inserted or if we need to make copies.
1122  */
1123  tmp = object_create_arch(at);
1124  if (settings.real_wiz == FALSE)
1125  SET_FLAG(tmp, FLAG_WAS_WIZ);
1126  if (set_magic)
1127  set_abs_magic(tmp, magic);
1128  if (art)
1129  give_artifact_abilities(tmp, art->item);
1130  if (need_identify(tmp)) {
1131  SET_FLAG(tmp, FLAG_IDENTIFIED);
1134  }
1135 
1136  /*
1137  * This entire block here tries to find variable pairings,
1138  * eg, 'hp 4' or the like. The mess here is that values
1139  * can be quoted (eg "my cool sword"); So the basic logic
1140  * is we want to find two spaces, but if we got a quote,
1141  * any spaces there don't count.
1142  */
1143  while (*bp2 && bp2 <= endline) {
1144  gotspace = 0;
1145  gotquote = 0;
1146  /* find the first quote */
1147  for (bp3 = bp2; *bp3 && gotspace < 2 && gotquote < 2; bp3++) {
1148  /* Found a quote - now lets find the second one */
1149  if (*bp3 == '"') {
1150  *bp3 = ' ';
1151  bp2 = bp3+1; /* Update start of string */
1152  bp3++;
1153  gotquote++;
1154  while (*bp3) {
1155  if (*bp3 == '"') {
1156  *bp3 = '\0';
1157  gotquote++;
1158  } else
1159  bp3++;
1160  }
1161  } else if (*bp3 == ' ') {
1162  gotspace++;
1163  }
1164  }
1165 
1166  /*
1167  * If we got two spaces, send the second one to null.
1168  * if we've reached the end of the line, increase gotspace -
1169  * this is perfectly valid for the list entry listed.
1170  */
1171  if (gotspace == 2 || gotquote == 2) {
1172  bp3--; /* Undo the extra increment */
1173  *bp3 = '\0';
1174  } else if (*bp3 == '\0')
1175  gotspace++;
1176 
1177  if ((gotquote && gotquote != 2)
1178  || (gotspace != 2 && gotquote != 2)) {
1179  /*
1180  * Unfortunately, we've clobbered lots of values, so printing
1181  * out what we have probably isn't useful. Break out, because
1182  * trying to recover is probably won't get anything useful
1183  * anyways, and we'd be confused about end of line pointers
1184  * anyways.
1185  */
1187  "Malformed create line: %s",
1188  bp2);
1189  break;
1190  }
1191  /* bp2 should still point to the start of this line,
1192  * with bp3 pointing to the end
1193  */
1194  if (set_variable(tmp, bp2) == -1)
1196  "Unknown variable %s",
1197  bp2);
1198  else
1200  "(%s#%d)->%s",
1201  tmp->name, tmp->count, bp2);
1202  bp2 = bp3+1;
1203  }
1204 
1205  if (at->clone.nrof) {
1206  if (at_spell)
1207  object_insert_in_ob(arch_to_object(at_spell), tmp);
1208 
1209  if (set_nrof)
1210  tmp->nrof = nrof;
1211 
1212  if (at->clone.randomitems != NULL && !at_spell) {
1213  create_treasure(at->clone.randomitems, tmp, 0, op->map->difficulty, 0);
1214  if (QUERY_FLAG(tmp, FLAG_MONSTER)) {
1216  }
1217  }
1218 
1219  /* Multipart objects can't be in inventory, put'em on floor. */
1220  if (!tmp->more) {
1221  tmp = object_insert_in_ob(tmp, op);
1222  } else {
1223  object_insert_in_map_at(tmp, op->map, op, 0, op->x, op->y);
1224  }
1225 
1226  /* Let's put this created item on stack so dm can access it easily. */
1227  dm_stack_push(op->contr, tmp->count);
1228 
1229  return;
1230  }
1231 
1232  for (i = 0; i < (set_nrof ? nrof : 1); i++) {
1233  archetype *atmp;
1234  object *prev = NULL, *head = NULL, *dup;
1235 
1236  for (atmp = at; atmp != NULL; atmp = atmp->more) {
1237  dup = arch_to_object(atmp);
1238 
1239  if (at_spell)
1240  object_insert_in_ob(arch_to_object(at_spell), dup);
1241 
1242  /*
1243  * The head is what contains all the important bits,
1244  * so just copying it over should be fine.
1245  */
1246  if (head == NULL) {
1247  head = dup;
1248  object_copy(tmp, dup);
1249  }
1250  if (settings.real_wiz == FALSE)
1251  SET_FLAG(dup, FLAG_WAS_WIZ);
1252  dup->x = op->x+dup->arch->clone.x;
1253  dup->y = op->y+dup->arch->clone.y;
1254  dup->map = op->map;
1255 
1256  if (head != dup) {
1257  dup->head = head;
1258  prev->more = dup;
1259  }
1260  prev = dup;
1261  }
1262 
1263  if (QUERY_FLAG(head, FLAG_ALIVE)) {
1264  object *check = head;
1265  int size_x = 0;
1266  int size_y = 0;
1267 
1268  while (check) {
1269  size_x = MAX(size_x, check->arch->clone.x);
1270  size_y = MAX(size_y, check->arch->clone.y);
1271  check = check->more;
1272  }
1273 
1274  if (out_of_map(op->map, head->x+size_x, head->y+size_y)) {
1275  if (head->x < size_x || head->y < size_y) {
1276  dm_stack_pop(op->contr);
1279  "Object too big to insert in map, or wrong position.");
1281  return;
1282  }
1283 
1284  check = head;
1285  while (check) {
1286  check->x -= size_x;
1287  check->y -= size_y;
1288  check = check->more;
1289  }
1290  }
1291 
1292  object_insert_in_map_at(head, op->map, op, 0, head->x, head->y);
1293  } else
1294  head = object_insert_in_ob(head, op);
1295 
1296  /* Let's put this created item on stack so dm can access it easily. */
1297  /* Wonder if we really want to push all of these, but since
1298  * things like rods have nrof 0, we want to cover those.
1299  */
1300  dm_stack_push(op->contr, head->count);
1301 
1302  if (at->clone.randomitems != NULL && !at_spell) {
1303  create_treasure(at->clone.randomitems, head, 0, op->map->difficulty, 0);
1304  if (QUERY_FLAG(head, FLAG_MONSTER)) {
1306  }
1307  }
1308  }
1309 
1310  /* free the one we used to copy */
1312 }
1313 
1314 /*
1315  * Now follows dm-commands which are also acceptable from sockets
1316  */
1317 
1326 void command_inventory(object *op, const char *params) {
1327  object *tmp;
1328  int i;
1329 
1330  if (*params == '\0') {
1331  inventory(op, NULL);
1332  return;
1333  }
1334 
1335  if (!sscanf(params, "%d", &i) || (tmp = object_find_by_tag_global(i)) == NULL) {
1337  "Inventory of what object (nr)?");
1338  return;
1339  }
1340 
1341  inventory(op, tmp);
1342 }
1343 
1356 void command_skills(object *op, const char *params) {
1357  show_skills(op, *params == '\0' ? NULL : params);
1358 }
1359 
1368 void command_dump(object *op, const char *params) {
1369  object *tmp;
1370  StringBuffer *sb;
1371  char *diff;
1372 
1373  tmp = get_dm_object(op->contr, &params, NULL);
1374  if (!tmp)
1375  return;
1376 
1377  sb = stringbuffer_new();
1378  object_dump(tmp, sb);
1379  diff = stringbuffer_finish(sb);
1381  free(diff);
1382  if (QUERY_FLAG(tmp, FLAG_OBJ_ORIGINAL))
1384  "Object is marked original");
1385 }
1386 
1396 void command_mon_aggr(object *op, const char *params) {
1397  if (op->enemy || !QUERY_FLAG(op, FLAG_UNAGGRESSIVE)) {
1398  object_set_enemy(op, NULL);
1401  "Aggression turned OFF");
1402  } else {
1406  "Aggression turned ON");
1407  }
1408 }
1409 
1422 void command_possess(object *op, const char *params) {
1423  object *victim;
1424  player *pl;
1425  int i;
1426  char buf[MAX_BUF];
1427 
1428  victim = NULL;
1429  if (*params != '\0') {
1430  if (sscanf(params, "%d", &i))
1431  victim = object_find_by_tag_global(i);
1432  else if (sscanf(params, "%s", buf))
1433  victim = object_find_by_name_global(buf);
1434  }
1435  if (victim == NULL) {
1437  "Patch what object (nr)?");
1438  return;
1439  }
1440 
1441  if (victim == op) {
1443  "As insane as you are, I cannot allow you to possess yourself.");
1444  return;
1445  }
1446 
1447  /* make the switch */
1448  pl = op->contr;
1449  victim->contr = pl;
1450  pl->ob = victim;
1451  victim->type = PLAYER;
1452  SET_FLAG(victim, FLAG_WIZ);
1453 
1454  /* basic patchup */
1455  /* The use of hard coded values is terrible. Note
1456  * that really, to be fair, this shouldn't get changed at
1457  * all - if you are possessing a kobold, you should have the
1458  * same limitations. As it is, as more body locations are added,
1459  * this will give this player more locations than perhaps
1460  * they should be allowed.
1461  */
1462  for (i = 0; i < NUM_BODY_LOCATIONS; i++)
1463  if (i == 1 || i == 6 || i == 8 || i == 9)
1464  victim->body_info[i] = 2;
1465  else
1466  victim->body_info[i] = 1;
1467 
1468  esrv_new_player(pl, 80); /* just pick a weight, we don't care */
1469  esrv_send_inventory(victim, victim);
1470 
1471  fix_object(victim);
1472 
1473  do_some_living(victim);
1474 }
1475 
1483 void command_patch(object *op, const char *params) {
1484  const char *arg, *arg2;
1485  object *tmp;
1486 
1487  tmp = get_dm_object(op->contr, &params, NULL);
1488  if (!tmp)
1489  /* Player already informed of failure */
1490  return;
1491 
1492  /* params set to first value by get_dm_default */
1493  arg = params;
1494  if (*arg == '\0') {
1496  "Patch what values?");
1497  return;
1498  }
1499 
1500  if ((arg2 = strchr(arg, ' ')))
1501  arg2++;
1502  if (settings.real_wiz == FALSE)
1503  SET_FLAG(tmp, FLAG_WAS_WIZ); /* To avoid cheating */
1504  if (set_variable(tmp, arg) == -1)
1506  "Unknown variable %s",
1507  arg);
1508  else {
1510  "(%s#%d)->%s=%s",
1511  tmp->name, tmp->count, arg, arg2);
1512  }
1513 }
1514 
1523 void command_remove(object *op, const char *params) {
1524  object *tmp;
1525  int from;
1526 
1527  tmp = get_dm_object(op->contr, &params, &from);
1528  if (!tmp) {
1530  "Remove what object (nr)?");
1531  return;
1532  }
1533 
1534  if (tmp->type == PLAYER) {
1536  "Unable to remove a player!");
1537  return;
1538  }
1539 
1540  if (QUERY_FLAG(tmp, FLAG_REMOVED)) {
1541  char name[MAX_BUF];
1542 
1543  query_name(tmp, name, MAX_BUF);
1545  "%s is already removed!",
1546  name);
1547  return;
1548  }
1549 
1550  if (from != STACK_FROM_STACK)
1551  /* Item is either stack top, or is a number thus is now stack top, let's remove it */
1552  dm_stack_pop(op->contr);
1553 
1554  /* Always work on the head - otherwise object will get in odd state */
1555  tmp = HEAD(tmp);
1556  if (tmp->speed != 0) {
1557  tmp->speed = 0;
1558  object_update_speed(tmp);
1559  }
1560  object_remove(tmp);
1561 }
1562 
1570 void command_free(object *op, const char *params) {
1571  object *tmp;
1572  int from;
1573 
1574  tmp = get_dm_object(op->contr, &params, &from);
1575 
1576  if (!tmp) {
1578  "Free what object (nr)?");
1579  return;
1580  }
1581 
1582  if (from != STACK_FROM_STACK)
1583  /* Item is either stack top, or is a number thus is now stack top, let's remove it */
1584  dm_stack_pop(op->contr);
1585 
1586  tmp = HEAD(tmp);
1587  if (!QUERY_FLAG(tmp, FLAG_REMOVED)) {
1589  "Warning: item was not removed, will do so now.");
1590  object_remove(tmp);
1591  }
1592 
1594 }
1595 
1604 void command_addexp(object *op, const char *params) {
1605  char buf[MAX_BUF], skill[MAX_BUF];
1606  int i, q;
1607  object *skillob = NULL;
1608  player *pl;
1609 
1610  skill[0] = '\0';
1611  if ((*params == '\0')
1612  || (strlen(params) > MAX_BUF)
1613  || ((q = sscanf(params, "%s %d %[^\r\n]", buf, &i, skill)) < 2)) {
1615  "Usage: addexp player quantity [skill].");
1616  return;
1617  }
1618 
1619  for (pl = first_player; pl != NULL; pl = pl->next)
1620  if (!strncmp(pl->ob->name, buf, MAX_NAME))
1621  break;
1622 
1623  if (pl == NULL) {
1625  "No such player.");
1626  return;
1627  }
1628 
1629  if (q >= 3) {
1630  skillob = find_skill_by_name(pl->ob, skill);
1631  if (!skillob) {
1633  "Unable to find skill %s in %s",
1634  skill, buf);
1635  return;
1636  }
1637 
1638  i = check_exp_adjust(skillob, i);
1639  skillob->stats.exp += i;
1640  calc_perm_exp(skillob);
1641  player_lvl_adj(pl->ob, skillob);
1642  }
1643 
1644  pl->ob->stats.exp += i;
1645  calc_perm_exp(pl->ob);
1646  player_lvl_adj(pl->ob, NULL);
1647 
1648  if (settings.real_wiz == FALSE)
1649  SET_FLAG(pl->ob, FLAG_WAS_WIZ);
1650 }
1651 
1660 void command_speed(object *op, const char *params) {
1661  int i;
1662 
1663  if (*params == '\0' || !sscanf(params, "%d", &i)) {
1665  "Current speed is %d",
1666  max_time);
1667  return;
1668  }
1669 
1670  set_max_time(i);
1671  reset_sleep();
1673  "The speed is changed to %d.",
1674  i);
1675 }
1676 
1677 /**************************************************************************/
1678 /* Mods made by Tyler Van Gorder, May 10-13, 1992. */
1679 /* CSUChico : tvangod@cscihp.ecst.csuchico.edu */
1680 /**************************************************************************/
1681 
1690 void command_stats(object *op, const char *params) {
1691  player *pl;
1692 
1693  if (*params == '\0') {
1695  "Who?");
1696  return;
1697  }
1698 
1699  pl = find_player_partial_name(params);
1700  if (pl == NULL) {
1702  "No such player.");
1703  return;
1704  }
1705 
1707  "[Fixed]Statistics for %s:", pl->ob->name);
1708 
1710  "[fixed]Str : %-2d H.P. : %-4d MAX : %d",
1711  pl->ob->stats.Str, pl->ob->stats.hp, pl->ob->stats.maxhp);
1712 
1714  "[fixed]Dex : %-2d S.P. : %-4d MAX : %d",
1715  pl->ob->stats.Dex, pl->ob->stats.sp, pl->ob->stats.maxsp);
1716 
1718  "[fixed]Con : %-2d AC : %-4d WC : %d",
1719  pl->ob->stats.Con, pl->ob->stats.ac, pl->ob->stats.wc);
1720 
1722  "[fixed]Int : %-2d Damage : %d",
1723  pl->ob->stats.Int, pl->ob->stats.dam);
1724 
1726  "[fixed]Wis : %-2d EXP : %"FMT64,
1727  pl->ob->stats.Wis, pl->ob->stats.exp);
1728 
1730  "[fixed]Pow : %-2d Grace : %d",
1731  pl->ob->stats.Pow, pl->ob->stats.grace);
1732 
1734  "[fixed]Cha : %-2d Food : %d",
1735  pl->ob->stats.Cha, pl->ob->stats.food);
1736 }
1737 
1747 void command_abil(object *op, const char *params) {
1748  char thing[20], thing2[20];
1749  int iii;
1750  player *pl;
1751 
1752  iii = 0;
1753  thing[0] = '\0';
1754  thing2[0] = '\0';
1755  if (*params == '\0'
1756  || sscanf(params, "%s %s %d", thing, thing2, &iii) != 3
1757  || thing[0] == '\0') {
1759  "Who?");
1760  return;
1761  }
1762 
1763  if (thing2[0] == '\0') {
1765  "You can't change that.");
1766  return;
1767  }
1768 
1769  if (iii < MIN_STAT || iii > settings.max_stat) {
1771  "Illegal range of stat.\n");
1772  return;
1773  }
1774 
1775  for (pl = first_player; pl != NULL; pl = pl->next) {
1776  if (!strcmp(pl->ob->name, thing)) {
1777  if (settings.real_wiz == FALSE)
1778  SET_FLAG(pl->ob, FLAG_WAS_WIZ);
1779  if (!strcmp("str", thing2))
1780  pl->ob->stats.Str = iii, pl->orig_stats.Str = iii;
1781  if (!strcmp("dex", thing2))
1782  pl->ob->stats.Dex = iii, pl->orig_stats.Dex = iii;
1783  if (!strcmp("con", thing2))
1784  pl->ob->stats.Con = iii, pl->orig_stats.Con = iii;
1785  if (!strcmp("wis", thing2))
1786  pl->ob->stats.Wis = iii, pl->orig_stats.Wis = iii;
1787  if (!strcmp("cha", thing2))
1788  pl->ob->stats.Cha = iii, pl->orig_stats.Cha = iii;
1789  if (!strcmp("int", thing2))
1790  pl->ob->stats.Int = iii, pl->orig_stats.Int = iii;
1791  if (!strcmp("pow", thing2))
1792  pl->ob->stats.Pow = iii, pl->orig_stats.Pow = iii;
1794  "%s has been altered.",
1795  pl->ob->name);
1796  fix_object(pl->ob);
1797  return;
1798  }
1799  }
1800 
1802  "No such player.");
1803 }
1804 
1813 void command_reset(object *op, const char *params) {
1814  mapstruct *m;
1815  object *dummy = NULL, *tmp = NULL;
1816  char path[HUGE_BUF];
1817  const char *space, *confirmation = NULL;
1818  int res = 0;
1819 
1820  if (*params == '\0') {
1822  MSG_TYPE_COMMAND_ERROR, "Which map should be reset?");
1823  return;
1824  }
1825 
1826  space = strchr(params, ' ');
1827  if (space != NULL) {
1828  confirmation = params;
1829  params = space + 1;
1830  }
1831 
1832  /* Use the DM's map if the current map was given. */
1833  if (strcmp(params, ".") == 0) {
1834  snprintf(path, sizeof(path), "%s", op->map->path);
1835  } else {
1836  path_combine_and_normalize(op->map->path, params, path, sizeof(path));
1837  }
1838 
1839  m = has_been_loaded(path);
1840  if (m == NULL) {
1842  MSG_TYPE_COMMAND_ERROR, "No such map.");
1843  return;
1844  }
1845 
1846  if (confirmation) {
1847  if (strcmp(params, ".") == 0 && m->unique) {
1850  "Cannot reset a unique player map while on it. Use "
1851  "'reset full-reset %s' while standing somewhere else.",
1852  m->path);
1853  return;
1854  }
1855 
1856  if (strncmp("full-reset", confirmation, strlen("full-reset"))) {
1858  MSG_TYPE_COMMAND_ERROR, "Confirm using 'full-reset'.");
1859  return;
1860  }
1861  }
1862 
1863  /* Forbid using reset on our own map when we're in a transport, as
1864  * it has the displeasant effect of crashing the server.
1865  * - gros, July 25th 2006 */
1866  if ((op->contr && op->contr->transport) && (op->map == m)) {
1868  "You need to disembark first.");
1869  return;
1870  }
1871 
1872  snprintf(path, sizeof(path), "%s", m->path);
1873 
1874  if (m->in_memory != MAP_SWAPPED) {
1875  if (m->in_memory != MAP_IN_MEMORY) {
1876  LOG(llevError, "Tried to swap out map which was not in memory.\n");
1877  return;
1878  }
1879 
1880  /*
1881  * Only attempt to remove the player that is doing the reset, and not other
1882  * players or wiz's.
1883  */
1884  if (op->map == m) {
1885  if (strncmp(m->path, "/random/", 8) == 0) {
1886  /* This is not a very satisfying solution - it would be much better
1887  * to recreate a random map with the same seed value as the old one.
1888  * Unfortunately, I think recreating the map would require some
1889  * knowledge about its 'parent', which appears very non-trivial to
1890  * me.
1891  * On the other hand, this should prevent the freeze that this
1892  * situation caused. - gros, 26th July 2006.
1893  */
1895  "You cannot reset a random map when inside it.");
1896  return;
1897  }
1898 
1899  dummy = object_new();
1900  dummy->map = NULL;
1901  EXIT_X(dummy) = op->x;
1902  EXIT_Y(dummy) = op->y;
1903  EXIT_PATH(dummy) = add_string(op->map->path);
1904  object_remove(op);
1905  op->map = NULL;
1906  tmp = op;
1907  }
1908  res = swap_map(m);
1909  }
1910 
1911  if (res < 0 || m->in_memory != MAP_SWAPPED) {
1912  player *pl;
1913  int playercount = 0;
1914 
1915  /* Need to re-insert player if swap failed for some reason */
1916  if (tmp) {
1917  object_insert_in_map_at(op, m, NULL, 0, op->x, op->y);
1919  }
1920 
1921  if (res < 0 && res != SAVE_ERROR_PLAYER)
1922  /* no need to warn if player on map, code below checks that. */
1924  "Reset failed, error code: %d.", res);
1925  else {
1927  "Reset failed, couldn't swap map, the following players are on it:");
1928  for (pl = first_player; pl != NULL; pl = pl->next) {
1929  if (pl->ob->map == m && pl->ob != op) {
1931  pl->ob->name);
1932  playercount++;
1933  }
1934  }
1935  if (!playercount)
1937  "hmm, I don't see any other players on this map, something else is the problem.");
1938  return;
1939  }
1940  }
1941 
1942  /* Here, map reset succeeded. */
1943 
1944  if (m && m->in_memory == MAP_SWAPPED) {
1945  if (confirmation) {
1947  LOG(llevDebug, "DM %s fully resetting map %s.\n", op->name, m->path);
1948  } else
1949  LOG(llevDebug, "DM %s resetting map %s.\n", op->name, m->path);
1950 
1951  /* setting this effectively causes an immediate reload */
1952  m->reset_time = 1;
1953  flush_old_maps();
1954  }
1955 
1956  /* Display the appropriate success message. */
1957  if (confirmation) {
1959  MSG_TYPE_COMMAND_DM, "Fully resetting map %s.", path);
1960  } else {
1962  MSG_TYPE_COMMAND_DM, "Resetting map %s.", path);
1963  }
1964 
1965  if (tmp) {
1966  enter_exit(tmp, dummy);
1968  }
1969 
1970  /* Remind the DM how to fully reset the map. */
1971  if (confirmation == NULL) {
1974  "Use 'reset full-reset %s' to fully reset the map.", params);
1975  }
1976 }
1977 
1986 void command_nowiz(object *op, const char *params) { /* 'noadm' is alias */
1987  CLEAR_FLAG(op, FLAG_WIZ);
1988  CLEAR_FLAG(op, FLAG_WIZPASS);
1989  CLEAR_FLAG(op, FLAG_WIZCAST);
1990  if (op->contr->followed_player)
1992 
1993  if (settings.real_wiz == TRUE)
1994  CLEAR_FLAG(op, FLAG_WAS_WIZ);
1995  if (op->contr->hidden) {
1996  unhide(op);
1997  } else
1999  "The Dungeon Master is gone..");
2000 
2001  update_los(op);
2002 }
2003 
2024 static int checkdm(object *op, const char *pl_name, const char *pl_passwd, const char *pl_host) {
2025  FILE *dmfile;
2026  char buf[MAX_BUF];
2027  char line_buf[160], name[160], passwd[160], host[160];
2028 
2029 #ifdef RESTRICTIVE_DM
2030  *pl_name = op->name ? op->name : "*";
2031 #endif
2032 
2033  snprintf(buf, sizeof(buf), "%s/%s", settings.confdir, DMFILE);
2034  if ((dmfile = fopen(buf, "r")) == NULL) {
2035  LOG(llevDebug, "Could not find DM file.\n");
2036  return 0;
2037  }
2038 
2039  while (fgets(line_buf, 160, dmfile) != NULL) {
2040  if (line_buf[0] == '#')
2041  continue;
2042  if (sscanf(line_buf, "%[^:]:%[^:]:%s\n", name, passwd, host) != 3) {
2043  LOG(llevError, "Warning - malformed dm file entry: %s\n", line_buf);
2044  } else if ((!strcmp(name, "*") || (pl_name && !strcmp(pl_name, name)))
2045  && (!strcmp(passwd, "*") || !strcmp(passwd, pl_passwd))
2046  && (!strcmp(host, "*") || !strcmp(host, pl_host))) {
2047  fclose(dmfile);
2048  return (1);
2049  }
2050  }
2051  fclose(dmfile);
2052  return (0);
2053 }
2054 
2069 static int do_wizard_dm(object *op, const char *params, int silent) {
2070  if (!op->contr)
2071  return 0;
2072 
2073  if (QUERY_FLAG(op, FLAG_WIZ)) {
2075  "You are already the Dungeon Master!");
2076  return 0;
2077  }
2078 
2079  if (checkdm(op, op->name, (*params != '\0' ? params : "*"), op->contr->socket.host)) {
2080  SET_FLAG(op, FLAG_WIZ);
2081  SET_FLAG(op, FLAG_WAS_WIZ);
2082  SET_FLAG(op, FLAG_WIZPASS);
2083  SET_FLAG(op, FLAG_WIZCAST);
2085  "Ok, you are the Dungeon Master!");
2086  /*
2087  * Remove setting flying here - that won't work, because next
2088  * fix_object() is called that will get cleared - proper solution
2089  * is probably something like a wiz_force which gives that and any
2090  * other desired abilities.
2091  */
2092  clear_los(op);
2093  op->contr->write_buf[0] = '\0';
2094 
2095  if (!silent)
2098  "The Dungeon Master has arrived!");
2099 
2100  return 1;
2101  }
2102 
2104  "Sorry Pal, I don't think so.");
2105  op->contr->write_buf[0] = '\0';
2106  return 0;
2107 }
2108 
2120 void command_dm(object *op, const char *params) {
2121  do_wizard_dm(op, params, 0);
2122 }
2123 
2132 void command_invisible(object *op, const char *params) {
2133  if (op) {
2134  op->invisible += 100;
2137  "You turn invisible.");
2138  }
2139 }
2140 
2158 static object *get_spell_by_name(object *op, const char *spell_name) {
2159  archetype *ar;
2160  archetype *found;
2161  int conflict_found;
2162  size_t spell_name_length;
2163 
2164  /* First check for full name matches. */
2165  conflict_found = 0;
2166  found = NULL;
2167  for (ar = first_archetype; ar != NULL; ar = ar->next) {
2168  if (ar->clone.type != SPELL)
2169  continue;
2170 
2171  if (strncmp(ar->name, "spelldirect_", 12) == 0)
2172  continue;
2173 
2174  if (strcmp(ar->clone.name, spell_name) != 0)
2175  continue;
2176 
2177  if (found != NULL) {
2178  if (!conflict_found) {
2179  conflict_found = 1;
2181  "More than one archetype matches the spell name %s:",
2182  spell_name);
2184  "- %s",
2185  found->name);
2186  }
2188  "- %s",
2189  ar->name);
2190  continue;
2191  }
2192 
2193  found = ar;
2194  }
2195 
2196  /* No match if more more than one archetype matches. */
2197  if (conflict_found)
2198  return NULL;
2199 
2200  /* Return if exactly one archetype matches. */
2201  if (found != NULL)
2202  return arch_to_object(found);
2203 
2204  /* No full match found: now check for partial matches. */
2205  spell_name_length = strlen(spell_name);
2206  conflict_found = 0;
2207  found = NULL;
2208  for (ar = first_archetype; ar != NULL; ar = ar->next) {
2209  if (ar->clone.type != SPELL)
2210  continue;
2211 
2212  if (strncmp(ar->name, "spelldirect_", 12) == 0)
2213  continue;
2214 
2215  if (strncmp(ar->clone.name, spell_name, spell_name_length) != 0)
2216  continue;
2217 
2218  if (found != NULL) {
2219  if (!conflict_found) {
2220  conflict_found = 1;
2222  "More than one spell matches %s:",
2223  spell_name);
2225  "- %s",
2226  found->clone.name);
2227  }
2229  "- %s",
2230  ar->clone.name);
2231  continue;
2232  }
2233 
2234  found = ar;
2235  }
2236 
2237  /* No match if more more than one archetype matches. */
2238  if (conflict_found)
2239  return NULL;
2240 
2241  /* Return if exactly one archetype matches. */
2242  if (found != NULL)
2243  return arch_to_object(found);
2244 
2245  /* No spell found: just print an error message. */
2247  "The spell %s does not exist.",
2248  spell_name);
2249  return NULL;
2250 }
2251 
2262 static void command_learn_spell_or_prayer(object *op, const char *params, int special_prayer) {
2263  object *tmp;
2264 
2265  if (op->contr == NULL || *params == '\0') {
2267  "Which spell do you want to learn?");
2268  return;
2269  }
2270 
2271  tmp = get_spell_by_name(op, params);
2272  if (tmp == NULL) {
2273  return;
2274  }
2275 
2276  if (check_spell_known(op, tmp->name)) {
2278  "You already know the spell %s.",
2279  tmp->name);
2280  return;
2281  }
2282 
2283  do_learn_spell(op, tmp, special_prayer);
2285 }
2286 
2295 void command_learn_spell(object *op, const char *params) {
2296  command_learn_spell_or_prayer(op, params, 0);
2297 }
2298 
2307 void command_learn_special_prayer(object *op, const char *params) {
2308  command_learn_spell_or_prayer(op, params, 1);
2309 }
2310 
2320 void command_forget_spell(object *op, const char *params) {
2321  object *spell;
2322 
2323  if (op->contr == NULL || *params == '\0') {
2325  "Which spell do you want to forget?");
2326  return;
2327  }
2328 
2329  spell = lookup_spell_by_name(op, params);
2330  if (spell == NULL) {
2332  "You do not know the spell %s.",
2333  params);
2334  return;
2335  }
2336 
2337  do_forget_spell(op, spell->name);
2338 }
2339 
2348 void command_listplugins(object *op, const char *params) {
2350 }
2351 
2362 void command_loadplugin(object *op, const char *params) {
2363  char buf[MAX_BUF];
2364 
2365  if (*params == '\0') {
2367  "Load which plugin?");
2368  return;
2369  }
2370 
2371  strcpy(buf, LIBDIR);
2372  strcat(buf, "/plugins/");
2373  strcat(buf, params);
2374  LOG(llevDebug, "Requested plugin file is %s\n", buf);
2375  if (plugins_init_plugin(buf) == 0) {
2376  LOG(llevInfo, "DM %s loaded plugin %s\n", op->name, params);
2378  "Plugin %s successfully loaded.",
2379  params);
2380  } else
2382  "Could not load plugin %s.",
2383  params);
2384 }
2385 
2396 void command_unloadplugin(object *op, const char *params) {
2397  if (*params == '\0') {
2399  "Remove which plugin?");
2400  return;
2401  }
2402 
2403  if (plugins_remove_plugin(params) == 0) {
2404  LOG(llevInfo, "DM %s unloaded plugin %s\n", op->name, params);
2406  "Plugin %s successfully removed.",
2407  params);
2408  } else
2410  "Could not remove plugin %s.",
2411  params);
2412 }
2413 
2424 void command_dmhide(object *op, const char *params) {
2425  if (!do_wizard_dm(op, params, 1))
2426  return;
2427 
2428  do_wizard_hide(op, 1);
2429 }
2430 
2439 void command_stack_pop(object *op, const char *params) {
2440  dm_stack_pop(op->contr);
2441 }
2442 
2451 void command_stack_push(object *op, const char *params) {
2452  object *ob;
2453  int from;
2454  ob = get_dm_object(op->contr, &params, &from);
2455 
2456  if (ob && from != STACK_FROM_NUMBER)
2457  /* Object was from stack, need to push it again */
2458  dm_stack_push(op->contr, ob->count);
2459 }
2460 
2469 void command_stack_list(object *op, const char *params) {
2470  int item;
2471  object *display;
2472  player *pl = op->contr;
2473 
2475  "Item stack contents:");
2476 
2477  for (item = 0; item < pl->stack_position; item++) {
2478  display = object_find_by_tag_global(pl->stack_items[item]);
2479  if (display)
2481  " %d : %s [%d]",
2482  item, display->name, display->count);
2483  else
2484  /* Item was freed */
2486  " %d : (lost item: %d)",
2487  item, pl->stack_items[item]);
2488  }
2489 }
2490 
2499 void command_stack_clear(object *op, const char *params) {
2500  op->contr->stack_position = 0;
2502  "Item stack cleared.");
2503 }
2504 
2524 void command_diff(object *op, const char *params) {
2525  object *left, *right;
2526  char *diff;
2527  StringBuffer *sb;
2528  int left_from, right_from;
2529 
2530  left = get_dm_object(op->contr, &params, &left_from);
2531  if (!left) {
2533  "Compare to what item?");
2534  return;
2535  }
2536 
2537  if (left_from == STACK_FROM_NUMBER)
2538  /* Item was stacked, remove it else right will be the same... */
2539  dm_stack_pop(op->contr);
2540 
2541  right = get_dm_object(op->contr, &params, &right_from);
2542 
2543  if (!right) {
2545  "Compare what item?");
2546  return;
2547  }
2548 
2550  "Item difference:");
2551 
2552  if (left_from == STACK_FROM_TOP && right_from == STACK_FROM_TOP) {
2553  /*
2554  * Special case: both items were taken from stack top.
2555  * Override the behaviour, taking left as item just below top, if exists.
2556  * See function description for why.
2557  * Besides, if we don't do anything, compare an item to itself, not really useful.
2558  */
2559  if (op->contr->stack_position > 1) {
2561  if (left)
2563  "(Note: first item taken from undertop)");
2564  else
2565  /* Stupid case: item under top was freed, fallback to stack top */
2566  left = right;
2567  }
2568  }
2569 
2570  sb = stringbuffer_new();
2571  get_ob_diff(sb, left, right);
2572  diff = stringbuffer_finish(sb);
2573  if (*diff == '\0') {
2574  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_DM, "Objects are the same.");
2575  } else {
2577  }
2578  free(diff);
2579 }
2580 
2588 void command_insert_into(object *op, const char *params) {
2589  object *left, *right, *inserted;
2590  int left_from, right_from;
2591  char what[MAX_BUF], where[MAX_BUF];
2592 
2593  left = get_dm_object(op->contr, &params, &left_from);
2594  if (!left) {
2596  "Insert into what object?");
2597  return;
2598  }
2599 
2600  if (left_from == STACK_FROM_NUMBER)
2601  /* Item was stacked, remove it else right will be the same... */
2602  dm_stack_pop(op->contr);
2603 
2604  right = get_dm_object(op->contr, &params, &right_from);
2605 
2606  if (!right) {
2608  "Insert what item?");
2609  return;
2610  }
2611 
2612  if (left_from == STACK_FROM_TOP && right_from == STACK_FROM_TOP) {
2613  /*
2614  * Special case: both items were taken from stack top.
2615  * Override the behaviour, taking left as item just below top, if exists.
2616  * See function description for why.
2617  * Besides, can't insert an item into itself.
2618  */
2619  if (op->contr->stack_position > 1) {
2621  if (left)
2623  "(Note: item to insert into taken from undertop)");
2624  else
2625  /* Stupid case: item under top was freed, fallback to stack top */
2626  left = right;
2627  }
2628  }
2629 
2630  if (left == right) {
2632  "Can't insert an object into itself!");
2633  return;
2634  }
2635 
2636  if (right->type == PLAYER) {
2638  "Can't insert a player into something!");
2639  return;
2640  }
2641 
2642  if (!QUERY_FLAG(right, FLAG_REMOVED))
2643  object_remove(right);
2644  inserted = object_insert_in_ob(right, left);
2645  if (left->type == PLAYER) {
2646  if (inserted != right)
2647  /* item was merged, so updating name and such. */
2648  esrv_update_item(UPD_WEIGHT|UPD_NAME|UPD_NROF, left, inserted);
2649  }
2650  query_name(inserted, what, MAX_BUF);
2651  query_name(left, where, MAX_BUF);
2653  "Inserted %s in %s",
2654  what, where);
2655 }
2656 
2665 void command_style_map_info(object *op, const char *params) {
2666  extern mapstruct *styles;
2667  mapstruct *mp;
2668  int maps_used = 0, mapmem = 0, objects_used = 0, x, y;
2669 
2670  for (mp = styles; mp != NULL; mp = mp->next) {
2671  maps_used++;
2672  mapmem += map_size(mp) * (sizeof(object *)+sizeof(MapSpace))+sizeof(mapstruct);
2673  for (x = 0; x < MAP_WIDTH(mp); x++) {
2674  for (y = 0; y < MAP_HEIGHT(mp); y++) {
2675  FOR_MAP_PREPARE(mp, x, y, tmp)
2676  objects_used++;
2677  FOR_MAP_FINISH();
2678  }
2679  }
2680  }
2682  "[fixed]Style maps loaded: %d",
2683  maps_used);
2685  "[fixed]Memory used, not");
2687  "[fixed]including objects: %d",
2688  mapmem);
2690  "[fixed]Style objects: %d",
2691  objects_used);
2693  "[fixed]Mem for objects: %lu",
2694  (unsigned long)(objects_used*sizeof(object)));
2695 }
2696 
2705 void command_follow(object *op, const char *params) {
2706  player *other;
2707 
2708  if (*params == '\0') {
2709  if (op->contr->followed_player != NULL) {
2710  draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, "You stop following %s.", op->contr->followed_player);
2712  }
2713  return;
2714  }
2715 
2716  other = find_player_partial_name(params);
2717  if (!other) {
2718  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, "No such player or ambiguous name.");
2719  return;
2720  }
2721  if (other == op->contr) {
2722  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, "You can't follow yourself.");
2723  return;
2724  }
2725 
2726  if (op->contr->followed_player)
2728 
2729  op->contr->followed_player = add_string(other->ob->name);
2731 }
2732 
2733 void command_purge_quest(object *op, const char * param) {
2734  free_quest();
2735  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, "Purged quest state.");
2736 }
2737 
2738 void command_purge_quest_definitions(object *op, const char * param) {
2740  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, "Purged quests definitions.");
2741 }
2742 
2751 void command_dumpbelow(object *op, const char *params) {
2752  if (op && op->below) {
2753  StringBuffer *sb;
2754  char *diff;
2755 
2756  sb = stringbuffer_new();
2757  object_dump(op->below, sb);
2758  diff = stringbuffer_finish(sb);
2760  free(diff);
2761 
2762  /* Let's push that item on the dm's stack */
2763  dm_stack_push(op->contr, op->below->count);
2764  }
2765 }
2766 
2772 void command_settings(object *op, const char *ignored) {
2773  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, i18n(op, "Server settings:"));
2774 
2775  draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, i18n(op, " * item power factor: %2f"), settings.item_power_factor);
2776 
2777  if (settings.not_permadeth) {
2778  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, i18n(op, " * death is not permanent"));
2779  } else if (settings.resurrection) {
2780  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, i18n(op, " * permanent death, resurrection is enabled"));
2781  } else {
2782  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, i18n(op, " * permanent death, resurrection is NOT enabled"));
2783  }
2784 
2785  if (settings.set_title) {
2786  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, i18n(op, " * players can set their title"));
2787  } else {
2788  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, i18n(op, " * players can't set their title"));
2789  }
2790 
2793  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, i18n(op, " * too much equipment can lead to spell failure and ill effects"));
2794  } else {
2795  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, i18n(op, " * too much equipment can lead to spell failure but no ill effects"));
2796  }
2797  } else {
2798  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, i18n(op, " * too much equipment can't lead to spell failure"));
2799  }
2800 
2801  if (settings.casting_time) {
2802  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, i18n(op, " * casting takes time"));
2803  } else {
2804  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, i18n(op, " * casting is immediate"));
2805  }
2806 
2807  draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, i18n(op, " * permanent experience: %d%%"), settings.permanent_exp_ratio);
2809 
2811 
2813  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, i18n(op, " * players can't steal from other players"));
2814  } else {
2815  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, i18n(op, " * players can steal from other players"));
2816  }
2817 
2819  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, i18n(op, " * players can create portals from their apartments"));
2820  } else {
2821  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, i18n(op, " * players can't create portals from their apartments"));
2822  }
2823 
2825  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, i18n(op, " * players can write spells they are denied"));
2826  } else {
2827  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, i18n(op, " * players can't write spells they are denied"));
2828  }
2829 }
#define MSG_TYPE_COMMAND_MAPS
Definition: newclient.h:500
void draw_ext_info_format(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *format,...)
Definition: main.c:315
void command_unloadplugin(object *op, const char *params)
Definition: c_wiz.c:2396
char path[HUGE_BUF]
Definition: map.h:365
uint8_t not_permadeth
Definition: global.h:258
void command_patch(object *op, const char *params)
Definition: c_wiz.c:1483
object * lookup_spell_by_name(object *op, const char *spname)
Definition: spell_util.c:451
int8_t Int
Definition: living.h:36
void command_diff(object *op, const char *params)
Definition: c_wiz.c:2524
#define NUM_BODY_LOCATIONS
Definition: object.h:13
Definition: player.h:92
void command_dumpbelow(object *op, const char *params)
Definition: c_wiz.c:2751
int8_t ac
Definition: living.h:38
#define BANISHFILE
Definition: config.h:561
void show_skills(object *op, const char *search)
Definition: skill_util.c:836
#define UP_OBJ_FACE
Definition: object.h:517
uint8_t create_home_portals
Definition: global.h:308
void command_forget_spell(object *op, const char *params)
Definition: c_wiz.c:2320
void command_dm(object *op, const char *params)
Definition: c_wiz.c:2120
int64_t check_exp_adjust(const object *op, int64_t exp)
Definition: living.c:2025
uint8_t max_stat
Definition: global.h:321
void enter_exit(object *op, object *exit_ob)
Definition: server.c:716
void command_loadtest(object *op, const char *params)
Definition: c_wiz.c:305
uint32_t worldmaptilesx
Definition: global.h:290
static object * get_dm_object(player *pl, const char **params, int *from)
Definition: c_wiz.c:195
object * check_spell_known(object *op, const char *name)
Definition: spell_util.c:435
void free_quest_definitions(void)
Definition: quest.c:1307
void command_shutdown(object *op, const char *params)
Definition: c_wiz.c:677
uint8_t spell_encumbrance
Definition: global.h:264
void object_give_identified_properties(object *op)
Definition: item.c:1376
#define SET_FLAG(xyz, p)
Definition: define.h:223
#define EVENT_KICK
Definition: plugin.h:97
void do_forget_spell(object *op, const char *spell)
Definition: apply.c:432
const artifactlist * find_artifactlist(int type)
Definition: artifact.c:647
#define NDI_ALL
Definition: newclient.h:246
Definition: object.h:221
static int do_wizard_dm(object *op, const char *params, int silent)
Definition: c_wiz.c:2069
uint8_t death_penalty_level
Definition: global.h:256
void command_hide(object *op, const char *params)
Definition: c_wiz.c:388
void do_some_living(object *op)
Definition: player.c:3282
void command_learn_spell(object *op, const char *params)
Definition: c_wiz.c:2295
uint32_t map_size(mapstruct *m)
Definition: map.c:828
#define NDI_ORANGE
Definition: newclient.h:225
void command_follow(object *op, const char *params)
Definition: c_wiz.c:2705
#define FLAG_FRIENDLY
Definition: define.h:246
void command_dump(object *op, const char *params)
Definition: c_wiz.c:1368
int16_t players
Definition: map.h:344
struct artifactstruct * items
Definition: artifact.h:30
void command_learn_special_prayer(object *op, const char *params)
Definition: c_wiz.c:2307
void command_stack_pop(object *op, const char *params)
Definition: c_wiz.c:2439
#define DMFILE
Definition: config.h:370
void command_kick(object *op, const char *params)
Definition: c_wiz.c:576
int save_player(object *op, int flag)
Definition: login.c:211
StringBuffer * stringbuffer_new(void)
Definition: stringbuffer.c:57
uint32_t in_memory
Definition: map.h:345
void command_overlay_reset(object *op, const char *params)
Definition: c_wiz.c:608
uint32_t worldmapstarty
Definition: global.h:289
#define HUGE_BUF
Definition: define.h:37
void command_stack_list(object *op, const char *params)
Definition: c_wiz.c:2469
void esrv_update_item(int flags, object *pl, object *op)
Definition: main.c:342
struct treasureliststruct * randomitems
Definition: object.h:385
#define MAP_HEIGHT(m)
Definition: map.h:80
void command_abil(object *op, const char *params)
Definition: c_wiz.c:1747
object clone
Definition: object.h:470
socket_struct socket
Definition: player.h:94
int16_t invisible
Definition: object.h:360
short freearr_x[SIZEOFFREE]
Definition: object.c:65
uint32_t reset_time
Definition: map.h:332
void command_dmhide(object *op, const char *params)
Definition: c_wiz.c:2424
void esrv_send_inventory(object *pl, object *op)
Definition: item.c:307
void command_speed(object *op, const char *params)
Definition: c_wiz.c:1660
Definition: object.h:109
int64_t exp
Definition: living.h:47
#define FREE_OBJ_NO_DESTROY_CALLBACK
Definition: object.h:531
void command_summon(object *op, const char *params)
Definition: c_wiz.c:874
void command_create(object *op, const char *params)
Definition: c_wiz.c:987
void command_possess(object *op, const char *params)
Definition: c_wiz.c:1422
enum Sock_Status status
Definition: newserver.h:90
#define TRUE
Definition: compat.h:10
#define FALSE
Definition: compat.h:11
#define MAX(x, y)
Definition: compat.h:20
void object_update(object *op, int action)
Definition: object.c:1260
uint8_t death_penalty_ratio
Definition: global.h:255
int16_t sp
Definition: living.h:42
const object * find_god(const char *name)
Definition: gods.c:80
void command_insert_into(object *op, const char *params)
Definition: c_wiz.c:2588
#define safe_strncpy
Definition: compat.h:23
void free_quest(void)
Definition: quest.c:1289
uint32_t hidden
Definition: player.h:132
uint32_t worldmaptilesy
Definition: global.h:291
struct obj * enemy
Definition: object.h:381
struct archt * other_arch
Definition: object.h:413
#define STACK_SIZE
Definition: c_wiz.c:33
int swap_map(mapstruct *map)
Definition: swap.c:135
void command_freeze(object *op, const char *params)
Definition: c_wiz.c:753
void draw_ext_info(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *message)
Definition: main.c:310
Definition: object.h:465
#define ST_PLAYING
Definition: define.h:579
#define NDI_DK_ORANGE
Definition: newclient.h:227
char * host
Definition: newserver.h:100
Definition: object.h:220
void command_purge_quest(object *op, const char *param)
Definition: c_wiz.c:2733
object * get_jail_exit(object *op)
Definition: region.c:260
uint8_t casting_time
Definition: global.h:266
void command_inventory(object *op, const char *params)
Definition: c_wiz.c:1326
int16_t maxsp
Definition: living.h:43
int8_t Con
Definition: living.h:36
#define FLAG_REMOVED
Definition: define.h:232
int16_t hp
Definition: living.h:40
int stack_position
Definition: player.h:200
short freearr_y[SIZEOFFREE]
Definition: object.c:71
#define FLAG_KNOWN_MAGICAL
Definition: define.h:320
void create_treasure(treasurelist *t, object *op, int flag, int difficulty, int tries)
Definition: treasure.c:490
uint32_t no_shout
Definition: player.h:133
#define MSG_TYPE_ADMIN_DM
Definition: newclient.h:475
void command_mon_aggr(object *op, const char *params)
Definition: c_wiz.c:1396
#define MAP_IN_MEMORY
Definition: map.h:130
void object_free_drop_inventory(object *ob)
Definition: object.c:1389
int16_t y
Definition: object.h:326
void esrv_new_player(player *pl, uint32_t weight)
Definition: request.c:856
int set_variable(object *op, const char *buf)
object * object_insert_in_map_at(object *op, mapstruct *m, object *originator, int flag, int x, int y)
Definition: object.c:1936
int16_t maxhp
Definition: living.h:41
#define NDI_RED
Definition: newclient.h:224
void flush_old_maps(void)
Definition: swap.c:289
void player_lvl_adj(object *who, object *op)
Definition: living.c:1793
#define MSG_TYPE_COMMAND
Definition: newclient.h:379
void object_dump(const object *op, StringBuffer *sb)
Definition: object.c:425
#define FLAG_ALIVE
Definition: define.h:230
int legal_artifact_combination(const object *op, const artifact *art)
Definition: artifact.c:221
static void do_wizard_hide(object *op, int silent_dm)
Definition: c_wiz.c:351
object * object_new(void)
Definition: object.c:1068
mapstruct * styles
Definition: style.c:122
#define FLAG_OBJ_ORIGINAL
Definition: define.h:365
object * object_find_by_tag_global(tag_t i)
Definition: object.c:507
#define MAP_SWAPPED
Definition: map.h:131
#define LIBDIR
Definition: win32.h:99
object * object_insert_in_ob(object *op, object *where)
Definition: object.c:2705
float speed_left
Definition: object.h:329
#define MSG_TYPE_COMMAND_SUCCESS
Definition: newclient.h:510
#define MSG_TYPE_COMMAND_ERROR
Definition: newclient.h:509
uint32_t unique
Definition: map.h:337
int8_t Wis
Definition: living.h:36
#define FLAG_UNAGGRESSIVE
Definition: define.h:272
#define MSG_TYPE_ADMIN_PLAYER
Definition: newclient.h:474
struct mapdef * map
Definition: object.h:297
void monster_check_apply_all(object *monster)
Definition: monster.c:1821
int plugins_init_plugin(const char *libfile)
Definition: plugins.c:611
#define snprintf
Definition: win32.h:46
tag_t * stack_items
Definition: player.h:198
static int checkdm(object *op, const char *pl_name, const char *pl_passwd, const char *pl_host)
Definition: c_wiz.c:2024
static void dm_stack_push(player *pl, tag_t item)
Definition: c_wiz.c:149
object * transport
Definition: player.h:195
#define MAP_TIMEOUT(m)
Definition: map.h:66
#define FLAG_IDENTIFIED
Definition: define.h:261
char * path_combine_and_normalize(const char *src, const char *dst, char *path, size_t size)
Definition: path.c:172
#define FMT64
Definition: compat.h:12
void set_max_time(long t)
Definition: time.c:203
int16_t dam
Definition: living.h:46
static object * dm_stack_peek(player *pl)
Definition: c_wiz.c:119
void command_free(object *op, const char *params)
Definition: c_wiz.c:1570
const char * name
Definition: object.h:311
living orig_stats
Definition: player.h:148
void command_addexp(object *op, const char *params)
Definition: c_wiz.c:1604
struct obj * below
Definition: object.h:287
struct archt * more
Definition: object.h:469
int execute_global_event(int eventcode,...)
Definition: main.c:369
#define EXIT_PATH(xyz)
Definition: define.h:455
uint8_t state
Definition: player.h:118
void command_banish(object *op, const char *params)
Definition: c_wiz.c:522
archetype * find_archetype_by_object_name(const char *name)
Definition: arch.c:57
static void command_kick2(object *op, const char *params)
Definition: c_wiz.c:466
int8_t direction
Definition: object.h:334
uint32_t nrof
Definition: object.h:333
int8_t Cha
Definition: living.h:36
void hiscore_check(object *op, int quiet)
Definition: hiscore.c:303
#define EXIT_X(xyz)
Definition: define.h:457
object * object_find_by_name_global(const char *str)
Definition: object.c:530
uint8_t real_wiz
Definition: global.h:267
void do_learn_spell(object *op, object *spell, int special_prayer)
Definition: apply.c:391
Definition: object.h:111
struct pl * contr
Definition: object.h:276
int plugins_remove_plugin(const char *id)
Definition: plugins.c:702
#define NDI_LT_GREEN
Definition: newclient.h:229
#define FREE_AND_CLEAR_STR(xyz)
Definition: global.h:206
void command_setgod(object *op, const char *params)
Definition: c_wiz.c:416
static object * get_spell_by_name(object *op, const char *spell_name)
Definition: c_wiz.c:2158
archetype * try_find_archetype(const char *name)
Definition: arch.c:663
#define UPD_WEIGHT
Definition: newclient.h:291
uint32_t tag_t
Definition: object.h:12
float speed
Definition: object.h:328
Definition: object.h:214
#define QUERY_FLAG(xyz, p)
Definition: define.h:225
#define CLEAR_FLAG(xyz, p)
Definition: define.h:224
#define HEAD(op)
Definition: object.h:592
void clear_los(object *op)
Definition: los.c:248
#define FLAG_WIZ
Definition: define.h:231
#define MSG_TYPE_COMMAND_DEBUG
Definition: newclient.h:508
#define EXIT_Y(xyz)
Definition: define.h:458
void plugins_display_list(object *op)
Definition: plugins.c:744
#define MAX_BUF
Definition: define.h:35
int player_arrest(object *who)
Definition: c_wiz.c:797
void give_artifact_abilities(object *op, const object *artifact)
Definition: artifact.c:203
object * object_create_arch(archetype *at)
Definition: arch.c:733
#define MSG_TYPE_ADMIN
Definition: newclient.h:377
int16_t x
Definition: object.h:326
void command_listplugins(object *op, const char *params)
Definition: c_wiz.c:2348
void reset_sleep(void)
Definition: time.c:130
void command_help(object *op, const char *params)
Definition: c_misc.c:1706
int8_t wc
Definition: living.h:37
const char * confdir
Definition: global.h:241
static void unhide(object *op)
Definition: c_wiz.c:332
uint16_t difficulty
Definition: map.h:343
static void set_magic(int difficulty, object *op, int max_magic, int flags)
Definition: treasure.c:872
void inventory(object *op, object *inv)
Definition: c_object.c:1708
#define FOR_MAP_FINISH()
Definition: define.h:767
int8_t Str
Definition: living.h:36
void calc_perm_exp(object *op)
Definition: living.c:1864
void command_invisible(object *op, const char *params)
Definition: c_wiz.c:2132
int save_map(mapstruct *m, int flag)
Definition: map.c:1440
object * ob
Definition: player.h:158
int32_t timeout
Definition: map.h:341
int need_identify(const object *op)
Definition: item.c:1332
uint8_t permanent_exp_ratio
Definition: global.h:254
Definition: object.h:107
unsigned int uint32_t
Definition: win32.h:162
char killer[BIG_NAME]
Definition: player.h:171
int8_t body_info[NUM_BODY_LOCATIONS]
Definition: object.h:372
uint16_t set_friendly_fire
Definition: global.h:271
Definition: map.h:258
int16_t grace
Definition: living.h:44
#define UPD_NROF
Definition: newclient.h:296
int become_follower(object *op, const object *new_god)
Definition: gods.c:473
const char * localdir
Definition: global.h:243
tag_t count
Definition: object.h:299
living stats
Definition: object.h:368
#define FLAG_WIZCAST
Definition: define.h:290
mapstruct * has_been_loaded(const char *name)
Definition: map.c:77
int8_t Dex
Definition: living.h:36
struct archt * arch
Definition: object.h:412
#define MAP_WIDTH(m)
Definition: map.h:78
uint8_t no_player_stealing
Definition: global.h:307
#define unlink(__a)
Definition: win32.h:56
void command_overlay_save(object *op, const char *params)
Definition: c_wiz.c:588
void command_stack_clear(object *op, const char *params)
Definition: c_wiz.c:2499
uint8_t type
Definition: object.h:338
struct Settings settings
Definition: init.c:40
void object_set_enemy(object *op, object *enemy)
Definition: object.c:710
void command_purge_quest_definitions(object *op, const char *param)
Definition: c_wiz.c:2738
void object_free2(object *ob, int flags)
Definition: object.c:1412
struct archt * next
Definition: object.h:467
int out_of_map(mapstruct *m, int x, int y)
Definition: map.c:2306
uint32_t max_time
Definition: time.c:35
#define UPD_NAME
Definition: newclient.h:293
void command_nowiz(object *op, const char *params)
Definition: c_wiz.c:1986
void command_loadplugin(object *op, const char *params)
Definition: c_wiz.c:2362
void command_stack_push(object *op, const char *params)
Definition: c_wiz.c:2451
void command_arrest(object *op, const char *params)
Definition: c_wiz.c:829
void update_los(object *op)
Definition: los.c:455
sstring add_string(const char *str)
Definition: shstr.c:124
EXTERN player * first_player
Definition: global.h:117
struct pl * next
Definition: player.h:93
void command_skills(object *op, const char *params)
Definition: c_wiz.c:1356
#define FLAG_MONSTER
Definition: define.h:245
void object_copy(const object *src_ob, object *dest_ob)
Definition: object.c:869
int8_t Pow
Definition: living.h:36
uint8_t set_title
Definition: global.h:261
#define NDI_UNIQUE
Definition: newclient.h:245
#define MSG_SUBTYPE_NONE
Definition: newclient.h:398
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.c:51
#define FLAG_WAS_WIZ
Definition: define.h:234
#define MAX_NAME
Definition: define.h:41
#define FOR_MAP_PREPARE(map_, mx_, my_, it_)
Definition: define.h:760
static player * get_other_player_from_name(object *op, const char *name)
Definition: c_wiz.c:59
int cmd_shutdown_time
Definition: c_wiz.c:43
void set_abs_magic(object *op, int magic)
Definition: treasure.c:836
uint32_t worldmapstartx
Definition: global.h:288
struct mapdef * next
Definition: map.h:326
int object_find_free_spot(const object *ob, mapstruct *m, int x, int y, int start, int stop)
Definition: object.c:3430
void command_settings(object *op, const char *ignored)
Definition: c_wiz.c:2772
void query_name(const object *op, char *buf, size_t size)
Definition: item.c:626
object * item
Definition: artifact.h:15
int allow_denied_spells_writing
Definition: global.h:312
void create_overlay_pathname(const char *name, char *buf, size_t size)
Definition: map.c:123
Definition: map.h:325
void get_ob_diff(StringBuffer *sb, const object *op, const object *op2)
Definition: object.c:4863
char write_buf[MAX_BUF]
Definition: player.h:174
void command_stats(object *op, const char *params)
Definition: c_wiz.c:1690
void command_goto(object *op, const char *params)
Definition: c_wiz.c:729
#define FLAG_WIZPASS
Definition: define.h:315
void map_remove_unique_files(const mapstruct *map)
Definition: map.c:2690
#define SAVE_ERROR_PLAYER
Definition: map.h:152
void do_goto(object *op, const char *name, int x, int y)
Definition: c_move.c:151
uint8_t spell_failure_effects
Definition: global.h:265
void command_remove(object *op, const char *params)
Definition: c_wiz.c:1523
void fix_object(object *op)
Definition: living.c:1119
const char * i18n(const object *who, const char *code)
Definition: languages.c:69
player * find_player_partial_name(const char *plname)
Definition: player.c:109
void command_reset(object *op, const char *params)
Definition: c_wiz.c:1813
static object * find_object_both(const char *params)
Definition: c_wiz.c:401
EXTERN archetype * first_archetype
Definition: global.h:122
object * find_skill_by_name(object *who, const char *name)
Definition: skill_util.c:213
struct obj * more
Definition: object.h:295
object * arch_to_object(archetype *at)
Definition: arch.c:569
void object_update_speed(object *op)
Definition: object.c:1150
void command_teleport(object *op, const char *params)
Definition: c_wiz.c:921
static void command_learn_spell_or_prayer(object *op, const char *params, int special_prayer)
Definition: c_wiz.c:2262
sstring followed_player
Definition: player.h:199
float item_power_factor
Definition: global.h:300
const char * name
Definition: object.h:466
#define SAVE_MODE_OVERLAY
Definition: map.h:122
char * stringbuffer_finish(StringBuffer *sb)
Definition: stringbuffer.c:76
uint8_t resurrection
Definition: global.h:262
void command_toggle_shout(object *op, const char *params)
Definition: c_wiz.c:633
static void dm_stack_pop(player *pl)
Definition: c_wiz.c:94
void object_remove(object *op)
Definition: object.c:1669
void command_style_map_info(object *op, const char *params)
Definition: c_wiz.c:2665
struct artifactstruct * next
Definition: artifact.h:18
#define MSG_TYPE_COMMAND_DM
Definition: newclient.h:515
int32_t food
Definition: living.h:48
#define FLAG_FREED
Definition: define.h:233
#define EVENT_MUZZLE
Definition: plugin.h:96
uint32_t count
Definition: player.h:109