Crossfire Server, Trunk  R22010
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  events_execute_global_event(EVENT_KICK, op, *params == '\0' ? NULL : params);
477  object_remove(op);
478  removed = 1;
479  }
480  op->direction = 0;
482  "%s is kicked out of the game.",
483  op->name);
484  strcpy(op->contr->killer, "left");
485  hiscore_check(op, 0); /* Always check score */
486 
487  /*
488  * not sure how the player would be freed, but did see
489  * a crash here - if that is the case, don't save the
490  * the player.
491  */
492  if (!removed && !QUERY_FLAG(op, FLAG_FREED)) {
493  (void)save_player(op, 0);
494  if (op->map)
495  op->map->players--;
496  }
497 #if MAP_MAXTIMEOUT
498  if (op->map)
499  op->map->timeout = MAP_TIMEOUT(op->map);
500 #endif
501  pl->socket.status = Ns_Dead;
502  }
503  }
504 }
505 
521 void command_banish(object *op, const char *params) {
522  player *pl;
523  FILE *banishfile;
524  char buf[MAX_BUF];
525  time_t now;
526 
527  if (*params == '\0') {
529  "Usage: banish <player>.");
530  return;
531  }
532 
533  pl = get_other_player_from_name(op, params);
534  if (!pl)
535  return;
536 
537  snprintf(buf, sizeof(buf), "%s/%s", settings.localdir, BANISHFILE);
538 
539  if ((banishfile = fopen(buf, "a")) == NULL) {
540  LOG(llevDebug, "Could not find file banish_file.\n");
542  "Could not find banish_file.");
543  return;
544  }
545 
546  now = time(NULL);
547  /*
548  * Record this as a comment - then we don't have to worry about changing
549  * the parsing code.
550  */
551  fprintf(banishfile, "# %s (%s) banned by %s at %s\n", pl->ob->name, pl->socket.host, op->name, ctime(&now));
552  fprintf(banishfile, "*@%s\n", pl->socket.host);
553  fclose(banishfile);
554 
555  LOG(llevDebug, "! %s banned %s from IP: %s.\n", op->name, pl->ob->name, pl->socket.host);
556 
558  "You banish %s",
559  pl->ob->name);
560 
562  "%s banishes %s from the land!",
563  op->name, pl->ob->name);
564  command_kick2(op, pl->ob->name);
565 }
566 
575 void command_kick(object *op, const char *params) {
576  command_kick2(op, params);
577 }
578 
587 void command_overlay_save(object *op, const char *params) {
588  if (!op)
589  return;
590 
591  if (save_map(op->map, SAVE_MODE_OVERLAY) < 0)
593  "Overlay save error!");
594  else
596  "Current map has been saved as an overlay.");
597 }
598 
607 void command_overlay_reset(object *op, const char *params) {
608  char filename[MAX_BUF];
609  struct stat stats;
610 
611  create_overlay_pathname(op->map->path, filename, MAX_BUF);
612  if (!stat(filename, &stats))
613  if (!unlink(filename))
615  "Overlay successfully removed.");
616  else
618  "Overlay couldn't be removed.");
619  else
621  "No overlay for current map.");
622 }
623 
632 void command_toggle_shout(object *op, const char *params) {
633  player *pl;
634 
635  if (*params == '\0') {
637  "Usage: toggle_shout <player>.");
638  return;
639  }
640 
641  pl = get_other_player_from_name(op, params);
642  if (!pl)
643  return;
644 
645  if (pl->ob->contr->no_shout == 0) {
646  pl->ob->contr->no_shout = 1;
647 
649  "You have been muzzled by the DM!");
651  "You muzzle %s.",
652  pl->ob->name);
653 
655 
656  return;
657  }
658 
659  pl->ob->contr->no_shout = 0;
661  "You are allowed to shout and chat again.");
663  "You remove %s's muzzle.",
664  pl->ob->name);
665 }
666 
675 void command_shutdown(object *op, const char *params) {
676  if (strlen(params) == 0) {
677  /* Give DM command help and display current shutdown status. */
678  command_help(op, "shutdown");
679 
680  if (cmd_shutdown_time != 0) {
682  MSG_TYPE_COMMAND_DM, "Server is shutting down soon.");
683  }
684  } else if (strcmp(params, "cancel") == 0) {
685  /* Tell everyone that the server is no longer shutting down. */
686  if (cmd_shutdown_time != 0) {
688  MSG_TYPE_ADMIN_DM, "Server shutdown cancelled.");
689  cmd_shutdown_time = 0;
690  LOG(llevInfo, "Server shutdown cancelled by %s.\n", op->name);
691  } else {
693  MSG_TYPE_COMMAND_ERROR, "No shutdown is pending.");
694  }
695  } else if (strncmp(params, "now", 3) == 0) {
696  /* Announce and shut down immediately. */
698  MSG_TYPE_ADMIN_DM, "Server is shutting down now!");
699  cmd_shutdown_time = time(NULL);
700  LOG(llevInfo, "Server shutdown initiated by %s.\n", op->name);
701  } else {
702  /* Schedule (but don't announce) a shutdown. */
703  int minutes = atoi(params);
704 
705  if (minutes > 0 && minutes <= 720) {
708  "Server will shut down in %d minutes.", minutes);
709  cmd_shutdown_time = time(NULL) + minutes * 60;
710  LOG(llevInfo, "Server shutdown initiated by %s in %d minutes.\n", op->name, minutes);
711  } else {
714  "Please specify a reasonable time in minutes.");
715  }
716  }
717 }
718 
727 void command_goto(object *op, const char *params) {
728  if (!op)
729  return ;
730 
731  if (*params == '\0') {
733  "Go to what level?");
734  return;
735  }
736 
737  do_goto(op, params, -1, -1);
738 }
739 
748 void command_freeze(object *op, const char *params) {
749  int ticks;
750  player *pl;
751 
752  if (*params == '\0') {
754  "Usage: freeze [ticks] <player>.");
755  return;
756  }
757 
758  ticks = atoi(params);
759  if (ticks) {
760  while ((isdigit(*params) || isspace(*params)) && *params != 0)
761  params++;
762  if (*params == 0) {
764  "Usage: freeze [ticks] <player>.");
765  return;
766  }
767  } else
768  ticks = 100;
769 
770  pl = get_other_player_from_name(op, params);
771  if (!pl)
772  return;
773 
775  "You have been frozen by the DM!");
776 
778  "You freeze %s for %d ticks",
779  pl->ob->name, ticks);
780 
781  pl->ob->speed_left = -(pl->ob->speed*ticks);
782 }
783 
792 int player_arrest(object *who) {
793  object *dummy;
794  mapstruct *cur;
795  int x, y;
796 
797  if (who->type != PLAYER)
798  return -3;
799 
800  dummy = get_jail_exit(who);
801  if (!dummy) {
802  return -1;
803  }
804  cur = who->map;
805  x = who->x;
806  y = who->y;
807  enter_exit(who, dummy);
808  object_free(dummy, FREE_OBJ_NO_DESTROY_CALLBACK);
809 
810  if (cur == who->map && x == who->x && y == who->y)
811  return -2;
812 
813  return 0;
814 }
815 
824 void command_arrest(object *op, const char *params) {
825  player *pl;
826  int ret;
827 
828  if (!op)
829  return;
830  if (*params == '\0') {
832  "Usage: arrest <player>.");
833  return;
834  }
835  pl = get_other_player_from_name(op, params);
836  if (!pl)
837  return;
838 
839  ret = player_arrest(pl->ob);
840  if (ret == -1) {
841  /* we have nowhere to send the prisoner....*/
843  "Can't jail player, there is no map to hold them");
844  return;
845  }
846  if (ret == -2) {
847  /* something prevented jailing the player */
849  "Can't jail player, map loading issue or already in jail's position");
850  return;
851 
852  }
853 
855  "You have been arrested.");
857  "Jailed %s",
858  pl->ob->name);
859  LOG(llevInfo, "Player %s arrested by %s\n", pl->ob->name, op->name);
860 }
861 
869 void command_summon(object *op, const char *params) {
870  int i;
871  object *dummy;
872  player *pl;
873 
874  if (!op)
875  return;
876 
877  if (*params == '\0') {
879  "Usage: summon <player>.");
880  return;
881  }
882 
883  pl = get_other_player_from_name(op, params);
884  if (!pl)
885  return;
886 
887  i = object_find_free_spot(op, op->map, op->x, op->y, 1, 9);
888  if (i == -1) {
890  "Can not find a free spot to place summoned player.");
891  return;
892  }
893 
894  dummy = object_new();
895  EXIT_PATH(dummy) = add_string(op->map->path);
896  EXIT_X(dummy) = op->x+freearr_x[i];
897  EXIT_Y(dummy) = op->y+freearr_y[i];
898  enter_exit(pl->ob, dummy);
899  object_free(dummy, FREE_OBJ_NO_DESTROY_CALLBACK);
901  "You are summoned.");
903  "You summon %s",
904  pl->ob->name);
905 }
906 
915 /* mids 01/16/2002 */
916 void command_teleport(object *op, const char *params) {
917  int i;
918  object *dummy;
919  player *pl;
920 
921  if (!op)
922  return;
923 
924  if (*params == '\0') {
926  "Usage: teleport <player>.");
927  return;
928  }
929 
930  pl = find_player_partial_name(params);
931  if (!pl) {
933  "No such player or ambiguous name.");
934  return;
935  }
936 
937  i = object_find_free_spot(pl->ob, pl->ob->map, pl->ob->x, pl->ob->y, 1, 9);
938  if (i == -1) {
940  "Can not find a free spot to teleport to.");
941  return;
942  }
943 
944  dummy = object_new();
945  EXIT_PATH(dummy) = add_string(pl->ob->map->path);
946  EXIT_X(dummy) = pl->ob->x+freearr_x[i];
947  EXIT_Y(dummy) = pl->ob->y+freearr_y[i];
948  enter_exit(op, dummy);
949  object_free(dummy, FREE_OBJ_NO_DESTROY_CALLBACK);
950  if (!op->contr->hidden)
952  "You see a portal open.");
954  "You teleport to %s",
955  pl->ob->name);
956 }
957 
982 void command_create(object *op, const char *params) {
983  object *tmp = NULL;
984  uint32_t i;
985  int magic, set_magic = 0, set_nrof = 0, gotquote, gotspace;
986  uint32_t nrof;
987  char *cp, *bp, *bp2, *bp3, *endline, cpy[MAX_BUF];
988  archetype *at, *at_spell = NULL;
989  const artifact *art = NULL;
990 
991  if (!op)
992  return;
993 
994  if (*params == '\0') {
996  "Usage: create [nr] [magic] <archetype> [ of <artifact>] [variable_to_patch setting]");
997  return;
998  }
999  safe_strncpy(cpy, params, sizeof(cpy));
1000  bp = cpy;
1001 
1002  /* We need to know where the line ends */
1003  endline = bp+strlen(bp);
1004 
1005  if (sscanf(bp, "%u ", &nrof)) {
1006  if ((bp = strchr(cpy, ' ')) == NULL) {
1008  "Usage: create [nr] [magic] <archetype> [ of <artifact>] [variable_to_patch setting]");
1009  return;
1010  }
1011  bp++;
1012  set_nrof = 1;
1013  LOG(llevDebug, "%s creates: (%u) %s\n", op->name, nrof, bp);
1014  }
1015  if (sscanf(bp, "%d ", &magic)) {
1016  if ((bp = strchr(bp, ' ')) == NULL) {
1018  "Usage: create [nr] [magic] <archetype> [ of <artifact>] [variable_to_patch setting]");
1019  return;
1020  }
1021  bp++;
1022  set_magic = 1;
1023  LOG(llevDebug, "%s creates: (%d) (%d) %s\n", op->name, nrof, magic, bp);
1024  }
1025  if ((cp = strstr(bp, " of ")) != NULL) {
1026  *cp = '\0';
1027  cp += 4;
1028  }
1029  for (bp2 = bp; *bp2; bp2++) {
1030  if (*bp2 == ' ') {
1031  *bp2 = '\0';
1032  bp2++;
1033  break;
1034  }
1035  }
1036 
1037  if ((at = try_find_archetype(bp)) == NULL) {
1039  "No such archetype.");
1040  return;
1041  }
1042 
1043  if (cp) {
1044  char spell_name[MAX_BUF], *fsp = NULL;
1045 
1046  /*
1047  * Try to find a spell object for this. Note that
1048  * we also set up spell_name which is only
1049  * the first word.
1050  */
1051 
1052  at_spell = try_find_archetype(cp);
1053  if (!at_spell || at_spell->clone.type != SPELL)
1054  at_spell = find_archetype_by_object_name(cp);
1055  if (!at_spell || at_spell->clone.type != SPELL) {
1056  safe_strncpy(spell_name, cp, sizeof(spell_name));
1057  fsp = strchr(spell_name, ' ');
1058  if (fsp) {
1059  *fsp = 0;
1060  fsp++;
1061  at_spell = try_find_archetype(spell_name);
1062 
1063  /* Got a spell, update the first string pointer */
1064  if (at_spell && at_spell->clone.type == SPELL)
1065  bp2 = cp+strlen(spell_name)+1;
1066  else
1067  at_spell = NULL;
1068  } else
1069  at_spell = NULL;
1070  }
1071 
1072  /* OK - we didn't find a spell - presume the 'of'
1073  * in this case means its an artifact.
1074  */
1075  if (!at_spell) {
1076  if (find_artifactlist(at->clone.type) == NULL) {
1078  "No artifact list for type %d\n",
1079  at->clone.type);
1080  } else {
1081  art = find_artifactlist(at->clone.type)->items;
1082 
1083  do {
1084  if (!strcmp(art->item->name, cp) && legal_artifact_combination(&at->clone, art))
1085  break;
1086  art = art->next;
1087  } while (art != NULL);
1088  if (!art) {
1090  "No such artifact ([%d] of %s)",
1091  at->clone.type, cp);
1092  }
1093  }
1094  LOG(llevDebug, "%s creates: (%d) (%d) (%s) of (%s)\n", op->name, set_nrof ? nrof : 0, set_magic ? magic : 0, bp, cp);
1095  }
1096  } /* if cp */
1097 
1098  /* rods and potions can get their spell from the artifact */
1099  if ((at->clone.type == ROD || at->clone.type == POTION) && !at_spell && (!art || !art->item->other_arch)) {
1101  "Unable to find spell %s for object that needs it, or it is of wrong type",
1102  cp);
1103  return;
1104  }
1105  if ((at->clone.type == WAND || at->clone.type == SCROLL || at->clone.type == SPELLBOOK)
1106  && !at_spell) {
1108  "Unable to find spell %s for object that needs it, or it is of wrong type",
1109  cp);
1110  return;
1111  }
1112 
1113  /*
1114  * Rather than have two different blocks with a lot of similar code,
1115  * just create one object, do all the processing, and then determine
1116  * if that one object should be inserted or if we need to make copies.
1117  */
1118  tmp = object_create_arch(at);
1119  if (settings.real_wiz == FALSE)
1120  SET_FLAG(tmp, FLAG_WAS_WIZ);
1121  if (set_magic)
1122  set_abs_magic(tmp, magic);
1123  if (art)
1124  give_artifact_abilities(tmp, art->item);
1125  if (!is_identifiable_type(tmp)) {
1126  SET_FLAG(tmp, FLAG_IDENTIFIED);
1129  }
1130 
1131  /*
1132  * This entire block here tries to find variable pairings,
1133  * eg, 'hp 4' or the like. The mess here is that values
1134  * can be quoted (eg "my cool sword"); So the basic logic
1135  * is we want to find two spaces, but if we got a quote,
1136  * any spaces there don't count.
1137  */
1138  while (*bp2 && bp2 <= endline) {
1139  gotspace = 0;
1140  gotquote = 0;
1141  /* find the first quote */
1142  for (bp3 = bp2; *bp3 && gotspace < 2 && gotquote < 2; bp3++) {
1143  /* Found a quote - now lets find the second one */
1144  if (*bp3 == '"') {
1145  *bp3 = ' ';
1146  bp2 = bp3+1; /* Update start of string */
1147  bp3++;
1148  gotquote++;
1149  while (*bp3) {
1150  if (*bp3 == '"') {
1151  *bp3 = '\0';
1152  gotquote++;
1153  } else
1154  bp3++;
1155  }
1156  } else if (*bp3 == ' ') {
1157  gotspace++;
1158  }
1159  }
1160 
1161  /*
1162  * If we got two spaces, send the second one to null.
1163  * if we've reached the end of the line, increase gotspace -
1164  * this is perfectly valid for the list entry listed.
1165  */
1166  if (gotspace == 2 || gotquote == 2) {
1167  bp3--; /* Undo the extra increment */
1168  *bp3 = '\0';
1169  } else if (*bp3 == '\0')
1170  gotspace++;
1171 
1172  if ((gotquote && gotquote != 2)
1173  || (gotspace != 2 && gotquote != 2)) {
1174  /*
1175  * Unfortunately, we've clobbered lots of values, so printing
1176  * out what we have probably isn't useful. Break out, because
1177  * trying to recover is probably won't get anything useful
1178  * anyways, and we'd be confused about end of line pointers
1179  * anyways.
1180  */
1182  "Malformed create line: %s",
1183  bp2);
1184  break;
1185  }
1186  /* bp2 should still point to the start of this line,
1187  * with bp3 pointing to the end
1188  */
1189  if (set_variable(tmp, bp2) == -1)
1191  "Unknown variable %s",
1192  bp2);
1193  else
1195  "(%s#%d)->%s",
1196  tmp->name, tmp->count, bp2);
1197  bp2 = bp3+1;
1198  }
1199 
1200  if (at->clone.nrof) {
1201  if (at_spell)
1202  object_insert_in_ob(arch_to_object(at_spell), tmp);
1203 
1204  if (set_nrof)
1205  tmp->nrof = nrof;
1206 
1207  if (at->clone.randomitems != NULL && !at_spell) {
1208  create_treasure(at->clone.randomitems, tmp, 0, op->map->difficulty, 0);
1209  if (QUERY_FLAG(tmp, FLAG_MONSTER)) {
1211  }
1212  }
1213 
1214  /* Multipart objects can't be in inventory, put'em on floor. */
1215  if (!tmp->more) {
1216  tmp = object_insert_in_ob(tmp, op);
1217  } else {
1218  object_insert_in_map_at(tmp, op->map, op, 0, op->x, op->y);
1219  }
1220 
1221  /* Let's put this created item on stack so dm can access it easily. */
1222  dm_stack_push(op->contr, tmp->count);
1223 
1224  return;
1225  }
1226 
1227  for (i = 0; i < (set_nrof ? nrof : 1); i++) {
1228  archetype *atmp;
1229  object *prev = NULL, *head = NULL, *dup;
1230 
1231  for (atmp = at; atmp != NULL; atmp = atmp->more) {
1232  dup = arch_to_object(atmp);
1233 
1234  if (at_spell)
1235  object_insert_in_ob(arch_to_object(at_spell), dup);
1236 
1237  /*
1238  * The head is what contains all the important bits,
1239  * so just copying it over should be fine.
1240  */
1241  if (head == NULL) {
1242  head = dup;
1243  object_copy(tmp, dup);
1244  }
1245  if (settings.real_wiz == FALSE)
1246  SET_FLAG(dup, FLAG_WAS_WIZ);
1247  dup->x = op->x+dup->arch->clone.x;
1248  dup->y = op->y+dup->arch->clone.y;
1249  dup->map = op->map;
1250 
1251  if (head != dup) {
1252  dup->head = head;
1253  prev->more = dup;
1254  }
1255  prev = dup;
1256  }
1257 
1258  if (QUERY_FLAG(head, FLAG_ALIVE)) {
1259  object *check = head;
1260  int size_x = 0;
1261  int size_y = 0;
1262 
1263  while (check) {
1264  size_x = MAX(size_x, check->arch->clone.x);
1265  size_y = MAX(size_y, check->arch->clone.y);
1266  check = check->more;
1267  }
1268 
1269  if (out_of_map(op->map, head->x+size_x, head->y+size_y)) {
1270  if (head->x < size_x || head->y < size_y) {
1271  dm_stack_pop(op->contr);
1272  object_free(head, FREE_OBJ_NO_DESTROY_CALLBACK);
1274  "Object too big to insert in map, or wrong position.");
1275  object_free(tmp, FREE_OBJ_NO_DESTROY_CALLBACK);
1276  return;
1277  }
1278 
1279  check = head;
1280  while (check) {
1281  check->x -= size_x;
1282  check->y -= size_y;
1283  check = check->more;
1284  }
1285  }
1286 
1287  object_insert_in_map_at(head, op->map, op, 0, head->x, head->y);
1288  } else
1289  head = object_insert_in_ob(head, op);
1290 
1291  /* Let's put this created item on stack so dm can access it easily. */
1292  /* Wonder if we really want to push all of these, but since
1293  * things like rods have nrof 0, we want to cover those.
1294  */
1295  dm_stack_push(op->contr, head->count);
1296 
1297  if (at->clone.randomitems != NULL && !at_spell) {
1298  create_treasure(at->clone.randomitems, head, 0, op->map->difficulty, 0);
1299  if (QUERY_FLAG(head, FLAG_MONSTER)) {
1301  }
1302  }
1303  }
1304 
1305  /* free the one we used to copy */
1306  object_free(tmp, FREE_OBJ_NO_DESTROY_CALLBACK);
1307 }
1308 
1309 /*
1310  * Now follows dm-commands which are also acceptable from sockets
1311  */
1312 
1321 void command_inventory(object *op, const char *params) {
1322  object *tmp;
1323  int i;
1324 
1325  if (*params == '\0') {
1326  inventory(op, NULL);
1327  return;
1328  }
1329 
1330  if (!sscanf(params, "%d", &i) || (tmp = object_find_by_tag_global(i)) == NULL) {
1332  "Inventory of what object (nr)?");
1333  return;
1334  }
1335 
1336  inventory(op, tmp);
1337 }
1338 
1351 void command_skills(object *op, const char *params) {
1352  show_skills(op, *params == '\0' ? NULL : params);
1353 }
1354 
1363 void command_dump(object *op, const char *params) {
1364  object *tmp;
1365  StringBuffer *sb;
1366  char *diff;
1367 
1368  tmp = get_dm_object(op->contr, &params, NULL);
1369  if (!tmp)
1370  return;
1371 
1372  sb = stringbuffer_new();
1373  object_dump(tmp, sb);
1374  diff = stringbuffer_finish(sb);
1376  free(diff);
1377  if (QUERY_FLAG(tmp, FLAG_OBJ_ORIGINAL))
1379  "Object is marked original");
1380 }
1381 
1391 void command_mon_aggr(object *op, const char *params) {
1392  if (op->enemy || !QUERY_FLAG(op, FLAG_UNAGGRESSIVE)) {
1393  object_set_enemy(op, NULL);
1396  "Aggression turned OFF");
1397  } else {
1401  "Aggression turned ON");
1402  }
1403 }
1404 
1417 void command_possess(object *op, const char *params) {
1418  object *victim;
1419  player *pl;
1420  int i;
1421  char buf[MAX_BUF];
1422 
1423  victim = NULL;
1424  if (*params != '\0') {
1425  if (sscanf(params, "%d", &i))
1426  victim = object_find_by_tag_global(i);
1427  else if (sscanf(params, "%s", buf))
1428  victim = object_find_by_name_global(buf);
1429  }
1430  if (victim == NULL) {
1432  "Patch what object (nr)?");
1433  return;
1434  }
1435 
1436  if (victim == op) {
1438  "As insane as you are, I cannot allow you to possess yourself.");
1439  return;
1440  }
1441 
1442  /* make the switch */
1443  pl = op->contr;
1444  victim->contr = pl;
1445  pl->ob = victim;
1446  victim->type = PLAYER;
1447  SET_FLAG(victim, FLAG_WIZ);
1448 
1449  /* basic patchup */
1450  /* The use of hard coded values is terrible. Note
1451  * that really, to be fair, this shouldn't get changed at
1452  * all - if you are possessing a kobold, you should have the
1453  * same limitations. As it is, as more body locations are added,
1454  * this will give this player more locations than perhaps
1455  * they should be allowed.
1456  */
1457  for (i = 0; i < NUM_BODY_LOCATIONS; i++)
1458  if (i == 1 || i == 6 || i == 8 || i == 9)
1459  victim->body_info[i] = 2;
1460  else
1461  victim->body_info[i] = 1;
1462 
1463  esrv_new_player(pl, 80); /* just pick a weight, we don't care */
1464  esrv_send_inventory(victim, victim);
1465 
1466  fix_object(victim);
1467 
1468  do_some_living(victim);
1469 }
1470 
1478 void command_patch(object *op, const char *params) {
1479  const char *arg, *arg2;
1480  object *tmp;
1481 
1482  tmp = get_dm_object(op->contr, &params, NULL);
1483  if (!tmp)
1484  /* Player already informed of failure */
1485  return;
1486 
1487  /* params set to first value by get_dm_default */
1488  arg = params;
1489  if (*arg == '\0') {
1491  "Patch what values?");
1492  return;
1493  }
1494 
1495  if ((arg2 = strchr(arg, ' ')))
1496  arg2++;
1497  if (settings.real_wiz == FALSE)
1498  SET_FLAG(tmp, FLAG_WAS_WIZ); /* To avoid cheating */
1499  if (set_variable(tmp, arg) == -1)
1501  "Unknown variable %s",
1502  arg);
1503  else {
1505  "(%s#%d)->%s=%s",
1506  tmp->name, tmp->count, arg, arg2);
1507  }
1508 }
1509 
1518 void command_remove(object *op, const char *params) {
1519  object *tmp;
1520  int from;
1521 
1522  tmp = get_dm_object(op->contr, &params, &from);
1523  if (!tmp) {
1525  "Remove what object (nr)?");
1526  return;
1527  }
1528 
1529  if (tmp->type == PLAYER) {
1531  "Unable to remove a player!");
1532  return;
1533  }
1534 
1535  if (QUERY_FLAG(tmp, FLAG_REMOVED)) {
1536  char name[MAX_BUF];
1537 
1538  query_name(tmp, name, MAX_BUF);
1540  "%s is already removed!",
1541  name);
1542  return;
1543  }
1544 
1545  if (from != STACK_FROM_STACK)
1546  /* Item is either stack top, or is a number thus is now stack top, let's remove it */
1547  dm_stack_pop(op->contr);
1548 
1549  /* Always work on the head - otherwise object will get in odd state */
1550  tmp = HEAD(tmp);
1551  if (tmp->speed != 0) {
1552  tmp->speed = 0;
1553  object_update_speed(tmp);
1554  }
1555  object_remove(tmp);
1556 }
1557 
1565 void command_free(object *op, const char *params) {
1566  object *tmp;
1567  int from;
1568 
1569  tmp = get_dm_object(op->contr, &params, &from);
1570 
1571  if (!tmp) {
1573  "Free what object (nr)?");
1574  return;
1575  }
1576 
1577  if (from != STACK_FROM_STACK)
1578  /* Item is either stack top, or is a number thus is now stack top, let's remove it */
1579  dm_stack_pop(op->contr);
1580 
1581  tmp = HEAD(tmp);
1582  if (!QUERY_FLAG(tmp, FLAG_REMOVED)) {
1584  "Warning: item was not removed, will do so now.");
1585  object_remove(tmp);
1586  }
1587 
1589 }
1590 
1599 void command_addexp(object *op, const char *params) {
1600  char buf[MAX_BUF], skill[MAX_BUF];
1601  int i, q;
1602  object *skillob = NULL;
1603  player *pl;
1604 
1605  skill[0] = '\0';
1606  if ((*params == '\0')
1607  || (strlen(params) > MAX_BUF)
1608  || ((q = sscanf(params, "%s %d %[^\r\n]", buf, &i, skill)) < 2)) {
1610  "Usage: addexp player quantity [skill].");
1611  return;
1612  }
1613 
1614  for (pl = first_player; pl != NULL; pl = pl->next)
1615  if (!strncmp(pl->ob->name, buf, MAX_NAME))
1616  break;
1617 
1618  if (pl == NULL) {
1620  "No such player.");
1621  return;
1622  }
1623 
1624  if (q >= 3) {
1625  skillob = find_skill_by_name(pl->ob, skill);
1626  if (!skillob) {
1628  "Unable to find skill %s in %s",
1629  skill, buf);
1630  return;
1631  }
1632 
1633  i = check_exp_adjust(skillob, i);
1634  skillob->stats.exp += i;
1635  calc_perm_exp(skillob);
1636  player_lvl_adj(pl->ob, skillob);
1637  }
1638 
1639  pl->ob->stats.exp += i;
1640  calc_perm_exp(pl->ob);
1641  player_lvl_adj(pl->ob, NULL);
1642 
1643  if (settings.real_wiz == FALSE)
1644  SET_FLAG(pl->ob, FLAG_WAS_WIZ);
1645 }
1646 
1655 void command_speed(object *op, const char *params) {
1656  int i;
1657 
1658  if (*params == '\0' || !sscanf(params, "%d", &i)) {
1660  "Current speed is %d",
1661  max_time);
1662  return;
1663  }
1664 
1665  set_max_time(i);
1666  reset_sleep();
1668  "The speed is changed to %d.",
1669  i);
1670 }
1671 
1672 /**************************************************************************/
1673 /* Mods made by Tyler Van Gorder, May 10-13, 1992. */
1674 /* CSUChico : tvangod@cscihp.ecst.csuchico.edu */
1675 /**************************************************************************/
1676 
1685 void command_stats(object *op, const char *params) {
1686  player *pl;
1687 
1688  if (*params == '\0') {
1690  "Who?");
1691  return;
1692  }
1693 
1694  pl = find_player_partial_name(params);
1695  if (pl == NULL) {
1697  "No such player.");
1698  return;
1699  }
1700 
1702  "[Fixed]Statistics for %s:", pl->ob->name);
1703 
1705  "[fixed]Str : %-2d H.P. : %-4d MAX : %d",
1706  pl->ob->stats.Str, pl->ob->stats.hp, pl->ob->stats.maxhp);
1707 
1709  "[fixed]Dex : %-2d S.P. : %-4d MAX : %d",
1710  pl->ob->stats.Dex, pl->ob->stats.sp, pl->ob->stats.maxsp);
1711 
1713  "[fixed]Con : %-2d AC : %-4d WC : %d",
1714  pl->ob->stats.Con, pl->ob->stats.ac, pl->ob->stats.wc);
1715 
1717  "[fixed]Int : %-2d Damage : %d",
1718  pl->ob->stats.Int, pl->ob->stats.dam);
1719 
1721  "[fixed]Wis : %-2d EXP : %"FMT64,
1722  pl->ob->stats.Wis, pl->ob->stats.exp);
1723 
1725  "[fixed]Pow : %-2d Grace : %d",
1726  pl->ob->stats.Pow, pl->ob->stats.grace);
1727 
1729  "[fixed]Cha : %-2d Food : %d",
1730  pl->ob->stats.Cha, pl->ob->stats.food);
1731 }
1732 
1742 void command_abil(object *op, const char *params) {
1743  char thing[20], thing2[20];
1744  int iii;
1745  player *pl;
1746 
1747  iii = 0;
1748  thing[0] = '\0';
1749  thing2[0] = '\0';
1750  if (*params == '\0'
1751  || sscanf(params, "%s %s %d", thing, thing2, &iii) != 3
1752  || thing[0] == '\0') {
1754  "Who?");
1755  return;
1756  }
1757 
1758  if (thing2[0] == '\0') {
1760  "You can't change that.");
1761  return;
1762  }
1763 
1764  if (iii < MIN_STAT || iii > settings.max_stat) {
1766  "Illegal range of stat.\n");
1767  return;
1768  }
1769 
1770  for (pl = first_player; pl != NULL; pl = pl->next) {
1771  if (!strcmp(pl->ob->name, thing)) {
1772  if (settings.real_wiz == FALSE)
1773  SET_FLAG(pl->ob, FLAG_WAS_WIZ);
1774  if (!strcmp("str", thing2))
1775  pl->ob->stats.Str = iii, pl->orig_stats.Str = iii;
1776  if (!strcmp("dex", thing2))
1777  pl->ob->stats.Dex = iii, pl->orig_stats.Dex = iii;
1778  if (!strcmp("con", thing2))
1779  pl->ob->stats.Con = iii, pl->orig_stats.Con = iii;
1780  if (!strcmp("wis", thing2))
1781  pl->ob->stats.Wis = iii, pl->orig_stats.Wis = iii;
1782  if (!strcmp("cha", thing2))
1783  pl->ob->stats.Cha = iii, pl->orig_stats.Cha = iii;
1784  if (!strcmp("int", thing2))
1785  pl->ob->stats.Int = iii, pl->orig_stats.Int = iii;
1786  if (!strcmp("pow", thing2))
1787  pl->ob->stats.Pow = iii, pl->orig_stats.Pow = iii;
1789  "%s has been altered.",
1790  pl->ob->name);
1791  fix_object(pl->ob);
1792  return;
1793  }
1794  }
1795 
1797  "No such player.");
1798 }
1799 
1808 void command_reset(object *op, const char *params) {
1809  mapstruct *m;
1810  object *dummy = NULL, *tmp = NULL;
1811  char path[HUGE_BUF];
1812  const char *space, *confirmation = NULL;
1813  int res = 0;
1814 
1815  if (*params == '\0') {
1817  MSG_TYPE_COMMAND_ERROR, "Which map should be reset?");
1818  return;
1819  }
1820 
1821  space = strchr(params, ' ');
1822  if (space != NULL) {
1823  confirmation = params;
1824  params = space + 1;
1825  }
1826 
1827  /* Use the DM's map if the current map was given. */
1828  if (strcmp(params, ".") == 0) {
1829  strlcpy(path, op->map->path, sizeof(path));
1830  } else {
1831  path_combine_and_normalize(op->map->path, params, path, sizeof(path));
1832  }
1833 
1834  m = has_been_loaded(path);
1835  if (m == NULL) {
1837  MSG_TYPE_COMMAND_ERROR, "No such map.");
1838  return;
1839  }
1840 
1841  if (confirmation) {
1842  if (m->unique && (op->map == m)) {
1845  "Cannot reset a unique player map while on it. Use "
1846  "'reset full-reset %s' while standing somewhere else.",
1847  m->path);
1848  return;
1849  }
1850 
1851  if (strncmp("full-reset", confirmation, strlen("full-reset"))) {
1853  MSG_TYPE_COMMAND_ERROR, "Confirm using 'full-reset'.");
1854  return;
1855  }
1856  }
1857 
1858  /* Forbid using reset on our own map when we're in a transport, as
1859  * it has the displeasant effect of crashing the server.
1860  * - gros, July 25th 2006 */
1861  if ((op->contr && op->contr->transport) && (op->map == m)) {
1863  "You need to disembark first.");
1864  return;
1865  }
1866 
1867  strlcpy(path, m->path, sizeof(path));
1868 
1869  if (m->in_memory != MAP_SWAPPED) {
1870  if (m->in_memory != MAP_IN_MEMORY) {
1871  LOG(llevError, "Tried to swap out map which was not in memory.\n");
1872  return;
1873  }
1874 
1875  /*
1876  * Only attempt to remove the player that is doing the reset, and not other
1877  * players or wiz's.
1878  */
1879  if (op->map == m) {
1880  if (strncmp(m->path, "/random/", 8) == 0) {
1881  /* This is not a very satisfying solution - it would be much better
1882  * to recreate a random map with the same seed value as the old one.
1883  * Unfortunately, I think recreating the map would require some
1884  * knowledge about its 'parent', which appears very non-trivial to
1885  * me.
1886  * On the other hand, this should prevent the freeze that this
1887  * situation caused. - gros, 26th July 2006.
1888  */
1890  "You cannot reset a random map when inside it.");
1891  return;
1892  }
1893 
1894  dummy = object_new();
1895  dummy->map = NULL;
1896  EXIT_X(dummy) = op->x;
1897  EXIT_Y(dummy) = op->y;
1898  EXIT_PATH(dummy) = add_string(op->map->path);
1899  object_remove(op);
1900  op->map = NULL;
1901  tmp = op;
1902  }
1903  res = swap_map(m);
1904  }
1905 
1906  if (res < 0 || m->in_memory != MAP_SWAPPED) {
1907  player *pl;
1908  int playercount = 0;
1909 
1910  /* Need to re-insert player if swap failed for some reason */
1911  if (tmp) {
1912  object_insert_in_map_at(op, m, NULL, 0, op->x, op->y);
1913  object_free(dummy, FREE_OBJ_NO_DESTROY_CALLBACK);
1914  }
1915 
1916  if (res < 0 && res != SAVE_ERROR_PLAYER)
1917  /* no need to warn if player on map, code below checks that. */
1919  "Reset failed, error code: %d.", res);
1920  else {
1922  "Reset failed, couldn't swap map, the following players are on it:");
1923  for (pl = first_player; pl != NULL; pl = pl->next) {
1924  if (pl->ob->map == m && pl->ob != op) {
1926  pl->ob->name);
1927  playercount++;
1928  }
1929  }
1930  if (!playercount)
1932  "hmm, I don't see any other players on this map, something else is the problem.");
1933  return;
1934  }
1935  }
1936 
1937  /* Here, map reset succeeded. */
1938 
1939  if (m && m->in_memory == MAP_SWAPPED) {
1940  if (confirmation) {
1942  LOG(llevDebug, "DM %s fully resetting map %s.\n", op->name, m->path);
1943  } else
1944  LOG(llevDebug, "DM %s resetting map %s.\n", op->name, m->path);
1945 
1946  /* setting this effectively causes an immediate reload */
1947  m->reset_time = 1;
1948  flush_old_maps();
1949  }
1950 
1951  /* Display the appropriate success message. */
1952  if (confirmation) {
1954  MSG_TYPE_COMMAND_DM, "Fully resetting map %s.", path);
1955  } else {
1957  MSG_TYPE_COMMAND_DM, "Resetting map %s.", path);
1958  }
1959 
1960  if (tmp) {
1961  enter_exit(tmp, dummy);
1962  object_free(dummy, FREE_OBJ_NO_DESTROY_CALLBACK);
1963  }
1964 
1965  /* Remind the DM how to fully reset the map. */
1966  if (confirmation == NULL) {
1969  "Use 'reset full-reset %s' to fully reset the map.", params);
1970  }
1971 }
1972 
1981 void command_nowiz(object *op, const char *params) { /* 'noadm' is alias */
1982  CLEAR_FLAG(op, FLAG_WIZ);
1983  CLEAR_FLAG(op, FLAG_WIZPASS);
1984  CLEAR_FLAG(op, FLAG_WIZCAST);
1985  if (op->contr->followed_player)
1986  FREE_AND_CLEAR_STR(op->contr->followed_player);
1987 
1988  if (settings.real_wiz == TRUE)
1989  CLEAR_FLAG(op, FLAG_WAS_WIZ);
1990  if (op->contr->hidden) {
1991  unhide(op);
1992  } else
1994  "The Dungeon Master is gone..");
1995 
1996  update_los(op);
1997 }
1998 
2019 static int checkdm(object *op, const char *pl_name, const char *pl_passwd, const char *pl_host) {
2020  FILE *dmfile;
2021  char buf[MAX_BUF];
2022  char line_buf[160], name[160], passwd[160], host[160];
2023 
2024 #ifdef RESTRICTIVE_DM
2025  *pl_name = op->name ? op->name : "*";
2026 #endif
2027 
2028  snprintf(buf, sizeof(buf), "%s/%s", settings.confdir, DMFILE);
2029  if ((dmfile = fopen(buf, "r")) == NULL) {
2030  LOG(llevDebug, "Could not find DM file.\n");
2031  return 0;
2032  }
2033 
2034  while (fgets(line_buf, 160, dmfile) != NULL) {
2035  // Skip empty lines as well as commented ones.
2036  if (line_buf[0] == '#' || line_buf[0] == '\n')
2037  continue;
2038  if (sscanf(line_buf, "%[^:]:%[^:]:%s\n", name, passwd, host) != 3) {
2039  LOG(llevError, "Warning - malformed dm file entry: %s\n", line_buf);
2040  } else if ((!strcmp(name, "*") || (pl_name && !strcmp(pl_name, name)))
2041  && (!strcmp(passwd, "*") || !strcmp(passwd, pl_passwd))
2042  && (!strcmp(host, "*") || !strcmp(host, pl_host))) {
2043  fclose(dmfile);
2044  return (1);
2045  }
2046  }
2047  fclose(dmfile);
2048  return (0);
2049 }
2050 
2065 static int do_wizard_dm(object *op, const char *params, int silent) {
2066  if (!op->contr)
2067  return 0;
2068 
2069  if (QUERY_FLAG(op, FLAG_WIZ)) {
2071  "You are already the Dungeon Master!");
2072  return 0;
2073  }
2074 
2075  if (checkdm(op, op->name, (*params != '\0' ? params : "*"), op->contr->socket.host)) {
2076  SET_FLAG(op, FLAG_WIZ);
2077  SET_FLAG(op, FLAG_WAS_WIZ);
2078  SET_FLAG(op, FLAG_WIZPASS);
2079  SET_FLAG(op, FLAG_WIZCAST);
2081  "Ok, you are the Dungeon Master!");
2082  /*
2083  * Remove setting flying here - that won't work, because next
2084  * fix_object() is called that will get cleared - proper solution
2085  * is probably something like a wiz_force which gives that and any
2086  * other desired abilities.
2087  */
2088  clear_los(op->contr);
2089  op->contr->write_buf[0] = '\0';
2090 
2091  if (!silent)
2094  "The Dungeon Master has arrived!");
2095 
2096  return 1;
2097  }
2098 
2100  "Sorry Pal, I don't think so.");
2101  op->contr->write_buf[0] = '\0';
2102  return 0;
2103 }
2104 
2116 void command_dm(object *op, const char *params) {
2117  do_wizard_dm(op, params, 0);
2118 }
2119 
2128 void command_invisible(object *op, const char *params) {
2129  if (op) {
2130  op->invisible += 100;
2131  object_update(op, UP_OBJ_FACE);
2133  "You turn invisible.");
2134  }
2135 }
2136 
2154 static object *get_spell_by_name(object *op, const char *spell_name) {
2155  archetype *ar;
2156  archetype *found;
2157  int conflict_found;
2158  size_t spell_name_length;
2159 
2160  /* First check for full name matches. */
2161  conflict_found = 0;
2162  found = NULL;
2163  for (ar = get_next_archetype(NULL); ar != NULL; ar = get_next_archetype(ar)) {
2164  if (ar->clone.type != SPELL)
2165  continue;
2166 
2167  if (strncmp(ar->name, "spelldirect_", 12) == 0)
2168  continue;
2169 
2170  if (strcmp(ar->clone.name, spell_name) != 0)
2171  continue;
2172 
2173  if (found != NULL) {
2174  if (!conflict_found) {
2175  conflict_found = 1;
2177  "More than one archetype matches the spell name %s:",
2178  spell_name);
2180  "- %s",
2181  found->name);
2182  }
2184  "- %s",
2185  ar->name);
2186  continue;
2187  }
2188 
2189  found = ar;
2190  }
2191 
2192  /* No match if more more than one archetype matches. */
2193  if (conflict_found)
2194  return NULL;
2195 
2196  /* Return if exactly one archetype matches. */
2197  if (found != NULL)
2198  return arch_to_object(found);
2199 
2200  /* No full match found: now check for partial matches. */
2201  spell_name_length = strlen(spell_name);
2202  conflict_found = 0;
2203  found = NULL;
2204 
2205  for (ar = get_next_archetype(NULL); ar != NULL; ar = get_next_archetype(ar)) {
2206  if (ar->clone.type != SPELL)
2207  continue;
2208 
2209  if (strncmp(ar->name, "spelldirect_", 12) == 0)
2210  continue;
2211 
2212  if (strncmp(ar->clone.name, spell_name, spell_name_length) != 0)
2213  continue;
2214 
2215  if (found != NULL) {
2216  if (!conflict_found) {
2217  conflict_found = 1;
2219  "More than one spell matches %s:",
2220  spell_name);
2222  "- %s",
2223  found->clone.name);
2224  }
2226  "- %s",
2227  ar->clone.name);
2228  continue;
2229  }
2230 
2231  found = ar;
2232  }
2233 
2234  /* No match if more more than one archetype matches. */
2235  if (conflict_found)
2236  return NULL;
2237 
2238  /* Return if exactly one archetype matches. */
2239  if (found != NULL)
2240  return arch_to_object(found);
2241 
2242  /* No spell found: just print an error message. */
2244  "The spell %s does not exist.",
2245  spell_name);
2246  return NULL;
2247 }
2248 
2259 static void command_learn_spell_or_prayer(object *op, const char *params, int special_prayer) {
2260  object *tmp;
2261 
2262  if (op->contr == NULL || *params == '\0') {
2264  "Which spell do you want to learn?");
2265  return;
2266  }
2267 
2268  tmp = get_spell_by_name(op, params);
2269  if (tmp == NULL) {
2270  return;
2271  }
2272 
2273  if (check_spell_known(op, tmp->name)) {
2275  "You already know the spell %s.",
2276  tmp->name);
2277  return;
2278  }
2279 
2280  do_learn_spell(op, tmp, special_prayer);
2281  object_free(tmp, FREE_OBJ_NO_DESTROY_CALLBACK);
2282 }
2283 
2292 void command_learn_spell(object *op, const char *params) {
2293  command_learn_spell_or_prayer(op, params, 0);
2294 }
2295 
2304 void command_learn_special_prayer(object *op, const char *params) {
2305  command_learn_spell_or_prayer(op, params, 1);
2306 }
2307 
2317 void command_forget_spell(object *op, const char *params) {
2318  object *spell;
2319 
2320  if (op->contr == NULL || *params == '\0') {
2322  "Which spell do you want to forget?");
2323  return;
2324  }
2325 
2326  spell = lookup_spell_by_name(op, params);
2327  if (spell == NULL) {
2329  "You do not know the spell %s.",
2330  params);
2331  return;
2332  }
2333 
2334  do_forget_spell(op, spell->name);
2335 }
2336 
2345 void command_listplugins(object *op, const char *params) {
2347 }
2348 
2359 void command_loadplugin(object *op, const char *params) {
2360  char buf[MAX_BUF];
2361 
2362  if (*params == '\0') {
2364  "Load which plugin?");
2365  return;
2366  }
2367 
2368  snprintf(buf, sizeof(buf), LIBDIR"/plugins/%s", params);
2369  LOG(llevDebug, "Requested plugin file is %s\n", buf);
2370  if (plugins_init_plugin(buf) == 0) {
2371  LOG(llevInfo, "DM %s loaded plugin %s\n", op->name, params);
2373  "Plugin %s successfully loaded.",
2374  params);
2375  } else
2377  "Could not load plugin %s.",
2378  params);
2379 }
2380 
2391 void command_unloadplugin(object *op, const char *params) {
2392  if (*params == '\0') {
2394  "Remove which plugin?");
2395  return;
2396  }
2397 
2398  if (plugins_remove_plugin(params) == 0) {
2399  LOG(llevInfo, "DM %s unloaded plugin %s\n", op->name, params);
2401  "Plugin %s successfully removed.",
2402  params);
2403  } else
2405  "Could not remove plugin %s.",
2406  params);
2407 }
2408 
2419 void command_dmhide(object *op, const char *params) {
2420  if (!do_wizard_dm(op, params, 1))
2421  return;
2422 
2423  do_wizard_hide(op, 1);
2424 }
2425 
2434 void command_stack_pop(object *op, const char *params) {
2435  dm_stack_pop(op->contr);
2436 }
2437 
2446 void command_stack_push(object *op, const char *params) {
2447  object *ob;
2448  int from;
2449  ob = get_dm_object(op->contr, &params, &from);
2450 
2451  if (ob && from != STACK_FROM_NUMBER)
2452  /* Object was from stack, need to push it again */
2453  dm_stack_push(op->contr, ob->count);
2454 }
2455 
2464 void command_stack_list(object *op, const char *params) {
2465  int item;
2466  object *display;
2467  player *pl = op->contr;
2468 
2470  "Item stack contents:");
2471 
2472  for (item = 0; item < pl->stack_position; item++) {
2473  display = object_find_by_tag_global(pl->stack_items[item]);
2474  if (display)
2476  " %d : %s [%d]",
2477  item, display->name, display->count);
2478  else
2479  /* Item was freed */
2481  " %d : (lost item: %d)",
2482  item, pl->stack_items[item]);
2483  }
2484 }
2485 
2494 void command_stack_clear(object *op, const char *params) {
2495  op->contr->stack_position = 0;
2497  "Item stack cleared.");
2498 }
2499 
2519 void command_diff(object *op, const char *params) {
2520  object *left, *right;
2521  char *diff;
2522  StringBuffer *sb;
2523  int left_from, right_from;
2524 
2525  left = get_dm_object(op->contr, &params, &left_from);
2526  if (!left) {
2528  "Compare to what item?");
2529  return;
2530  }
2531 
2532  if (left_from == STACK_FROM_NUMBER)
2533  /* Item was stacked, remove it else right will be the same... */
2534  dm_stack_pop(op->contr);
2535 
2536  right = get_dm_object(op->contr, &params, &right_from);
2537 
2538  if (!right) {
2540  "Compare what item?");
2541  return;
2542  }
2543 
2545  "Item difference:");
2546 
2547  if (left_from == STACK_FROM_TOP && right_from == STACK_FROM_TOP) {
2548  /*
2549  * Special case: both items were taken from stack top.
2550  * Override the behaviour, taking left as item just below top, if exists.
2551  * See function description for why.
2552  * Besides, if we don't do anything, compare an item to itself, not really useful.
2553  */
2554  if (op->contr->stack_position > 1) {
2555  left = object_find_by_tag_global(op->contr->stack_items[op->contr->stack_position-2]);
2556  if (left)
2558  "(Note: first item taken from undertop)");
2559  else
2560  /* Stupid case: item under top was freed, fallback to stack top */
2561  left = right;
2562  }
2563  }
2564 
2565  sb = stringbuffer_new();
2566  get_ob_diff(sb, left, right);
2567  diff = stringbuffer_finish(sb);
2568  if (*diff == '\0') {
2569  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_DM, "Objects are the same.");
2570  } else {
2572  }
2573  free(diff);
2574 }
2575 
2583 void command_insert_into(object *op, const char *params) {
2584  object *left, *right, *inserted;
2585  int left_from, right_from;
2586  char what[MAX_BUF], where[MAX_BUF];
2587 
2588  left = get_dm_object(op->contr, &params, &left_from);
2589  if (!left) {
2591  "Insert into what object?");
2592  return;
2593  }
2594 
2595  if (left_from == STACK_FROM_NUMBER)
2596  /* Item was stacked, remove it else right will be the same... */
2597  dm_stack_pop(op->contr);
2598 
2599  right = get_dm_object(op->contr, &params, &right_from);
2600 
2601  if (!right) {
2603  "Insert what item?");
2604  return;
2605  }
2606 
2607  if (left_from == STACK_FROM_TOP && right_from == STACK_FROM_TOP) {
2608  /*
2609  * Special case: both items were taken from stack top.
2610  * Override the behaviour, taking left as item just below top, if exists.
2611  * See function description for why.
2612  * Besides, can't insert an item into itself.
2613  */
2614  if (op->contr->stack_position > 1) {
2615  left = object_find_by_tag_global(op->contr->stack_items[op->contr->stack_position-2]);
2616  if (left)
2618  "(Note: item to insert into taken from undertop)");
2619  else
2620  /* Stupid case: item under top was freed, fallback to stack top */
2621  left = right;
2622  }
2623  }
2624 
2625  if (left == right) {
2627  "Can't insert an object into itself!");
2628  return;
2629  }
2630 
2631  if (right->type == PLAYER) {
2633  "Can't insert a player into something!");
2634  return;
2635  }
2636 
2637  if (!QUERY_FLAG(right, FLAG_REMOVED))
2638  object_remove(right);
2639  inserted = object_insert_in_ob(right, left);
2640  if (left->type == PLAYER) {
2641  if (inserted != right)
2642  /* item was merged, so updating name and such. */
2643  esrv_update_item(UPD_WEIGHT|UPD_NAME|UPD_NROF, left, inserted);
2644  }
2645  query_name(inserted, what, MAX_BUF);
2646  query_name(left, where, MAX_BUF);
2648  "Inserted %s in %s",
2649  what, where);
2650 }
2651 
2660 void command_style_map_info(object *op, const char *params) {
2661  extern mapstruct *styles;
2662  mapstruct *mp;
2663  int maps_used = 0, mapmem = 0, objects_used = 0, x, y;
2664 
2665  for (mp = styles; mp != NULL; mp = mp->next) {
2666  maps_used++;
2667  mapmem += map_size(mp) * (sizeof(object *)+sizeof(MapSpace))+sizeof(mapstruct);
2668  for (x = 0; x < MAP_WIDTH(mp); x++) {
2669  for (y = 0; y < MAP_HEIGHT(mp); y++) {
2670  FOR_MAP_PREPARE(mp, x, y, tmp)
2671  objects_used++;
2672  FOR_MAP_FINISH();
2673  }
2674  }
2675  }
2677  "[fixed]Style maps loaded: %d",
2678  maps_used);
2680  "[fixed]Memory used, not");
2682  "[fixed]including objects: %d",
2683  mapmem);
2685  "[fixed]Style objects: %d",
2686  objects_used);
2688  "[fixed]Mem for objects: %lu",
2689  (unsigned long)(objects_used*sizeof(object)));
2690 }
2691 
2700 void command_follow(object *op, const char *params) {
2701  player *other;
2702 
2703  if (*params == '\0') {
2704  if (op->contr->followed_player != NULL) {
2705  draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, "You stop following %s.", op->contr->followed_player);
2706  FREE_AND_CLEAR_STR(op->contr->followed_player);
2707  }
2708  return;
2709  }
2710 
2711  other = find_player_partial_name(params);
2712  if (!other) {
2713  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, "No such player or ambiguous name.");
2714  return;
2715  }
2716  if (other == op->contr) {
2717  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, "You can't follow yourself.");
2718  return;
2719  }
2720 
2721  if (op->contr->followed_player)
2722  FREE_AND_CLEAR_STR(op->contr->followed_player);
2723 
2724  op->contr->followed_player = add_string(other->ob->name);
2725  draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, "Following %s.", op->contr->followed_player);
2726 }
2727 
2728 void command_purge_quest(object *op, const char * param) {
2729  free_quest();
2730  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, "Purged quest state.");
2731 }
2732 
2733 void command_purge_quest_definitions(object *op, const char * param) {
2735  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, "Purged quests definitions.");
2736 }
2737 
2738 static void do_dump(object *who, object *what) {
2739  StringBuffer *sb;
2740  char *diff;
2741 
2742  sb = stringbuffer_new();
2743  object_dump(what, sb);
2744  diff = stringbuffer_finish(sb);
2746  free(diff);
2747 
2748  /* Let's push that item on the dm's stack */
2749  dm_stack_push(who->contr, what->count);
2750 }
2751 
2760 void command_dumpbelow(object *op, const char *params) {
2761  if (op && op->below) {
2762  do_dump(op, op->below);
2763  }
2764 }
2765 
2774 void command_dumpabove(object *op, const char *params) {
2775  if (op && op->above) {
2776  do_dump(op, op->above);
2777  }
2778 }
2779 
2785 void command_settings(object *op, const char *ignored) {
2786  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, i18n(op, "Server settings:"));
2787 
2788  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);
2789 
2790  if (settings.not_permadeth) {
2791  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, i18n(op, " * death is not permanent"));
2792  } else if (settings.resurrection) {
2793  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, i18n(op, " * permanent death, resurrection is enabled"));
2794  } else {
2795  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, i18n(op, " * permanent death, resurrection is NOT enabled"));
2796  }
2797 
2798  if (settings.set_title) {
2799  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, i18n(op, " * players can set their title"));
2800  } else {
2801  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, i18n(op, " * players can't set their title"));
2802  }
2803 
2806  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"));
2807  } else {
2808  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"));
2809  }
2810  } else {
2811  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"));
2812  }
2813 
2814  if (settings.casting_time) {
2815  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, i18n(op, " * casting takes time"));
2816  } else {
2817  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, i18n(op, " * casting is immediate"));
2818  }
2819 
2820  draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, i18n(op, " * permanent experience: %d%%"), settings.permanent_exp_ratio);
2822 
2824 
2826  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, i18n(op, " * players can't steal from other players"));
2827  } else {
2828  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, i18n(op, " * players can steal from other players"));
2829  }
2830 
2832  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, i18n(op, " * players can create portals from their apartments"));
2833  } else {
2834  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, i18n(op, " * players can't create portals from their apartments"));
2835  }
2836 
2838  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, i18n(op, " * players can write spells they are denied"));
2839  } else {
2840  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, i18n(op, " * players can't write spells they are denied"));
2841  }
2842 }
#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:313
void command_unloadplugin(object *op, const char *params)
Definition: c_wiz.c:2391
char path[HUGE_BUF]
Definition: map.h:365
uint8_t not_permadeth
Definition: global.h:261
#define EVENT_KICK
Definition: events.h:42
void command_patch(object *op, const char *params)
Definition: c_wiz.c:1478
object * lookup_spell_by_name(object *op, const char *spname)
Definition: spell_util.c:449
int8_t Int
Definition: living.h:36
void command_diff(object *op, const char *params)
Definition: c_wiz.c:2519
Definition: player.h:92
void command_dumpbelow(object *op, const char *params)
Definition: c_wiz.c:2760
#define BANISHFILE
Definition: config.h:521
void show_skills(object *op, const char *search)
Definition: skill_util.c:851
uint8_t create_home_portals
Definition: global.h:311
void command_forget_spell(object *op, const char *params)
Definition: c_wiz.c:2317
void command_dm(object *op, const char *params)
Definition: c_wiz.c:2116
int64_t check_exp_adjust(const object *op, int64_t exp)
Definition: living.c:2089
void object_free(object *ob, int flags)
Definition: object.c:1348
uint8_t max_stat
Definition: global.h:324
void enter_exit(object *op, object *exit_ob)
Definition: server.c:708
void command_loadtest(object *op, const char *params)
Definition: c_wiz.c:305
uint32_t worldmaptilesx
Definition: global.h:293
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:433
void free_quest_definitions(void)
Definition: quest.c:1321
void command_shutdown(object *op, const char *params)
Definition: c_wiz.c:675
uint8_t spell_encumbrance
Definition: global.h:267
void object_give_identified_properties(object *op)
Definition: item.c:1324
#define SET_FLAG(xyz, p)
Definition: define.h:223
void do_forget_spell(object *op, const char *spell)
Definition: apply.c:525
const artifactlist * find_artifactlist(int type)
Definition: artifact.c:644
#define NDI_ALL
Definition: newclient.h:246
static int do_wizard_dm(object *op, const char *params, int silent)
Definition: c_wiz.c:2065
StringBuffer * buf
Definition: readable.c:1591
uint8_t death_penalty_level
Definition: global.h:259
void command_hide(object *op, const char *params)
Definition: c_wiz.c:388
void do_some_living(object *op)
Definition: player.c:3237
void command_learn_spell(object *op, const char *params)
Definition: c_wiz.c:2292
uint32_t map_size(mapstruct *m)
Definition: map.c:825
#define NDI_ORANGE
Definition: newclient.h:225
void command_follow(object *op, const char *params)
Definition: c_wiz.c:2700
#define FLAG_FRIENDLY
Definition: define.h:246
void command_dump(object *op, const char *params)
Definition: c_wiz.c:1363
struct artifactstruct * items
Definition: artifact.h:30
void command_learn_special_prayer(object *op, const char *params)
Definition: c_wiz.c:2304
void command_stack_pop(object *op, const char *params)
Definition: c_wiz.c:2434
#define DMFILE
Definition: config.h:368
void command_kick(object *op, const char *params)
Definition: c_wiz.c:575
int save_player(object *op, int flag)
Definition: login.c:212
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:607
uint32_t worldmapstarty
Definition: global.h:292
#define HUGE_BUF
Definition: define.h:37
void command_stack_list(object *op, const char *params)
Definition: c_wiz.c:2464
void esrv_update_item(int flags, object *pl, object *op)
Definition: main.c:340
#define MAP_HEIGHT(m)
Definition: map.h:80
void command_abil(object *op, const char *params)
Definition: c_wiz.c:1742
socket_struct socket
Definition: player.h:94
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:2419
void esrv_send_inventory(object *pl, object *op)
Definition: item.c:307
void command_speed(object *op, const char *params)
Definition: c_wiz.c:1655
void command_summon(object *op, const char *params)
Definition: c_wiz.c:869
void command_create(object *op, const char *params)
Definition: c_wiz.c:982
void command_possess(object *op, const char *params)
Definition: c_wiz.c:1417
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:1190
uint8_t death_penalty_ratio
Definition: global.h:258
const object * find_god(const char *name)
Definition: gods.c:80
void command_insert_into(object *op, const char *params)
Definition: c_wiz.c:2583
#define safe_strncpy
Definition: compat.h:23
void free_quest(void)
Definition: quest.c:1303
uint32_t worldmaptilesy
Definition: global.h:294
#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:748
void draw_ext_info(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *message)
Definition: main.c:308
#define ST_PLAYING
Definition: define.h:578
#define NDI_DK_ORANGE
Definition: newclient.h:227
char * host
Definition: newserver.h:100
void command_purge_quest(object *op, const char *param)
Definition: c_wiz.c:2728
object * get_jail_exit(object *op)
Definition: region.c:260
uint8_t casting_time
Definition: global.h:269
void command_inventory(object *op, const char *params)
Definition: c_wiz.c:1321
int8_t Con
Definition: living.h:36
archetype * try_find_archetype(const char *name)
Definition: assets.cpp:255
#define FLAG_REMOVED
Definition: define.h:232
void events_execute_global_event(int eventcode,...)
Definition: events.cpp:27
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:252
#define MSG_TYPE_ADMIN_DM
Definition: newclient.h:475
void command_mon_aggr(object *op, const char *params)
Definition: c_wiz.c:1391
#define MAP_IN_MEMORY
Definition: map.h:130
void object_free_drop_inventory(object *ob)
Definition: object.c:1316
void esrv_new_player(player *pl, uint32_t weight)
Definition: request.c:868
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:1849
#define NDI_RED
Definition: newclient.h:224
void flush_old_maps(void)
Definition: swap.c:244
void player_lvl_adj(object *who, object *op)
Definition: living.c:1817
#define MSG_TYPE_COMMAND
Definition: newclient.h:379
void object_dump(const object *op, StringBuffer *sb)
Definition: object.c:415
#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:1011
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:491
#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:2602
#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
object * arch_to_object(archetype *at)
Definition: arch.cpp:232
int8_t Wis
Definition: living.h:36
#define FLAG_UNAGGRESSIVE
Definition: define.h:272
#define MSG_TYPE_ADMIN_PLAYER
Definition: newclient.h:474
void clear_los(player *pl)
Definition: los.c:252
void monster_check_apply_all(object *monster)
Definition: monster.c:1827
int plugins_init_plugin(const char *libfile)
Definition: plugins.c:356
#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:2019
static void dm_stack_push(player *pl, tag_t item)
Definition: c_wiz.c:149
#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
static object * dm_stack_peek(player *pl)
Definition: c_wiz.c:119
void command_free(object *op, const char *params)
Definition: c_wiz.c:1565
living orig_stats
Definition: player.h:148
void command_addexp(object *op, const char *params)
Definition: c_wiz.c:1599
#define EXIT_PATH(xyz)
Definition: define.h:454
uint8_t state
Definition: player.h:118
void command_banish(object *op, const char *params)
Definition: c_wiz.c:521
static void command_kick2(object *op, const char *params)
Definition: c_wiz.c:466
int8_t Cha
Definition: living.h:36
void hiscore_check(object *op, int quiet)
Definition: hiscore.c:344
#define EXIT_X(xyz)
Definition: define.h:456
object * object_find_by_name_global(const char *str)
Definition: object.c:511
uint8_t real_wiz
Definition: global.h:270
void do_learn_spell(object *op, object *spell, int special_prayer)
Definition: apply.c:484
int plugins_remove_plugin(const char *id)
Definition: plugins.c:447
archetype * get_next_archetype(archetype *current)
Definition: assets.cpp:247
#define NDI_LT_GREEN
Definition: newclient.h:229
#define FREE_AND_CLEAR_STR(xyz)
Definition: global.h:198
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:2154
#define UPD_WEIGHT
Definition: newclient.h:291
#define QUERY_FLAG(xyz, p)
Definition: define.h:225
#define CLEAR_FLAG(xyz, p)
Definition: define.h:224
#define FLAG_WIZ
Definition: define.h:231
#define MSG_TYPE_COMMAND_DEBUG
Definition: newclient.h:508
#define EXIT_Y(xyz)
Definition: define.h:457
#define EVENT_MUZZLE
Definition: events.h:50
void plugins_display_list(object *op)
Definition: plugins.c:496
#define MAX_BUF
Definition: define.h:35
void command_dumpabove(object *op, const char *params)
Definition: c_wiz.c:2774
int player_arrest(object *who)
Definition: c_wiz.c:792
void give_artifact_abilities(object *op, const object *artifact)
Definition: artifact.c:203
#define MSG_TYPE_ADMIN
Definition: newclient.h:377
void command_listplugins(object *op, const char *params)
Definition: c_wiz.c:2345
void reset_sleep(void)
Definition: time.c:130
void command_help(object *op, const char *params)
Definition: c_misc.c:1760
const char * confdir
Definition: global.h:244
static void unhide(object *op)
Definition: c_wiz.c:332
static void do_dump(object *who, object *what)
Definition: c_wiz.c:2738
static void set_magic(int difficulty, object *op, int max_magic, int flags)
Definition: treasure.c:649
void inventory(object *op, object *inv)
Definition: c_object.c:2005
object * object_create_arch(archetype *at)
Definition: arch.cpp:301
#define FOR_MAP_FINISH()
Definition: define.h:767
int8_t Str
Definition: living.h:36
void calc_perm_exp(object *op)
Definition: living.c:1901
void command_invisible(object *op, const char *params)
Definition: c_wiz.c:2128
int save_map(mapstruct *m, int flag)
Definition: map.c:1418
object * ob
Definition: player.h:158
uint8_t permanent_exp_ratio
Definition: global.h:257
unsigned int uint32_t
Definition: win32.h:162
uint16_t set_friendly_fire
Definition: global.h:274
Definition: map.h:258
#define UPD_NROF
Definition: newclient.h:296
int become_follower(object *op, const object *new_god)
Definition: gods.c:478
const char * localdir
Definition: global.h:246
#define FLAG_WIZCAST
Definition: define.h:290
mapstruct * has_been_loaded(const char *name)
Definition: map.c:87
int8_t Dex
Definition: living.h:36
#define MAP_WIDTH(m)
Definition: map.h:78
uint8_t no_player_stealing
Definition: global.h:310
#define unlink(__a)
Definition: win32.h:56
void command_overlay_save(object *op, const char *params)
Definition: c_wiz.c:587
void command_stack_clear(object *op, const char *params)
Definition: c_wiz.c:2494
struct Settings settings
Definition: init.c:39
void object_set_enemy(object *op, object *enemy)
Definition: object.c:679
void command_purge_quest_definitions(object *op, const char *param)
Definition: c_wiz.c:2733
int out_of_map(mapstruct *m, int x, int y)
Definition: map.c:2304
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:1981
void command_loadplugin(object *op, const char *params)
Definition: c_wiz.c:2359
void command_stack_push(object *op, const char *params)
Definition: c_wiz.c:2446
void command_arrest(object *op, const char *params)
Definition: c_wiz.c:824
void update_los(object *op)
Definition: los.c:459
sstring add_string(const char *str)
Definition: shstr.c:124
EXTERN player * first_player
Definition: global.h:115
struct pl * next
Definition: player.h:93
void command_skills(object *op, const char *params)
Definition: c_wiz.c:1351
archetype * find_archetype_by_object_name(const char *name)
Definition: arch.cpp:55
#define FLAG_MONSTER
Definition: define.h:245
void object_copy(const object *src_ob, object *dest_ob)
Definition: object.c:824
int8_t Pow
Definition: living.h:36
uint8_t set_title
Definition: global.h:264
#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:601
uint32_t worldmapstartx
Definition: global.h:291
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:3291
void command_settings(object *op, const char *ignored)
Definition: c_wiz.c:2785
void query_name(const object *op, char *buf, size_t size)
Definition: item.c:583
object * item
Definition: artifact.h:15
int allow_denied_spells_writing
Definition: global.h:315
void create_overlay_pathname(const char *name, char *buf, size_t size)
Definition: map.c:133
Definition: map.h:325
int is_identifiable_type(const object *op)
Definition: item.c:1292
void get_ob_diff(StringBuffer *sb, const object *op, const object *op2)
Definition: object.c:4724
void command_stats(object *op, const char *params)
Definition: c_wiz.c:1685
void command_goto(object *op, const char *params)
Definition: c_wiz.c:727
#define FLAG_WIZPASS
Definition: define.h:315
void map_remove_unique_files(const mapstruct *map)
Definition: map.c:2689
#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:268
void command_remove(object *op, const char *params)
Definition: c_wiz.c:1518
void fix_object(object *op)
Definition: living.c:1124
const char * i18n(const object *who, const char *code)
Definition: languages.c:55
player * find_player_partial_name(const char *plname)
Definition: player.c:110
void command_reset(object *op, const char *params)
Definition: c_wiz.c:1808
static object * find_object_both(const char *params)
Definition: c_wiz.c:401
object * find_skill_by_name(object *who, const char *name)
Definition: skill_util.c:202
void object_update_speed(object *op)
Definition: object.c:1086
void command_teleport(object *op, const char *params)
Definition: c_wiz.c:916
static void command_learn_spell_or_prayer(object *op, const char *params, int special_prayer)
Definition: c_wiz.c:2259
float item_power_factor
Definition: global.h:303
#define SAVE_MODE_OVERLAY
Definition: map.h:122
char * stringbuffer_finish(StringBuffer *sb)
Definition: stringbuffer.c:76
size_t strlcpy(char *dst, const char *src, size_t size)
Definition: porting.c:370
uint8_t resurrection
Definition: global.h:265
void command_toggle_shout(object *op, const char *params)
Definition: c_wiz.c:632
static void dm_stack_pop(player *pl)
Definition: c_wiz.c:94
void object_remove(object *op)
Definition: object.c:1588
void command_style_map_info(object *op, const char *params)
Definition: c_wiz.c:2660
struct artifactstruct * next
Definition: artifact.h:18
#define MSG_TYPE_COMMAND_DM
Definition: newclient.h:515
#define FLAG_FREED
Definition: define.h:233