|
Atrinik Server 2.5
|
00001 /************************************************************************ 00002 * Atrinik, a Multiplayer Online Role Playing Game * 00003 * * 00004 * Copyright (C) 2009-2011 Alex Tokar and Atrinik Development Team * 00005 * * 00006 * Fork from Daimonin (Massive Multiplayer Online Role Playing Game) * 00007 * and Crossfire (Multiplayer game for X-windows). * 00008 * * 00009 * This program is free software; you can redistribute it and/or modify * 00010 * it under the terms of the GNU General Public License as published by * 00011 * the Free Software Foundation; either version 2 of the License, or * 00012 * (at your option) any later version. * 00013 * * 00014 * This program is distributed in the hope that it will be useful, * 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00017 * GNU General Public License for more details. * 00018 * * 00019 * You should have received a copy of the GNU General Public License * 00020 * along with this program; if not, write to the Free Software * 00021 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * 00022 * * 00023 * The author can be reached at admin@atrinik.org * 00024 ************************************************************************/ 00025 00030 #include <global.h> 00031 #undef SS_STATISTICS 00032 #include <shstr.h> 00033 00039 static player *get_other_player_from_name(object *op, char *name) 00040 { 00041 player *pl; 00042 00043 if (!name) 00044 { 00045 return NULL; 00046 } 00047 00048 adjust_player_name(name); 00049 00050 for (pl = first_player; pl; pl = pl->next) 00051 { 00052 if (!strncasecmp(pl->ob->name, name, MAX_NAME)) 00053 { 00054 break; 00055 } 00056 } 00057 00058 if (pl == NULL) 00059 { 00060 new_draw_info(0, COLOR_WHITE, op, "No such player."); 00061 return NULL; 00062 } 00063 00064 if (pl->ob == op) 00065 { 00066 new_draw_info(0, COLOR_WHITE, op, "You can't do that to yourself."); 00067 return NULL; 00068 } 00069 00070 if (pl->state != ST_PLAYING) 00071 { 00072 new_draw_info(0, COLOR_WHITE, op, "That player is in no state for that right now."); 00073 return NULL; 00074 } 00075 00076 return pl; 00077 } 00078 00085 static object *find_object_rec(object *ob, const char *name, tag_t count) 00086 { 00087 object *tmp; 00088 00089 for (tmp = ob; tmp; tmp = tmp->below) 00090 { 00091 if ((name && tmp->name == name) || (count && tmp->count == count)) 00092 { 00093 return tmp; 00094 } 00095 else if (tmp->inv) 00096 { 00097 object *tmp2 = find_object_rec(tmp->inv, name, count); 00098 00099 if (tmp2) 00100 { 00101 return tmp2; 00102 } 00103 } 00104 } 00105 00106 return NULL; 00107 } 00108 00115 static object *find_object_both(object *op, char *params) 00116 { 00117 tag_t count = 0; 00118 const char *name = NULL; 00119 player *pl; 00120 object *tmp, *tmp2; 00121 int x, y; 00122 00123 if (!params) 00124 { 00125 return NULL; 00126 } 00127 00128 if (params[0] == '#') 00129 { 00130 count = atol(params + 1); 00131 } 00132 else 00133 { 00134 name = find_string(params); 00135 } 00136 00137 /* If find_string() can't find the string, then it's impossible that 00138 * op->name will match. */ 00139 if (!name && !count) 00140 { 00141 return NULL; 00142 } 00143 00144 /* First search through the players */ 00145 for (pl = first_player; pl; pl = pl->next) 00146 { 00147 if ((name && pl->ob->name == name) || (count && pl->ob->count == count)) 00148 { 00149 return pl->ob; 00150 } 00151 } 00152 00153 /* Otherwise search below the DM */ 00154 for (tmp = get_map_ob(op->map, op->x, op->y); tmp; tmp = tmp->above) 00155 { 00156 tmp2 = find_object_rec(tmp, name, count); 00157 00158 if (tmp2) 00159 { 00160 return tmp2; 00161 } 00162 } 00163 00164 /* No match? Search through the entire map... */ 00165 for (x = 0; x < MAP_WIDTH(op->map); x++) 00166 { 00167 for (y = 0; y < MAP_HEIGHT(op->map); y++) 00168 { 00169 for (tmp = get_map_ob(op->map, x, y); tmp; tmp = tmp->above) 00170 { 00171 tmp2 = find_object_rec(tmp, name, count); 00172 00173 if (tmp2) 00174 { 00175 return tmp2; 00176 } 00177 } 00178 } 00179 } 00180 00181 return NULL; 00182 } 00183 00189 static int dm_map_remove_players(mapstruct *m) 00190 { 00191 int count = 0; 00192 player *pl; 00193 00194 for (pl = first_player; pl; pl = pl->next) 00195 { 00196 if (pl->ob->map == m) 00197 { 00198 count++; 00199 remove_ob(pl->ob); 00200 pl->dm_removed_from_map = 1; 00201 pl->ob->map = NULL; 00202 } 00203 } 00204 00205 return count; 00206 } 00207 00212 static void dm_map_reinsert_players(mapstruct *m, object *op) 00213 { 00214 player *pl; 00215 00216 for (pl = first_player; pl; pl = pl->next) 00217 { 00218 if (pl->dm_removed_from_map) 00219 { 00220 pl->dm_removed_from_map = 0; 00221 insert_ob_in_map(pl->ob, m, NULL, INS_NO_MERGE); 00222 /* So that we don't access invalid values of old player's last_update map 00223 * pointer when sending map to the client. */ 00224 pl->last_update = NULL; 00225 00226 if (pl->ob != op) 00227 { 00228 if (QUERY_FLAG(pl->ob, FLAG_WIZ)) 00229 { 00230 new_draw_info_format(0, COLOR_WHITE, pl->ob, "Map reset by %s.", op->name); 00231 } 00232 /* Write a nice little confusing message to the players */ 00233 else 00234 { 00235 new_draw_info(0, COLOR_WHITE, pl->ob, "Your surroundings seem different but still familiar. Haven't you been here before?"); 00236 } 00237 } 00238 } 00239 } 00240 } 00241 00248 int command_setgod(object *op, char *params) 00249 { 00250 object *ob, *god; 00251 char *str; 00252 00253 if (!params || !(str = strchr(params, ' '))) 00254 { 00255 new_draw_info(0, COLOR_WHITE, op, "Usage: /setgod object god"); 00256 return 0; 00257 } 00258 00259 /* Kill the space, and set string to the next param */ 00260 *str++ = '\0'; 00261 00262 if (!(ob = find_object_both(op, params))) 00263 { 00264 new_draw_info_format(0, COLOR_WHITE, op, "Set whose god - can not find object %s?", params); 00265 return 1; 00266 } 00267 00268 /* Perhaps this is overly restrictive? Should we perhaps be able to 00269 * re-bless altars and the like? */ 00270 if (ob->type != PLAYER) 00271 { 00272 new_draw_info_format(0, COLOR_WHITE, op, "%s is not a player - can not change its god", ob->name); 00273 return 1; 00274 } 00275 00276 change_skill(ob, SK_PRAYING); 00277 00278 if (!ob->chosen_skill || ob->chosen_skill->stats.sp != SK_PRAYING) 00279 { 00280 new_draw_info_format(0, COLOR_WHITE, op, "%s doesn't have praying skill.", ob->name); 00281 return 1; 00282 } 00283 00284 god = find_god(str); 00285 00286 if (god == NULL) 00287 { 00288 new_draw_info_format(0, COLOR_WHITE, op, "No such god %s.", str); 00289 return 1; 00290 } 00291 00292 become_follower(ob, god); 00293 00294 return 1; 00295 } 00296 00304 int command_kick(object *ob, char *params) 00305 { 00306 player *pl, *pl_next; 00307 00308 if (ob && params == NULL) 00309 { 00310 new_draw_info_format(0, COLOR_WHITE, ob, "Use: /kick <name>"); 00311 return 1; 00312 } 00313 00314 if (ob && ob->name && !strncasecmp(ob->name, params, MAX_NAME)) 00315 { 00316 new_draw_info_format(0, COLOR_WHITE, ob, "You can't /kick yourself!"); 00317 return 1; 00318 } 00319 00320 for (pl = first_player; pl; pl = pl_next) 00321 { 00322 pl_next = pl->next; 00323 00324 /* Ignore players not playing. */ 00325 if (pl->state != ST_PLAYING) 00326 { 00327 continue; 00328 } 00329 00330 if (!ob || (pl->ob != ob && pl->ob->name && !strncasecmp(pl->ob->name, params, MAX_NAME))) 00331 { 00332 object *op = pl->ob; 00333 00334 remove_ob(op); 00335 check_walk_off(op, NULL, MOVE_APPLY_VANISHED); 00336 00337 if (params) 00338 { 00339 new_draw_info_format(NDI_ALL, COLOR_WHITE, ob, "%s was kicked out of the game.", op->name); 00340 } 00341 00342 LOG(llevChat, "Kick: %s was kicked out of the game by %s.\n", op->name, ob ? ob->name : "a shutdown"); 00343 00344 CONTR(op)->socket.status = Ns_Dead; 00345 remove_ns_dead_player(CONTR(op)); 00346 } 00347 } 00348 00349 return 1; 00350 } 00351 00357 int command_shutdown_now(object *op, char *params) 00358 { 00359 (void) params; 00360 00361 LOG(llevSystem, "Server shutdown started by %s\n", op->name); 00362 command_kick(NULL, NULL); 00363 cleanup(); 00364 exit(0); 00365 00366 /* Not reached */ 00367 return 1; 00368 } 00369 00375 int command_goto(object *op, char *params) 00376 { 00377 char name[MAX_BUF] = {"\0"}; 00378 int x = -1, y = -1; 00379 object *dummy; 00380 00381 if (!op) 00382 { 00383 return 0; 00384 } 00385 00386 if (params == NULL) 00387 { 00388 new_draw_info(0, COLOR_WHITE, op, "Go to what map?\nUsage: /goto <map> x y"); 00389 return 1; 00390 } 00391 00392 sscanf(params, "%s %d %d", name, &x, &y); 00393 00394 dummy = get_object(); 00395 dummy->map = op->map; 00396 dummy->stats.hp = x; 00397 dummy->stats.sp = y; 00398 FREE_AND_COPY_HASH(EXIT_PATH(dummy), name); 00399 FREE_AND_COPY_HASH(dummy->name, name); 00400 00401 enter_exit(op, dummy); 00402 00403 new_draw_info_format(0, COLOR_WHITE, op, "Difficulty: %d.", op->map->difficulty); 00404 00405 return 1; 00406 } 00407 00413 int command_freeze(object *op, char *params) 00414 { 00415 int ticks; 00416 player *pl; 00417 00418 if (!params) 00419 { 00420 new_draw_info(0, COLOR_WHITE, op, "Usage: /freeze [ticks] <player>"); 00421 return 1; 00422 } 00423 00424 ticks = atoi(params); 00425 00426 if (ticks) 00427 { 00428 while ((isdigit(*params) || isspace(*params)) && *params != 0) 00429 { 00430 params++; 00431 } 00432 00433 if (*params == 0) 00434 { 00435 new_draw_info(0, COLOR_WHITE, op, "Usage: /freeze [ticks] <player>"); 00436 return 1; 00437 } 00438 } 00439 else 00440 { 00441 ticks = 100; 00442 } 00443 00444 pl = get_other_player_from_name(op, params); 00445 00446 if (!pl) 00447 { 00448 return 1; 00449 } 00450 00451 new_draw_info(0, COLOR_RED, pl->ob, "You have been frozen by the DM!"); 00452 00453 new_draw_info_format(0, COLOR_WHITE, op, "You freeze %s for %d ticks.", pl->ob->name, ticks); 00454 00455 pl->ob->speed_left = -(pl->ob->speed * ticks); 00456 return 1; 00457 } 00458 00464 int command_summon(object *op, char *params) 00465 { 00466 int i; 00467 player *pl; 00468 00469 if (!op) 00470 { 00471 return 0; 00472 } 00473 00474 if (params == NULL) 00475 { 00476 new_draw_info(0, COLOR_WHITE, op, "Usage: /summon <player>."); 00477 return 1; 00478 } 00479 00480 pl = get_other_player_from_name(op, params); 00481 00482 if (!pl) 00483 { 00484 return 1; 00485 } 00486 00487 i = find_free_spot(op->arch, op, op->map, op->x, op->y, 1, SIZEOFFREE1 + 1); 00488 00489 if (i == -1 || op->x + freearr_x[i] < 0 || op->y + freearr_y[i] < 0 || op->x + freearr_x[i] >= MAP_WIDTH(op->map) || op->y + freearr_y[i] >= MAP_HEIGHT(op->map)) 00490 { 00491 new_draw_info(0, COLOR_WHITE, op, "Can not find a free spot to place summoned player."); 00492 return 1; 00493 } 00494 00495 remove_ob(pl->ob); 00496 pl->ob->x = op->x + freearr_x[i]; 00497 pl->ob->y = op->y + freearr_y[i]; 00498 insert_ob_in_map(pl->ob, op->map, NULL, INS_NO_MERGE); 00499 new_draw_info(0, COLOR_WHITE, pl->ob, "You are summoned."); 00500 new_draw_info_format(0, COLOR_WHITE, op, "You summon %s.", pl->ob->name); 00501 return 1; 00502 } 00503 00509 int command_teleport(object *op, char *params) 00510 { 00511 int i; 00512 player *pl; 00513 00514 if (!op) 00515 { 00516 return 0; 00517 } 00518 00519 if (params == NULL) 00520 { 00521 new_draw_info(0, COLOR_WHITE, op, "Usage: /teleport <player>."); 00522 return 1; 00523 } 00524 00525 pl = get_other_player_from_name(op, params); 00526 00527 if (!pl) 00528 { 00529 return 1; 00530 } 00531 00532 i = find_free_spot(pl->ob->arch, pl->ob, pl->ob->map, pl->ob->x, pl->ob->y, 1, SIZEOFFREE1 + 1); 00533 00534 if (i == -1 || pl->ob->x + freearr_x[i] < 0 || pl->ob->y + freearr_y[i] < 0 || pl->ob->x + freearr_x[i] >= MAP_WIDTH(pl->ob->map) || pl->ob->y + freearr_y[i] >= MAP_HEIGHT(pl->ob->map)) 00535 { 00536 new_draw_info(0, COLOR_WHITE, op, "Can not find a free spot to teleport to."); 00537 return 1; 00538 } 00539 00540 remove_ob(op); 00541 op->x = pl->ob->x + freearr_x[i]; 00542 op->y = pl->ob->y + freearr_y[i]; 00543 insert_ob_in_map(op, pl->ob->map, NULL, INS_NO_MERGE); 00544 00545 if (!CONTR(op)->dm_stealth) 00546 { 00547 new_draw_info(0, COLOR_WHITE, pl->ob, "You see a portal open."); 00548 } 00549 00550 new_draw_info_format(0, COLOR_WHITE, op, "You teleport to %s.", pl->ob->name); 00551 00552 return 1; 00553 } 00554 00560 int command_create(object *op, char *params) 00561 { 00562 object *tmp = NULL; 00563 int magic, set_magic = 0, set_nrof = 0, gotquote, gotspace; 00564 sint32 i, nrof; 00565 char *cp, *bp, *bp2, *bp3, *bp4, *endline; 00566 archetype *at; 00567 artifact *art = NULL; 00568 00569 if (params == NULL) 00570 { 00571 new_draw_info(0, COLOR_WHITE, op, "Usage: /create [nr] [magic] <archetype> [ of <artifact>] [variable_to_patch setting]"); 00572 return 1; 00573 } 00574 00575 bp = params; 00576 00577 /* We need to know where the line ends */ 00578 endline = bp + strlen(bp); 00579 00580 if (sscanf(bp, "%d ", &nrof)) 00581 { 00582 if (!(bp = strchr(params, ' '))) 00583 { 00584 new_draw_info(0, COLOR_WHITE, op, "Usage: /create [nr] [magic] <archetype> [ of <artifact>] [variable_to_patch setting]"); 00585 return 1; 00586 } 00587 00588 nrof = MAX(1, MIN(nrof, 1000)); 00589 00590 bp++; 00591 set_nrof = 1; 00592 } 00593 00594 if (sscanf(bp, "%d ", &magic)) 00595 { 00596 if (!(bp = strchr(bp, ' '))) 00597 { 00598 new_draw_info(0, COLOR_WHITE, op, "Usage: /create [nr] [magic] <archetype> [ of <artifact>] [variable_to_patch setting]"); 00599 return 1; 00600 } 00601 00602 bp++; 00603 set_magic = 1; 00604 } 00605 00606 if ((cp = strstr(bp, " of "))) 00607 { 00608 *cp = '\0'; 00609 cp += 4; 00610 } 00611 00612 for (bp2 = bp; *bp2; bp2++) 00613 { 00614 if (*bp2 == ' ') 00615 { 00616 *bp2 = '\0'; 00617 bp2++; 00618 break; 00619 } 00620 } 00621 00622 /* First step: browse the archetypes for the name. */ 00623 if (!(at = find_archetype(bp))) 00624 { 00625 new_draw_info(0, COLOR_WHITE, op, "No such archetype or artifact name."); 00626 return 1; 00627 } 00628 00629 if (cp) 00630 { 00631 if (find_artifactlist(at->clone.type) == NULL) 00632 { 00633 new_draw_info_format(0, COLOR_WHITE, op, "No artifact list for type %d\n", at->clone.type); 00634 } 00635 else 00636 { 00637 art = find_artifactlist(at->clone.type)->items; 00638 00639 do 00640 { 00641 if (!strcmp(art->name, cp)) 00642 { 00643 break; 00644 } 00645 00646 art = art->next; 00647 } while (art); 00648 00649 if (!art) 00650 { 00651 new_draw_info_format(0, COLOR_WHITE, op, "No such artifact ([%d] of %s)", at->clone.type, cp); 00652 } 00653 } 00654 } 00655 00656 /* Rather than have two different blocks with a lot of similar code, 00657 * just create one object, do all the processing, and then determine 00658 * if that one object should be inserted or if we need to make copies. */ 00659 tmp = arch_to_object(at); 00660 00661 if (set_magic) 00662 { 00663 set_abs_magic(tmp, magic); 00664 } 00665 00666 if (art) 00667 { 00668 give_artifact_abilities(tmp, art); 00669 } 00670 00671 if (need_identify(tmp)) 00672 { 00673 SET_FLAG(tmp, FLAG_IDENTIFIED); 00674 } 00675 00676 /* This entire block here tries to find variable pairings, 00677 * eg, 'hp 4' or the like. The mess here is that values 00678 * can be quoted (eg "my cool sword"); So the basic logic 00679 * is we want to find two spaces, but if we got a quote, 00680 * any spaces there don't count. */ 00681 while (*bp2 && bp2 <= endline) 00682 { 00683 bp4 = NULL; 00684 gotspace = 0; 00685 gotquote = 0; 00686 00687 /* Find the first quote. */ 00688 for (bp3 = bp2; *bp3 && gotspace < 2; bp3++) 00689 { 00690 /* Found a quote. */ 00691 if (*bp3 == '"') 00692 { 00693 *bp3 = ' '; 00694 gotquote++; 00695 bp3++; 00696 00697 for (bp4 = bp3; *bp4; bp4++) 00698 { 00699 if (*bp4 == '"') 00700 { 00701 *bp4 = '\0'; 00702 break; 00703 } 00704 } 00705 } 00706 else if (*bp3 == ' ') 00707 { 00708 gotspace++; 00709 } 00710 } 00711 00712 if (!gotquote) 00713 { 00714 /* Then find the second space. */ 00715 for (bp3 = bp2; *bp3; bp3++) 00716 { 00717 if (*bp3 == ' ') 00718 { 00719 bp3++; 00720 00721 for (bp4 = bp3; *bp4; bp4++) 00722 { 00723 if (*bp4 == ' ') 00724 { 00725 *bp4 = '\0'; 00726 break; 00727 } 00728 } 00729 00730 break; 00731 } 00732 } 00733 } 00734 00735 if (!bp4) 00736 { 00737 /* Unfortunately, we've clobbered lots of values, so printing 00738 * out what we have probably isn't useful. Break out, because 00739 * trying to recover is probably won't get anything useful 00740 * anyways, and we'd be confused about end of line pointers 00741 * anyways. */ 00742 new_draw_info_format(0, COLOR_WHITE, op, "Malformed create line: %s", bp2); 00743 break; 00744 } 00745 00746 /* bp2 should still point to the start of this line, 00747 * with bp3 pointing to the end. */ 00748 if (set_variable(tmp, bp2) == -1) 00749 { 00750 new_draw_info_format(0, COLOR_WHITE, op, "Unknown variable %s", bp2); 00751 } 00752 else 00753 { 00754 new_draw_info_format(0, COLOR_WHITE, op, "(%s)->%s", tmp->name, bp2); 00755 } 00756 00757 if (gotquote) 00758 { 00759 bp2 = bp4 + 2; 00760 } 00761 else 00762 { 00763 bp2 = bp4 + 1; 00764 } 00765 } 00766 00767 if (at->clone.nrof) 00768 { 00769 if (set_nrof) 00770 { 00771 tmp->nrof = nrof; 00772 } 00773 00774 if (tmp->randomitems) 00775 { 00776 create_treasure(tmp->randomitems, tmp, GT_APPLY, tmp->type == MONSTER ? tmp->level : get_environment_level(tmp), T_STYLE_UNSET, ART_CHANCE_UNSET, 0, NULL); 00777 } 00778 00779 /* If the created object is alive or is multi arch, insert it on 00780 * the map. */ 00781 if (IS_LIVE(tmp) || tmp->more) 00782 { 00783 if (tmp->type == MONSTER) 00784 { 00785 fix_monster(tmp); 00786 } 00787 00788 insert_ob_in_map(tmp, op->map, op, INS_NO_MERGE | INS_NO_WALK_ON); 00789 } 00790 /* Into the DM's inventory otherwise. */ 00791 else 00792 { 00793 tmp = insert_ob_in_ob(tmp, op); 00794 esrv_send_item(op, tmp); 00795 } 00796 00797 return 1; 00798 } 00799 00800 for (i = 0; i < (set_nrof ? nrof : 1); i++) 00801 { 00802 archetype *atmp; 00803 object *prev = NULL, *head = NULL, *ob_dup; 00804 00805 for (atmp = at; atmp; atmp = atmp->more) 00806 { 00807 ob_dup = arch_to_object(atmp); 00808 00809 /* The head is what contains all the important bits, 00810 * so just copying it over should be fine. */ 00811 if (head == NULL) 00812 { 00813 head = ob_dup; 00814 copy_object(tmp, ob_dup, 0); 00815 } 00816 00817 ob_dup->x = op->x + ob_dup->arch->clone.x; 00818 ob_dup->y = op->y + ob_dup->arch->clone.y; 00819 ob_dup->map = op->map; 00820 00821 if (head != ob_dup) 00822 { 00823 ob_dup->head = head; 00824 prev->more = ob_dup; 00825 } 00826 00827 prev = ob_dup; 00828 } 00829 00830 if (head->randomitems) 00831 { 00832 create_treasure(head->randomitems, head, GT_APPLY, head->type == MONSTER ? head->level : get_environment_level(head), T_STYLE_UNSET, ART_CHANCE_UNSET, 0, NULL); 00833 } 00834 00835 /* If the created object is alive or is multi arch, insert it on 00836 * the map. */ 00837 if (IS_LIVE(head) || head->more) 00838 { 00839 if (head->type == MONSTER) 00840 { 00841 fix_monster(head); 00842 } 00843 00844 head = insert_ob_in_map(head, op->map, op, INS_NO_MERGE | INS_NO_WALK_ON); 00845 } 00846 /* Into the DM's inventory otherwise. */ 00847 else 00848 { 00849 head = insert_ob_in_ob(head, op); 00850 esrv_send_item(op, head); 00851 } 00852 00853 if (!set_nrof || nrof == 1) 00854 { 00855 new_draw_info_format(0, COLOR_WHITE, op, "Created %s (#%d)", query_name(head, NULL), head->count); 00856 } 00857 } 00858 00859 return 1; 00860 } 00861 00868 int command_inventory(object *op, char *params) 00869 { 00870 object *ob = NULL, *tmp; 00871 char *cp; 00872 00873 if (!params) 00874 { 00875 new_draw_info(0, COLOR_WHITE, op, "Inventory of what object?"); 00876 return 0; 00877 } 00878 00879 params = strtok(params, "$"); 00880 cp = strtok(NULL, "$"); 00881 00882 if (!strncmp(params, "me", 2)) 00883 { 00884 ob = op; 00885 } 00886 else 00887 { 00888 ob = find_object_both(op, params); 00889 00890 if (!ob) 00891 { 00892 new_draw_info(0, COLOR_WHITE, op, "No such object."); 00893 return 0; 00894 } 00895 } 00896 00897 new_draw_info_format(0, COLOR_WHITE, op, "\nInventory of '%s':\n", query_name(ob, op)); 00898 00899 for (tmp = ob->inv; tmp; tmp = tmp->below) 00900 { 00901 if (cp && !item_matched_string(op, tmp, cp)) 00902 { 00903 continue; 00904 } 00905 00906 new_draw_info_format(0, COLOR_WHITE, op, "#<green>%d</green>: %s", tmp->count, query_name(tmp, op)); 00907 } 00908 00909 return 1; 00910 } 00911 00917 int command_dump(object *op, char *params) 00918 { 00919 object *tmp; 00920 StringBuffer *sb; 00921 char *diff; 00922 00923 if (params != NULL && !strcmp(params, "me")) 00924 { 00925 tmp = op; 00926 } 00927 else if (params == NULL || !(tmp = find_object_both(op, params))) 00928 { 00929 new_draw_info(0, COLOR_WHITE, op, "Dump what object?"); 00930 return 1; 00931 } 00932 00933 sb = stringbuffer_new(); 00934 stringbuffer_append_printf(sb, "count %d\n", tmp->count); 00935 dump_object(tmp, sb); 00936 diff = stringbuffer_finish(sb); 00937 new_draw_info(0, COLOR_WHITE, op, diff); 00938 free(diff); 00939 return 1; 00940 } 00941 00947 int command_patch(object *op, char *params) 00948 { 00949 char *arg, *arg2; 00950 object *tmp = NULL; 00951 00952 if (params != NULL) 00953 { 00954 if (!strncmp(params, "me", 2)) 00955 { 00956 tmp = op; 00957 } 00958 else 00959 { 00960 char name[MAX_BUF]; 00961 00962 if (sscanf(params, "%s", name) == 1) 00963 { 00964 tmp = find_object_both(op, name); 00965 } 00966 } 00967 } 00968 00969 if (tmp == NULL) 00970 { 00971 new_draw_info(0, COLOR_WHITE, op, "Patch what object?"); 00972 return 1; 00973 } 00974 00975 arg = strchr(params, ' '); 00976 00977 if (arg == NULL) 00978 { 00979 new_draw_info(0, COLOR_WHITE, op, "Patch what values?"); 00980 return 1; 00981 } 00982 00983 if ((arg2 = strchr(++arg, ' '))) 00984 { 00985 arg2++; 00986 } 00987 00988 if (!strncmp(arg, "msg", 3)) 00989 { 00990 char buf[HUGE_BUF / 2]; 00991 00992 arg += 4; 00993 00994 if (!arg || *arg == '\0') 00995 { 00996 FREE_AND_CLEAR_HASH(tmp->msg); 00997 new_draw_info_format(0, COLOR_WHITE, op, "(%s#%d)->msg=", tmp->name, tmp->count); 00998 return 1; 00999 } 01000 01001 buf[0] = '\0'; 01002 01003 if (tmp->msg) 01004 { 01005 strncpy(buf, tmp->msg, sizeof(buf) - 1); 01006 } 01007 01008 convert_newline(arg); 01009 01010 if (buf_overflow(buf, arg, sizeof(buf) - 1)) 01011 { 01012 new_draw_info(0, COLOR_RED, op, "Message string would overflow."); 01013 return 1; 01014 } 01015 01016 strncat(buf, arg, sizeof(buf) - strlen(buf) - 1); 01017 FREE_AND_COPY_HASH(tmp->msg, buf); 01018 new_draw_info_format(0, COLOR_WHITE, op, "(%s#%d)->msg=%s", tmp->name, tmp->count, buf); 01019 } 01020 else if (set_variable(tmp, arg) == -1) 01021 { 01022 new_draw_info_format(0, COLOR_WHITE, op, "Unknown variable %s", arg); 01023 } 01024 else 01025 { 01026 new_draw_info_format(0, COLOR_WHITE, op, "(%s#%d)->%s=%s", tmp->name, tmp->count, arg, arg2); 01027 } 01028 01029 return 1; 01030 } 01031 01037 int command_remove(object *op, char *params) 01038 { 01039 object *tmp; 01040 01041 if (params == NULL || !(tmp = find_object_both(op, params))) 01042 { 01043 new_draw_info(0, COLOR_WHITE, op, "Remove what object?"); 01044 return 1; 01045 } 01046 01047 if (tmp->type == PLAYER) 01048 { 01049 new_draw_info(0, COLOR_WHITE, op, "Cannot remove a player!"); 01050 return 1; 01051 } 01052 01053 if (QUERY_FLAG(tmp, FLAG_REMOVED)) 01054 { 01055 new_draw_info_format(0, COLOR_WHITE, op, "%s is already removed!", query_name(tmp, NULL)); 01056 return 1; 01057 } 01058 01059 /* Ensure we have head. */ 01060 if (tmp->head) 01061 { 01062 tmp = tmp->head; 01063 } 01064 01065 if (tmp->speed != 0) 01066 { 01067 tmp->speed = 0; 01068 update_ob_speed(tmp); 01069 } 01070 01071 remove_ob(tmp); 01072 check_walk_off(tmp, NULL, MOVE_APPLY_VANISHED); 01073 return 1; 01074 } 01075 01081 int command_addexp(object *op, char *params) 01082 { 01083 char buf[MAX_BUF]; 01084 int snr; 01085 sint64 exp; 01086 object *exp_skill, *exp_ob; 01087 player *pl; 01088 01089 if (params == NULL || sscanf(params, "%s %d %"FMT64, buf, &snr, &exp) != 3) 01090 { 01091 int i; 01092 01093 new_draw_info(0, COLOR_WHITE, op, "Usage: /addexp <who> <skill nr> <exp>\nSkills/Nr: "); 01094 01095 for (i = 0; i < NROFSKILLS; i++) 01096 { 01097 new_draw_info_format(0, COLOR_WHITE, op, "%d: %s", i, skills[i].name); 01098 } 01099 01100 return 1; 01101 } 01102 01103 for (pl = first_player; pl != NULL; pl = pl->next) 01104 { 01105 if (!strncasecmp(pl->ob->name, buf, MAX_NAME)) 01106 { 01107 break; 01108 } 01109 } 01110 01111 if (pl == NULL) 01112 { 01113 new_draw_info(0, COLOR_WHITE, op, "No such player."); 01114 return 1; 01115 } 01116 01117 /* Safety check */ 01118 if (snr < 0 || snr >= NROFSKILLS) 01119 { 01120 new_draw_info(0, COLOR_WHITE, op, "No such skill."); 01121 return 1; 01122 } 01123 01124 exp_skill = pl->skill_ptr[snr]; 01125 01126 /* Our player doesn't have this skill? */ 01127 if (!exp_skill) 01128 { 01129 new_draw_info_format(0, COLOR_WHITE, op, "Player %s does not know the skill '%s'.", pl->ob->name, skills[snr].name); 01130 return 0; 01131 } 01132 01133 /* If we are full in this skill, there is nothing to do */ 01134 if (exp_skill->level >= MAXLEVEL && exp > 0) 01135 { 01136 return 0; 01137 } 01138 01139 /* We will sure change skill exp, mark for update */ 01140 pl->update_skills = 1; 01141 exp_ob = exp_skill->exp_obj; 01142 01143 if (!exp_ob) 01144 { 01145 LOG(llevBug, "add_exp() skill:%s - no exp_ob found!\n", query_name(exp_skill, NULL)); 01146 return 0; 01147 } 01148 01149 /* First we see what we can add to our skill */ 01150 exp = adjust_exp(pl->ob, exp_skill, exp); 01151 01152 /* adjust_exp has adjust the skill and all exp_obj and player exp */ 01153 /* now lets check for level up in all categories */ 01154 player_lvl_adj(pl->ob, exp_skill); 01155 player_lvl_adj(pl->ob, exp_ob); 01156 player_lvl_adj(pl->ob, NULL); 01157 01158 return 1; 01159 } 01160 01166 int command_speed(object *op, char *params) 01167 { 01168 int i; 01169 01170 if (params == NULL || !sscanf(params, "%d", &i)) 01171 { 01172 new_draw_info_format(0, COLOR_WHITE, op, "Current speed is %ld.", max_time); 01173 return 1; 01174 } 01175 01176 set_max_time(i); 01177 reset_sleep(); 01178 new_draw_info(0, COLOR_WHITE, op, "The speed has changed."); 01179 return 1; 01180 } 01181 01187 int command_stats(object *op, char *params) 01188 { 01189 player *pl; 01190 01191 if (params == NULL) 01192 { 01193 new_draw_info(0, COLOR_WHITE, op, "Who?"); 01194 return 1; 01195 } 01196 01197 for (pl = first_player; pl != NULL; pl = pl->next) 01198 { 01199 if (!strcmp(pl->ob->name, params)) 01200 { 01201 new_draw_info_format(0, COLOR_WHITE, op, "Str : %-2d H.P. : %-4d MAX : %d", pl->ob->stats.Str, pl->ob->stats.hp, pl->ob->stats.maxhp); 01202 new_draw_info_format(0, COLOR_WHITE, op, "Dex : %-2d S.P. : %-4d MAX : %d", pl->ob->stats.Dex, pl->ob->stats.sp, pl->ob->stats.maxsp); 01203 new_draw_info_format(0, COLOR_WHITE, op, "Con : %-2d AC : %-4d WC : %d", pl->ob->stats.Con, pl->ob->stats.ac, pl->ob->stats.wc); 01204 new_draw_info_format(0, COLOR_WHITE, op, "Wis : %-2d EXP : %"FMT64, pl->ob->stats.Wis, pl->ob->stats.exp); 01205 new_draw_info_format(0, COLOR_WHITE, op, "Cha : %-2d Food : %d", pl->ob->stats.Cha, pl->ob->stats.food); 01206 new_draw_info_format(0, COLOR_WHITE, op, "Int : %-2d Damage : %d", pl->ob->stats.Int, pl->ob->stats.dam); 01207 new_draw_info_format(0, COLOR_WHITE, op, "Pow : %-2d Grace : %d", pl->ob->stats.Pow, pl->ob->stats.grace); 01208 return 1; 01209 } 01210 } 01211 01212 if (pl == NULL) 01213 { 01214 new_draw_info(0, COLOR_WHITE, op, "No such player."); 01215 } 01216 01217 return 1; 01218 } 01219 01226 int command_resetmap(object *op, char *params) 01227 { 01228 mapstruct *m; 01229 shstr *path; 01230 int flags; 01231 01232 if (params == NULL) 01233 { 01234 m = has_been_loaded_sh(op->map->path); 01235 } 01236 else 01237 { 01238 shstr *mapfile_sh = add_string(params); 01239 01240 m = has_been_loaded_sh(mapfile_sh); 01241 free_string_shared(mapfile_sh); 01242 } 01243 01244 if (m == NULL) 01245 { 01246 new_draw_info(0, COLOR_WHITE, op, "No such map."); 01247 return 1; 01248 } 01249 01250 if (MAP_UNIQUE(m) && MAP_NOSAVE(m)) 01251 { 01252 new_draw_info(0, COLOR_WHITE, op, "Cannot reset unique no-save map."); 01253 return 1; 01254 } 01255 01256 if (!strncmp(m->path, "/random/", 8)) 01257 { 01258 new_draw_info(0, COLOR_WHITE, op, "You cannot reset a random map."); 01259 return 1; 01260 } 01261 01262 if (m->in_memory != MAP_IN_MEMORY) 01263 { 01264 LOG(llevBug, "Tried to swap out map which was not in memory.\n"); 01265 return 0; 01266 } 01267 01268 new_draw_info_format(0, COLOR_WHITE, op, "Start resetting map %s.", m->path); 01269 new_draw_info_format(0, COLOR_WHITE, op, "Removed %d players from map. Reset map.", dm_map_remove_players(m)); 01270 m->reset_time = seconds(); 01271 m->map_flags |= MAP_FLAG_FIXED_RTIME; 01272 /* Store the path, so we can load it after swapping is done. */ 01273 path = add_refcount(m->path); 01274 flags = MAP_NAME_SHARED | (MAP_UNIQUE(m) ? MAP_PLAYER_UNIQUE : 0); 01275 swap_map(m, 1); 01276 01277 m = ready_map_name(path, flags); 01278 free_string_shared(path); 01279 new_draw_info(0, COLOR_WHITE, op, "Resetmap done."); 01280 dm_map_reinsert_players(m, op); 01281 01282 return 1; 01283 } 01284 01290 int command_nowiz(object *op, char *params) 01291 { 01292 (void) params; 01293 01294 CLEAR_FLAG(op, FLAG_WIZ); 01295 CONTR(op)->followed_player[0] = '\0'; 01296 CLEAR_FLAG(op, FLAG_WIZPASS); 01297 CLEAR_MULTI_FLAG(op, FLAG_FLYING); 01298 fix_player(op); 01299 CONTR(op)->socket.update_tile = 0; 01300 esrv_send_inventory(op, op); 01301 CONTR(op)->update_los = 1; 01302 new_draw_info(0, COLOR_WHITE, op, "DM mode deactivated."); 01303 01304 return 1; 01305 } 01306 01314 static int checkdm(object *op, char *pl_passwd) 01315 { 01316 char name[MAX_BUF], passwd[MAX_BUF], host[MAX_BUF], buf[MAX_BUF], filename[MAX_BUF]; 01317 FILE *fp; 01318 01319 snprintf(filename, sizeof(filename), "%s/%s", settings.localdir, DMFILE); 01320 01321 if ((fp = fopen(filename, "r")) == NULL) 01322 { 01323 LOG(llevBug, "Could not read DM file.\n"); 01324 return 0; 01325 } 01326 01327 while(fgets(buf, sizeof(buf), fp) != NULL) 01328 { 01329 if (buf[0] == '#' || buf[0] == '\n') 01330 { 01331 continue; 01332 } 01333 01334 if (sscanf(buf, "%[^:]:%[^:]:%s\n", name, passwd, host) != 3) 01335 { 01336 LOG(llevBug, "Malformed dm file entry: %s", buf); 01337 } 01338 else if ((!strcmp(name, "*") || (op->name && !strcmp(op->name, name))) && (!strcmp(passwd, "*") || !strcmp(passwd, pl_passwd)) && (!strcmp(host, "*") || !strcmp(host, CONTR(op)->socket.host))) 01339 { 01340 fclose(fp); 01341 return 1; 01342 } 01343 } 01344 01345 fclose(fp); 01346 01347 return 0; 01348 } 01349 01355 int command_dm(object *op, char *params) 01356 { 01357 CONTR(op)->socket.ext_title_flag = 1; 01358 01359 /* IF we are DM, then turn mode off */ 01360 if (QUERY_FLAG(op, FLAG_WIZ) && op->type == PLAYER) 01361 { 01362 /* First remove all the spells */ 01363 send_spelllist_cmd(op, NULL, SPLIST_MODE_REMOVE); 01364 command_nowiz(op, params); 01365 /* Now that we are out of DM mode, add the known ones back */ 01366 send_spelllist_cmd(op, NULL, SPLIST_MODE_ADD); 01367 return 1; 01368 } 01369 01370 if (op->type != PLAYER || !CONTR(op)) 01371 { 01372 return 0; 01373 } 01374 01375 if (checkdm(op, (params ? params : "*"))) 01376 { 01377 SET_FLAG(op, FLAG_WIZ); 01378 SET_FLAG(op, FLAG_WAS_WIZ); 01379 SET_FLAG(op, FLAG_WIZPASS); 01380 01381 new_draw_info_format(0, COLOR_WHITE, op, "DM mode activated for %s!", op->name); 01382 SET_MULTI_FLAG(op, FLAG_FLYING); 01383 01384 esrv_send_inventory(op, op); 01385 01386 /* Send all the spells */ 01387 send_spelllist_cmd(op, NULL, SPLIST_MODE_ADD); 01388 01389 clear_los(op); 01390 01391 /* force a draw_look() */ 01392 CONTR(op)->socket.update_tile = 0; 01393 CONTR(op)->update_los = 1; 01394 } 01395 01396 return 1; 01397 } 01398 01406 static int command_learn_spell_or_prayer(object *op, char *params, int special_prayer) 01407 { 01408 int spell; 01409 01410 if (op->type != PLAYER || CONTR(op) == NULL || params == NULL) 01411 { 01412 return 0; 01413 } 01414 01415 if ((spell = look_up_spell_name(params)) < 0) 01416 { 01417 new_draw_info(0, COLOR_WHITE, op, "Unknown spell."); 01418 return 1; 01419 } 01420 01421 if (check_spell_known(op, spell)) 01422 { 01423 new_draw_info_format(0, COLOR_WHITE, op, "You already know the spell %s.", params); 01424 return 0; 01425 } 01426 01427 do_learn_spell(op, spell, special_prayer); 01428 return 1; 01429 } 01430 01436 int command_learn_spell(object *op, char *params) 01437 { 01438 return command_learn_spell_or_prayer(op, params, 0); 01439 } 01440 01446 int command_learn_special_prayer(object *op, char *params) 01447 { 01448 return command_learn_spell_or_prayer(op, params, 1); 01449 } 01450 01456 int command_forget_spell(object *op, char *params) 01457 { 01458 int spell; 01459 01460 if (op->type != PLAYER || CONTR(op) == NULL || params == NULL) 01461 { 01462 return 0; 01463 } 01464 01465 if ((spell = look_up_spell_name(params)) < 0) 01466 { 01467 new_draw_info(0, COLOR_WHITE, op, "Unknown spell."); 01468 return 1; 01469 } 01470 01471 do_forget_spell(op, spell); 01472 return 1; 01473 } 01474 01480 int command_listplugins(object *op, char *params) 01481 { 01482 (void) params; 01483 01484 display_plugins_list(op); 01485 return 1; 01486 } 01487 01495 int command_loadplugin(object *op, char *params) 01496 { 01497 char buf[MAX_BUF]; 01498 01499 if (!params) 01500 { 01501 new_draw_info(0, COLOR_WHITE, op, "Load what plugin?"); 01502 return 1; 01503 } 01504 01505 snprintf(buf, sizeof(buf), "%s/%s", PLUGINDIR, params); 01506 init_plugin(buf); 01507 01508 return 1; 01509 } 01510 01518 int command_unloadplugin(object *op, char *params) 01519 { 01520 if (!params) 01521 { 01522 new_draw_info(0, COLOR_WHITE, op, "Unload what plugin?"); 01523 return 1; 01524 } 01525 01526 remove_plugin(params); 01527 01528 return 1; 01529 } 01530 01536 void shutdown_agent(int timer, char *reason) 01537 { 01538 static int sd_timer = -1, m_count, real_count = -1; 01539 static struct timeval tv1, tv2; 01540 01541 if (timer == -1 && sd_timer == -1) 01542 { 01543 if (real_count > 0) 01544 { 01545 if (--real_count <= 0) 01546 { 01547 LOG(llevSystem, "Server shutdown started.\n"); 01548 command_kick(NULL, NULL); 01549 cleanup(); 01550 exit(0); 01551 } 01552 } 01553 01554 /* Nothing to do */ 01555 return; 01556 } 01557 01558 /* reset shutdown count */ 01559 if (timer != -1) 01560 { 01561 int t_min = timer / 60, t_sec = timer - (int) (timer / 60) * 60; 01562 01563 sd_timer = timer; 01564 01565 new_draw_info(NDI_PLAYER | NDI_ALL, COLOR_GREEN, NULL, "[Server]: ** SERVER SHUTDOWN STARTED **"); 01566 01567 if (reason) 01568 { 01569 new_draw_info_format(NDI_PLAYER | NDI_ALL, COLOR_GREEN, NULL, "[Server]: %s", reason); 01570 } 01571 01572 if (t_sec) 01573 { 01574 new_draw_info_format(NDI_PLAYER | NDI_ALL, COLOR_GREEN, NULL, "[Server]: SERVER REBOOT in %d minutes and %d seconds", t_min, t_sec); 01575 } 01576 else 01577 { 01578 new_draw_info_format(NDI_PLAYER | NDI_ALL, COLOR_GREEN, NULL, "[Server]: SERVER REBOOT in %d minutes", t_min); 01579 } 01580 01581 GETTIMEOFDAY(&tv1); 01582 m_count = timer / 60 - 1; 01583 real_count = -1; 01584 } 01585 /* Count the shutdown timer */ 01586 else 01587 { 01588 int t_min, t_sec = 0; 01589 01590 GETTIMEOFDAY(&tv2); 01591 01592 /* End countdown */ 01593 if ((int) (tv2.tv_sec - tv1.tv_sec) >= sd_timer) 01594 { 01595 new_draw_info(NDI_PLAYER | NDI_ALL, COLOR_GREEN, NULL, "[Server]: ** SERVER GOES DOWN NOW!!! **"); 01596 01597 if (reason) 01598 { 01599 new_draw_info_format(NDI_PLAYER | NDI_ALL, COLOR_GREEN, NULL, "[Server]: %s", reason); 01600 } 01601 01602 sd_timer = -1; 01603 real_count = 30; 01604 } 01605 01606 t_min = (sd_timer - (int) (tv2.tv_sec - tv1.tv_sec)) / 60; 01607 t_sec = (sd_timer - (int) (tv2.tv_sec - tv1.tv_sec)) - (int) ((sd_timer - (int) (tv2.tv_sec - tv1.tv_sec)) / 60) * 60; 01608 01609 if ((t_min == m_count && !t_sec)) 01610 { 01611 m_count = t_min - 1; 01612 01613 if (t_sec) 01614 { 01615 new_draw_info_format(NDI_PLAYER | NDI_ALL, COLOR_GREEN, NULL, "[Server]: SERVER REBOOT in %d minutes and %d seconds", t_min, t_sec); 01616 } 01617 else 01618 { 01619 new_draw_info_format(NDI_PLAYER | NDI_ALL, COLOR_GREEN, NULL, "[Server]: SERVER REBOOT in %d minutes", t_min); 01620 } 01621 } 01622 } 01623 } 01624 01631 int command_motd_set(object *op, char *params) 01632 { 01633 char filename[MAX_BUF]; 01634 01635 /* No params, show usage. */ 01636 if (params == NULL) 01637 { 01638 new_draw_info(0, COLOR_WHITE, op, "Usage:\nRevert to original MotD: /motd_set original\nAppend to custom MotD: /motd_set message"); 01639 return 0; 01640 } 01641 01642 snprintf(filename, sizeof(filename), "%s/motd_custom", settings.localdir); 01643 01644 /* If we are not reverting to original MotD */ 01645 if (strcmp(params, "original")) 01646 { 01647 FILE *fp; 01648 01649 if (!(fp = fopen(filename, "a"))) 01650 { 01651 new_draw_info(0, COLOR_RED, op, "Could not open file for appending data."); 01652 return 0; 01653 } 01654 01655 fprintf(fp, "%s\n", params); 01656 fclose(fp); 01657 01658 new_draw_info(0, COLOR_GREEN, op, "Appended to custom Message of the Day."); 01659 } 01660 else 01661 { 01662 unlink(filename); 01663 new_draw_info(0, COLOR_GREEN, op, "Reverted original Message of the Day."); 01664 } 01665 01666 return 1; 01667 } 01668 01674 int command_ban(object *op, char *params) 01675 { 01676 if (params == NULL) 01677 { 01678 return 1; 01679 } 01680 01681 /* Add a new ban */ 01682 if (strncmp(params, "add ", 4) == 0) 01683 { 01684 if (add_ban(params + 4)) 01685 { 01686 new_draw_info(0, COLOR_GREEN, op, "Added new ban successfully."); 01687 } 01688 else 01689 { 01690 new_draw_info(0, COLOR_RED, op, "Failed to add new ban!"); 01691 } 01692 } 01693 /* Remove ban */ 01694 else if (strncmp(params, "remove ", 7) == 0) 01695 { 01696 if (remove_ban(params + 7)) 01697 { 01698 new_draw_info(0, COLOR_GREEN, op, "Removed ban successfully."); 01699 } 01700 else 01701 { 01702 new_draw_info(0, COLOR_RED, op, "Failed to remove ban!"); 01703 } 01704 } 01705 /* List bans */ 01706 else if (strncmp(params, "list", 4) == 0) 01707 { 01708 list_bans(op); 01709 } 01710 01711 return 1; 01712 } 01713 01719 int command_debug(object *op, char *params) 01720 { 01721 int i; 01722 01723 if (params == NULL || !sscanf(params, "%d", &i)) 01724 { 01725 new_draw_info_format(0, COLOR_WHITE, op, "Debug level is %d.", settings.debug); 01726 return 1; 01727 } 01728 01729 settings.debug = (enum LogLevel) FABS(i); 01730 new_draw_info_format(0, COLOR_WHITE, op, "Set debug level to %d.", i); 01731 return 1; 01732 } 01733 01739 int command_dumpbelowfull(object *op, char *params) 01740 { 01741 object *tmp; 01742 StringBuffer *sb; 01743 char *diff; 01744 01745 (void) params; 01746 01747 new_draw_info(0, COLOR_WHITE, op, "OBJECTS ON THIS TILE"); 01748 new_draw_info(0, COLOR_WHITE, op, "-------------------"); 01749 01750 for (tmp = get_map_ob(op->map, op->x, op->y); tmp; tmp = tmp->above) 01751 { 01752 /* Exclude the DM player object */ 01753 if (tmp == op) 01754 { 01755 continue; 01756 } 01757 01758 sb = stringbuffer_new(); 01759 stringbuffer_append_printf(sb, "count %d\n", tmp->count); 01760 dump_object(tmp, sb); 01761 diff = stringbuffer_finish(sb); 01762 new_draw_info(0, COLOR_WHITE, op, diff); 01763 free(diff); 01764 01765 if (tmp->above && tmp->above != op) 01766 { 01767 new_draw_info(0, COLOR_WHITE, op, ">next object<"); 01768 } 01769 } 01770 01771 new_draw_info(0, COLOR_WHITE, op, "------------------"); 01772 01773 return 1; 01774 } 01775 01781 int command_dumpbelow(object *op, char *params) 01782 { 01783 object *tmp; 01784 int i = 0; 01785 01786 (void) params; 01787 01788 new_draw_info(0, COLOR_WHITE, op, "OBJECTS ON THIS TILE"); 01789 new_draw_info(0, COLOR_WHITE, op, "-------------------"); 01790 01791 for (tmp = get_map_ob(op->map, op->x, op->y); tmp; tmp = tmp->above, i++) 01792 { 01793 /* Exclude the DM player object */ 01794 if (tmp == op) 01795 { 01796 continue; 01797 } 01798 01799 new_draw_info_format(0, COLOR_WHITE, op, "#%d >%s< >%s< >%s<", i, query_name(tmp, NULL), tmp->arch ? (tmp->arch->name ? tmp->arch->name : "no arch name") : "NO ARCH", tmp->env ? query_name(tmp->env, NULL) : ""); 01800 } 01801 01802 new_draw_info(0, COLOR_WHITE, op, "------------------"); 01803 01804 return 1; 01805 } 01806 01812 int command_wizpass(object *op, char *params) 01813 { 01814 int i; 01815 01816 if (!op) 01817 { 01818 return 0; 01819 } 01820 01821 if (!params) 01822 { 01823 i = !QUERY_FLAG(op, FLAG_WIZPASS); 01824 } 01825 else 01826 { 01827 i = onoff_value(params); 01828 } 01829 01830 if (i) 01831 { 01832 new_draw_info(0, COLOR_WHITE, op, "You will now walk through walls."); 01833 SET_FLAG(op, FLAG_WIZPASS); 01834 } 01835 else 01836 { 01837 new_draw_info(0, COLOR_WHITE, op, "You will now be stopped by walls."); 01838 CLEAR_FLAG(op, FLAG_WIZPASS); 01839 } 01840 01841 return 1; 01842 } 01843 01849 int command_dumpallarchetypes(object *op, char *params) 01850 { 01851 (void) params; 01852 (void) op; 01853 dump_all_archetypes(); 01854 return 1; 01855 } 01856 01864 int command_dm_stealth(object *op, char *params) 01865 { 01866 (void) params; 01867 01868 if (op->type != PLAYER || !CONTR(op)) 01869 { 01870 return 1; 01871 } 01872 01873 if (CONTR(op)->dm_stealth) 01874 { 01875 CONTR(op)->dm_stealth = 0; 01876 } 01877 else 01878 { 01879 CONTR(op)->dm_stealth = 1; 01880 } 01881 01882 new_draw_info_format(0, COLOR_WHITE, op, "Toggled dm_stealth to %d.", CONTR(op)->dm_stealth); 01883 return 1; 01884 } 01885 01891 int command_dm_light(object *op, char *params) 01892 { 01893 (void) params; 01894 01895 if (op->type != PLAYER || !CONTR(op)) 01896 { 01897 return 1; 01898 } 01899 01900 if (CONTR(op)->dm_light) 01901 { 01902 CONTR(op)->dm_light = 0; 01903 } 01904 else 01905 { 01906 CONTR(op)->dm_light = 1; 01907 } 01908 01909 new_draw_info_format(0, COLOR_WHITE, op, "Toggled dm_light to %d.", CONTR(op)->dm_light); 01910 return 1; 01911 } 01912 01918 int command_dm_password(object *op, char *params) 01919 { 01920 FILE *fp, *fpout; 01921 const char *name_hash; 01922 char filename[MAX_BUF], bufall[MAX_BUF], outfile[MAX_BUF]; 01923 char name[MAX_BUF], password[MAX_BUF]; 01924 01925 if (!params || sscanf(params, "%s %s", name, password) != 2) 01926 { 01927 new_draw_info(0, COLOR_RED, op, "Usage: /dm_password <player name> <new password>"); 01928 return 0; 01929 } 01930 01931 adjust_player_name(name); 01932 snprintf(filename, sizeof(filename), "%s/%s/%s/%s.pl", settings.localdir, settings.playerdir, name, name); 01933 01934 if (!player_exists(name)) 01935 { 01936 new_draw_info_format(0, COLOR_WHITE, op, "Player %s doesn't exist.", name); 01937 } 01938 01939 strncpy(outfile, filename, sizeof(outfile)); 01940 strncat(outfile, ".tmp", sizeof(outfile) - strlen(outfile) - 1); 01941 01942 if (!(fp = fopen(filename, "r"))) 01943 { 01944 new_draw_info_format(0, COLOR_RED, op, "Error opening file %s.", filename); 01945 return 0; 01946 } 01947 01948 if (!(fpout = fopen(outfile, "w"))) 01949 { 01950 new_draw_info_format(0, COLOR_RED, op, "Error opening file %s.", outfile); 01951 return 0; 01952 } 01953 01954 while (fgets(bufall, sizeof(bufall) - 1, fp)) 01955 { 01956 if (!strncmp(bufall, "password ", 9)) 01957 { 01958 fprintf(fpout, "password %s\n", crypt_string(password, NULL)); 01959 } 01960 else 01961 { 01962 fputs(bufall, fpout); 01963 } 01964 } 01965 01966 if ((name_hash = find_string(name))) 01967 { 01968 player *pl; 01969 01970 for (pl = first_player; pl; pl = pl->next) 01971 { 01972 if (pl->ob && pl->ob->name == name_hash) 01973 { 01974 strcpy(pl->password, crypt_string(password, NULL)); 01975 break; 01976 } 01977 } 01978 } 01979 01980 fclose(fp); 01981 fclose(fpout); 01982 unlink(filename); 01983 rename(outfile, filename); 01984 01985 new_draw_info_format(0, COLOR_GREEN, op, "Done. Changed password of %s to %s!", name, password); 01986 return 0; 01987 } 01988 01994 int command_dumpactivelist(object *op, char *params) 01995 { 01996 int count = 0; 01997 object *tmp; 01998 01999 (void) params; 02000 02001 for (tmp = active_objects; tmp; tmp = tmp->active_next) 02002 { 02003 count++; 02004 LOG(llevSystem, "%08d %03d %f %s (%s)\n", tmp->count, tmp->type, tmp->speed, query_short_name(tmp, NULL), tmp->arch->name ? tmp->arch->name : "<NA>"); 02005 } 02006 02007 new_draw_info_format(0, COLOR_WHITE, op, "Active objects: %d (dumped to log)", count); 02008 LOG(llevSystem, "Active objects: %d\n", count); 02009 02010 return 1; 02011 } 02012 02018 int command_shutdown(object *op, char *params) 02019 { 02020 char *bp = NULL; 02021 int i = -2; 02022 02023 if (params == NULL) 02024 { 02025 new_draw_info(0, COLOR_WHITE, op, "Usage: /shutdown <seconds> [reason]"); 02026 return 1; 02027 } 02028 02029 sscanf(params, "%d ", &i); 02030 02031 if ((bp = strchr(params, ' ')) != NULL) 02032 { 02033 bp++; 02034 } 02035 02036 if (bp && *bp == '\0') 02037 { 02038 bp = NULL; 02039 } 02040 02041 if (i < -1) 02042 { 02043 new_draw_info(0, COLOR_WHITE, op, "Usage: /shutdown <seconds> [reason]"); 02044 return 1; 02045 } 02046 02047 LOG(llevSystem, "Shutdown agent started!\n"); 02048 shutdown_agent(i, bp); 02049 new_draw_info_format(0, COLOR_GREEN, op, "Shutdown agent started! Timer set to %d seconds.", i); 02050 02051 return 1; 02052 } 02053 02059 int command_setmaplight(object *op, char *params) 02060 { 02061 int i; 02062 02063 if (params == NULL || !sscanf(params, "%d", &i)) 02064 { 02065 return 0; 02066 } 02067 02068 set_map_darkness(op->map, i); 02069 02070 new_draw_info_format(0, COLOR_WHITE, op, "WIZ: set map darkness: %d -> map:%s (%d)", i, op->map->path, MAP_OUTDOORS(op->map)); 02071 02072 return 1; 02073 } 02074 02080 int command_dumpmap(object *op, char *params) 02081 { 02082 (void) params; 02083 02084 if (op) 02085 { 02086 dump_map(op->map); 02087 } 02088 02089 return 1; 02090 } 02091 02097 int command_dumpallmaps(object *op, char *params) 02098 { 02099 (void) params; 02100 (void) op; 02101 02102 dump_all_maps(); 02103 02104 return 1; 02105 } 02106 02116 int command_malloc(object *op, char *params) 02117 { 02118 #ifdef MEMPOOL_TRACKING 02119 if (params) 02120 { 02121 int force_flag = 0, i; 02122 02123 if (strcmp(params, "free") && strcmp(params, "force")) 02124 { 02125 new_draw_info(0, COLOR_WHITE, op, "Usage: /malloc [free | force]"); 02126 return 1; 02127 } 02128 02129 if (strcmp(params, "force") == 0) 02130 { 02131 force_flag = 1; 02132 } 02133 02134 for (i = 0; i < nrof_mempools; i++) 02135 { 02136 if (force_flag == 1 || mempools[i]->flags & MEMPOOL_ALLOW_FREEING) 02137 { 02138 #if 0 02139 free_empty_puddles(mempools[i]); 02140 #endif 02141 } 02142 } 02143 } 02144 #else 02145 (void) params; 02146 #endif 02147 02148 malloc_info(op); 02149 return 1; 02150 } 02151 02157 int command_maps(object *op, char *params) 02158 { 02159 (void) params; 02160 02161 maps_info(op); 02162 return 1; 02163 } 02164 02170 int command_strings(object *op, char *params) 02171 { 02172 char buf[HUGE_BUF]; 02173 02174 (void) params; 02175 02176 LOG(llevSystem, "HASH TABLE DUMP\n"); 02177 02178 ss_dump_statistics(buf, sizeof(buf)); 02179 new_draw_info(0, COLOR_WHITE, op, buf); 02180 LOG(llevSystem, "%s\n", buf); 02181 02182 ss_dump_table(SS_DUMP_TOTALS, buf, sizeof(buf)); 02183 new_draw_info(0, COLOR_WHITE, op, buf); 02184 LOG(llevSystem, "%s\n", buf); 02185 02186 return 1; 02187 } 02188 02194 int command_ssdumptable(object *op, char *params) 02195 { 02196 (void) params; 02197 (void) op; 02198 02199 ss_dump_table(SS_DUMP_TABLE, NULL, 0); 02200 return 1; 02201 } 02202 02208 int command_follow(object *op, char *params) 02209 { 02210 player *pl; 02211 02212 if (!params) 02213 { 02214 if (CONTR(op)->followed_player[0]) 02215 { 02216 new_draw_info_format(0, COLOR_WHITE, op, "You stop following %s.", CONTR(op)->followed_player); 02217 CONTR(op)->followed_player[0] = '\0'; 02218 } 02219 02220 return 0; 02221 } 02222 02223 pl = get_other_player_from_name(op, params); 02224 02225 if (!pl) 02226 { 02227 return 0; 02228 } 02229 02230 CONTR(op)->followed_player[0] = '\0'; 02231 strncpy(CONTR(op)->followed_player, params, sizeof(CONTR(op)->followed_player)); 02232 02233 new_draw_info_format(0, COLOR_GREEN, op, "Following %s.", params); 02234 return 0; 02235 } 02236 02242 int command_insert_into(object *op, char *params) 02243 { 02244 object *ob, *marked; 02245 02246 if (!params) 02247 { 02248 new_draw_info(0, COLOR_RED, op, "What object to insert something into?"); 02249 return 0; 02250 } 02251 02252 marked = find_marked_object(op); 02253 02254 if (!marked) 02255 { 02256 new_draw_info(0, COLOR_RED, op, "You need to mark the object to insert."); 02257 return 0; 02258 } 02259 02260 ob = find_object_both(op, params); 02261 02262 if (!ob) 02263 { 02264 new_draw_info(0, COLOR_RED, op, "No such object."); 02265 return 0; 02266 } 02267 02268 remove_ob(marked); 02269 insert_ob_in_ob(marked, ob); 02270 esrv_send_item(op, marked); 02271 fix_player(op); 02272 new_draw_info_format(0, COLOR_GREEN, op, "Successfully inserted '%s' into '%s'.", query_name(marked, NULL), ob->name); 02273 return 0; 02274 } 02275 02281 int command_arrest(object *op, char *params) 02282 { 02283 object *dummy; 02284 player *pl; 02285 02286 if (!params) 02287 { 02288 new_draw_info(0, COLOR_RED, op, "Usage: /arrest <player>."); 02289 return 1; 02290 } 02291 02292 pl = get_other_player_from_name(op, params); 02293 02294 if (!pl) 02295 { 02296 return 1; 02297 } 02298 02299 dummy = get_jail_exit(pl->ob); 02300 02301 if (!dummy) 02302 { 02303 /* We have nowhere to send the prisoner....*/ 02304 new_draw_info(0, COLOR_RED, op, "Can't jail player, there is no map to hold them."); 02305 return 1; 02306 } 02307 02308 enter_exit(pl->ob, dummy); 02309 new_draw_info_format(0, COLOR_GREEN, op, "Jailed %s.", pl->ob->name); 02310 LOG(llevChat, "Arrest: Player %s arrested by %s\n", pl->ob->name, op->name); 02311 return 1; 02312 } 02313 02319 int command_cmd_permission(object *op, char *params) 02320 { 02321 char *cp; 02322 player *pl; 02323 int i; 02324 02325 if (!params) 02326 { 02327 new_draw_info(0, COLOR_RED, op, "Usage: /cmd_permission <player> <add-remove-list> [command]"); 02328 return 1; 02329 } 02330 02331 cp = strchr(params, ' '); 02332 02333 if (!cp) 02334 { 02335 return 1; 02336 } 02337 02338 *(cp++) = '\0'; 02339 02340 pl = find_player(params); 02341 02342 if (!pl) 02343 { 02344 new_draw_info(0, COLOR_WHITE, op, "No such player."); 02345 return 1; 02346 } 02347 02348 if (!strncmp(cp, "add ", 4)) 02349 { 02350 cp += 4; 02351 02352 if (cp[0] == '/') 02353 { 02354 cp++; 02355 } 02356 02357 for (i = 0; i < pl->num_cmd_permissions; i++) 02358 { 02359 if (pl->cmd_permissions[i] && !strcmp(pl->cmd_permissions[i], cp)) 02360 { 02361 new_draw_info_format(0, COLOR_RED, op, "%s already has permission for /%s.", pl->ob->name, cp); 02362 return 1; 02363 } 02364 } 02365 02366 pl->num_cmd_permissions++; 02367 pl->cmd_permissions = realloc(pl->cmd_permissions, sizeof(char *) * pl->num_cmd_permissions); 02368 pl->cmd_permissions[pl->num_cmd_permissions - 1] = strdup_local(cp); 02369 new_draw_info_format(0, COLOR_GREEN, op, "%s has been granted permission for /%s.", pl->ob->name, cp); 02370 } 02371 else if (!strncmp(cp, "remove ", 7)) 02372 { 02373 cp += 7; 02374 02375 if (cp[0] == '/') 02376 { 02377 cp++; 02378 } 02379 02380 for (i = 0; i < pl->num_cmd_permissions; i++) 02381 { 02382 if (pl->cmd_permissions[i] && !strcmp(pl->cmd_permissions[i], cp)) 02383 { 02384 FREE_AND_NULL_PTR(pl->cmd_permissions[i]); 02385 new_draw_info_format(0, COLOR_GREEN, op, "%s has had permission for /%s command removed.", pl->ob->name, cp); 02386 return 1; 02387 } 02388 } 02389 02390 new_draw_info_format(0, COLOR_RED, op, "%s does not have permission for /%s.", pl->ob->name, cp); 02391 } 02392 else if (!strncmp(cp, "list", 4)) 02393 { 02394 if (pl->cmd_permissions) 02395 { 02396 new_draw_info_format(0, COLOR_WHITE, op, "%s has permissions for the following commands:\n", pl->ob->name); 02397 02398 for (i = 0; i < pl->num_cmd_permissions; i++) 02399 { 02400 if (pl->cmd_permissions[i]) 02401 { 02402 new_draw_info_format(0, COLOR_WHITE, op, "/%s", pl->cmd_permissions[i]); 02403 } 02404 } 02405 } 02406 else 02407 { 02408 new_draw_info_format(0, COLOR_WHITE, op, "%s has no command permissions.", pl->ob->name); 02409 } 02410 } 02411 02412 return 1; 02413 } 02414 02420 int command_map_save(object *op, char *params) 02421 { 02422 char buf[MAX_BUF], path[MAX_BUF], map_path[MAX_BUF]; 02423 struct stat stats; 02424 mapstruct *m; 02425 02426 (void) params; 02427 02428 /* Don't allow doing this for unique or random maps. */ 02429 if (MAP_UNIQUE(op->map) || !strncmp(op->map->path, "/random/", 8)) 02430 { 02431 new_draw_info(0, COLOR_WHITE, op, "Cannot be used on unique or random maps."); 02432 return 1; 02433 } 02434 02435 /* Store the map's path. */ 02436 strncpy(map_path, op->map->path, sizeof(map_path)); 02437 /* Create a path name to the actual map file. */ 02438 strncpy(path, create_pathname(op->map->path), sizeof(path) - 1); 02439 /* Path to the original file. */ 02440 snprintf(buf, sizeof(buf), "%s.map_old", path); 02441 02442 /* No original file yet? Create one. */ 02443 if (stat(buf, &stats)) 02444 { 02445 FILE *fp = fopen(buf, "w"); 02446 02447 if (!fp) 02448 { 02449 LOG(llevBug, "command_map_save(): Could not open '%s' for writing.\n", buf); 02450 new_draw_info_format(0, COLOR_WHITE, op, "Could not open '%s' for writing.", buf); 02451 return 1; 02452 } 02453 02454 copy_file(path, fp); 02455 fclose(fp); 02456 } 02457 02458 /* Remove players from the map. */ 02459 m = op->map; 02460 dm_map_remove_players(m); 02461 02462 /* Try to save the map. */ 02463 if (new_save_map(m, 1) == -1) 02464 { 02465 unlink(path); 02466 rename(buf, path); 02467 new_draw_info(0, COLOR_WHITE, op, "Map save error!"); 02468 } 02469 else 02470 { 02471 new_draw_info(0, COLOR_WHITE, op, "Current map has been saved to the original map file."); 02472 } 02473 02474 free_map(m, 1); 02475 /* Reload the map and re-insert players. */ 02476 m = ready_map_name(map_path, 0); 02477 dm_map_reinsert_players(m, op); 02478 return 1; 02479 } 02480 02486 int command_map_reset(object *op, char *params) 02487 { 02488 char buf[MAX_BUF], path[MAX_BUF]; 02489 struct stat stats; 02490 02491 (void) params; 02492 02493 /* Create a path name to the actual map file. */ 02494 strncpy(path, create_pathname(op->map->path), sizeof(path) - 1); 02495 /* Path to the original file. */ 02496 snprintf(buf, sizeof(buf), "%s.map_old", path); 02497 02498 /* Is there the original map file? */ 02499 if (!stat(buf, &stats)) 02500 { 02501 unlink(path); 02502 rename(buf, path); 02503 new_draw_info(0, COLOR_WHITE, op, "Current map reset."); 02504 } 02505 else 02506 { 02507 new_draw_info(0, COLOR_WHITE, op, "There is no original map to reset to."); 02508 } 02509 02510 return 1; 02511 } 02512 02518 int command_map_patch(object *op, char *params) 02519 { 02520 if (!params) 02521 { 02522 new_draw_info(0, COLOR_WHITE, op, "Patch what values?"); 02523 return 1; 02524 } 02525 02526 if (map_set_variable(op->map, params) == -1) 02527 { 02528 new_draw_info_format(0, COLOR_WHITE, op, "Unknown value for map header: %s", params); 02529 } 02530 else 02531 { 02532 new_draw_info_format(0, COLOR_WHITE, op, "(%s)->%s", op->map->name, params); 02533 } 02534 02535 return 1; 02536 } 02537 02543 int command_no_shout(object *op, char *params) 02544 { 02545 player *pl; 02546 02547 if (!params) 02548 { 02549 new_draw_info(0, COLOR_RED, op, "Usage: /no_shout <player>"); 02550 return 1; 02551 } 02552 02553 pl = find_player(params); 02554 02555 if (!pl) 02556 { 02557 new_draw_info(0, COLOR_WHITE, op, "No such player."); 02558 return 1; 02559 } 02560 02561 if (pl->no_shout) 02562 { 02563 new_draw_info_format(0, COLOR_WHITE, op, "%s is able to shout again.", pl->ob->name); 02564 pl->no_shout = 0; 02565 } 02566 else 02567 { 02568 new_draw_info_format(0, COLOR_WHITE, op, "%s is now not able to shout.", pl->ob->name); 02569 pl->no_shout = 1; 02570 } 02571 02572 return 1; 02573 } 02574 02580 int command_dmtake(object *op, char *params) 02581 { 02582 object *tmp; 02583 02584 if (!params) 02585 { 02586 new_draw_info(0, COLOR_WHITE, op, "Take what object?"); 02587 return 1; 02588 } 02589 02590 tmp = find_object_both(op, params); 02591 02592 if (!tmp) 02593 { 02594 new_draw_info(0, COLOR_WHITE, op, "No such object."); 02595 return 1; 02596 } 02597 02598 if (tmp->env == op) 02599 { 02600 return 1; 02601 } 02602 02603 pick_up(op, tmp, 0); 02604 return 1; 02605 } 02606 02614 int command_server_shout(object *op, char *params) 02615 { 02616 player *pl; 02617 02618 params = cleanup_chat_string(params); 02619 02620 if (!params || *params == '\0') 02621 { 02622 return 0; 02623 } 02624 02625 LOG(llevChat, "Server shout: %s: %s\n", op->name, params); 02626 02627 for (pl = first_player; pl; pl = pl->next) 02628 { 02629 if (can_do_wiz_command(pl, "server_shout")) 02630 { 02631 new_draw_info_format(NDI_PLAYER, COLOR_GREEN, pl->ob, "[Server] (%s): %s", op->name, params); 02632 } 02633 else 02634 { 02635 new_draw_info_format(NDI_PLAYER, COLOR_GREEN, pl->ob, "[Server]: %s", params); 02636 } 02637 } 02638 02639 return 1; 02640 } 02641 02649 int command_mod_shout(object *op, char *params) 02650 { 02651 player *pl; 02652 02653 params = cleanup_chat_string(params); 02654 02655 if (!params || *params == '\0') 02656 { 02657 return 0; 02658 } 02659 02660 LOG(llevChat, "Mod shout: %s: %s\n", op->name, params); 02661 02662 for (pl = first_player; pl; pl = pl->next) 02663 { 02664 if (can_do_wiz_command(pl, "mod_shout")) 02665 { 02666 new_draw_info_format(NDI_PLAYER, COLOR_BRIGHT_PURPLE, pl->ob, "[Moderator] (%s): %s", op->name, params); 02667 } 02668 else 02669 { 02670 new_draw_info_format(NDI_PLAYER, COLOR_BRIGHT_PURPLE, pl->ob, "[Moderator]: %s", params); 02671 } 02672 } 02673 02674 return 1; 02675 }
1.7.4