Crossfire Server, Trunk  R20513
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 
340 static void do_wizard_hide(object *op, int silent_dm) {
341  if (op->contr->hidden) {
342  op->contr->hidden = 0;
343  op->invisible = 1;
345  "You are no longer hidden from other players");
346  op->map->players++;
349  "%s has entered the game.",
350  op->name);
351  if (!silent_dm) {
354  "The Dungeon Master has arrived!");
355  }
356  } else {
357  op->contr->hidden = 1;
359  "Other players will no longer see you.");
360  op->map->players--;
361  if (!silent_dm) {
364  "The Dungeon Master is gone..");
365  }
368  "%s leaves the game.",
369  op->name);
372  "%s left the game.",
373  op->name);
374  }
375 }
376 
385 void command_hide(object *op, const char *params) {
386  do_wizard_hide(op, 0);
387 }
388 
398 static object *find_object_both(const char *params) {
399  if (params[0] == '#')
400  return object_find_by_tag_global(atol(params+1));
401  else
402  return object_find_by_name_global(params);
403 }
404 
413 void command_setgod(object *op, const char *params) {
414  object *ob;
415  const object *god;
416  char *str;
417 
418  if (*params == '\0' || !(str = strchr(params, ' '))) {
420  "Usage: set_god player god");
421  return;
422  }
423 
424  /* kill the space, and set string to the next param */
425  *str++ = '\0';
426  if (!(ob = find_object_both(params))) {
428  "Set whose god - can not find object %s?",
429  params);
430  return;
431  }
432 
433  /*
434  * Perhaps this is overly restrictive? Should we perhaps be able
435  * to rebless altars and the like?
436  */
437  if (ob->type != PLAYER) {
439  "%s is not a player - can not change its god",
440  ob->name);
441  return;
442  }
443 
444  god = find_god(str);
445  if (god == NULL) {
447  "No such god %s.",
448  str);
449  return;
450  }
451 
452  become_follower(ob, god);
453 }
454 
463 static void command_kick2(object *op, const char *params) {
464  struct pl *pl;
465 
466  for (pl = first_player; pl != NULL; pl = pl->next) {
467  if ((*params == '\0' || !strcmp(pl->ob->name, params)) && pl->ob != op) {
468  object *op;
469  int removed = 0;
470 
471  op = pl->ob;
472  if (!QUERY_FLAG(op, FLAG_REMOVED)) {
473  /* Avion : Here we handle the KICK global event */
474  execute_global_event(EVENT_KICK, op, *params == '\0' ? NULL : params);
475  object_remove(op);
476  removed = 1;
477  }
478  op->direction = 0;
480  "%s is kicked out of the game.",
481  op->name);
482  strcpy(op->contr->killer, "left");
483  hiscore_check(op, 0); /* Always check score */
484 
485  /*
486  * not sure how the player would be freed, but did see
487  * a crash here - if that is the case, don't save the
488  * the player.
489  */
490  if (!removed && !QUERY_FLAG(op, FLAG_FREED)) {
491  (void)save_player(op, 0);
492  if (op->map)
493  op->map->players--;
494  }
495 #if MAP_MAXTIMEOUT
496  if (op->map)
497  op->map->timeout = MAP_TIMEOUT(op->map);
498 #endif
499  pl->socket.status = Ns_Dead;
500  }
501  }
502 }
503 
519 void command_banish(object *op, const char *params) {
520  player *pl;
521  FILE *banishfile;
522  char buf[MAX_BUF];
523  time_t now;
524 
525  if (*params == '\0') {
527  "Usage: banish <player>.");
528  return;
529  }
530 
531  pl = get_other_player_from_name(op, params);
532  if (!pl)
533  return;
534 
535  snprintf(buf, sizeof(buf), "%s/%s", settings.localdir, BANISHFILE);
536 
537  if ((banishfile = fopen(buf, "a")) == NULL) {
538  LOG(llevDebug, "Could not find file banish_file.\n");
540  "Could not find banish_file.");
541  return;
542  }
543 
544  now = time(NULL);
545  /*
546  * Record this as a comment - then we don't have to worry about changing
547  * the parsing code.
548  */
549  fprintf(banishfile, "# %s (%s) banned by %s at %s\n", pl->ob->name, pl->socket.host, op->name, ctime(&now));
550  fprintf(banishfile, "*@%s\n", pl->socket.host);
551  fclose(banishfile);
552 
553  LOG(llevDebug, "! %s banned %s from IP: %s.\n", op->name, pl->ob->name, pl->socket.host);
554 
556  "You banish %s",
557  pl->ob->name);
558 
560  "%s banishes %s from the land!",
561  op->name, pl->ob->name);
562  command_kick2(op, pl->ob->name);
563 }
564 
573 void command_kick(object *op, const char *params) {
574  command_kick2(op, params);
575 }
576 
585 void command_overlay_save(object *op, const char *params) {
586  if (!op)
587  return;
588 
589  if (save_map(op->map, SAVE_MODE_OVERLAY) < 0)
591  "Overlay save error!");
592  else
594  "Current map has been saved as an overlay.");
595 }
596 
605 void command_overlay_reset(object *op, const char *params) {
606  char filename[MAX_BUF];
607  struct stat stats;
608 
609  create_overlay_pathname(op->map->path, filename, MAX_BUF);
610  if (!stat(filename, &stats))
611  if (!unlink(filename))
613  "Overlay successfully removed.");
614  else
616  "Overlay couldn't be removed.");
617  else
619  "No overlay for current map.");
620 }
621 
630 void command_toggle_shout(object *op, const char *params) {
631  player *pl;
632 
633  if (*params == '\0') {
635  "Usage: toggle_shout <player>.");
636  return;
637  }
638 
639  pl = get_other_player_from_name(op, params);
640  if (!pl)
641  return;
642 
643  if (pl->ob->contr->no_shout == 0) {
644  pl->ob->contr->no_shout = 1;
645 
647  "You have been muzzled by the DM!");
649  "You muzzle %s.",
650  pl->ob->name);
651 
652  /* Avion : Here we handle the MUZZLE global event */
653  execute_global_event(EVENT_MUZZLE, pl->ob, params);
654 
655  return;
656  }
657 
658  pl->ob->contr->no_shout = 0;
660  "You are allowed to shout and chat again.");
662  "You remove %s's muzzle.",
663  pl->ob->name);
664 }
665 
674 void command_shutdown(object *op, const char *params) {
675  if (strlen(params) == 0) {
676  /* Give DM command help and display current shutdown status. */
677  command_help(op, "shutdown");
678 
679  if (cmd_shutdown_time != 0) {
681  MSG_TYPE_COMMAND_DM, "Server is shutting down soon.");
682  }
683  } else if (strcmp(params, "cancel") == 0) {
684  /* Tell everyone that the server is no longer shutting down. */
685  if (cmd_shutdown_time != 0) {
687  MSG_TYPE_ADMIN_DM, "Server shutdown cancelled.");
688  cmd_shutdown_time = 0;
689  LOG(llevInfo, "Server shutdown cancelled by %s.\n", op->name);
690  } else {
692  MSG_TYPE_COMMAND_ERROR, "No shutdown is pending.");
693  }
694  } else if (strncmp(params, "now", 3) == 0) {
695  /* Announce and shut down immediately. */
697  MSG_TYPE_ADMIN_DM, "Server is shutting down now!");
698  cmd_shutdown_time = time(NULL);
699  LOG(llevInfo, "Server shutdown initiated by %s.\n", op->name);
700  } else {
701  /* Schedule (but don't announce) a shutdown. */
702  int minutes = atoi(params);
703 
704  if (minutes > 0 && minutes <= 720) {
707  "Server will shut down in %d minutes.", minutes);
708  cmd_shutdown_time = time(NULL) + minutes * 60;
709  LOG(llevInfo, "Server shutdown initiated by %s in %d minutes.\n", op->name, minutes);
710  } else {
713  "Please specify a reasonable time in minutes.");
714  }
715  }
716 }
717 
726 void command_goto(object *op, const char *params) {
727  const char *name;
728  object *dummy;
729 
730  if (!op)
731  return ;
732 
733  if (*params == '\0') {
735  "Go to what level?");
736  return;
737  }
738 
739  name = params;
740  dummy = object_new();
741  dummy->map = op->map;
742  EXIT_PATH(dummy) = add_string(name);
743  EXIT_X(dummy) = -1;
744  EXIT_Y(dummy) = -1;
745  dummy->name = add_string(name);
746 
747  enter_exit(op, dummy);
750  "Difficulty: %d.",
751  op->map->difficulty);
752 }
753 
762 void command_freeze(object *op, const char *params) {
763  int ticks;
764  player *pl;
765 
766  if (*params == '\0') {
768  "Usage: freeze [ticks] <player>.");
769  return;
770  }
771 
772  ticks = atoi(params);
773  if (ticks) {
774  while ((isdigit(*params) || isspace(*params)) && *params != 0)
775  params++;
776  if (*params == 0) {
778  "Usage: freeze [ticks] <player>.");
779  return;
780  }
781  } else
782  ticks = 100;
783 
784  pl = get_other_player_from_name(op, params);
785  if (!pl)
786  return;
787 
789  "You have been frozen by the DM!");
790 
792  "You freeze %s for %d ticks",
793  pl->ob->name, ticks);
794 
795  pl->ob->speed_left = -(pl->ob->speed*ticks);
796 }
797 
806 int player_arrest(object *who) {
807  object *dummy;
808  mapstruct *cur;
809  int x, y;
810 
811  if (who->type != PLAYER)
812  return -3;
813 
814  dummy = get_jail_exit(who);
815  if (!dummy) {
816  return -1;
817  }
818  cur = who->map;
819  x = who->x;
820  y = who->y;
821  enter_exit(who, dummy);
823 
824  if (cur == who->map && x == who->x && y == who->y)
825  return -2;
826 
827  return 0;
828 }
829 
838 void command_arrest(object *op, const char *params) {
839  player *pl;
840  int ret;
841 
842  if (!op)
843  return;
844  if (*params == '\0') {
846  "Usage: arrest <player>.");
847  return;
848  }
849  pl = get_other_player_from_name(op, params);
850  if (!pl)
851  return;
852 
853  ret = player_arrest(pl->ob);
854  if (ret == -1) {
855  /* we have nowhere to send the prisoner....*/
857  "Can't jail player, there is no map to hold them");
858  return;
859  }
860  if (ret == -2) {
861  /* something prevented jailing the player */
863  "Can't jail player, map loading issue or already in jail's position");
864  return;
865 
866  }
867 
869  "You have been arrested.");
871  "Jailed %s",
872  pl->ob->name);
873  LOG(llevInfo, "Player %s arrested by %s\n", pl->ob->name, op->name);
874 }
875 
883 void command_summon(object *op, const char *params) {
884  int i;
885  object *dummy;
886  player *pl;
887 
888  if (!op)
889  return;
890 
891  if (*params == '\0') {
893  "Usage: summon <player>.");
894  return;
895  }
896 
897  pl = get_other_player_from_name(op, params);
898  if (!pl)
899  return;
900 
901  i = object_find_free_spot(op, op->map, op->x, op->y, 1, 9);
902  if (i == -1) {
904  "Can not find a free spot to place summoned player.");
905  return;
906  }
907 
908  dummy = object_new();
909  EXIT_PATH(dummy) = add_string(op->map->path);
910  EXIT_X(dummy) = op->x+freearr_x[i];
911  EXIT_Y(dummy) = op->y+freearr_y[i];
912  enter_exit(pl->ob, dummy);
915  "You are summoned.");
917  "You summon %s",
918  pl->ob->name);
919 }
920 
929 /* mids 01/16/2002 */
930 void command_teleport(object *op, const char *params) {
931  int i;
932  object *dummy;
933  player *pl;
934 
935  if (!op)
936  return;
937 
938  if (*params == '\0') {
940  "Usage: teleport <player>.");
941  return;
942  }
943 
944  pl = find_player_partial_name(params);
945  if (!pl) {
947  "No such player or ambiguous name.");
948  return;
949  }
950 
951  i = object_find_free_spot(pl->ob, pl->ob->map, pl->ob->x, pl->ob->y, 1, 9);
952  if (i == -1) {
954  "Can not find a free spot to teleport to.");
955  return;
956  }
957 
958  dummy = object_new();
959  EXIT_PATH(dummy) = add_string(pl->ob->map->path);
960  EXIT_X(dummy) = pl->ob->x+freearr_x[i];
961  EXIT_Y(dummy) = pl->ob->y+freearr_y[i];
962  enter_exit(op, dummy);
964  if (!op->contr->hidden)
966  "You see a portal open.");
968  "You teleport to %s",
969  pl->ob->name);
970 }
971 
996 void command_create(object *op, const char *params) {
997  object *tmp = NULL;
998  uint32_t i;
999  int magic, set_magic = 0, set_nrof = 0, gotquote, gotspace;
1000  uint32_t nrof;
1001  char *cp, *bp, *bp2, *bp3, *endline, cpy[MAX_BUF];
1002  archetype *at, *at_spell = NULL;
1003  const artifact *art = NULL;
1004 
1005  if (!op)
1006  return;
1007 
1008  if (*params == '\0') {
1010  "Usage: create [nr] [magic] <archetype> [ of <artifact>] [variable_to_patch setting]");
1011  return;
1012  }
1013  safe_strncpy(cpy, params, sizeof(cpy));
1014  bp = cpy;
1015 
1016  /* We need to know where the line ends */
1017  endline = bp+strlen(bp);
1018 
1019  if (sscanf(bp, "%u ", &nrof)) {
1020  if ((bp = strchr(cpy, ' ')) == NULL) {
1022  "Usage: create [nr] [magic] <archetype> [ of <artifact>] [variable_to_patch setting]");
1023  return;
1024  }
1025  bp++;
1026  set_nrof = 1;
1027  LOG(llevDebug, "%s creates: (%u) %s\n", op->name, nrof, bp);
1028  }
1029  if (sscanf(bp, "%d ", &magic)) {
1030  if ((bp = strchr(bp, ' ')) == NULL) {
1032  "Usage: create [nr] [magic] <archetype> [ of <artifact>] [variable_to_patch setting]");
1033  return;
1034  }
1035  bp++;
1036  set_magic = 1;
1037  LOG(llevDebug, "%s creates: (%d) (%d) %s\n", op->name, nrof, magic, bp);
1038  }
1039  if ((cp = strstr(bp, " of ")) != NULL) {
1040  *cp = '\0';
1041  cp += 4;
1042  }
1043  for (bp2 = bp; *bp2; bp2++) {
1044  if (*bp2 == ' ') {
1045  *bp2 = '\0';
1046  bp2++;
1047  break;
1048  }
1049  }
1050 
1051  if ((at = try_find_archetype(bp)) == NULL) {
1053  "No such archetype.");
1054  return;
1055  }
1056 
1057  if (cp) {
1058  char spell_name[MAX_BUF], *fsp = NULL;
1059 
1060  /*
1061  * Try to find a spell object for this. Note that
1062  * we also set up spell_name which is only
1063  * the first word.
1064  */
1065 
1066  at_spell = try_find_archetype(cp);
1067  if (!at_spell || at_spell->clone.type != SPELL)
1068  at_spell = find_archetype_by_object_name(cp);
1069  if (!at_spell || at_spell->clone.type != SPELL) {
1070  safe_strncpy(spell_name, cp, sizeof(spell_name));
1071  fsp = strchr(spell_name, ' ');
1072  if (fsp) {
1073  *fsp = 0;
1074  fsp++;
1075  at_spell = try_find_archetype(spell_name);
1076 
1077  /* Got a spell, update the first string pointer */
1078  if (at_spell && at_spell->clone.type == SPELL)
1079  bp2 = cp+strlen(spell_name)+1;
1080  else
1081  at_spell = NULL;
1082  } else
1083  at_spell = NULL;
1084  }
1085 
1086  /* OK - we didn't find a spell - presume the 'of'
1087  * in this case means its an artifact.
1088  */
1089  if (!at_spell) {
1090  if (find_artifactlist(at->clone.type) == NULL) {
1092  "No artifact list for type %d\n",
1093  at->clone.type);
1094  } else {
1095  art = find_artifactlist(at->clone.type)->items;
1096 
1097  do {
1098  if (!strcmp(art->item->name, cp) && legal_artifact_combination(&at->clone, art))
1099  break;
1100  art = art->next;
1101  } while (art != NULL);
1102  if (!art) {
1104  "No such artifact ([%d] of %s)",
1105  at->clone.type, cp);
1106  }
1107  }
1108  LOG(llevDebug, "%s creates: (%d) (%d) (%s) of (%s)\n", op->name, set_nrof ? nrof : 0, set_magic ? magic : 0, bp, cp);
1109  }
1110  } /* if cp */
1111 
1112  /* rods and potions can get their spell from the artifact */
1113  if ((at->clone.type == ROD || at->clone.type == POTION) && !at_spell && (!art || !art->item->other_arch)) {
1115  "Unable to find spell %s for object that needs it, or it is of wrong type",
1116  cp);
1117  return;
1118  }
1119  if ((at->clone.type == WAND || at->clone.type == SCROLL || at->clone.type == SPELLBOOK)
1120  && !at_spell) {
1122  "Unable to find spell %s for object that needs it, or it is of wrong type",
1123  cp);
1124  return;
1125  }
1126 
1127  /*
1128  * Rather than have two different blocks with a lot of similar code,
1129  * just create one object, do all the processing, and then determine
1130  * if that one object should be inserted or if we need to make copies.
1131  */
1132  tmp = object_create_arch(at);
1133  if (settings.real_wiz == FALSE)
1134  SET_FLAG(tmp, FLAG_WAS_WIZ);
1135  if (set_magic)
1136  set_abs_magic(tmp, magic);
1137  if (art)
1138  give_artifact_abilities(tmp, art->item);
1139  if (need_identify(tmp)) {
1140  SET_FLAG(tmp, FLAG_IDENTIFIED);
1143  }
1144 
1145  /*
1146  * This entire block here tries to find variable pairings,
1147  * eg, 'hp 4' or the like. The mess here is that values
1148  * can be quoted (eg "my cool sword"); So the basic logic
1149  * is we want to find two spaces, but if we got a quote,
1150  * any spaces there don't count.
1151  */
1152  while (*bp2 && bp2 <= endline) {
1153  gotspace = 0;
1154  gotquote = 0;
1155  /* find the first quote */
1156  for (bp3 = bp2; *bp3 && gotspace < 2 && gotquote < 2; bp3++) {
1157  /* Found a quote - now lets find the second one */
1158  if (*bp3 == '"') {
1159  *bp3 = ' ';
1160  bp2 = bp3+1; /* Update start of string */
1161  bp3++;
1162  gotquote++;
1163  while (*bp3) {
1164  if (*bp3 == '"') {
1165  *bp3 = '\0';
1166  gotquote++;
1167  } else
1168  bp3++;
1169  }
1170  } else if (*bp3 == ' ') {
1171  gotspace++;
1172  }
1173  }
1174 
1175  /*
1176  * If we got two spaces, send the second one to null.
1177  * if we've reached the end of the line, increase gotspace -
1178  * this is perfectly valid for the list entry listed.
1179  */
1180  if (gotspace == 2 || gotquote == 2) {
1181  bp3--; /* Undo the extra increment */
1182  *bp3 = '\0';
1183  } else if (*bp3 == '\0')
1184  gotspace++;
1185 
1186  if ((gotquote && gotquote != 2)
1187  || (gotspace != 2 && gotquote != 2)) {
1188  /*
1189  * Unfortunately, we've clobbered lots of values, so printing
1190  * out what we have probably isn't useful. Break out, because
1191  * trying to recover is probably won't get anything useful
1192  * anyways, and we'd be confused about end of line pointers
1193  * anyways.
1194  */
1196  "Malformed create line: %s",
1197  bp2);
1198  break;
1199  }
1200  /* bp2 should still point to the start of this line,
1201  * with bp3 pointing to the end
1202  */
1203  if (set_variable(tmp, bp2) == -1)
1205  "Unknown variable %s",
1206  bp2);
1207  else
1209  "(%s#%d)->%s",
1210  tmp->name, tmp->count, bp2);
1211  bp2 = bp3+1;
1212  }
1213 
1214  if (at->clone.nrof) {
1215  if (at_spell)
1216  object_insert_in_ob(arch_to_object(at_spell), tmp);
1217 
1218  if (set_nrof)
1219  tmp->nrof = nrof;
1220 
1221  if (at->clone.randomitems != NULL && !at_spell) {
1222  create_treasure(at->clone.randomitems, tmp, 0, op->map->difficulty, 0);
1223  if (QUERY_FLAG(tmp, FLAG_MONSTER)) {
1225  }
1226  }
1227 
1228  /* Multipart objects can't be in inventory, put'em on floor. */
1229  if (!tmp->more) {
1230  tmp = object_insert_in_ob(tmp, op);
1231  } else {
1232  object_insert_in_map_at(tmp, op->map, op, 0, op->x, op->y);
1233  }
1234 
1235  /* Let's put this created item on stack so dm can access it easily. */
1236  dm_stack_push(op->contr, tmp->count);
1237 
1238  return;
1239  }
1240 
1241  for (i = 0; i < (set_nrof ? nrof : 1); i++) {
1242  archetype *atmp;
1243  object *prev = NULL, *head = NULL, *dup;
1244 
1245  for (atmp = at; atmp != NULL; atmp = atmp->more) {
1246  dup = arch_to_object(atmp);
1247 
1248  if (at_spell)
1249  object_insert_in_ob(arch_to_object(at_spell), dup);
1250 
1251  /*
1252  * The head is what contains all the important bits,
1253  * so just copying it over should be fine.
1254  */
1255  if (head == NULL) {
1256  head = dup;
1257  object_copy(tmp, dup);
1258  }
1259  if (settings.real_wiz == FALSE)
1260  SET_FLAG(dup, FLAG_WAS_WIZ);
1261  dup->x = op->x+dup->arch->clone.x;
1262  dup->y = op->y+dup->arch->clone.y;
1263  dup->map = op->map;
1264 
1265  if (head != dup) {
1266  dup->head = head;
1267  prev->more = dup;
1268  }
1269  prev = dup;
1270  }
1271 
1272  if (QUERY_FLAG(head, FLAG_ALIVE)) {
1273  object *check = head;
1274  int size_x = 0;
1275  int size_y = 0;
1276 
1277  while (check) {
1278  size_x = MAX(size_x, check->arch->clone.x);
1279  size_y = MAX(size_y, check->arch->clone.y);
1280  check = check->more;
1281  }
1282 
1283  if (out_of_map(op->map, head->x+size_x, head->y+size_y)) {
1284  if (head->x < size_x || head->y < size_y) {
1285  dm_stack_pop(op->contr);
1288  "Object too big to insert in map, or wrong position.");
1290  return;
1291  }
1292 
1293  check = head;
1294  while (check) {
1295  check->x -= size_x;
1296  check->y -= size_y;
1297  check = check->more;
1298  }
1299  }
1300 
1301  object_insert_in_map_at(head, op->map, op, 0, head->x, head->y);
1302  } else
1303  head = object_insert_in_ob(head, op);
1304 
1305  /* Let's put this created item on stack so dm can access it easily. */
1306  /* Wonder if we really want to push all of these, but since
1307  * things like rods have nrof 0, we want to cover those.
1308  */
1309  dm_stack_push(op->contr, head->count);
1310 
1311  if (at->clone.randomitems != NULL && !at_spell) {
1312  create_treasure(at->clone.randomitems, head, 0, op->map->difficulty, 0);
1313  if (QUERY_FLAG(head, FLAG_MONSTER)) {
1315  }
1316  }
1317  }
1318 
1319  /* free the one we used to copy */
1321 }
1322 
1323 /*
1324  * Now follows dm-commands which are also acceptable from sockets
1325  */
1326 
1335 void command_inventory(object *op, const char *params) {
1336  object *tmp;
1337  int i;
1338 
1339  if (*params == '\0') {
1340  inventory(op, NULL);
1341  return;
1342  }
1343 
1344  if (!sscanf(params, "%d", &i) || (tmp = object_find_by_tag_global(i)) == NULL) {
1346  "Inventory of what object (nr)?");
1347  return;
1348  }
1349 
1350  inventory(op, tmp);
1351 }
1352 
1365 void command_skills(object *op, const char *params) {
1366  show_skills(op, *params == '\0' ? NULL : params);
1367 }
1368 
1377 void command_dump(object *op, const char *params) {
1378  object *tmp;
1379  StringBuffer *sb;
1380  char *diff;
1381 
1382  tmp = get_dm_object(op->contr, &params, NULL);
1383  if (!tmp)
1384  return;
1385 
1386  sb = stringbuffer_new();
1387  object_dump(tmp, sb);
1388  diff = stringbuffer_finish(sb);
1390  free(diff);
1391  if (QUERY_FLAG(tmp, FLAG_OBJ_ORIGINAL))
1393  "Object is marked original");
1394 }
1395 
1405 void command_mon_aggr(object *op, const char *params) {
1406  if (op->enemy || !QUERY_FLAG(op, FLAG_UNAGGRESSIVE)) {
1407  object_set_enemy(op, NULL);
1410  "Aggression turned OFF");
1411  } else {
1415  "Aggression turned ON");
1416  }
1417 }
1418 
1431 void command_possess(object *op, const char *params) {
1432  object *victim;
1433  player *pl;
1434  int i;
1435  char buf[MAX_BUF];
1436 
1437  victim = NULL;
1438  if (*params != '\0') {
1439  if (sscanf(params, "%d", &i))
1440  victim = object_find_by_tag_global(i);
1441  else if (sscanf(params, "%s", buf))
1442  victim = object_find_by_name_global(buf);
1443  }
1444  if (victim == NULL) {
1446  "Patch what object (nr)?");
1447  return;
1448  }
1449 
1450  if (victim == op) {
1452  "As insane as you are, I cannot allow you to possess yourself.");
1453  return;
1454  }
1455 
1456  /* make the switch */
1457  pl = op->contr;
1458  victim->contr = pl;
1459  pl->ob = victim;
1460  victim->type = PLAYER;
1461  SET_FLAG(victim, FLAG_WIZ);
1462 
1463  /* basic patchup */
1464  /* The use of hard coded values is terrible. Note
1465  * that really, to be fair, this shouldn't get changed at
1466  * all - if you are possessing a kobold, you should have the
1467  * same limitations. As it is, as more body locations are added,
1468  * this will give this player more locations than perhaps
1469  * they should be allowed.
1470  */
1471  for (i = 0; i < NUM_BODY_LOCATIONS; i++)
1472  if (i == 1 || i == 6 || i == 8 || i == 9)
1473  victim->body_info[i] = 2;
1474  else
1475  victim->body_info[i] = 1;
1476 
1477  esrv_new_player(pl, 80); /* just pick a weight, we don't care */
1478  esrv_send_inventory(victim, victim);
1479 
1480  fix_object(victim);
1481 
1482  do_some_living(victim);
1483 }
1484 
1492 void command_patch(object *op, const char *params) {
1493  const char *arg, *arg2;
1494  object *tmp;
1495 
1496  tmp = get_dm_object(op->contr, &params, NULL);
1497  if (!tmp)
1498  /* Player already informed of failure */
1499  return;
1500 
1501  /* params set to first value by get_dm_default */
1502  arg = params;
1503  if (*arg == '\0') {
1505  "Patch what values?");
1506  return;
1507  }
1508 
1509  if ((arg2 = strchr(arg, ' ')))
1510  arg2++;
1511  if (settings.real_wiz == FALSE)
1512  SET_FLAG(tmp, FLAG_WAS_WIZ); /* To avoid cheating */
1513  if (set_variable(tmp, arg) == -1)
1515  "Unknown variable %s",
1516  arg);
1517  else {
1519  "(%s#%d)->%s=%s",
1520  tmp->name, tmp->count, arg, arg2);
1521  }
1522 }
1523 
1532 void command_remove(object *op, const char *params) {
1533  object *tmp;
1534  int from;
1535 
1536  tmp = get_dm_object(op->contr, &params, &from);
1537  if (!tmp) {
1539  "Remove what object (nr)?");
1540  return;
1541  }
1542 
1543  if (tmp->type == PLAYER) {
1545  "Unable to remove a player!");
1546  return;
1547  }
1548 
1549  if (QUERY_FLAG(tmp, FLAG_REMOVED)) {
1550  char name[MAX_BUF];
1551 
1552  query_name(tmp, name, MAX_BUF);
1554  "%s is already removed!",
1555  name);
1556  return;
1557  }
1558 
1559  if (from != STACK_FROM_STACK)
1560  /* Item is either stack top, or is a number thus is now stack top, let's remove it */
1561  dm_stack_pop(op->contr);
1562 
1563  /* Always work on the head - otherwise object will get in odd state */
1564  tmp = HEAD(tmp);
1565  if (tmp->speed != 0) {
1566  tmp->speed = 0;
1567  object_update_speed(tmp);
1568  }
1569  object_remove(tmp);
1570 }
1571 
1579 void command_free(object *op, const char *params) {
1580  object *tmp;
1581  int from;
1582 
1583  tmp = get_dm_object(op->contr, &params, &from);
1584 
1585  if (!tmp) {
1587  "Free what object (nr)?");
1588  return;
1589  }
1590 
1591  if (from != STACK_FROM_STACK)
1592  /* Item is either stack top, or is a number thus is now stack top, let's remove it */
1593  dm_stack_pop(op->contr);
1594 
1595  tmp = HEAD(tmp);
1596  if (!QUERY_FLAG(tmp, FLAG_REMOVED)) {
1598  "Warning: item was not removed, will do so now.");
1599  object_remove(tmp);
1600  }
1601 
1603 }
1604 
1613 void command_addexp(object *op, const char *params) {
1614  char buf[MAX_BUF], skill[MAX_BUF];
1615  int i, q;
1616  object *skillob = NULL;
1617  player *pl;
1618 
1619  skill[0] = '\0';
1620  if ((*params == '\0')
1621  || (strlen(params) > MAX_BUF)
1622  || ((q = sscanf(params, "%s %d %[^\r\n]", buf, &i, skill)) < 2)) {
1624  "Usage: addexp player quantity [skill].");
1625  return;
1626  }
1627 
1628  for (pl = first_player; pl != NULL; pl = pl->next)
1629  if (!strncmp(pl->ob->name, buf, MAX_NAME))
1630  break;
1631 
1632  if (pl == NULL) {
1634  "No such player.");
1635  return;
1636  }
1637 
1638  if (q >= 3) {
1639  skillob = find_skill_by_name(pl->ob, skill);
1640  if (!skillob) {
1642  "Unable to find skill %s in %s",
1643  skill, buf);
1644  return;
1645  }
1646 
1647  i = check_exp_adjust(skillob, i);
1648  skillob->stats.exp += i;
1649  calc_perm_exp(skillob);
1650  player_lvl_adj(pl->ob, skillob);
1651  }
1652 
1653  pl->ob->stats.exp += i;
1654  calc_perm_exp(pl->ob);
1655  player_lvl_adj(pl->ob, NULL);
1656 
1657  if (settings.real_wiz == FALSE)
1658  SET_FLAG(pl->ob, FLAG_WAS_WIZ);
1659 }
1660 
1669 void command_speed(object *op, const char *params) {
1670  int i;
1671 
1672  if (*params == '\0' || !sscanf(params, "%d", &i)) {
1674  "Current speed is %d",
1675  max_time);
1676  return;
1677  }
1678 
1679  set_max_time(i);
1680  reset_sleep();
1682  "The speed is changed to %d.",
1683  i);
1684 }
1685 
1686 /**************************************************************************/
1687 /* Mods made by Tyler Van Gorder, May 10-13, 1992. */
1688 /* CSUChico : tvangod@cscihp.ecst.csuchico.edu */
1689 /**************************************************************************/
1690 
1699 void command_stats(object *op, const char *params) {
1700  player *pl;
1701 
1702  if (*params == '\0') {
1704  "Who?");
1705  return;
1706  }
1707 
1708  pl = find_player_partial_name(params);
1709  if (pl == NULL) {
1711  "No such player.");
1712  return;
1713  }
1714 
1716  "[Fixed]Statistics for %s:", pl->ob->name);
1717 
1719  "[fixed]Str : %-2d H.P. : %-4d MAX : %d",
1720  pl->ob->stats.Str, pl->ob->stats.hp, pl->ob->stats.maxhp);
1721 
1723  "[fixed]Dex : %-2d S.P. : %-4d MAX : %d",
1724  pl->ob->stats.Dex, pl->ob->stats.sp, pl->ob->stats.maxsp);
1725 
1727  "[fixed]Con : %-2d AC : %-4d WC : %d",
1728  pl->ob->stats.Con, pl->ob->stats.ac, pl->ob->stats.wc);
1729 
1731  "[fixed]Int : %-2d Damage : %d",
1732  pl->ob->stats.Int, pl->ob->stats.dam);
1733 
1735  "[fixed]Wis : %-2d EXP : %"FMT64,
1736  pl->ob->stats.Wis, pl->ob->stats.exp);
1737 
1739  "[fixed]Pow : %-2d Grace : %d",
1740  pl->ob->stats.Pow, pl->ob->stats.grace);
1741 
1743  "[fixed]Cha : %-2d Food : %d",
1744  pl->ob->stats.Cha, pl->ob->stats.food);
1745 }
1746 
1756 void command_abil(object *op, const char *params) {
1757  char thing[20], thing2[20];
1758  int iii;
1759  player *pl;
1760 
1761  iii = 0;
1762  thing[0] = '\0';
1763  thing2[0] = '\0';
1764  if (*params == '\0'
1765  || sscanf(params, "%s %s %d", thing, thing2, &iii) != 3
1766  || thing[0] == '\0') {
1768  "Who?");
1769  return;
1770  }
1771 
1772  if (thing2[0] == '\0') {
1774  "You can't change that.");
1775  return;
1776  }
1777 
1778  if (iii < MIN_STAT || iii > settings.max_stat) {
1780  "Illegal range of stat.\n");
1781  return;
1782  }
1783 
1784  for (pl = first_player; pl != NULL; pl = pl->next) {
1785  if (!strcmp(pl->ob->name, thing)) {
1786  if (settings.real_wiz == FALSE)
1787  SET_FLAG(pl->ob, FLAG_WAS_WIZ);
1788  if (!strcmp("str", thing2))
1789  pl->ob->stats.Str = iii, pl->orig_stats.Str = iii;
1790  if (!strcmp("dex", thing2))
1791  pl->ob->stats.Dex = iii, pl->orig_stats.Dex = iii;
1792  if (!strcmp("con", thing2))
1793  pl->ob->stats.Con = iii, pl->orig_stats.Con = iii;
1794  if (!strcmp("wis", thing2))
1795  pl->ob->stats.Wis = iii, pl->orig_stats.Wis = iii;
1796  if (!strcmp("cha", thing2))
1797  pl->ob->stats.Cha = iii, pl->orig_stats.Cha = iii;
1798  if (!strcmp("int", thing2))
1799  pl->ob->stats.Int = iii, pl->orig_stats.Int = iii;
1800  if (!strcmp("pow", thing2))
1801  pl->ob->stats.Pow = iii, pl->orig_stats.Pow = iii;
1803  "%s has been altered.",
1804  pl->ob->name);
1805  fix_object(pl->ob);
1806  return;
1807  }
1808  }
1809 
1811  "No such player.");
1812 }
1813 
1822 void command_reset(object *op, const char *params) {
1823  mapstruct *m;
1824  object *dummy = NULL, *tmp = NULL;
1825  char path[HUGE_BUF];
1826  const char *space, *confirmation = NULL;
1827  int res = 0;
1828 
1829  if (*params == '\0') {
1831  MSG_TYPE_COMMAND_ERROR, "Which map should be reset?");
1832  return;
1833  }
1834 
1835  space = strchr(params, ' ');
1836  if (space != NULL) {
1837  confirmation = params;
1838  params = space + 1;
1839  }
1840 
1841  /* Use the DM's map if the current map was given. */
1842  if (strcmp(params, ".") == 0) {
1843  snprintf(path, sizeof(path), "%s", op->map->path);
1844  } else {
1845  path_combine_and_normalize(op->map->path, params, path, sizeof(path));
1846  }
1847 
1848  m = has_been_loaded(path);
1849  if (m == NULL) {
1851  MSG_TYPE_COMMAND_ERROR, "No such map.");
1852  return;
1853  }
1854 
1855  if (confirmation) {
1856  if (strcmp(params, ".") == 0 && m->unique) {
1859  "Cannot reset a unique player map while on it. Use "
1860  "'reset full-reset %s' while standing somewhere else.",
1861  m->path);
1862  return;
1863  }
1864 
1865  if (strncmp("full-reset", confirmation, strlen("full-reset"))) {
1867  MSG_TYPE_COMMAND_ERROR, "Confirm using 'full-reset'.");
1868  return;
1869  }
1870  }
1871 
1872  /* Forbid using reset on our own map when we're in a transport, as
1873  * it has the displeasant effect of crashing the server.
1874  * - gros, July 25th 2006 */
1875  if ((op->contr && op->contr->transport) && (op->map == m)) {
1877  "You need to disembark first.");
1878  return;
1879  }
1880 
1881  snprintf(path, sizeof(path), "%s", m->path);
1882 
1883  if (m->in_memory != MAP_SWAPPED) {
1884  if (m->in_memory != MAP_IN_MEMORY) {
1885  LOG(llevError, "Tried to swap out map which was not in memory.\n");
1886  return;
1887  }
1888 
1889  /*
1890  * Only attempt to remove the player that is doing the reset, and not other
1891  * players or wiz's.
1892  */
1893  if (op->map == m) {
1894  if (strncmp(m->path, "/random/", 8) == 0) {
1895  /* This is not a very satisfying solution - it would be much better
1896  * to recreate a random map with the same seed value as the old one.
1897  * Unfortunately, I think recreating the map would require some
1898  * knowledge about its 'parent', which appears very non-trivial to
1899  * me.
1900  * On the other hand, this should prevent the freeze that this
1901  * situation caused. - gros, 26th July 2006.
1902  */
1904  "You cannot reset a random map when inside it.");
1905  return;
1906  }
1907 
1908  dummy = object_new();
1909  dummy->map = NULL;
1910  EXIT_X(dummy) = op->x;
1911  EXIT_Y(dummy) = op->y;
1912  EXIT_PATH(dummy) = add_string(op->map->path);
1913  object_remove(op);
1914  op->map = NULL;
1915  tmp = op;
1916  }
1917  res = swap_map(m);
1918  }
1919 
1920  if (res < 0 || m->in_memory != MAP_SWAPPED) {
1921  player *pl;
1922  int playercount = 0;
1923 
1924  /* Need to re-insert player if swap failed for some reason */
1925  if (tmp) {
1926  object_insert_in_map_at(op, m, NULL, 0, op->x, op->y);
1928  }
1929 
1930  if (res < 0 && res != SAVE_ERROR_PLAYER)
1931  /* no need to warn if player on map, code below checks that. */
1933  "Reset failed, error code: %d.", res);
1934  else {
1936  "Reset failed, couldn't swap map, the following players are on it:");
1937  for (pl = first_player; pl != NULL; pl = pl->next) {
1938  if (pl->ob->map == m && pl->ob != op) {
1940  pl->ob->name);
1941  playercount++;
1942  }
1943  }
1944  if (!playercount)
1946  "hmm, I don't see any other players on this map, something else is the problem.");
1947  return;
1948  }
1949  }
1950 
1951  /* Here, map reset succeeded. */
1952 
1953  if (m && m->in_memory == MAP_SWAPPED) {
1954  if (confirmation) {
1956  LOG(llevDebug, "DM %s fully resetting map %s.\n", op->name, m->path);
1957  } else
1958  LOG(llevDebug, "DM %s resetting map %s.\n", op->name, m->path);
1959 
1960  /* setting this effectively causes an immediate reload */
1961  m->reset_time = 1;
1962  flush_old_maps();
1963  }
1964 
1965  /* Display the appropriate success message. */
1966  if (confirmation) {
1968  MSG_TYPE_COMMAND_DM, "Fully resetting map %s.", path);
1969  } else {
1971  MSG_TYPE_COMMAND_DM, "Resetting map %s.", path);
1972  }
1973 
1974  if (tmp) {
1975  enter_exit(tmp, dummy);
1977  }
1978 
1979  /* Remind the DM how to fully reset the map. */
1980  if (confirmation == NULL) {
1983  "Use 'reset full-reset %s' to fully reset the map.", params);
1984  }
1985 }
1986 
1995 void command_nowiz(object *op, const char *params) { /* 'noadm' is alias */
1996  CLEAR_FLAG(op, FLAG_WIZ);
1997  CLEAR_FLAG(op, FLAG_WIZPASS);
1998  CLEAR_FLAG(op, FLAG_WIZCAST);
1999  if (op->contr->followed_player)
2001 
2002  if (settings.real_wiz == TRUE)
2003  CLEAR_FLAG(op, FLAG_WAS_WIZ);
2004  if (op->contr->hidden) {
2006  "You are no longer hidden from other players");
2007  op->map->players++;
2009  "%s has entered the game.",
2010  op->name);
2011  op->contr->hidden = 0;
2012  op->invisible = 1;
2013  } else
2015  "The Dungeon Master is gone..");
2016 
2017  update_los(op);
2018 }
2019 
2040 static int checkdm(object *op, const char *pl_name, const char *pl_passwd, const char *pl_host) {
2041  FILE *dmfile;
2042  char buf[MAX_BUF];
2043  char line_buf[160], name[160], passwd[160], host[160];
2044 
2045 #ifdef RESTRICTIVE_DM
2046  *pl_name = op->name ? op->name : "*";
2047 #endif
2048 
2049  snprintf(buf, sizeof(buf), "%s/%s", settings.confdir, DMFILE);
2050  if ((dmfile = fopen(buf, "r")) == NULL) {
2051  LOG(llevDebug, "Could not find DM file.\n");
2052  return 0;
2053  }
2054 
2055  while (fgets(line_buf, 160, dmfile) != NULL) {
2056  if (line_buf[0] == '#')
2057  continue;
2058  if (sscanf(line_buf, "%[^:]:%[^:]:%s\n", name, passwd, host) != 3) {
2059  LOG(llevError, "Warning - malformed dm file entry: %s\n", line_buf);
2060  } else if ((!strcmp(name, "*") || (pl_name && !strcmp(pl_name, name)))
2061  && (!strcmp(passwd, "*") || !strcmp(passwd, pl_passwd))
2062  && (!strcmp(host, "*") || !strcmp(host, pl_host))) {
2063  fclose(dmfile);
2064  return (1);
2065  }
2066  }
2067  fclose(dmfile);
2068  return (0);
2069 }
2070 
2085 static int do_wizard_dm(object *op, const char *params, int silent) {
2086  if (!op->contr)
2087  return 0;
2088 
2089  if (QUERY_FLAG(op, FLAG_WIZ)) {
2091  "You are already the Dungeon Master!");
2092  return 0;
2093  }
2094 
2095  if (checkdm(op, op->name, (*params != '\0' ? params : "*"), op->contr->socket.host)) {
2096  SET_FLAG(op, FLAG_WIZ);
2097  SET_FLAG(op, FLAG_WAS_WIZ);
2098  SET_FLAG(op, FLAG_WIZPASS);
2099  SET_FLAG(op, FLAG_WIZCAST);
2101  "Ok, you are the Dungeon Master!");
2102  /*
2103  * Remove setting flying here - that won't work, because next
2104  * fix_object() is called that will get cleared - proper solution
2105  * is probably something like a wiz_force which gives that and any
2106  * other desired abilities.
2107  */
2108  clear_los(op);
2109  op->contr->write_buf[0] = '\0';
2110 
2111  if (!silent)
2114  "The Dungeon Master has arrived!");
2115 
2116  return 1;
2117  }
2118 
2120  "Sorry Pal, I don't think so.");
2121  op->contr->write_buf[0] = '\0';
2122  return 0;
2123 }
2124 
2136 void command_dm(object *op, const char *params) {
2137  do_wizard_dm(op, params, 0);
2138 }
2139 
2148 void command_invisible(object *op, const char *params) {
2149  if (op) {
2150  op->invisible += 100;
2153  "You turn invisible.");
2154  }
2155 }
2156 
2174 static object *get_spell_by_name(object *op, const char *spell_name) {
2175  archetype *ar;
2176  archetype *found;
2177  int conflict_found;
2178  size_t spell_name_length;
2179 
2180  /* First check for full name matches. */
2181  conflict_found = 0;
2182  found = NULL;
2183  for (ar = first_archetype; ar != NULL; ar = ar->next) {
2184  if (ar->clone.type != SPELL)
2185  continue;
2186 
2187  if (strncmp(ar->name, "spelldirect_", 12) == 0)
2188  continue;
2189 
2190  if (strcmp(ar->clone.name, spell_name) != 0)
2191  continue;
2192 
2193  if (found != NULL) {
2194  if (!conflict_found) {
2195  conflict_found = 1;
2197  "More than one archetype matches the spell name %s:",
2198  spell_name);
2200  "- %s",
2201  found->name);
2202  }
2204  "- %s",
2205  ar->name);
2206  continue;
2207  }
2208 
2209  found = ar;
2210  }
2211 
2212  /* No match if more more than one archetype matches. */
2213  if (conflict_found)
2214  return NULL;
2215 
2216  /* Return if exactly one archetype matches. */
2217  if (found != NULL)
2218  return arch_to_object(found);
2219 
2220  /* No full match found: now check for partial matches. */
2221  spell_name_length = strlen(spell_name);
2222  conflict_found = 0;
2223  found = NULL;
2224  for (ar = first_archetype; ar != NULL; ar = ar->next) {
2225  if (ar->clone.type != SPELL)
2226  continue;
2227 
2228  if (strncmp(ar->name, "spelldirect_", 12) == 0)
2229  continue;
2230 
2231  if (strncmp(ar->clone.name, spell_name, spell_name_length) != 0)
2232  continue;
2233 
2234  if (found != NULL) {
2235  if (!conflict_found) {
2236  conflict_found = 1;
2238  "More than one spell matches %s:",
2239  spell_name);
2241  "- %s",
2242  found->clone.name);
2243  }
2245  "- %s",
2246  ar->clone.name);
2247  continue;
2248  }
2249 
2250  found = ar;
2251  }
2252 
2253  /* No match if more more than one archetype matches. */
2254  if (conflict_found)
2255  return NULL;
2256 
2257  /* Return if exactly one archetype matches. */
2258  if (found != NULL)
2259  return arch_to_object(found);
2260 
2261  /* No spell found: just print an error message. */
2263  "The spell %s does not exist.",
2264  spell_name);
2265  return NULL;
2266 }
2267 
2278 static void command_learn_spell_or_prayer(object *op, const char *params, int special_prayer) {
2279  object *tmp;
2280 
2281  if (op->contr == NULL || *params == '\0') {
2283  "Which spell do you want to learn?");
2284  return;
2285  }
2286 
2287  tmp = get_spell_by_name(op, params);
2288  if (tmp == NULL) {
2289  return;
2290  }
2291 
2292  if (check_spell_known(op, tmp->name)) {
2294  "You already know the spell %s.",
2295  tmp->name);
2296  return;
2297  }
2298 
2299  do_learn_spell(op, tmp, special_prayer);
2301 }
2302 
2311 void command_learn_spell(object *op, const char *params) {
2312  command_learn_spell_or_prayer(op, params, 0);
2313 }
2314 
2323 void command_learn_special_prayer(object *op, const char *params) {
2324  command_learn_spell_or_prayer(op, params, 1);
2325 }
2326 
2336 void command_forget_spell(object *op, const char *params) {
2337  object *spell;
2338 
2339  if (op->contr == NULL || *params == '\0') {
2341  "Which spell do you want to forget?");
2342  return;
2343  }
2344 
2345  spell = lookup_spell_by_name(op, params);
2346  if (spell == NULL) {
2348  "You do not know the spell %s.",
2349  params);
2350  return;
2351  }
2352 
2353  do_forget_spell(op, spell->name);
2354 }
2355 
2364 void command_listplugins(object *op, const char *params) {
2366 }
2367 
2378 void command_loadplugin(object *op, const char *params) {
2379  char buf[MAX_BUF];
2380 
2381  if (*params == '\0') {
2383  "Load which plugin?");
2384  return;
2385  }
2386 
2387  strcpy(buf, LIBDIR);
2388  strcat(buf, "/plugins/");
2389  strcat(buf, params);
2390  LOG(llevDebug, "Requested plugin file is %s\n", buf);
2391  if (plugins_init_plugin(buf) == 0) {
2392  LOG(llevInfo, "DM %s loaded plugin %s\n", op->name, params);
2394  "Plugin %s successfully loaded.",
2395  params);
2396  } else
2398  "Could not load plugin %s.",
2399  params);
2400 }
2401 
2412 void command_unloadplugin(object *op, const char *params) {
2413  if (*params == '\0') {
2415  "Remove which plugin?");
2416  return;
2417  }
2418 
2419  if (plugins_remove_plugin(params) == 0) {
2420  LOG(llevInfo, "DM %s unloaded plugin %s\n", op->name, params);
2422  "Plugin %s successfully removed.",
2423  params);
2424  } else
2426  "Could not remove plugin %s.",
2427  params);
2428 }
2429 
2440 void command_dmhide(object *op, const char *params) {
2441  if (!do_wizard_dm(op, params, 1))
2442  return;
2443 
2444  do_wizard_hide(op, 1);
2445 }
2446 
2455 void command_stack_pop(object *op, const char *params) {
2456  dm_stack_pop(op->contr);
2457 }
2458 
2467 void command_stack_push(object *op, const char *params) {
2468  object *ob;
2469  int from;
2470  ob = get_dm_object(op->contr, &params, &from);
2471 
2472  if (ob && from != STACK_FROM_NUMBER)
2473  /* Object was from stack, need to push it again */
2474  dm_stack_push(op->contr, ob->count);
2475 }
2476 
2485 void command_stack_list(object *op, const char *params) {
2486  int item;
2487  object *display;
2488  player *pl = op->contr;
2489 
2491  "Item stack contents:");
2492 
2493  for (item = 0; item < pl->stack_position; item++) {
2494  display = object_find_by_tag_global(pl->stack_items[item]);
2495  if (display)
2497  " %d : %s [%d]",
2498  item, display->name, display->count);
2499  else
2500  /* Item was freed */
2502  " %d : (lost item: %d)",
2503  item, pl->stack_items[item]);
2504  }
2505 }
2506 
2515 void command_stack_clear(object *op, const char *params) {
2516  op->contr->stack_position = 0;
2518  "Item stack cleared.");
2519 }
2520 
2540 void command_diff(object *op, const char *params) {
2541  object *left, *right;
2542  char *diff;
2543  StringBuffer *sb;
2544  int left_from, right_from;
2545 
2546  left = get_dm_object(op->contr, &params, &left_from);
2547  if (!left) {
2549  "Compare to what item?");
2550  return;
2551  }
2552 
2553  if (left_from == STACK_FROM_NUMBER)
2554  /* Item was stacked, remove it else right will be the same... */
2555  dm_stack_pop(op->contr);
2556 
2557  right = get_dm_object(op->contr, &params, &right_from);
2558 
2559  if (!right) {
2561  "Compare what item?");
2562  return;
2563  }
2564 
2566  "Item difference:");
2567 
2568  if (left_from == STACK_FROM_TOP && right_from == STACK_FROM_TOP) {
2569  /*
2570  * Special case: both items were taken from stack top.
2571  * Override the behaviour, taking left as item just below top, if exists.
2572  * See function description for why.
2573  * Besides, if we don't do anything, compare an item to itself, not really useful.
2574  */
2575  if (op->contr->stack_position > 1) {
2577  if (left)
2579  "(Note: first item taken from undertop)");
2580  else
2581  /* Stupid case: item under top was freed, fallback to stack top */
2582  left = right;
2583  }
2584  }
2585 
2586  sb = stringbuffer_new();
2587  get_ob_diff(sb, left, right);
2588  diff = stringbuffer_finish(sb);
2589  if (*diff == '\0') {
2590  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_DM, "Objects are the same.");
2591  } else {
2593  }
2594  free(diff);
2595 }
2596 
2604 void command_insert_into(object *op, const char *params) {
2605  object *left, *right, *inserted;
2606  int left_from, right_from;
2607  char what[MAX_BUF], where[MAX_BUF];
2608 
2609  left = get_dm_object(op->contr, &params, &left_from);
2610  if (!left) {
2612  "Insert into what object?");
2613  return;
2614  }
2615 
2616  if (left_from == STACK_FROM_NUMBER)
2617  /* Item was stacked, remove it else right will be the same... */
2618  dm_stack_pop(op->contr);
2619 
2620  right = get_dm_object(op->contr, &params, &right_from);
2621 
2622  if (!right) {
2624  "Insert what item?");
2625  return;
2626  }
2627 
2628  if (left_from == STACK_FROM_TOP && right_from == STACK_FROM_TOP) {
2629  /*
2630  * Special case: both items were taken from stack top.
2631  * Override the behaviour, taking left as item just below top, if exists.
2632  * See function description for why.
2633  * Besides, can't insert an item into itself.
2634  */
2635  if (op->contr->stack_position > 1) {
2637  if (left)
2639  "(Note: item to insert into taken from undertop)");
2640  else
2641  /* Stupid case: item under top was freed, fallback to stack top */
2642  left = right;
2643  }
2644  }
2645 
2646  if (left == right) {
2648  "Can't insert an object into itself!");
2649  return;
2650  }
2651 
2652  if (right->type == PLAYER) {
2654  "Can't insert a player into something!");
2655  return;
2656  }
2657 
2658  if (!QUERY_FLAG(right, FLAG_REMOVED))
2659  object_remove(right);
2660  inserted = object_insert_in_ob(right, left);
2661  if (left->type == PLAYER) {
2662  if (inserted != right)
2663  /* item was merged, so updating name and such. */
2664  esrv_update_item(UPD_WEIGHT|UPD_NAME|UPD_NROF, left, inserted);
2665  }
2666  query_name(inserted, what, MAX_BUF);
2667  query_name(left, where, MAX_BUF);
2669  "Inserted %s in %s",
2670  what, where);
2671 }
2672 
2681 void command_style_map_info(object *op, const char *params) {
2682  extern mapstruct *styles;
2683  mapstruct *mp;
2684  int maps_used = 0, mapmem = 0, objects_used = 0, x, y;
2685 
2686  for (mp = styles; mp != NULL; mp = mp->next) {
2687  maps_used++;
2688  mapmem += map_size(mp) * (sizeof(object *)+sizeof(MapSpace))+sizeof(mapstruct);
2689  for (x = 0; x < MAP_WIDTH(mp); x++) {
2690  for (y = 0; y < MAP_HEIGHT(mp); y++) {
2691  FOR_MAP_PREPARE(mp, x, y, tmp)
2692  objects_used++;
2693  FOR_MAP_FINISH();
2694  }
2695  }
2696  }
2698  "[fixed]Style maps loaded: %d",
2699  maps_used);
2701  "[fixed]Memory used, not");
2703  "[fixed]including objects: %d",
2704  mapmem);
2706  "[fixed]Style objects: %d",
2707  objects_used);
2709  "[fixed]Mem for objects: %lu",
2710  (unsigned long)(objects_used*sizeof(object)));
2711 }
2712 
2721 void command_follow(object *op, const char *params) {
2722  player *other;
2723 
2724  if (*params == '\0') {
2725  if (op->contr->followed_player != NULL) {
2726  draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, "You stop following %s.", op->contr->followed_player);
2728  }
2729  return;
2730  }
2731 
2732  other = find_player_partial_name(params);
2733  if (!other) {
2734  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, "No such player or ambiguous name.");
2735  return;
2736  }
2737  if (other == op->contr) {
2738  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, "You can't follow yourself.");
2739  return;
2740  }
2741 
2742  if (op->contr->followed_player)
2744 
2745  op->contr->followed_player = add_string(other->ob->name);
2747 }
2748 
2749 void command_purge_quest(object *op, const char * param) {
2750  free_quest();
2751  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, "Purged quest state.");
2752 }
2753 
2754 void command_purge_quest_definitions(object *op, const char * param) {
2756  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, "Purged quests definitions.");
2757 }
2758 
2767 void command_dumpbelow(object *op, const char *params) {
2768  if (op && op->below) {
2769  StringBuffer *sb;
2770  char *diff;
2771 
2772  sb = stringbuffer_new();
2773  object_dump(op->below, sb);
2774  diff = stringbuffer_finish(sb);
2776  free(diff);
2777 
2778  /* Let's push that item on the dm's stack */
2779  dm_stack_push(op->contr, op->below->count);
2780  }
2781 }
2782 
2788 void command_settings(object *op, const char *ignored) {
2789  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, i18n(op, "Server settings:"));
2790 
2791  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);
2792 
2793  if (settings.not_permadeth) {
2794  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, i18n(op, " * death is not permanent"));
2795  } else if (settings.resurrection) {
2796  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, i18n(op, " * permanent death, resurrection is enabled"));
2797  } else {
2798  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, i18n(op, " * permanent death, resurrection is NOT enabled"));
2799  }
2800 
2801  if (settings.set_title) {
2802  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, i18n(op, " * players can set their title"));
2803  } else {
2804  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, i18n(op, " * players can't set their title"));
2805  }
2806 
2809  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"));
2810  } else {
2811  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"));
2812  }
2813  } else {
2814  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"));
2815  }
2816 
2817  if (settings.casting_time) {
2818  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, i18n(op, " * casting takes time"));
2819  } else {
2820  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, i18n(op, " * casting is immediate"));
2821  }
2822 
2823  draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, i18n(op, " * permanent experience: %d%%"), settings.permanent_exp_ratio);
2825 
2827 
2829  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, i18n(op, " * players can't steal from other players"));
2830  } else {
2831  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, i18n(op, " * players can steal from other players"));
2832  }
2833 
2835  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, i18n(op, " * players can create portals from their apartments"));
2836  } else {
2837  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, i18n(op, " * players can't create portals from their apartments"));
2838  }
2839 
2841  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, i18n(op, " * players can write spells they are denied"));
2842  } else {
2843  draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, i18n(op, " * players can't write spells they are denied"));
2844  }
2845 }
#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,...)
Sends message to player(s).
Definition: main.c:315
void command_unloadplugin(object *op, const char *params)
Unloads the given plugin.
Definition: c_wiz.c:2412
Error, serious thing.
Definition: logger.h:11
char path[HUGE_BUF]
Filename of the map.
Definition: map.h:365
uint8_t not_permadeth
If true, death is non-permament.
Definition: global.h:260
void command_patch(object *op, const char *params)
Wizard wants to altar an object.
Definition: c_wiz.c:1492
object * lookup_spell_by_name(object *op, const char *spname)
Look at object &#39;op&#39; and see if they know the spell spname.
Definition: spell_util.c:451
int8_t Int
Definition: living.h:35
void command_diff(object *op, const char *params)
Get a diff of specified items.
Definition: c_wiz.c:2540
#define NUM_BODY_LOCATIONS
Number of body locations.
Definition: object.h:13
One player.
Definition: player.h:92
void command_dumpbelow(object *op, const char *params)
Player wants to dump object below her.
Definition: c_wiz.c:2767
int8_t ac
Armour Class, how hard to hit, the lower the better.
Definition: living.h:37
#define BANISHFILE
Definition: config.h:570
void show_skills(object *op, const char *search)
Displays a player&#39;s skill list, and some other non skill related info (god, max weapon improvements...
Definition: skill_util.c:837
#define UP_OBJ_FACE
Only thing that changed was the face.
Definition: object.h:519
uint8_t create_home_portals
If 1, can create portals in unique maps (apartments)
Definition: global.h:309
void command_forget_spell(object *op, const char *params)
Command for players to forget a spell.
Definition: c_wiz.c:2336
void command_dm(object *op, const char *params)
Actual command to perhaps become dm.
Definition: c_wiz.c:2136
int64_t check_exp_adjust(const object *op, int64_t exp)
Returns the maximum experience the object can gain or lose.
Definition: living.c:1999
Spell-related defines: spellpath, subtypes, ...
Information.
Definition: logger.h:12
uint8_t max_stat
Maximum stat value - 255 should be sufficient.
Definition: global.h:322
void enter_exit(object *op, object *exit_ob)
Tries to move &#39;op&#39; to exit_ob.
Definition: server.c:706
void command_loadtest(object *op, const char *params)
This command will stress server.
Definition: c_wiz.c:305
uint32_t worldmaptilesx
Number of tiles wide the worldmap is.
Definition: global.h:291
static object * get_dm_object(player *pl, const char **params, int *from)
Checks &#39;params&#39; for object code.
Definition: c_wiz.c:195
object * check_spell_known(object *op, const char *name)
Checks to see if player knows the spell.
Definition: spell_util.c:435
void free_quest_definitions(void)
Free all quest definitions and steps.
Definition: quest.c:1307
void command_shutdown(object *op, const char *params)
Totally shutdowns the server.
Definition: c_wiz.c:674
uint8_t spell_encumbrance
Encumbrance effects spells.
Definition: global.h:266
void object_give_identified_properties(object *op)
Ensure op has all its "identified" properties set.
Definition: item.c:1375
#define SET_FLAG(xyz, p)
Definition: define.h:223
#define EVENT_KICK
A player was Kicked by a DM.
Definition: plugin.h:97
void do_forget_spell(object *op, const char *spell)
Erases spell from player&#39;s inventory.
Definition: apply.c:432
const artifactlist * find_artifactlist(int type)
Searches the artifact lists and returns one that has the same type of objects on it.
Definition: artifact.c:630
#define NDI_ALL
Inform all players of this message.
Definition: newclient.h:246
See Scroll.
Definition: object.h:221
static int do_wizard_dm(object *op, const char *params, int silent)
Actually changes a player to wizard.
Definition: c_wiz.c:2085
uint8_t death_penalty_level
How many levels worth of exp may be lost on one death.
Definition: global.h:258
void command_hide(object *op, const char *params)
Wizard &#39;hide&#39; command.
Definition: c_wiz.c:385
void do_some_living(object *op)
Regenerate hp/sp/gr, decreases food.
Definition: player.c:3286
void command_learn_spell(object *op, const char *params)
Wizard wants to learn a regular spell.
Definition: c_wiz.c:2311
uint32_t map_size(mapstruct *m)
Calculate map size without intermediate sign extension.
Definition: map.c:830
#define NDI_ORANGE
Definition: newclient.h:225
void command_follow(object *op, const char *params)
DM wants to follow a player, or stop following a player.
Definition: c_wiz.c:2721
#define FLAG_FRIENDLY
Will help players.
Definition: define.h:246
void command_dump(object *op, const char *params)
Dumps the difference between an object and its archetype.
Definition: c_wiz.c:1377
int16_t players
How many players are on this level right now.
Definition: map.h:344
struct artifactstruct * items
Artifacts for this type.
Definition: artifact.h:30
void command_learn_special_prayer(object *op, const char *params)
Wizard wants to learn a god-given spell.
Definition: c_wiz.c:2323
void command_stack_pop(object *op, const char *params)
Pop the stack top.
Definition: c_wiz.c:2455
#define DMFILE
File containing valid names that can be dm, one on each line.
Definition: config.h:370
void command_kick(object *op, const char *params)
Kicks a player from the server.
Definition: c_wiz.c:573
int save_player(object *op, int flag)
Saves a player to disk.
Definition: login.c:211
StringBuffer * stringbuffer_new(void)
Create a new string buffer.
Definition: stringbuffer.c:57
uint32_t in_memory
Combination of IN_MEMORY_xxx flags.
Definition: map.h:345
void command_overlay_reset(object *op, const char *params)
Removes the overlay for op&#39;s current map.
Definition: c_wiz.c:605
uint32_t worldmapstarty
Starting y tile for the worldmap.
Definition: global.h:290
#define HUGE_BUF
Used for messages - some can be quite long.
Definition: define.h:37
void command_stack_list(object *op, const char *params)
Displays stack contents.
Definition: c_wiz.c:2485
void esrv_update_item(int flags, object *pl, object *op)
Updates object *op for player *pl.
Definition: main.c:342
See Spellbook.
Definition: object.h:203
struct treasureliststruct * randomitems
Items to be generated.
Definition: object.h:385
#define MAP_HEIGHT(m)
Map height.
Definition: map.h:80
void command_abil(object *op, const char *params)
Changes an object&#39;s statistics.
Definition: c_wiz.c:1756
object clone
An object from which to do object_copy()
Definition: object.h:470
socket_struct socket
Socket information for this player.
Definition: player.h:94
int16_t invisible
How much longer the object will be invis.
Definition: object.h:360
short freearr_x[SIZEOFFREE]
X offset when searching around a spot.
Definition: object.c:65
uint32_t reset_time
When this map should reset.
Definition: map.h:332
void command_dmhide(object *op, const char *params)
A players wants to become DM and hide.
Definition: c_wiz.c:2440
void esrv_send_inventory(object *pl, object *op)
Sends inventory of a container.
Definition: item.c:307
void command_speed(object *op, const char *params)
Changes the server speed.
Definition: c_wiz.c:1669
See Rod.
Definition: object.h:109
int64_t exp
Experience.
Definition: living.h:46
#define FREE_OBJ_NO_DESTROY_CALLBACK
Do not run the destroy callback.
Definition: object.h:533
void command_summon(object *op, const char *params)
Summons player near DM.
Definition: c_wiz.c:883
void command_create(object *op, const char *params)
Wizard wants to create an object.
Definition: c_wiz.c:996
void command_possess(object *op, const char *params)
DM can possess a monster.
Definition: c_wiz.c:1431
enum Sock_Status status
Definition: newserver.h:100
#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)
object_update() updates the array which represents the map.
Definition: object.c:1239
uint8_t death_penalty_ratio
Hhow much exp should be lost at death.
Definition: global.h:257
int16_t sp
Spell points.
Definition: living.h:41
const object * find_god(const char *name)
Returns pointer to specified god&#39;s object through pntr_to_god_obj().
Definition: gods.c:80
void command_insert_into(object *op, const char *params)
Puts an object into another.
Definition: c_wiz.c:2604
Global type definitions and header inclusions.
#define safe_strncpy
Definition: compat.h:23
void free_quest(void)
Free all quest status structures.
Definition: quest.c:1289
uint32_t hidden
If True, player (DM) is hidden from view.
Definition: player.h:132
uint32_t worldmaptilesy
Number of tiles high the worldmap is.
Definition: global.h:292
struct obj * enemy
Monster/player to follow even if not closest.
Definition: object.h:381
struct archt * other_arch
Pointer used for various things - mostly used for what this objects turns into or what this object cr...
Definition: object.h:413
#define STACK_SIZE
Stack size, static.
Definition: c_wiz.c:33
int swap_map(mapstruct *map)
Swaps a map to disk.
Definition: swap.c:135
void command_freeze(object *op, const char *params)
Freezes a player for a specified tick count, 100 by default.
Definition: c_wiz.c:762
void draw_ext_info(int flags, int pri, const object *pl, uint8_t type, uint8_t subtype, const char *message)
Sends message to player(s).
Definition: main.c:310
The archetype structure is a set of rules on how to generate and manipulate objects which point to ar...
Definition: object.h:465
#define ST_PLAYING
Usual state.
Definition: define.h:577
#define NDI_DK_ORANGE
DarkOrange2.
Definition: newclient.h:227
char * host
Which host it is connected from (ip address).
Definition: newserver.h:110
See Wand & Staff.
Definition: object.h:220
void command_purge_quest(object *op, const char *param)
Definition: c_wiz.c:2749
object * get_jail_exit(object *op)
Returns an object which is an exit through which the player represented by op should be sent in order...
Definition: region.c:260
uint8_t casting_time
It takes awhile to cast a spell.
Definition: global.h:268
void command_inventory(object *op, const char *params)
Shows the inventory or some item.
Definition: c_wiz.c:1335
int16_t maxsp
Max spell points.
Definition: living.h:42
int8_t Con
Definition: living.h:35
#define FLAG_REMOVED
Object is not in any map or invenory.
Definition: define.h:232
int16_t hp
Hit Points.
Definition: living.h:39
int stack_position
Current stack position, 0 for no item.
Definition: player.h:200
short freearr_y[SIZEOFFREE]
Y offset when searching around a spot.
Definition: object.c:71
#define FLAG_KNOWN_MAGICAL
The object is known to be magical.
Definition: define.h:320
void create_treasure(treasurelist *t, object *op, int flag, int difficulty, int tries)
This calls the appropriate treasure creation function.
Definition: treasure.c:490
uint32_t no_shout
if True, player is *not *able to use shout command.
Definition: player.h:133
#define MSG_TYPE_ADMIN_DM
DM related admin actions.
Definition: newclient.h:475
void command_mon_aggr(object *op, const char *params)
When DM is possessing a monster, flip aggression on and off, to allow better motion.
Definition: c_wiz.c:1405
#define MAP_IN_MEMORY
Map is fully loaded.
Definition: map.h:130
void object_free_drop_inventory(object *ob)
Frees everything allocated by an object, removes it from the list of used objects, and puts it on the list of free objects.
Definition: object.c:1368
int16_t y
Position in the map for this object.
Definition: object.h:326
void esrv_new_player(player *pl, uint32_t weight)
Tells the client that here is a player it should start using.
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)
Same as object_insert_in_map() except it handle separate coordinates and do a clean job preparing mul...
Definition: object.c:1921
int16_t maxhp
Max hit points.
Definition: living.h:40
#define NDI_RED
Definition: newclient.h:224
void flush_old_maps(void)
Removes tmp-files of maps which are going to be reset next time they are visited. ...
Definition: swap.c:294
void player_lvl_adj(object *who, object *op)
For the new exp system.
Definition: living.c:1768
#define MSG_TYPE_COMMAND
Responses to commands, eg, who.
Definition: newclient.h:379
void object_dump(const object *op, StringBuffer *sb)
Dumps an object.
Definition: object.c:394
#define FLAG_ALIVE
Object can fight (or be fought)
Definition: define.h:230
int legal_artifact_combination(const object *op, const artifact *art)
Checks if op can be combined with art.
Definition: artifact.c:221
static void do_wizard_hide(object *op, int silent_dm)
Actually hides or unhides specified player (obviously a DM).
Definition: c_wiz.c:340
object * object_new(void)
Grabs an object from the list of unused objects, makes sure it is initialised, and returns it...
Definition: object.c:1037
mapstruct * styles
Loaded styles maps cache, to avoid having to load all the time.
Definition: style.c:122
#define FLAG_OBJ_ORIGINAL
NEVER SET THIS.
Definition: define.h:365
object * object_find_by_tag_global(tag_t i)
Returns the object which has the count-variable equal to the argument.
Definition: object.c:476
#define MAP_SWAPPED
Map spaces have been saved to disk.
Definition: map.h:131
#define LIBDIR
Definition: win32.h:99
object * object_insert_in_ob(object *op, object *where)
This function inserts the object op in the linked list inside the object environment.
Definition: object.c:2690
float speed_left
How much speed is left to spend this round.
Definition: object.h:329
#define MSG_TYPE_COMMAND_SUCCESS
Successful result from command.
Definition: newclient.h:510
#define MSG_TYPE_COMMAND_ERROR
Bad syntax/can&#39;t use command.
Definition: newclient.h:509
Defines and variables used by the artifact generation routines.
uint32_t unique
If set, this is a per player unique map.
Definition: map.h:337
int8_t Wis
Definition: living.h:35
#define FLAG_UNAGGRESSIVE
Monster doesn&#39;t attack players.
Definition: define.h:272
#define MSG_TYPE_ADMIN_PLAYER
Player coming/going/death.
Definition: newclient.h:474
struct mapdef * map
Pointer to the map in which this object is present.
Definition: object.h:297
void monster_check_apply_all(object *monster)
Calls monster_check_apply() for all inventory objects.
Definition: monster.c:1757
int plugins_init_plugin(const char *libfile)
Try to load the specified plugin.
Definition: plugins.c:607
#define snprintf
Definition: win32.h:46
tag_t * stack_items
Item stack for patch/dump/...
Definition: player.h:198
static int checkdm(object *op, const char *pl_name, const char *pl_passwd, const char *pl_host)
object *op is trying to become dm.
Definition: c_wiz.c:2040
static void dm_stack_push(player *pl, tag_t item)
Push specified item on player stack.
Definition: c_wiz.c:149
object * transport
Transport the player is in.
Definition: player.h:195
#define MAP_TIMEOUT(m)
Definition: map.h:66
#define FLAG_IDENTIFIED
Player knows full info about item.
Definition: define.h:261
char * path_combine_and_normalize(const char *src, const char *dst, char *path, size_t size)
Combines the 2 paths.
Definition: path.c:172
#define FMT64
Definition: compat.h:12
void set_max_time(long t)
Sets the max speed.
Definition: time.c:203
int16_t dam
How much damage this object does when hitting.
Definition: living.h:45
static object * dm_stack_peek(player *pl)
Get current stack top item for player.
Definition: c_wiz.c:119
void command_free(object *op, const char *params)
Totally free an object.
Definition: c_wiz.c:1579
const char * name
The name of the object, obviously...
Definition: object.h:311
living orig_stats
Permanent real stats of player.
Definition: player.h:148
void command_addexp(object *op, const char *params)
This adds exp to a player.
Definition: c_wiz.c:1613
struct obj * below
Pointer to the object stacked below this one.
Definition: object.h:287
struct archt * more
Next part of a linked object.
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
Input state of the player (name, password, etc).
Definition: player.h:118
void command_banish(object *op, const char *params)
Add player&#39;s IP to ban_file and kick them off the server.
Definition: c_wiz.c:519
archetype * find_archetype_by_object_name(const char *name)
This function retrieves an archetype given the name that appears during the game (for example...
Definition: arch.c:57
static void command_kick2(object *op, const char *params)
Kicks a player from the server.
Definition: c_wiz.c:463
int8_t direction
Means the object is moving that way.
Definition: object.h:334
uint32_t nrof
How many of the objects.
Definition: object.h:333
int8_t Cha
Definition: living.h:35
void hiscore_check(object *op, int quiet)
Checks if player should enter the hiscore, and if so writes her into the list.
Definition: hiscore.c:302
#define EXIT_X(xyz)
Definition: define.h:457
object * object_find_by_name_global(const char *str)
Finds an object by name.
Definition: object.c:499
uint8_t real_wiz
Use mud-like wizards.
Definition: global.h:269
void do_learn_spell(object *op, object *spell, int special_prayer)
Actually makes op learn spell.
Definition: apply.c:391
See Potion.
Definition: object.h:111
struct pl * contr
Pointer to the player which control this object.
Definition: object.h:276
int plugins_remove_plugin(const char *id)
Unload the specified plugin.
Definition: plugins.c:698
#define NDI_LT_GREEN
DarkSeaGreen, which is actually paler than seagreen - also background color.
Definition: newclient.h:229
#define FREE_AND_CLEAR_STR(xyz)
Release the shared string, and set it to NULL.
Definition: global.h:208
void command_setgod(object *op, const char *params)
Sets the god for some objects.
Definition: c_wiz.c:413
static object * get_spell_by_name(object *op, const char *spell_name)
Returns spell object (from archetypes) by name.
Definition: c_wiz.c:2174
archetype * try_find_archetype(const char *name)
Finds, using the hashtable, which archetype matches the given name.
Definition: arch.c:666
#define UPD_WEIGHT
Definition: newclient.h:291
uint32_t tag_t
Object tag, unique during the whole game.
Definition: object.h:12
Item is somewhere in stack.
Definition: c_wiz.c:38
float speed
The overall speed of this object.
Definition: object.h:328
See Spell.
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)
Returns the head part of an object.
Definition: object.h:594
void clear_los(object *op)
Clears/initialises the los-array associated to the player controlling the object. ...
Definition: los.c:248
#define FLAG_WIZ
Object has special privilegies.
Definition: define.h:231
#define MSG_TYPE_COMMAND_DEBUG
Various debug type commands.
Definition: newclient.h:508
#define EXIT_Y(xyz)
Definition: define.h:458
void plugins_display_list(object *op)
Displays a list of loaded plugins (keystrings and description) in the game log window.
Definition: plugins.c:740
#define MAX_BUF
Used for all kinds of things.
Definition: define.h:35
This is one artifact, ie one special item.
Definition: artifact.h:14
int player_arrest(object *who)
Put a player into jail, taking into account cursed exits and player&#39;s region.
Definition: c_wiz.c:806
void give_artifact_abilities(object *op, const object *artifact)
Fixes the given object, giving it the abilities and titles it should have due to the second artifact-...
Definition: artifact.c:203
object * object_create_arch(archetype *at)
Create a full object using the given archetype.
Definition: arch.c:736
#define MSG_TYPE_ADMIN
Definition: newclient.h:377
int16_t x
Definition: object.h:326
void command_listplugins(object *op, const char *params)
Lists all plugins currently loaded with their IDs and full names.
Definition: c_wiz.c:2364
Skill-related defines, including subtypes.
void reset_sleep(void)
Initialise all variables used in the timing routines.
Definition: time.c:130
void command_help(object *op, const char *params)
Player is asking for some help.
Definition: c_misc.c:1706
int8_t wc
Weapon Class, how skilled, the lower the better.
Definition: living.h:36
const char * confdir
Configuration files.
Definition: global.h:243
uint16_t difficulty
What level the player should be to play here.
Definition: map.h:343
static void set_magic(int difficulty, object *op, int max_magic, int flags)
Sets a random magical bonus in the given object based upon the given difficulty, and the given max po...
Definition: treasure.c:872
void inventory(object *op, object *inv)
Prints object&#39;s inventory.
Definition: c_object.c:1694
#define FOR_MAP_FINISH()
Finishes FOR_MAP_PREPARE().
Definition: define.h:765
int8_t Str
Definition: living.h:35
void calc_perm_exp(object *op)
Ensure that the permanent experience requirements in an exp object are met.
Definition: living.c:1838
void command_invisible(object *op, const char *params)
Wizard wants to become invisible.
Definition: c_wiz.c:2148
int save_map(mapstruct *m, int flag)
Saves a map to file.
Definition: map.c:1436
object * ob
The object representing the player.
Definition: player.h:158
int32_t timeout
Swapout is set to this.
Definition: map.h:341
int need_identify(const object *op)
This function really should not exist - by default, any item not identified should need it...
Definition: item.c:1331
uint8_t permanent_exp_ratio
How much exp should be &#39;permenant&#39; and unable to be lost.
Definition: global.h:256
See Player.
Definition: object.h:107
unsigned int uint32_t
Definition: win32.h:162
char killer[BIG_NAME]
Who killed this player.
Definition: player.h:171
int8_t body_info[NUM_BODY_LOCATIONS]
Body info as loaded from the file.
Definition: object.h:372
uint16_t set_friendly_fire
Percent of damage done by peaceful player vs player damage.
Definition: global.h:272
This structure contains all information related to one map square.
Definition: map.h:258
int16_t grace
Grace.
Definition: living.h:43
#define UPD_NROF
Definition: newclient.h:296
int become_follower(object *op, const object *new_god)
This function is called whenever a player has switched to a new god.
Definition: gods.c:466
const char * localdir
Read/write data files.
Definition: global.h:245
tag_t count
Unique object number for this object.
Definition: object.h:299
living stats
Str, Con, Dex, etc.
Definition: object.h:368
#define FLAG_WIZCAST
The wizard can cast spells in no-magic area.
Definition: define.h:290
mapstruct * has_been_loaded(const char *name)
Checks whether map has been loaded.
Definition: map.c:79
int8_t Dex
Definition: living.h:35
struct archt * arch
Pointer to archetype.
Definition: object.h:412
#define MAP_WIDTH(m)
Map width.
Definition: map.h:78
Only for debugging purposes.
Definition: logger.h:13
uint8_t no_player_stealing
If 1, can not steal from other players.
Definition: global.h:308
#define unlink(__a)
Definition: win32.h:56
void command_overlay_save(object *op, const char *params)
Saves the op&#39;s map as an overlay - objects are persisted.
Definition: c_wiz.c:585
void command_stack_clear(object *op, const char *params)
Empty DM item stack.
Definition: c_wiz.c:2515
uint8_t type
PLAYER, BULLET, etc.
Definition: object.h:338
struct Settings settings
Server settings.
Definition: init.c:40
void object_set_enemy(object *op, object *enemy)
Sets the enemy of an object.
Definition: object.c:679
void command_purge_quest_definitions(object *op, const char *param)
Definition: c_wiz.c:2754
void object_free2(object *ob, int flags)
Frees everything allocated by an object, removes it from the list of used objects, and puts it on the list of free objects.
Definition: object.c:1391
struct archt * next
Next archetype in a linked list.
Definition: object.h:467
int out_of_map(mapstruct *m, int x, int y)
this returns TRUE if the coordinates (x,y) are out of map m.
Definition: map.c:2294
uint32_t max_time
Gloabal variables:
Definition: time.c:35
#define UPD_NAME
Definition: newclient.h:293
void command_nowiz(object *op, const char *params)
Steps down from wizard mode.
Definition: c_wiz.c:1995
void command_loadplugin(object *op, const char *params)
Loads the given plugin.
Definition: c_wiz.c:2378
void command_stack_push(object *op, const char *params)
Push specified item on stack.
Definition: c_wiz.c:2467
void command_arrest(object *op, const char *params)
Wizard jails player.
Definition: c_wiz.c:838
void update_los(object *op)
Recalculates the array which specifies what is visible for the given player-object.
Definition: los.c:455
Item is stack top.
Definition: c_wiz.c:37
Item was not found.
Definition: c_wiz.c:36
sstring add_string(const char *str)
This will add &#39;str&#39; to the hash table.
Definition: shstr.c:124
EXTERN player * first_player
First player.
Definition: global.h:117
struct pl * next
Pointer to next player, NULL if this is last.
Definition: player.h:93
void command_skills(object *op, const char *params)
Player is asking for her skills.
Definition: c_wiz.c:1365
#define FLAG_MONSTER
Will attack players.
Definition: define.h:245
void object_copy(const object *src_ob, object *dest_ob)
Copy object first frees everything allocated by the second object, and then copies the contents of th...
Definition: object.c:838
int8_t Pow
Definition: living.h:35
uint8_t set_title
Players can set thier title.
Definition: global.h:263
#define NDI_UNIQUE
Print immediately, don&#39;t buffer.
Definition: newclient.h:245
#define MSG_SUBTYPE_NONE
Definition: newclient.h:398
void LOG(LogLevel logLevel, const char *format,...)
Logs a message to stderr, or to file.
Definition: logger.c:51
#define FLAG_WAS_WIZ
Player was once a wiz.
Definition: define.h:234
#define MAX_NAME
Definition: define.h:41
#define FOR_MAP_PREPARE(map_, mx_, my_, it_)
Constructs a loop iterating over all objects of a map tile.
Definition: define.h:758
static player * get_other_player_from_name(object *op, const char *name)
Enough of the DM functions seem to need this that I broke it out to a seperate function.
Definition: c_wiz.c:59
int cmd_shutdown_time
Time, in seconds from epoch, of server shutdown.
Definition: c_wiz.c:43
void set_abs_magic(object *op, int magic)
Sets magical bonus in an object, and recalculates the effect on the armour variable, and the effect on speed of armour.
Definition: treasure.c:836
uint32_t worldmapstartx
Starting x tile for the worldmap.
Definition: global.h:289
struct mapdef * next
Next map, linked list.
Definition: map.h:326
int object_find_free_spot(const object *ob, mapstruct *m, int x, int y, int start, int stop)
object_find_free_spot(object, map, x, y, start, stop) will search for a spot at the given map and coo...
Definition: object.c:3415
A buffer that will be expanded as content is added to it.
Definition: stringbuffer.c:25
void command_settings(object *op, const char *ignored)
Wizard wants to know some server settings, so display.
Definition: c_wiz.c:2788
void query_name(const object *op, char *buf, size_t size)
Describes an item.
Definition: item.c:625
object * item
Special values of the artifact.
Definition: artifact.h:15
int allow_denied_spells_writing
If set, players can write spells they can&#39;t cast.
Definition: global.h:313
void create_overlay_pathname(const char *name, char *buf, size_t size)
Same as create_pathname(), but for the overlay maps.
Definition: map.c:125
This is a game-map.
Definition: map.h:325
Item is a number (may be top)
Definition: c_wiz.c:39
void get_ob_diff(StringBuffer *sb, const object *op, const object *op2)
Returns a pointer to a static string which contains all variables which are different in the two give...
Definition: object.c:4845
char write_buf[MAX_BUF]
Holds arbitrary input from client.
Definition: player.h:174
void command_stats(object *op, const char *params)
Displays the statistics of a player.
Definition: c_wiz.c:1699
void command_goto(object *op, const char *params)
Wizard teleports to a map.
Definition: c_wiz.c:726
#define FLAG_WIZPASS
The wizard can go through walls.
Definition: define.h:315
void map_remove_unique_files(const mapstruct *map)
Remove files containing the map&#39;s unique items.
Definition: map.c:2667
#define SAVE_ERROR_PLAYER
Player on map to save.
Definition: map.h:152
uint8_t spell_failure_effects
Nasty backlash to spell failures.
Definition: global.h:267
void command_remove(object *op, const char *params)
Remove an object from its position.
Definition: c_wiz.c:1532
void fix_object(object *op)
Updates all abilities given by applied objects in the inventory of the given object.
Definition: living.c:1120
const char * i18n(const object *who, const char *code)
Translate a message in the appropriate language.
Definition: languages.c:69
player * find_player_partial_name(const char *plname)
Find a player by a partial name.
Definition: player.c:109
void command_reset(object *op, const char *params)
Resets a map.
Definition: c_wiz.c:1822
static object * find_object_both(const char *params)
This finds and returns the object which matches the name or object number (specified via num #whateve...
Definition: c_wiz.c:398
EXTERN archetype * first_archetype
First archetype.
Definition: global.h:122
object * find_skill_by_name(object *who, const char *name)
This returns the skill pointer of the given name (the one that accumulates exp, has the level...
Definition: skill_util.c:213
struct obj * more
Pointer to the rest of a large body of objects.
Definition: object.h:295
object * arch_to_object(archetype *at)
Creates and returns a new object which is a copy of the given archetype.
Definition: arch.c:571
void object_update_speed(object *op)
Updates the speed of an object.
Definition: object.c:1129
void command_teleport(object *op, const char *params)
Teleport next to target player.
Definition: c_wiz.c:930
static void command_learn_spell_or_prayer(object *op, const char *params, int special_prayer)
Wizards wants to learn a spell.
Definition: c_wiz.c:2278
sstring followed_player
Player the DM is following.
Definition: player.h:199
float item_power_factor
See note in setings file.
Definition: global.h:301
const char * name
More definite name, like "generate_kobold".
Definition: object.h:466
#define SAVE_MODE_OVERLAY
Map is persisted as an overlay.
Definition: map.h:122
char * stringbuffer_finish(StringBuffer *sb)
Deallocate the string buffer instance and return the string.
Definition: stringbuffer.c:76
uint8_t resurrection
Ressurection possible w/ permadeth on.
Definition: global.h:264
void command_toggle_shout(object *op, const char *params)
A simple toggle for the no_shout field.
Definition: c_wiz.c:630
static void dm_stack_pop(player *pl)
Remove an item from the wizard&#39;s item stack.
Definition: c_wiz.c:94
void object_remove(object *op)
This function removes the object op from the linked list of objects which it is currently tied to...
Definition: object.c:1654
void command_style_map_info(object *op, const char *params)
Displays information about styles loaded for random maps.
Definition: c_wiz.c:2681
struct artifactstruct * next
Next artifact in the list.
Definition: artifact.h:18
#define MSG_TYPE_COMMAND_DM
DM related commands.
Definition: newclient.h:515
int32_t food
How much food in stomach.
Definition: living.h:47
#define FLAG_FREED
Object is in the list of free objects.
Definition: define.h:233
#define EVENT_MUZZLE
A player was Muzzled (no_shout set).
Definition: plugin.h:96
uint32_t count
Any numbers typed before a command.
Definition: player.h:109