00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00035 #include <global.h>
00036 #ifndef __CEXTRACT__
00037 #include <sproto.h>
00038 #endif
00039 #include <spells.h>
00040 #include <treasure.h>
00041 #include <skills.h>
00042
00043
00044 #define STACK_SIZE 50
00046 enum {
00047 STACK_FROM_NONE = 0,
00048 STACK_FROM_TOP = 1,
00049 STACK_FROM_STACK = 2,
00050 STACK_FROM_NUMBER = 3
00051 };
00052
00067 static player *get_other_player_from_name(object *op, const char *name) {
00068 player *pl;
00069
00070 if (!name)
00071 return NULL;
00072
00073 for (pl = first_player; pl != NULL; pl = pl->next)
00074 if (!strncmp(pl->ob->name, name, MAX_NAME))
00075 break;
00076
00077 if (pl == NULL) {
00078 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
00079 "No such player.", NULL);
00080 return NULL;
00081 }
00082
00083 if (pl->ob == op) {
00084 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
00085 "You can't do that to yourself.", NULL);
00086 return NULL;
00087 }
00088 if (pl->state != ST_PLAYING) {
00089 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
00090 "That player is in no state for that right now.", NULL);
00091 return NULL;
00092 }
00093 return pl;
00094 }
00095
00108 int command_loadtest(object *op, char *params) {
00109 uint32 x, y;
00110 char buf[1024];
00111
00112 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_DEBUG,
00113 "loadtest will stress server through teleporting at different map places. "
00114 "Use at your own risk. Very long loop used so server may have to be reset. "
00115 "type loadtest TRUE to run",
00116 NULL);
00117 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_DEBUG,
00118 "{%s}",
00119 "{%s}",
00120 params);
00121 if (!params)
00122 return 0;
00123 if (strncmp(params, "TRUE", 4))
00124 return 0;
00125
00126 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_DEBUG,
00127 "gogogo", NULL);
00128
00129 for (x = 0; x < settings.worldmaptilesx; x++) {
00130 for (y = 0; y < settings.worldmaptilesy; y++) {
00131 snprintf(buf, sizeof(buf), "/world/world_%u_%u", x+settings.worldmapstartx, y+settings.worldmapstarty);
00132 command_goto(op, buf);
00133 }
00134 }
00135
00136 return 0;
00137 }
00138
00147 void do_wizard_hide(object *op, int silent_dm) {
00148 if (op->contr->hidden) {
00149 op->contr->hidden = 0;
00150 op->invisible = 1;
00151 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_SUCCESS,
00152 "You are no longer hidden from other players", NULL);
00153 op->map->players++;
00154 draw_ext_info_format(NDI_UNIQUE|NDI_ALL|NDI_DK_ORANGE, 5, NULL,
00155 MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_PLAYER,
00156 "%s has entered the game.",
00157 "%s has entered the game.",
00158 op->name);
00159 if (!silent_dm) {
00160 draw_ext_info(NDI_UNIQUE|NDI_ALL|NDI_LT_GREEN, 1, NULL,
00161 MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM,
00162 "The Dungeon Master has arrived!", NULL);
00163 }
00164 } else {
00165 op->contr->hidden = 1;
00166 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_SUCCESS,
00167 "Other players will no longer see you.", NULL);
00168 op->map->players--;
00169 if (!silent_dm) {
00170 draw_ext_info(NDI_UNIQUE|NDI_ALL|NDI_LT_GREEN, 1, NULL,
00171 MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM,
00172 "The Dungeon Master is gone..", NULL);
00173 }
00174 draw_ext_info_format(NDI_UNIQUE|NDI_ALL|NDI_DK_ORANGE, 5, NULL,
00175 MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_PLAYER,
00176 "%s leaves the game.",
00177 "%s leaves the game.",
00178 op->name);
00179 draw_ext_info_format(NDI_UNIQUE|NDI_ALL|NDI_DK_ORANGE, 5, NULL,
00180 MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_PLAYER,
00181 "%s left the game.",
00182 "%s left the game.",
00183 op->name);
00184 }
00185 }
00186
00197 int command_hide(object *op, char *params) {
00198 do_wizard_hide(op, 0);
00199 return 1;
00200 }
00201
00211 static object *find_object_both(char *params) {
00212 if (!params)
00213 return NULL;
00214 if (params[0] == '#')
00215 return find_object(atol(params+1));
00216 else
00217 return find_object_name(params);
00218 }
00219
00232 int command_setgod(object *op, char *params) {
00233 object *ob;
00234 const object *god;
00235 char *str;
00236
00237 if (!params || !(str = strchr(params, ' '))) {
00238 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
00239 "Usage: setgod object god", NULL);
00240 return 0;
00241 }
00242
00243
00244 *str++ = '\0';
00245 if (!(ob = find_object_both(params))) {
00246 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
00247 "Set whose god - can not find object %s?",
00248 "Set whose god - can not find object %s?",
00249 params);
00250 return 1;
00251 }
00252
00253
00254
00255
00256
00257 if (ob->type != PLAYER) {
00258 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
00259 "%s is not a player - can not change its god",
00260 "%s is not a player - can not change its god",
00261 ob->name);
00262 return 1;
00263 }
00264
00265 god = find_god(str);
00266 if (god == NULL) {
00267 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
00268 "No such god %s.",
00269 "No such god %s.",
00270 str);
00271 return 1;
00272 }
00273
00274 become_follower(ob, god);
00275 return 1;
00276 }
00277
00293 int command_banish(object *op, char *params) {
00294 player *pl;
00295 FILE *banishfile;
00296 char buf[MAX_BUF];
00297 time_t now;
00298
00299 if (!params) {
00300 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
00301 "Usage: banish <player>.", NULL);
00302 return 1;
00303 }
00304
00305 pl = get_other_player_from_name(op, params);
00306 if (!pl)
00307 return 1;
00308
00309 snprintf(buf, sizeof(buf), "%s/%s", settings.localdir, BANISHFILE);
00310
00311 if ((banishfile = fopen(buf, "a")) == NULL) {
00312 LOG(llevDebug, "Could not find file banish_file.\n");
00313 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
00314 "Could not find banish_file.", NULL);
00315 return 0;
00316 }
00317
00318 now = time(NULL);
00319
00320
00321
00322
00323 fprintf(banishfile, "# %s (%s) banned by %s at %s\n", pl->ob->name, pl->socket.host, op->name, ctime(&now));
00324 fprintf(banishfile, "*@%s\n", pl->socket.host);
00325 fclose(banishfile);
00326
00327 LOG(llevDebug, "! %s banned %s from IP: %s.\n", op->name, pl->ob->name, pl->socket.host);
00328
00329 draw_ext_info_format(NDI_UNIQUE|NDI_RED, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_DM,
00330 "You banish %s",
00331 "You banish %s",
00332 pl->ob->name);
00333
00334 draw_ext_info_format(NDI_UNIQUE|NDI_ALL|NDI_RED, 5, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM,
00335 "%s banishes %s from the land!",
00336 "%s banishes %s from the land!",
00337 op->name, pl->ob->name);
00338 command_kick(op, pl->ob->name);
00339 return 1;
00340 }
00341
00352 int command_kick(object *op, const char *params) {
00353 struct pl *pl;
00354
00355 for (pl = first_player; pl != NULL; pl = pl->next) {
00356 if ((params == NULL || !strcmp(pl->ob->name, params)) && pl->ob != op) {
00357 object *op;
00358 int removed = 0;
00359
00360 op = pl->ob;
00361 if (!QUERY_FLAG(op, FLAG_REMOVED)) {
00362
00363 execute_global_event(EVENT_KICK, op, params);
00364 remove_ob(op);
00365 removed = 1;
00366 }
00367 op->direction = 0;
00368 draw_ext_info_format(NDI_UNIQUE|NDI_ALL|NDI_RED, 5, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM,
00369 "%s is kicked out of the game.",
00370 "%s is kicked out of the game.",
00371 op->name);
00372 strcpy(op->contr->killer, "left");
00373 check_score(op, 0);
00374
00375
00376
00377
00378
00379
00380 if (!removed && !QUERY_FLAG(op, FLAG_FREED)) {
00381 (void)save_player(op, 0);
00382 if (op->map)
00383 op->map->players--;
00384 }
00385 #if MAP_MAXTIMEOUT
00386 if (op->map)
00387 op->map->timeout = MAP_TIMEOUT(op->map);
00388 #endif
00389 pl->socket.status = Ns_Dead;
00390 }
00391 }
00392
00393 return 1;
00394 }
00395
00406 int command_overlay_save(object *op, char *params) {
00407 if (!op)
00408 return 0;
00409
00410 if (save_map(op->map, SAVE_MODE_OVERLAY) < 0)
00411 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_SUCCESS,
00412 "Overlay save error!", NULL);
00413 else
00414 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_SUCCESS,
00415 "Current map has been saved as an overlay.", NULL);
00416
00417 return 1;
00418 }
00419
00430 int command_overlay_reset(object *op, char *params) {
00431 char filename[MAX_BUF];
00432 struct stat stats;
00433
00434 create_overlay_pathname(op->map->path, filename, MAX_BUF);
00435 if (!stat(filename, &stats))
00436 if (!unlink(filename))
00437 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_DM,
00438 "Overlay successfully removed.", NULL);
00439 else
00440 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_DM,
00441 "Overlay couldn't be removed.", NULL);
00442 else
00443 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_DM,
00444 "No overlay for current map.", NULL);
00445
00446 return 1;
00447 }
00448
00459 int command_toggle_shout(object *op, char *params) {
00460 player *pl;
00461
00462 if (!params) {
00463 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
00464 "Usage: toggle_shout <player>.", NULL);
00465 return 1;
00466 }
00467
00468 pl = get_other_player_from_name(op, params);
00469 if (!pl)
00470 return 1;
00471
00472 if (pl->ob->contr->no_shout == 0) {
00473 pl->ob->contr->no_shout = 1;
00474
00475 draw_ext_info(NDI_UNIQUE|NDI_RED, 0, pl->ob, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM,
00476 "You have been muzzled by the DM!", NULL);
00477 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_DM,
00478 "You muzzle %s.",
00479 "You muzzle %s.",
00480 pl->ob->name);
00481
00482
00483 execute_global_event(EVENT_MUZZLE, pl->ob, params);
00484
00485 return 1;
00486 } else {
00487 pl->ob->contr->no_shout = 0;
00488 draw_ext_info(NDI_UNIQUE|NDI_ORANGE, 0, pl->ob, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM,
00489 "You are allowed to shout and chat again.", NULL);
00490 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_DM,
00491 "You remove %s's muzzle.",
00492 "You remove %s's muzzle.",
00493 pl->ob->name);
00494 return 1;
00495 }
00496 }
00497
00508 int command_shutdown(object *op, char *params) {
00509
00510
00511
00512
00513 command_kick(op, NULL);
00514 check_score(op, 0);
00515 (void)save_player(op, 0);
00516 play_again(op);
00517 cleanup();
00518
00519 return 1;
00520 }
00521
00532 int command_goto(object *op, char *params) {
00533 char *name;
00534 object *dummy;
00535
00536 if (!op)
00537 return 0;
00538
00539 if (params == NULL) {
00540 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
00541 "Go to what level?", NULL);
00542 return 1;
00543 }
00544
00545 name = params;
00546 dummy = get_object();
00547 dummy->map = op->map;
00548 EXIT_PATH(dummy) = add_string(name);
00549 dummy->name = add_string(name);
00550
00551 enter_exit(op, dummy);
00552 free_object(dummy);
00553 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_DM,
00554 "Difficulty: %d.",
00555 "Difficulty: %d.",
00556 op->map->difficulty);
00557
00558 return 1;
00559 }
00560
00571 int command_freeze(object *op, char *params) {
00572 int ticks;
00573 player *pl;
00574
00575 if (!params) {
00576 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
00577 "Usage: freeze [ticks] <player>.", NULL);
00578 return 1;
00579 }
00580
00581 ticks = atoi(params);
00582 if (ticks) {
00583 while ((isdigit(*params) || isspace(*params)) && *params != 0)
00584 params++;
00585 if (*params == 0) {
00586 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
00587 "Usage: freeze [ticks] <player>.", NULL);
00588 return 1;
00589 }
00590 } else
00591 ticks = 100;
00592
00593 pl = get_other_player_from_name(op, params);
00594 if (!pl)
00595 return 1;
00596
00597 draw_ext_info(NDI_UNIQUE|NDI_RED, 0, pl->ob, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM,
00598 "You have been frozen by the DM!", NULL);
00599
00600 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_DM,
00601 "You freeze %s for %d ticks",
00602 "You freeze %s for %d ticks",
00603 pl->ob->name, ticks);
00604
00605 pl->ob->speed_left = -(pl->ob->speed*ticks);
00606 return 0;
00607 }
00608
00619 int command_arrest(object *op, char *params) {
00620 object *dummy;
00621 player *pl;
00622
00623 if (!op)
00624 return 0;
00625 if (params == NULL) {
00626 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
00627 "Usage: arrest <player>.", NULL);
00628 return 1;
00629 }
00630 pl = get_other_player_from_name(op, params);
00631 if (!pl)
00632 return 1;
00633 dummy = get_jail_exit(pl->ob);
00634 if (!dummy) {
00635
00636 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
00637 "Can't jail player, there is no map to hold them", NULL);
00638 return 0;
00639 }
00640 enter_exit(pl->ob, dummy);
00641 free_object(dummy);
00642 draw_ext_info(NDI_UNIQUE, 0, pl->ob, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM,
00643 "You have been arrested.", NULL);
00644 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_DM,
00645 "Jailed %s",
00646 "Jailed %s",
00647 pl->ob->name);
00648 LOG(llevInfo, "Player %s arrested by %s\n", pl->ob->name, op->name);
00649 return 1;
00650 }
00651
00661 int command_summon(object *op, char *params) {
00662 int i;
00663 object *dummy;
00664 player *pl;
00665
00666 if (!op)
00667 return 0;
00668
00669 if (params == NULL) {
00670 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
00671 "Usage: summon <player>.", NULL);
00672 return 1;
00673 }
00674
00675 pl = get_other_player_from_name(op, params);
00676 if (!pl)
00677 return 1;
00678
00679 i = find_free_spot(op, op->map, op->x, op->y, 1, 9);
00680 if (i == -1) {
00681 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
00682 "Can not find a free spot to place summoned player.", NULL);
00683 return 1;
00684 }
00685
00686 dummy = get_object();
00687 EXIT_PATH(dummy) = add_string(op->map->path);
00688 EXIT_X(dummy) = op->x+freearr_x[i];
00689 EXIT_Y(dummy) = op->y+freearr_y[i];
00690 enter_exit(pl->ob, dummy);
00691 free_object(dummy);
00692 draw_ext_info(NDI_UNIQUE, 0, pl->ob, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM,
00693 "You are summoned.", NULL);
00694 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_DM,
00695 "You summon %s",
00696 "You summon %s",
00697 pl->ob->name);
00698 return 1;
00699 }
00700
00711
00712 int command_teleport(object *op, char *params) {
00713 int i;
00714 object *dummy;
00715 player *pl;
00716
00717 if (!op)
00718 return 0;
00719
00720 if (params == NULL) {
00721 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
00722 "Usage: teleport <player>.", NULL);
00723 return 0;
00724 }
00725
00726 pl = find_player_partial_name(params);
00727 if (!pl) {
00728 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
00729 "No such player or ambiguous name.", NULL);
00730 return 0;
00731 }
00732
00733 i = find_free_spot(pl->ob, pl->ob->map, pl->ob->x, pl->ob->y, 1, 9);
00734 if (i == -1) {
00735 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
00736 "Can not find a free spot to teleport to.", NULL);
00737 return 0;
00738 }
00739
00740 dummy = get_object();
00741 EXIT_PATH(dummy) = add_string(pl->ob->map->path);
00742 EXIT_X(dummy) = pl->ob->x+freearr_x[i];
00743 EXIT_Y(dummy) = pl->ob->y+freearr_y[i];
00744 enter_exit(op, dummy);
00745 free_object(dummy);
00746 if (!op->contr->hidden)
00747 draw_ext_info(NDI_UNIQUE, 0, pl->ob, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM,
00748 "You see a portal open.", NULL);
00749 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_DM,
00750 "You teleport to %s",
00751 "You teleport to %s",
00752 pl->ob->name);
00753
00754 return 1;
00755 }
00756
00783 int command_create(object *op, char *params) {
00784 object *tmp = NULL;
00785 int i, magic, set_magic = 0, set_nrof = 0, gotquote, gotspace;
00786 uint32 nrof;
00787 char buf[MAX_BUF], *cp, *bp = buf, *bp2, *bp3, *bp4, *endline;
00788 archetype *at, *at_spell = NULL;
00789 artifact *art = NULL;
00790
00791 if (!op)
00792 return 0;
00793
00794 if (params == NULL) {
00795 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
00796 "Usage: create [nr] [magic] <archetype> [ of <artifact>] [variable_to_patch setting]",
00797 NULL);
00798 return 1;
00799 }
00800 bp = params;
00801
00802
00803 endline = bp+strlen(bp);
00804
00805 if (sscanf(bp, "%u ", &nrof)) {
00806 if ((bp = strchr(params, ' ')) == NULL) {
00807 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
00808 "Usage: create [nr] [magic] <archetype> [ of <artifact>] [variable_to_patch setting]",
00809 NULL);
00810 return 1;
00811 }
00812 bp++;
00813 set_nrof = 1;
00814 LOG(llevDebug, "%s creates: (%u) %s\n", op->name, nrof, bp);
00815 }
00816 if (sscanf(bp, "%d ", &magic)) {
00817 if ((bp = strchr(bp, ' ')) == NULL) {
00818 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
00819 "Usage: create [nr] [magic] <archetype> [ of <artifact>] [variable_to_patch setting]",
00820 NULL);
00821 return 1;
00822 }
00823 bp++;
00824 set_magic = 1;
00825 LOG(llevDebug, "%s creates: (%d) (%d) %s\n", op->name, nrof, magic, bp);
00826 }
00827 if ((cp = strstr(bp, " of ")) != NULL) {
00828 *cp = '\0';
00829 cp += 4;
00830 }
00831 for (bp2 = bp; *bp2; bp2++) {
00832 if (*bp2 == ' ') {
00833 *bp2 = '\0';
00834 bp2++;
00835 break;
00836 }
00837 }
00838
00839 if ((at = find_archetype(bp)) == NULL) {
00840 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
00841 "No such archetype.", NULL);
00842 return 1;
00843 }
00844
00845 if (cp) {
00846 char spell_name[MAX_BUF], *fsp = NULL;
00847
00848
00849
00850
00851
00852
00853
00854 at_spell = find_archetype(cp);
00855 if (!at_spell || at_spell->clone.type != SPELL)
00856 at_spell = find_archetype_by_object_name(cp);
00857 if (!at_spell || at_spell->clone.type != SPELL) {
00858 strcpy(spell_name, cp);
00859 fsp = strchr(spell_name, ' ');
00860 if (fsp) {
00861 *fsp = 0;
00862 fsp++;
00863 at_spell = find_archetype(spell_name);
00864
00865
00866 if (at_spell && at_spell->clone.type == SPELL)
00867 bp2 = cp+strlen(spell_name)+1;
00868 else
00869 at_spell = NULL;
00870 } else
00871 at_spell = NULL;
00872 }
00873
00874
00875
00876
00877 if (!at_spell) {
00878 if (find_artifactlist(at->clone.type) == NULL) {
00879 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
00880 "No artifact list for type %d\n",
00881 "No artifact list for type %d\n",
00882 at->clone.type);
00883 } else {
00884 art = find_artifactlist(at->clone.type)->items;
00885
00886 do {
00887 if (!strcmp(art->item->name, cp))
00888 break;
00889 art = art->next;
00890 } while (art != NULL);
00891 if (!art) {
00892 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
00893 "No such artifact ([%d] of %s)",
00894 "No such artifact ([%d] of %s)",
00895 at->clone.type, cp);
00896 }
00897 }
00898 LOG(llevDebug, "%s creates: (%d) (%d) (%s) of (%s)\n", op->name, set_nrof ? nrof : 0, set_magic ? magic : 0, bp, cp);
00899 }
00900 }
00901
00902 if ((at->clone.type == ROD || at->clone.type == WAND || at->clone.type == SCROLL || at->clone.type == HORN || at->clone.type == SPELLBOOK)
00903 && !at_spell) {
00904 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
00905 "Unable to find spell %s for object that needs it, or it is of wrong type",
00906 "Unable to find spell %s for object that needs it, or it is of wrong type",
00907 cp);
00908 return 1;
00909 }
00910
00911
00912
00913
00914
00915
00916 tmp = object_create_arch(at);
00917 if (settings.real_wiz == FALSE)
00918 SET_FLAG(tmp, FLAG_WAS_WIZ);
00919 if (set_magic)
00920 set_abs_magic(tmp, magic);
00921 if (art)
00922 give_artifact_abilities(tmp, art->item);
00923 if (need_identify(tmp)) {
00924 SET_FLAG(tmp, FLAG_IDENTIFIED);
00925 CLEAR_FLAG(tmp, FLAG_KNOWN_MAGICAL);
00926 }
00927
00928
00929
00930
00931
00932
00933
00934
00935 while (*bp2 && bp2 <= endline) {
00936 bp4 = NULL;
00937 gotspace = 0;
00938 gotquote = 0;
00939
00940 for (bp3 = bp2; *bp3 && gotspace < 2 && gotquote < 2; bp3++) {
00941
00942
00943 if (*bp3 == '"') {
00944 *bp3 = ' ';
00945 bp2 = bp3+1;
00946 bp3++;
00947 gotquote++;
00948 while (*bp3) {
00949 if (*bp3 == '"') {
00950 *bp3 = '\0';
00951 gotquote++;
00952 } else
00953 bp3++;
00954 }
00955 } else if (*bp3 == ' ') {
00956 gotspace++;
00957 }
00958 }
00959
00960
00961
00962
00963
00964
00965 if (gotspace == 2 || gotquote == 2) {
00966 bp3--;
00967 *bp3 = '\0';
00968 } else if (*bp3 == '\0')
00969 gotspace++;
00970
00971 if ((gotquote && gotquote != 2)
00972 || (gotspace != 2 && gotquote != 2)) {
00973
00974
00975
00976
00977
00978
00979
00980 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
00981 "Malformed create line: %s",
00982 "Malformed create line: %s",
00983 bp2);
00984 break;
00985 }
00986
00987
00988
00989 if (set_variable(tmp, bp2) == -1)
00990 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
00991 "Unknown variable %s",
00992 "Unknown variable %s",
00993 bp2);
00994 else
00995 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_DM,
00996 "(%s#%d)->%s",
00997 "(%s#%d)->%s",
00998 tmp->name, tmp->count, bp2);
00999 bp2 = bp3+1;
01000 }
01001
01002 if (at->clone.nrof) {
01003 if (at_spell)
01004 insert_ob_in_ob(arch_to_object(at_spell), tmp);
01005
01006 tmp->x = op->x;
01007 tmp->y = op->y;
01008 if (set_nrof)
01009 tmp->nrof = nrof;
01010 tmp->map = op->map;
01011
01012 if (at->clone.randomitems != NULL && !at_spell)
01013 create_treasure(at->clone.randomitems, tmp, GT_APPLY,
01014 op->map->difficulty, 0);
01015
01016
01017 if (!tmp->more) {
01018 tmp = insert_ob_in_ob(tmp, op);
01019 } else {
01020 insert_ob_in_map_at(tmp, op->map, op, 0, op->x, op->y);
01021 }
01022
01023
01024 dm_stack_push(op->contr, tmp->count);
01025
01026 return 1;
01027 } else {
01028 for (i = 0; i < (set_nrof ? nrof : 1); i++) {
01029 archetype *atmp;
01030 object *prev = NULL, *head = NULL, *dup;
01031
01032 for (atmp = at; atmp != NULL; atmp = atmp->more) {
01033 dup = arch_to_object(atmp);
01034
01035 if (at_spell)
01036 insert_ob_in_ob(arch_to_object(at_spell), dup);
01037
01038
01039
01040
01041
01042 if (head == NULL) {
01043 head = dup;
01044 copy_object(tmp, dup);
01045 }
01046 if (settings.real_wiz == FALSE)
01047 SET_FLAG(dup, FLAG_WAS_WIZ);
01048 dup->x = op->x+dup->arch->clone.x;
01049 dup->y = op->y+dup->arch->clone.y;
01050 dup->map = op->map;
01051
01052 if (head != dup) {
01053 dup->head = head;
01054 prev->more = dup;
01055 }
01056 prev = dup;
01057 }
01058
01059 if (QUERY_FLAG(head, FLAG_ALIVE)) {
01060 object *check = head;
01061 int size_x = 0;
01062 int size_y = 0;
01063
01064 while (check) {
01065 size_x = MAX(size_x, check->arch->clone.x);
01066 size_y = MAX(size_y, check->arch->clone.y);
01067 check = check->more;
01068 }
01069
01070 if (out_of_map(op->map, head->x+size_x, head->y+size_y)) {
01071 if (head->x < size_x || head->y < size_y) {
01072 dm_stack_pop(op->contr);
01073 free_object(head);
01074 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
01075 "Object too big to insert in map, or wrong position.", NULL);
01076 free_object(tmp);
01077 return 1;
01078 }
01079
01080 check = head;
01081 while (check) {
01082 check->x -= size_x;
01083 check->y -= size_y;
01084 check = check->more;
01085 }
01086 }
01087
01088 insert_ob_in_map(head, op->map, op, 0);
01089 } else
01090 head = insert_ob_in_ob(head, op);
01091
01092
01093
01094
01095
01096 dm_stack_push(op->contr, head->count);
01097
01098 if (at->clone.randomitems != NULL && !at_spell)
01099 create_treasure(at->clone.randomitems, head, GT_APPLY, op->map->difficulty, 0);
01100 }
01101
01102
01103 free_object(tmp);
01104 }
01105
01106 return 1;
01107 }
01108
01109
01110
01111
01112
01123 int command_inventory(object *op, char *params) {
01124 object *tmp;
01125 int i;
01126
01127 if (!params) {
01128 inventory(op, NULL);
01129 return 0;
01130 }
01131
01132 if (!sscanf(params, "%d", &i) || (tmp = find_object(i)) == NULL) {
01133 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
01134 "Inventory of what object (nr)?", NULL);
01135 return 1;
01136 }
01137
01138 inventory(op, tmp);
01139 return 1;
01140 }
01141
01156 int command_skills(object *op, char *params) {
01157 show_skills(op, params);
01158 return 0;
01159 }
01160
01171 int command_dump(object *op, char *params) {
01172 object *tmp;
01173 StringBuffer *sb;
01174 char *diff;
01175
01176 tmp = get_dm_object(op->contr, ¶ms, NULL);
01177 if (!tmp)
01178 return 1;
01179
01180 sb = stringbuffer_new();
01181 dump_object(tmp, sb);
01182 diff = stringbuffer_finish(sb);
01183 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_DM, diff, diff);
01184 free(diff);
01185 if (QUERY_FLAG(tmp, FLAG_OBJ_ORIGINAL))
01186 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_DM,
01187 "Object is marked original", NULL);
01188 return 1;
01189 }
01190
01202 int command_mon_aggr(object *op, char *params) {
01203 if (op->enemy || !QUERY_FLAG(op, FLAG_UNAGGRESSIVE)) {
01204 op->enemy = NULL;
01205 SET_FLAG(op, FLAG_UNAGGRESSIVE);
01206 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_DM,
01207 "Aggression turned OFF", NULL);
01208 } else {
01209 CLEAR_FLAG(op, FLAG_FRIENDLY);
01210 CLEAR_FLAG(op, FLAG_UNAGGRESSIVE);
01211 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_DM,
01212 "Aggression turned ON", NULL);
01213 }
01214
01215 return 1;
01216 }
01217
01232 int command_possess(object *op, char *params) {
01233 object *victim;
01234 player *pl;
01235 int i;
01236 char buf[MAX_BUF];
01237
01238 victim = NULL;
01239 if (params != NULL) {
01240 if (sscanf(params, "%d", &i))
01241 victim = find_object(i);
01242 else if (sscanf(params, "%s", buf))
01243 victim = find_object_name(buf);
01244 }
01245 if (victim == NULL) {
01246 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
01247 "Patch what object (nr)?", NULL);
01248 return 1;
01249 }
01250
01251 if (victim == op) {
01252 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
01253 "As insane as you are, I cannot allow you to possess yourself.", NULL);
01254 return 1;
01255 }
01256
01257
01258 pl = op->contr;
01259 victim->contr = pl;
01260 pl->ob = victim;
01261 victim->type = PLAYER;
01262 SET_FLAG(victim, FLAG_WIZ);
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272 for (i = 0; i < NUM_BODY_LOCATIONS; i++)
01273 if (i == 1 || i == 6 || i == 8 || i == 9)
01274 victim->body_info[i] = 2;
01275 else
01276 victim->body_info[i] = 1;
01277
01278 esrv_new_player(pl, 80);
01279 esrv_send_inventory(victim, victim);
01280
01281 fix_object(victim);
01282
01283 do_some_living(victim);
01284 return 1;
01285 }
01286
01296 int command_patch(object *op, char *params) {
01297 char *arg, *arg2;
01298 object *tmp;
01299
01300 tmp = get_dm_object(op->contr, ¶ms, NULL);
01301 if (!tmp)
01302
01303 return 1;
01304
01305
01306 arg = params;
01307 if (arg == NULL) {
01308 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
01309 "Patch what values?", NULL);
01310 return 1;
01311 }
01312
01313 if ((arg2 = strchr(arg, ' ')))
01314 arg2++;
01315 if (settings.real_wiz == FALSE)
01316 SET_FLAG(tmp, FLAG_WAS_WIZ);
01317 if (set_variable(tmp, arg) == -1)
01318 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
01319 "Unknown variable %s",
01320 "Unknown variable %s",
01321 arg);
01322 else {
01323 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_DM,
01324 "(%s#%d)->%s=%s",
01325 "(%s#%d)->%s=%s",
01326 tmp->name, tmp->count, arg, arg2);
01327 }
01328
01329 return 1;
01330 }
01331
01342 int command_remove(object *op, char *params) {
01343 object *tmp;
01344 int from;
01345
01346 tmp = get_dm_object(op->contr, ¶ms, &from);
01347 if (!tmp) {
01348 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
01349 "Remove what object (nr)?", NULL);
01350 return 1;
01351 }
01352
01353 if (tmp->type == PLAYER) {
01354 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
01355 "Unable to remove a player!", NULL);
01356 return 1;
01357 }
01358
01359 if (QUERY_FLAG(tmp, FLAG_REMOVED)) {
01360 char name[MAX_BUF];
01361
01362 query_name(tmp, name, MAX_BUF);
01363 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
01364 "%s is already removed!",
01365 "%s is already removed!",
01366 name);
01367 return 1;
01368 }
01369
01370 if (from != STACK_FROM_STACK)
01371
01372 dm_stack_pop(op->contr);
01373
01374
01375 if (tmp->head)
01376 tmp = tmp->head;
01377 if (tmp->speed != 0) {
01378 tmp->speed = 0;
01379 update_ob_speed(tmp);
01380 }
01381 remove_ob(tmp);
01382 return 1;
01383 }
01384
01394 int command_free(object *op, char *params) {
01395 object *tmp;
01396 int from;
01397
01398 tmp = get_dm_object(op->contr, ¶ms, &from);
01399
01400 if (!tmp) {
01401 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
01402 "Free what object (nr)?", NULL);
01403 return 1;
01404 }
01405
01406 if (from != STACK_FROM_STACK)
01407
01408 dm_stack_pop(op->contr);
01409
01410 if (tmp->head)
01411 tmp = tmp->head;
01412
01413 if (!QUERY_FLAG(tmp, FLAG_REMOVED)) {
01414 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_DM,
01415 "Warning: item was not removed, will do so now.", NULL);
01416 remove_ob(tmp);
01417 }
01418
01419 free_object(tmp);
01420 return 1;
01421 }
01422
01433 int command_addexp(object *op, char *params) {
01434 char buf[MAX_BUF], skill[MAX_BUF];
01435 int i, q;
01436 object *skillob = NULL;
01437 player *pl;
01438
01439 skill[0] = '\0';
01440 if ((params == NULL)
01441 || (strlen(params) > MAX_BUF)
01442 || ((q = sscanf(params, "%s %d %s", buf, &i, skill)) < 2)) {
01443 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
01444 "Usage: addexp player quantity [skill].", NULL);
01445 return 1;
01446 }
01447
01448 for (pl = first_player; pl != NULL; pl = pl->next)
01449 if (!strncmp(pl->ob->name, buf, MAX_NAME))
01450 break;
01451
01452 if (pl == NULL) {
01453 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
01454 "No such player.", NULL);
01455 return 1;
01456 }
01457
01458 if (q >= 3) {
01459 skillob = find_skill_by_name(pl->ob, skill);
01460 if (!skillob) {
01461 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
01462 "Unable to find skill %s in %s",
01463 "Unable to find skill %s in %s",
01464 skill, buf);
01465 return 1;
01466 }
01467
01468 i = check_exp_adjust(skillob, i);
01469 skillob->stats.exp += i;
01470 calc_perm_exp(skillob);
01471 player_lvl_adj(pl->ob, skillob);
01472 }
01473
01474 pl->ob->stats.exp += i;
01475 calc_perm_exp(pl->ob);
01476 player_lvl_adj(pl->ob, NULL);
01477
01478 if (settings.real_wiz == FALSE)
01479 SET_FLAG(pl->ob, FLAG_WAS_WIZ);
01480 return 1;
01481 }
01482
01493 int command_speed(object *op, char *params) {
01494 int i;
01495
01496 if (params == NULL || !sscanf(params, "%d", &i)) {
01497 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_DM,
01498 "Current speed is %d",
01499 "Current speed is %d",
01500 max_time);
01501 return 1;
01502 }
01503
01504 set_max_time(i);
01505 reset_sleep();
01506 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_DM,
01507 "The speed is changed to %d.",
01508 "The speed is changed to %d.",
01509 i);
01510 return 1;
01511 }
01512
01513
01514
01515
01516
01517
01528 int command_stats(object *op, char *params) {
01529 player *pl;
01530
01531 if (params == NULL) {
01532 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
01533 "Who?", NULL);
01534 return 1;
01535 }
01536
01537 pl = find_player_partial_name(params);
01538 if (pl == NULL) {
01539 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
01540 "No such player.", NULL);
01541 return 1;
01542 }
01543
01544 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_DM,
01545 "[Fixed]Statistics for %s:", "Statistics for %s:", pl->ob->name);
01546
01547 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_DM,
01548 "[fixed]Str : %-2d H.P. : %-4d MAX : %d",
01549 "Str : %-2d H.P. : %-4d MAX : %d",
01550 pl->ob->stats.Str, pl->ob->stats.hp, pl->ob->stats.maxhp);
01551
01552 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_DM,
01553 "[fixed]Dex : %-2d S.P. : %-4d MAX : %d",
01554 "Dex : %-2d S.P. : %-4d MAX : %d",
01555 pl->ob->stats.Dex, pl->ob->stats.sp, pl->ob->stats.maxsp);
01556
01557 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_DM,
01558 "[fixed]Con : %-2d AC : %-4d WC : %d",
01559 "Con : %-2d AC : %-4d WC : %d",
01560 pl->ob->stats.Con, pl->ob->stats.ac, pl->ob->stats.wc);
01561
01562 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_DM,
01563 "[fixed]Int : %-2d Damage : %d",
01564 "Int : %-2d Damage : %d",
01565 pl->ob->stats.Int, pl->ob->stats.dam);
01566
01567 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_DM,
01568 "[fixed]Wis : %-2d EXP : %"FMT64,
01569 "Wis : %-2d EXP : %"FMT64,
01570 pl->ob->stats.Wis, pl->ob->stats.exp);
01571
01572 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_DM,
01573 "[fixed]Pow : %-2d Grace : %d",
01574 "Pow : %-2d Grace : %d",
01575 pl->ob->stats.Pow, pl->ob->stats.grace);
01576
01577 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_DM,
01578 "[fixed]Cha : %-2d Food : %d",
01579 "Cha : %-2d Food : %d",
01580 pl->ob->stats.Cha, pl->ob->stats.food);
01581 return 1;
01582 }
01583
01595 int command_abil(object *op, char *params) {
01596 char thing[20], thing2[20];
01597 int iii;
01598 player *pl;
01599
01600 iii = 0;
01601 thing[0] = '\0';
01602 thing2[0] = '\0';
01603 if (params == NULL
01604 || !sscanf(params, "%s %s %d", thing, thing2, &iii)
01605 || thing == NULL) {
01606 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
01607 "Who?", NULL);
01608 return 1;
01609 }
01610
01611 if (thing2 == NULL) {
01612 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
01613 "You can't change that.", NULL);
01614 return 1;
01615 }
01616
01617 if (iii < MIN_STAT || iii > MAX_STAT) {
01618 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
01619 "Illegal range of stat.\n", NULL);
01620 return 1;
01621 }
01622
01623 for (pl = first_player; pl != NULL; pl = pl->next) {
01624 if (!strcmp(pl->ob->name, thing)) {
01625 if (settings.real_wiz == FALSE)
01626 SET_FLAG(pl->ob, FLAG_WAS_WIZ);
01627 if (!strcmp("str", thing2))
01628 pl->ob->stats.Str = iii, pl->orig_stats.Str = iii;
01629 if (!strcmp("dex", thing2))
01630 pl->ob->stats.Dex = iii, pl->orig_stats.Dex = iii;
01631 if (!strcmp("con", thing2))
01632 pl->ob->stats.Con = iii, pl->orig_stats.Con = iii;
01633 if (!strcmp("wis", thing2))
01634 pl->ob->stats.Wis = iii, pl->orig_stats.Wis = iii;
01635 if (!strcmp("cha", thing2))
01636 pl->ob->stats.Cha = iii, pl->orig_stats.Cha = iii;
01637 if (!strcmp("int", thing2))
01638 pl->ob->stats.Int = iii, pl->orig_stats.Int = iii;
01639 if (!strcmp("pow", thing2))
01640 pl->ob->stats.Pow = iii, pl->orig_stats.Pow = iii;
01641 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_DM,
01642 "%s has been altered.",
01643 "%s has been altered.",
01644 pl->ob->name);
01645 fix_object(pl->ob);
01646 return 1;
01647 }
01648 }
01649
01650 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
01651 "No such player.", NULL);
01652 return 1;
01653 }
01654
01665 int command_reset(object *op, char *params) {
01666 mapstruct *m;
01667 object *dummy = NULL, *tmp = NULL;
01668 char path[HUGE_BUF];
01669 int res = 0;
01670
01671 if (params == NULL) {
01672 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
01673 "Reset what map [name]?", NULL);
01674 return 1;
01675 }
01676
01677 if (strcmp(params, ".") == 0)
01678 snprintf(path, sizeof(path), "%s", op->map->path);
01679 else
01680 path_combine_and_normalize(op->map->path, params, path, sizeof(path));
01681 m = has_been_loaded(path);
01682 if (m == NULL) {
01683 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
01684 "No such map.", NULL);
01685 return 1;
01686 }
01687
01688
01689
01690
01691 if ((op->contr && op->contr->transport) && (op->map == m)) {
01692 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
01693 "You need to disembark first.", NULL);
01694 return 1;
01695 }
01696
01697 snprintf(path, sizeof(path), "%s", m->path);
01698
01699 if (m->in_memory != MAP_SWAPPED) {
01700 if (m->in_memory != MAP_IN_MEMORY) {
01701 LOG(llevError, "Tried to swap out map which was not in memory.\n");
01702 return 0;
01703 }
01704
01705
01706
01707
01708
01709 if (op->map == m) {
01710 if (strncmp(m->path, "/random/", 8) == 0) {
01711
01712
01713
01714
01715
01716
01717
01718
01719 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
01720 "You cannot reset a random map when inside it.", NULL);
01721 return 1;
01722 }
01723
01724 dummy = get_object();
01725 dummy->map = NULL;
01726 EXIT_X(dummy) = op->x;
01727 EXIT_Y(dummy) = op->y;
01728 EXIT_PATH(dummy) = add_string(op->map->path);
01729 remove_ob(op);
01730 op->map = NULL;
01731 tmp = op;
01732 }
01733 res = swap_map(m);
01734 }
01735
01736 if (res < 0 || m->in_memory != MAP_SWAPPED) {
01737 player *pl;
01738 int playercount = 0;
01739
01740
01741 if (tmp) {
01742 insert_ob_in_map(op, m, NULL, 0);
01743 free_object(dummy);
01744 }
01745
01746 if (res < 0 && res != SAVE_ERROR_PLAYER)
01747
01748 draw_ext_info_format(NDI_UNIQUE|NDI_RED, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
01749 "Reset failed, error code: %d.", NULL, res);
01750 else {
01751 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
01752 "Reset failed, couldn't swap map, the following players are on it:",
01753 NULL);
01754 for (pl = first_player; pl != NULL; pl = pl->next) {
01755 if (pl->ob->map == m && pl->ob != op) {
01756 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
01757 pl->ob->name, NULL);
01758 playercount++;
01759 }
01760 }
01761 if (!playercount)
01762 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
01763 "hmm, I don't see any other players on this map, something else is the problem.",
01764 NULL);
01765 return 1;
01766 }
01767 }
01768
01769
01770
01771 if (m && m->in_memory == MAP_SWAPPED) {
01772 LOG(llevDebug, "DM %s Resetting map %s.\n", op->name, m->path);
01773
01774
01775 m->reset_time = 1;
01776 flush_old_maps();
01777 }
01778
01779 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_DM,
01780 "Resetting map %s.",
01781 "Resetting map %s.",
01782 path);
01783
01784 if (tmp) {
01785 enter_exit(tmp, dummy);
01786 free_object(dummy);
01787 }
01788
01789 return 1;
01790 }
01791
01802 int command_nowiz(object *op, char *params) {
01803 CLEAR_FLAG(op, FLAG_WIZ);
01804 CLEAR_FLAG(op, FLAG_WIZPASS);
01805 CLEAR_FLAG(op, FLAG_WIZCAST);
01806 if (op->contr->followed_player)
01807 FREE_AND_CLEAR_STR(op->contr->followed_player);
01808
01809 if (settings.real_wiz == TRUE)
01810 CLEAR_FLAG(op, FLAG_WAS_WIZ);
01811 if (op->contr->hidden) {
01812 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_DM,
01813 "You are no longer hidden from other players", NULL);
01814 op->map->players++;
01815 draw_ext_info_format(NDI_UNIQUE|NDI_ALL|NDI_DK_ORANGE, 5, NULL, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_PLAYER,
01816 "%s has entered the game.",
01817 "%s has entered the game.",
01818 op->name);
01819 op->contr->hidden = 0;
01820 op->invisible = 1;
01821 } else
01822 draw_ext_info(NDI_UNIQUE|NDI_ALL|NDI_LT_GREEN, 1, NULL, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM,
01823 "The Dungeon Master is gone..", NULL);
01824
01825 update_los(op);
01826
01827 return 1;
01828 }
01829
01850 static int checkdm(object *op, const char *pl_name, const char *pl_passwd, const char *pl_host) {
01851 FILE *dmfile;
01852 char buf[MAX_BUF];
01853 char line_buf[160], name[160], passwd[160], host[160];
01854
01855 #ifdef RESTRICTIVE_DM
01856 *pl_name = op->name ? op->name : "*";
01857 #endif
01858
01859 snprintf(buf, sizeof(buf), "%s/%s", settings.confdir, DMFILE);
01860 if ((dmfile = fopen(buf, "r")) == NULL) {
01861 LOG(llevDebug, "Could not find DM file.\n");
01862 return 0;
01863 }
01864
01865 while (fgets(line_buf, 160, dmfile) != NULL) {
01866 if (line_buf[0] == '#')
01867 continue;
01868 if (sscanf(line_buf, "%[^:]:%[^:]:%s\n", name, passwd, host) != 3) {
01869 LOG(llevError, "Warning - malformed dm file entry: %s\n", line_buf);
01870 } else if ((!strcmp(name, "*") || (pl_name && !strcmp(pl_name, name)))
01871 && (!strcmp(passwd, "*") || !strcmp(passwd, pl_passwd))
01872 && (!strcmp(host, "*") || !strcmp(host, pl_host))) {
01873 fclose(dmfile);
01874 return (1);
01875 }
01876 }
01877 fclose(dmfile);
01878 return (0);
01879 }
01880
01895 int do_wizard_dm(object *op, char *params, int silent) {
01896 if (!op->contr)
01897 return 0;
01898
01899 if (QUERY_FLAG(op, FLAG_WIZ)) {
01900 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
01901 "You are already the Dungeon Master!", NULL);
01902 return 0;
01903 }
01904
01905 if (checkdm(op, op->name, (params ? params : "*"), op->contr->socket.host)) {
01906 SET_FLAG(op, FLAG_WIZ);
01907 SET_FLAG(op, FLAG_WAS_WIZ);
01908 SET_FLAG(op, FLAG_WIZPASS);
01909 SET_FLAG(op, FLAG_WIZCAST);
01910 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_DM,
01911 "Ok, you are the Dungeon Master!", NULL);
01912
01913
01914
01915
01916
01917
01918 clear_los(op);
01919 op->contr->write_buf[0] = '\0';
01920
01921 if (!silent)
01922 draw_ext_info(NDI_UNIQUE|NDI_ALL|NDI_LT_GREEN, 1, NULL,
01923 MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM,
01924 "The Dungeon Master has arrived!", NULL);
01925
01926 return 1;
01927 } else {
01928 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
01929 "Sorry Pal, I don't think so.", NULL);
01930 op->contr->write_buf[0] = '\0';
01931 return 0;
01932 }
01933 }
01934
01946 int command_dm(object *op, char *params) {
01947 do_wizard_dm(op, params, 0);
01948 return 1;
01949 }
01950
01961 int command_invisible(object *op, char *params) {
01962 if (op) {
01963 op->invisible += 100;
01964 update_object(op, UP_OBJ_FACE);
01965 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_DM,
01966 "You turn invisible.", NULL);
01967 }
01968
01969 return 0;
01970 }
01971
01989 static object *get_spell_by_name(object *op, const char *spell_name) {
01990 archetype *ar;
01991 archetype *found;
01992 int conflict_found;
01993 size_t spell_name_length;
01994
01995
01996 conflict_found = 0;
01997 found = NULL;
01998 for (ar = first_archetype; ar != NULL; ar = ar->next) {
01999 if (ar->clone.type != SPELL)
02000 continue;
02001
02002 if (strncmp(ar->name, "spelldirect_", 12) == 0)
02003 continue;
02004
02005 if (strcmp(ar->clone.name, spell_name) != 0)
02006 continue;
02007
02008 if (found != NULL) {
02009 if (!conflict_found) {
02010 conflict_found = 1;
02011 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
02012 "More than one archetype matches the spell name %s:",
02013 "More than one archetype matches the spell name %s:",
02014 spell_name);
02015 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
02016 "- %s",
02017 "- %s",
02018 found->name);
02019 }
02020 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
02021 "- %s",
02022 "- %s",
02023 ar->name);
02024 continue;
02025 }
02026
02027 found = ar;
02028 }
02029
02030
02031 if (conflict_found)
02032 return NULL;
02033
02034
02035 if (found != NULL)
02036 return arch_to_object(found);
02037
02038
02039 spell_name_length = strlen(spell_name);
02040 conflict_found = 0;
02041 found = NULL;
02042 for (ar = first_archetype; ar != NULL; ar = ar->next) {
02043 if (ar->clone.type != SPELL)
02044 continue;
02045
02046 if (strncmp(ar->name, "spelldirect_", 12) == 0)
02047 continue;
02048
02049 if (strncmp(ar->clone.name, spell_name, spell_name_length) != 0)
02050 continue;
02051
02052 if (found != NULL) {
02053 if (!conflict_found) {
02054 conflict_found = 1;
02055 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
02056 "More than one spell matches %s:",
02057 "More than one spell matches %s:",
02058 spell_name);
02059 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
02060 "- %s",
02061 "- %s",
02062 found->clone.name);
02063 }
02064 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
02065 "- %s",
02066 "- %s",
02067 ar->clone.name);
02068 continue;
02069 }
02070
02071 found = ar;
02072 }
02073
02074
02075 if (conflict_found)
02076 return NULL;
02077
02078
02079 if (found != NULL)
02080 return arch_to_object(found);
02081
02082
02083 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
02084 "The spell %s does not exist.",
02085 "The spell %s does not exist.",
02086 spell_name);
02087 return NULL;
02088 }
02089
02104 static int command_learn_spell_or_prayer(object *op, char *params, int special_prayer) {
02105 object *tmp;
02106
02107 if (op->contr == NULL || params == NULL) {
02108 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
02109 "Which spell do you want to learn?", NULL);
02110 return 0;
02111 }
02112
02113 tmp = get_spell_by_name(op, params);
02114 if (tmp == NULL) {
02115 return 0;
02116 }
02117
02118 if (check_spell_known(op, tmp->name)) {
02119 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
02120 "You already know the spell %s.",
02121 "You already know the spell %s.",
02122 tmp->name);
02123 return 0;
02124 }
02125
02126 do_learn_spell(op, tmp, special_prayer);
02127 free_object(tmp);
02128 return 1;
02129 }
02130
02143 int command_learn_spell(object *op, char *params) {
02144 return command_learn_spell_or_prayer(op, params, 0);
02145 }
02146
02159 int command_learn_special_prayer(object *op, char *params) {
02160 return command_learn_spell_or_prayer(op, params, 1);
02161 }
02162
02173 int command_forget_spell(object *op, char *params) {
02174 object *spell;
02175
02176 if (op->contr == NULL || params == NULL) {
02177 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
02178 "Which spell do you want to forget?", NULL);
02179 return 0;
02180 }
02181
02182 spell = lookup_spell_by_name(op, params);
02183 if (spell == NULL) {
02184 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
02185 "You do not know the spell %s.",
02186 "You do not know the spell %s.",
02187 params);
02188 return 0;
02189 }
02190
02191 do_forget_spell(op, spell->name);
02192 return 1;
02193 }
02194
02205 int command_listplugins(object *op, char *params) {
02206 plugins_display_list(op);
02207 return 1;
02208 }
02209
02222 int command_loadplugin(object *op, char *params) {
02223 char buf[MAX_BUF];
02224
02225 if (params == NULL) {
02226 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
02227 "Load which plugin?", NULL);
02228 return 1;
02229 }
02230
02231 strcpy(buf, LIBDIR);
02232 strcat(buf, "/plugins/");
02233 strcat(buf, params);
02234 LOG(llevDebug, "Requested plugin file is %s\n", buf);
02235 if (plugins_init_plugin(buf) == 0) {
02236 LOG(llevInfo, "DM %s loaded plugin %s\n", op->name, params);
02237 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_DM,
02238 "Plugin %s successfully loaded.",
02239 "Plugin %s successfully loaded.",
02240 params);
02241 } else
02242 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
02243 "Could not load plugin %s.",
02244 "Could not load plugin %s.",
02245 params);
02246 return 1;
02247 }
02248
02261 int command_unloadplugin(object *op, char *params) {
02262 if (params == NULL) {
02263 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
02264 "Remove which plugin?", NULL);
02265 return 1;
02266 }
02267
02268 if (plugins_remove_plugin(params) == 0) {
02269 LOG(llevInfo, "DM %s unloaded plugin %s\n", op->name, params);
02270 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_DM,
02271 "Plugin %s successfully removed.",
02272 "Plugin %s successfully removed.",
02273 params);
02274 } else
02275 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
02276 "Could not remove plugin %s.",
02277 "Could not remove plugin %s.",
02278 params);
02279 return 1;
02280 }
02281
02296 int command_dmhide(object *op, char *params) {
02297 if (!do_wizard_dm(op, params, 1))
02298 return 0;
02299
02300 do_wizard_hide(op, 1);
02301 return 1;
02302 }
02303
02310 void dm_stack_pop(player *pl) {
02311 if (!pl->stack_items || !pl->stack_position) {
02312 draw_ext_info(NDI_UNIQUE, 0, pl->ob, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
02313 "Empty stack!", NULL);
02314 return;
02315 }
02316
02317 pl->stack_position--;
02318 draw_ext_info_format(NDI_UNIQUE, 0, pl->ob, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_DM,
02319 "Popped item from stack, %d left.",
02320 "Popped item from stack, %d left.",
02321 pl->stack_position);
02322 }
02323
02336 object *dm_stack_peek(player *pl) {
02337 object *ob;
02338
02339 if (!pl->stack_position) {
02340 draw_ext_info(NDI_UNIQUE, 0, pl->ob, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
02341 "Empty stack!", NULL);
02342 return NULL;
02343 }
02344
02345 ob = find_object(pl->stack_items[pl->stack_position-1]);
02346 if (!ob) {
02347 draw_ext_info(NDI_UNIQUE, 0, pl->ob, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_DM,
02348 "Stacked item was removed!", NULL);
02349 dm_stack_pop(pl);
02350 return NULL;
02351 }
02352
02353 return ob;
02354 }
02355
02366 void dm_stack_push(player *pl, tag_t item) {
02367 if (!pl->stack_items) {
02368 pl->stack_items = (tag_t *)malloc(sizeof(tag_t)*STACK_SIZE);
02369 memset(pl->stack_items, 0, sizeof(tag_t)*STACK_SIZE);
02370 }
02371
02372 if (pl->stack_position == STACK_SIZE) {
02373 draw_ext_info(NDI_UNIQUE, 0, pl->ob, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
02374 "Item stack full!", NULL);
02375 return;
02376 }
02377
02378 pl->stack_items[pl->stack_position] = item;
02379 draw_ext_info_format(NDI_UNIQUE, 0, pl->ob, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_DM,
02380 "Item stacked as %d.",
02381 "Item stacked as %d.",
02382 pl->stack_position);
02383 pl->stack_position++;
02384 }
02385
02413 object *get_dm_object(player *pl, char **params, int *from) {
02414 int item_tag, item_position;
02415 object *ob;
02416
02417 if (!pl)
02418 return NULL;
02419
02420 if (!params || !*params || **params == '\0') {
02421 if (from)
02422 *from = STACK_FROM_TOP;
02423
02424 return dm_stack_peek(pl);
02425 }
02426
02427
02428 while (**params == ' ')
02429 (*params)++;
02430
02431
02432 if (sscanf(*params, "%d", &item_tag)) {
02433
02434 while (isdigit(**params))
02435 (*params)++;
02436
02437
02438 while (**params == ' ')
02439 (*params)++;
02440
02441
02442 ob = find_object(item_tag);
02443 if (!ob) {
02444 if (from)
02445 *from = STACK_FROM_NONE;
02446 draw_ext_info_format(NDI_UNIQUE, 0, pl->ob, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
02447 "No such item %d!",
02448 "No such item %d!",
02449 item_tag);
02450 return NULL;
02451 }
02452
02453
02454 dm_stack_push(pl, item_tag);
02455 if (from)
02456 *from = STACK_FROM_NUMBER;
02457 return ob;
02458 }
02459
02460
02461 if (sscanf(*params, "$%d", &item_position)) {
02462
02463 (*params)++;
02464
02465 while (isdigit(**params))
02466 (*params)++;
02467 while (**params == ' ')
02468 (*params)++;
02469
02470 if (item_position >= pl->stack_position) {
02471 if (from)
02472 *from = STACK_FROM_NONE;
02473 draw_ext_info_format(NDI_UNIQUE, 0, pl->ob, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
02474 "No such stack item %d!",
02475 "No such stack item %d!",
02476 item_position);
02477 return NULL;
02478 }
02479
02480 ob = find_object(pl->stack_items[item_position]);
02481 if (!ob) {
02482 if (from)
02483 *from = STACK_FROM_NONE;
02484 draw_ext_info_format(NDI_UNIQUE, 0, pl->ob, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_DM,
02485 "Stack item %d was removed.",
02486 "Stack item %d was removed.",
02487 item_position);
02488 return NULL;
02489 }
02490
02491 if (from)
02492 *from = item_position < pl->stack_position-1 ? STACK_FROM_STACK : STACK_FROM_TOP;
02493 return ob;
02494 }
02495
02496
02497 if (!strncmp(*params, "me", 2)) {
02498 if (from)
02499 *from = STACK_FROM_NUMBER;
02500 dm_stack_push(pl, pl->ob->count);
02501
02502
02503 (*params) += 2;
02504 while (**params == ' ')
02505 (*params)++;
02506
02507 return pl->ob;
02508 }
02509
02510
02511 if (from)
02512 *from = STACK_FROM_TOP;
02513 return dm_stack_peek(pl);
02514 }
02515
02526 int command_stack_pop(object *op, char *params) {
02527 dm_stack_pop(op->contr);
02528 return 0;
02529 }
02530
02541 int command_stack_push(object *op, char *params) {
02542 object *ob;
02543 int from;
02544 ob = get_dm_object(op->contr, ¶ms, &from);
02545
02546 if (ob && from != STACK_FROM_NUMBER)
02547
02548 dm_stack_push(op->contr, ob->count);
02549
02550 return 0;
02551 }
02552
02563 int command_stack_list(object *op, char *params) {
02564 int item;
02565 object *display;
02566 player *pl = op->contr;
02567
02568 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_DM,
02569 "Item stack contents:", NULL);
02570
02571 for (item = 0; item < pl->stack_position; item++) {
02572 display = find_object(pl->stack_items[item]);
02573 if (display)
02574 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_DM,
02575 " %d : %s [%d]",
02576 " %d : %s [%d]",
02577 item, display->name, display->count);
02578 else
02579
02580 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_DM,
02581 " %d : (lost item: %d)",
02582 " %d : (lost item: %d)",
02583 item, pl->stack_items[item]);
02584 }
02585
02586 return 0;
02587 }
02588
02599 int command_stack_clear(object *op, char *params) {
02600 op->contr->stack_position = 0;
02601 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_DM,
02602 "Item stack cleared.", NULL);
02603 return 0;
02604 }
02605
02627 int command_diff(object *op, char *params) {
02628 object *left, *right, *top;
02629 char *diff;
02630 StringBuffer *sb;
02631 int left_from, right_from;
02632
02633 top = NULL;
02634
02635 left = get_dm_object(op->contr, ¶ms, &left_from);
02636 if (!left) {
02637 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
02638 "Compare to what item?", NULL);
02639 return 0;
02640 }
02641
02642 if (left_from == STACK_FROM_NUMBER)
02643
02644 dm_stack_pop(op->contr);
02645
02646 right = get_dm_object(op->contr, ¶ms, &right_from);
02647
02648 if (!right) {
02649 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
02650 "Compare what item?", NULL);
02651 return 0;
02652 }
02653
02654 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_DM,
02655 "Item difference:", NULL);
02656
02657 if (left_from == STACK_FROM_TOP && right_from == STACK_FROM_TOP) {
02658
02659
02660
02661
02662
02663
02664 if (op->contr->stack_position > 1) {
02665 left = find_object(op->contr->stack_items[op->contr->stack_position-2]);
02666 if (left)
02667 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_DM,
02668 "(Note: first item taken from undertop)", NULL);
02669 else
02670
02671 left = right;
02672 }
02673 }
02674
02675 sb = stringbuffer_new();
02676 get_ob_diff(sb, left, right);
02677 diff = stringbuffer_finish(sb);
02678 if (*diff == '\0') {
02679 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_DM, "Objects are the same.", NULL);
02680 } else {
02681 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_DM, diff, NULL);
02682 }
02683 free(diff);
02684 return 0;
02685 }
02686
02696 int command_insert_into(object *op, char *params) {
02697 object *left, *right, *inserted;
02698 int left_from, right_from;
02699 char what[MAX_BUF], where[MAX_BUF];
02700
02701 left = get_dm_object(op->contr, ¶ms, &left_from);
02702 if (!left) {
02703 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
02704 "Insert into what object?", NULL);
02705 return 0;
02706 }
02707
02708 if (left_from == STACK_FROM_NUMBER)
02709
02710 dm_stack_pop(op->contr);
02711
02712 right = get_dm_object(op->contr, ¶ms, &right_from);
02713
02714 if (!right) {
02715 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
02716 "Insert what item?", NULL);
02717 return 0;
02718 }
02719
02720 if (left_from == STACK_FROM_TOP && right_from == STACK_FROM_TOP) {
02721
02722
02723
02724
02725
02726
02727 if (op->contr->stack_position > 1) {
02728 left = find_object(op->contr->stack_items[op->contr->stack_position-2]);
02729 if (left)
02730 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_DM,
02731 "(Note: item to insert into taken from undertop)", NULL);
02732 else
02733
02734 left = right;
02735 }
02736 }
02737
02738 if (left == right) {
02739 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
02740 "Can't insert an object into itself!", NULL);
02741 return 0;
02742 }
02743
02744 if (right->type == PLAYER) {
02745 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_ERROR,
02746 "Can't insert a player into something!", NULL);
02747 return 0;
02748 }
02749
02750 if (!QUERY_FLAG(right, FLAG_REMOVED))
02751 remove_ob(right);
02752 inserted = insert_ob_in_ob(right, left);
02753 if (left->type == PLAYER) {
02754 if (inserted != right)
02755
02756 esrv_update_item(UPD_WEIGHT|UPD_NAME|UPD_NROF, left, inserted);
02757 }
02758 query_name(inserted, what, MAX_BUF);
02759 query_name(left, where, MAX_BUF);
02760 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_DM,
02761 "Inserted %s in %s",
02762 "Inserted %s in %s",
02763 what, where);
02764 return 0;
02765
02766 }
02767
02778 int command_style_map_info(object *op, char *params) {
02779 extern mapstruct *styles;
02780 mapstruct *mp;
02781 int maps_used = 0, mapmem = 0, objects_used = 0, x, y;
02782 object *tmp;
02783
02784 for (mp = styles; mp != NULL; mp = mp->next) {
02785 maps_used++;
02786 mapmem += MAP_WIDTH(mp)*MAP_HEIGHT(mp)*(sizeof(object *)+sizeof(MapSpace))+sizeof(mapstruct);
02787 for (x = 0; x < MAP_WIDTH(mp); x++) {
02788 for (y = 0; y < MAP_HEIGHT(mp); y++) {
02789 for (tmp = GET_MAP_OB(mp, x, y); tmp != NULL; tmp = tmp->above)
02790 objects_used++;
02791 }
02792 }
02793 }
02794 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_MAPS,
02795 "[fixed]Style maps loaded: %d",
02796 "Style maps loaded: %d",
02797 maps_used);
02798 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_MAPS,
02799 "[fixed]Memory used, not",
02800 "Memory used, not");
02801 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_MAPS,
02802 "[fixed]including objects: %d",
02803 "including objects: %d",
02804 mapmem);
02805 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_MAPS,
02806 "Style objects: %d",
02807 "Style objects: %d",
02808 objects_used);
02809 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_COMMAND, MSG_TYPE_COMMAND_MAPS,
02810 "Mem for objects: %d",
02811 "Mem for objects: %d",
02812 objects_used*sizeof(object));
02813 return 0;
02814 }
02815
02826 int command_follow(object *op, char *params) {
02827 player *other;
02828
02829 if (!params) {
02830 if (op->contr->followed_player != NULL) {
02831 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, "You stop following %s.", NULL, op->contr->followed_player);
02832 FREE_AND_CLEAR_STR(op->contr->followed_player);
02833 }
02834 return 0;
02835 }
02836
02837 other = find_player_partial_name(params);
02838 if (!other) {
02839 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, "No such player or ambiguous name.", NULL);
02840 return 0;
02841 }
02842 if (other == op->contr) {
02843 draw_ext_info(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, "You can't follow yourself.", NULL);
02844 return 0;
02845 }
02846
02847 if (op->contr->followed_player)
02848 FREE_AND_CLEAR_STR(op->contr->followed_player);
02849
02850 op->contr->followed_player = add_string(other->ob->name);
02851 draw_ext_info_format(NDI_UNIQUE, 0, op, MSG_TYPE_ADMIN, MSG_TYPE_ADMIN_DM, "Following %s.", NULL, op->contr->followed_player);
02852 return 0;
02853 }