|
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 00031 #include <global.h> 00032 00036 void maps_info(object *op) 00037 { 00038 mapstruct *m; 00039 char map_path[MAX_BUF]; 00040 long sec = seconds(); 00041 00042 new_draw_info_format(0, COLOR_WHITE, op, "Current time is: %02ld:%02ld:%02ld.", (sec % 86400) / 3600, (sec % 3600) / 60, sec % 60); 00043 new_draw_info(0, COLOR_WHITE, op, "Path Pl PlM IM TO Dif Reset"); 00044 00045 for (m = first_map; m != NULL; m = m->next) 00046 { 00047 /* Print out the last 18 characters of the map name... */ 00048 if (strlen(m->path) <= 18) 00049 { 00050 strcpy(map_path, m->path); 00051 } 00052 else 00053 { 00054 strcpy(map_path, m->path + strlen(m->path) - 18); 00055 } 00056 00057 new_draw_info_format(0, COLOR_WHITE, op, "%-18.18s %2d %c %4d %2d %02d:%02d:%02d", map_path, players_on_map(m), m->in_memory ? (m->in_memory == MAP_IN_MEMORY ? 'm' : 's') : 'X', m->timeout, m->difficulty, (MAP_WHEN_RESET(m) % 86400) / 3600, (MAP_WHEN_RESET(m) % 3600) / 60, MAP_WHEN_RESET(m) % 60); 00058 } 00059 } 00060 00066 int command_motd(object *op, char *params) 00067 { 00068 (void) params; 00069 00070 display_motd(op); 00071 return 1; 00072 } 00073 00077 static int count_active() 00078 { 00079 int i = 0; 00080 object *tmp = active_objects; 00081 00082 while (tmp != NULL) 00083 { 00084 tmp = tmp->active_next, i++; 00085 } 00086 00087 return i; 00088 } 00089 00093 void malloc_info(object *op) 00094 { 00095 int players, nrofmaps; 00096 int nrm = 0, mapmem = 0, anr, anims, sum_alloc = 0, sum_used = 0, i, tlnr, alnr; 00097 treasurelist *tl; 00098 player *pl; 00099 mapstruct *m; 00100 archetype *at; 00101 artifactlist *al; 00102 00103 for (tl = first_treasurelist, tlnr = 0; tl != NULL; tl = tl->next, tlnr++) 00104 { 00105 } 00106 00107 for (al = first_artifactlist, alnr = 0; al != NULL; al = al->next, alnr++) 00108 { 00109 } 00110 00111 for (at = first_archetype, anr = 0, anims = 0; at != NULL; at = at->more == NULL ? at->next : at->more, anr++) 00112 { 00113 } 00114 00115 for (i = 1; i < num_animations; i++) 00116 { 00117 anims += animations[i].num_animations; 00118 } 00119 00120 for (pl = first_player, players = 0; pl != NULL; pl = pl->next, players++) 00121 { 00122 } 00123 00124 for (m = first_map, nrofmaps = 0; m != NULL; m = m->next, nrofmaps++) 00125 { 00126 if (m->in_memory == MAP_IN_MEMORY) 00127 { 00128 mapmem += MAP_WIDTH(m) * MAP_HEIGHT(m) * (sizeof(object *) + sizeof(MapSpace)); 00129 nrm++; 00130 } 00131 } 00132 00133 new_draw_info_format(0, COLOR_WHITE, op, "Sizeof: object=%ld player=%ld map=%ld", (long) sizeof(object), (long) sizeof(player), (long) sizeof(mapstruct)); 00134 00135 dump_mempool_statistics(op, &sum_used, &sum_alloc); 00136 00137 new_draw_info_format(0, COLOR_WHITE, op, "%4d active objects", count_active()); 00138 00139 new_draw_info_format(0, COLOR_WHITE, op, "%4d maps allocated: %8d", nrofmaps, i = (nrofmaps * sizeof(mapstruct))); 00140 sum_alloc += i; 00141 sum_used += nrm * sizeof(mapstruct); 00142 00143 new_draw_info_format(0, COLOR_WHITE, op, "%4d maps in memory: %8d", nrm, mapmem); 00144 sum_alloc += mapmem; 00145 sum_used += mapmem; 00146 00147 new_draw_info_format(0, COLOR_WHITE, op, "%4d archetypes: %8d", anr, i = (anr * sizeof(archetype))); 00148 sum_alloc += i; 00149 sum_used += i; 00150 00151 new_draw_info_format(0, COLOR_WHITE, op, "%4d animations: %8d", anims, i = (anims * sizeof(Fontindex))); 00152 sum_alloc += i; 00153 sum_used += i; 00154 00155 new_draw_info_format(0, COLOR_WHITE, op, "%4d spells: %8d", NROFREALSPELLS, i = (NROFREALSPELLS * sizeof(spell_struct))); 00156 sum_alloc += i; 00157 sum_used += i; 00158 00159 new_draw_info_format(0, COLOR_WHITE, op, "%4d treasurelists %8d", tlnr, i = (tlnr * sizeof(treasurelist))); 00160 sum_alloc += i; 00161 sum_used += i; 00162 00163 new_draw_info_format(0, COLOR_WHITE, op, "%4ld treasures %8d", nroftreasures, i = (nroftreasures * sizeof(treasure))); 00164 sum_alloc += i; 00165 sum_used += i; 00166 00167 new_draw_info_format(0, COLOR_WHITE, op, "%4ld artifacts %8d", nrofartifacts, i = (nrofartifacts * sizeof(artifact))); 00168 sum_alloc += i; 00169 sum_used += i; 00170 00171 new_draw_info_format(0, COLOR_WHITE, op, "%4ld artifacts strngs %8d", nrofallowedstr, i = (nrofallowedstr * sizeof(linked_char))); 00172 sum_alloc += i; 00173 sum_used += i; 00174 00175 new_draw_info_format(0, COLOR_WHITE, op, "%4d artifactlists %8d", alnr, i = (alnr * sizeof(artifactlist))); 00176 sum_alloc += i; 00177 sum_used += i; 00178 00179 new_draw_info_format(0, COLOR_WHITE, op, "Total space allocated:%8d", sum_alloc); 00180 new_draw_info_format(0, COLOR_WHITE, op, "Total space used: %8d", sum_used); 00181 } 00182 00186 static void current_map_info(object *op) 00187 { 00188 mapstruct *m = op->map; 00189 MapSpace *msp; 00190 00191 if (!m) 00192 { 00193 return; 00194 } 00195 00196 msp = GET_MAP_SPACE_PTR(m, op->x, op->y); 00197 new_draw_info_format(0, COLOR_WHITE, op, "%s (%s, %s, x: %d, y: %d)", msp->map_info && OBJECT_VALID(msp->map_info, msp->map_info_count) && msp->map_info->race ? msp->map_info->race : m->name, msp->map_info && OBJECT_VALID(msp->map_info, msp->map_info_count) && msp->map_info->slaying ? msp->map_info->slaying : (m->bg_music ? m->bg_music : "no_music"), m->path, op->x, op->y); 00198 00199 if (QUERY_FLAG(op, FLAG_WIZ)) 00200 { 00201 new_draw_info_format(0, COLOR_WHITE, op, "Players: %d difficulty: %d size: %dx%d start: %dx%d", players_on_map(m), MAP_DIFFICULTY(m), MAP_WIDTH(m), MAP_HEIGHT(m), MAP_ENTER_X(m), MAP_ENTER_Y(m)); 00202 } 00203 00204 if (m->msg) 00205 { 00206 new_draw_info(0, COLOR_WHITE, op, m->msg); 00207 } 00208 } 00209 00218 int command_who(object *op, char *params) 00219 { 00220 player *pl; 00221 int ip = 0, il = 0, wiz; 00222 char buf[MAX_BUF], race[MAX_BUF]; 00223 00224 if (!op) 00225 { 00226 return 1; 00227 } 00228 00229 new_draw_info(0, COLOR_WHITE, op, " "); 00230 00231 wiz = QUERY_FLAG(op, FLAG_WIZ); 00232 00233 (void) params; 00234 00235 for (pl = first_player; pl; pl = pl->next) 00236 { 00237 if (pl->dm_stealth && !wiz) 00238 { 00239 continue; 00240 } 00241 00242 if (!pl->ob->map) 00243 { 00244 il++; 00245 continue; 00246 } 00247 00248 ip++; 00249 00250 if (pl->state == ST_PLAYING) 00251 { 00252 if (wiz) 00253 { 00254 snprintf(buf, sizeof(buf), "%s (%s) [%s] (#%d)", pl->ob->name, pl->socket.host, pl->ob->map->path, pl->ob->count); 00255 } 00256 else 00257 { 00258 snprintf(buf, sizeof(buf), "%s the %s %s (lvl %d)", pl->ob->name, gender_noun[object_get_gender(pl->ob)], player_get_race_class(pl->ob, race, sizeof(race)), pl->ob->level); 00259 00260 if (QUERY_FLAG(pl->ob, FLAG_WIZ)) 00261 { 00262 strncat(buf, " [WIZ]", sizeof(buf) - strlen(buf) - 1); 00263 } 00264 00265 if (pl->afk) 00266 { 00267 strncat(buf, " [AFK]", sizeof(buf) - strlen(buf) - 1); 00268 } 00269 00270 if (pl->socket.is_bot) 00271 { 00272 strncat(buf, " [BOT]", sizeof(buf) - strlen(buf) - 1); 00273 } 00274 00275 if (pl->class_ob && pl->class_ob->title) 00276 { 00277 strncat(buf, " ", sizeof(buf) - strlen(buf) - 1); 00278 strncat(buf, pl->class_ob->title, sizeof(buf) - strlen(buf) - 1); 00279 } 00280 } 00281 00282 new_draw_info(0, COLOR_WHITE, op, buf); 00283 } 00284 } 00285 00286 new_draw_info_format(0, COLOR_WHITE, op, "There %s %d player%s online (%d in login).", ip + il > 1 ? "are" : "is", ip + il, ip + il > 1 ? "s" : "", il); 00287 00288 return 1; 00289 } 00290 00296 int command_mapinfo(object *op, char *params) 00297 { 00298 (void) params; 00299 00300 current_map_info(op); 00301 return 1; 00302 } 00303 00309 int command_time(object *op, char *params) 00310 { 00311 (void) params; 00312 00313 time_info(op); 00314 return 1; 00315 } 00316 00322 int command_hiscore(object *op, char *params) 00323 { 00324 int results = 0; 00325 00326 if (params) 00327 { 00328 results = atoi(params); 00329 00330 /* If it was a number, don't bother using params to search in /hiscore. */ 00331 if (results != 0) 00332 { 00333 params = NULL; 00334 } 00335 else if (strlen(params) < PLAYER_NAME_MIN) 00336 { 00337 new_draw_info_format(0, COLOR_WHITE, op, "Your search term must be at least %d characters long.", PLAYER_NAME_MIN); 00338 return 1; 00339 } 00340 } 00341 00342 /* Add some limits. */ 00343 if (results <= 0) 00344 { 00345 results = 25; 00346 } 00347 else if (results > 50) 00348 { 00349 results = 50; 00350 } 00351 00352 hiscore_display(op, results, params); 00353 return 1; 00354 } 00355 00361 int command_version(object *op, char *params) 00362 { 00363 (void) params; 00364 00365 version(op); 00366 00367 return 1; 00368 } 00369 00375 int command_praying(object *op, char *params) 00376 { 00377 (void) params; 00378 00379 CONTR(op)->praying = 1; 00380 return 1; 00381 } 00382 00387 int onoff_value(char *line) 00388 { 00389 int i; 00390 00391 if (sscanf(line, "%d", &i)) 00392 { 00393 return (i != 0); 00394 } 00395 00396 switch (line[0]) 00397 { 00398 case 'o': 00399 switch (line[1]) 00400 { 00401 /* on */ 00402 case 'n': 00403 return 1; 00404 00405 /* o[ff] */ 00406 default: 00407 return 0; 00408 } 00409 00410 /* y[es] */ 00411 case 'y': 00412 /* k[ylla] */ 00413 case 'k': 00414 case 's': 00415 case 'd': 00416 return 1; 00417 00418 /* n[o] */ 00419 case 'n': 00420 /* e[i] */ 00421 case 'e': 00422 case 'u': 00423 default: 00424 return 0; 00425 } 00426 } 00427 00431 void receive_player_name(object *op) 00432 { 00433 adjust_player_name(CONTR(op)->write_buf + 1); 00434 00435 if (!check_name(CONTR(op), CONTR(op)->write_buf + 1)) 00436 { 00437 get_name(op); 00438 return; 00439 } 00440 00441 FREE_AND_COPY_HASH(op->name, CONTR(op)->write_buf + 1); 00442 00443 get_password(op); 00444 } 00445 00449 void receive_player_password(object *op) 00450 { 00451 unsigned int pwd_len = strlen(CONTR(op)->write_buf + 1); 00452 00453 if (pwd_len < PLAYER_PASSWORD_MIN || pwd_len > PLAYER_PASSWORD_MAX) 00454 { 00455 send_socket_message(COLOR_RED, &CONTR(op)->socket, "That password has an invalid length."); 00456 get_name(op); 00457 return; 00458 } 00459 00460 if (CONTR(op)->state == ST_CONFIRM_PASSWORD) 00461 { 00462 char cmd_buf[] = "X"; 00463 00464 if (!check_password(CONTR(op)->write_buf + 1, CONTR(op)->password)) 00465 { 00466 send_socket_message(COLOR_RED, &CONTR(op)->socket, "The passwords did not match."); 00467 get_name(op); 00468 return; 00469 } 00470 00471 Write_String_To_Socket(&CONTR(op)->socket, BINARY_CMD_NEW_CHAR, cmd_buf, 1); 00472 LOG(llevInfo, "NewChar send for %s\n", op->name); 00473 CONTR(op)->state = ST_ROLL_STAT; 00474 00475 return; 00476 } 00477 00478 strcpy(CONTR(op)->password, crypt_string(CONTR(op)->write_buf + 1, NULL)); 00479 CONTR(op)->state = ST_ROLL_STAT; 00480 check_login(op); 00481 return; 00482 } 00483 00491 int command_save(object *op, char *params) 00492 { 00493 (void) params; 00494 00495 if (MAP_PLAYER_NO_SAVE(op->map)) 00496 { 00497 new_draw_info(0, COLOR_WHITE, op, "You cannot save here."); 00498 } 00499 else if (save_player(op, 1)) 00500 { 00501 new_draw_info(0, COLOR_WHITE, op, "You have been saved."); 00502 } 00503 else 00504 { 00505 new_draw_info(0, COLOR_WHITE, op, "SAVE FAILED!"); 00506 } 00507 00508 return 1; 00509 } 00510 00516 int command_afk(object *op, char *params) 00517 { 00518 (void) params; 00519 00520 if (CONTR(op)->afk) 00521 { 00522 CONTR(op)->afk = 0; 00523 new_draw_info(0, COLOR_WHITE, op, "You are no longer AFK."); 00524 } 00525 else 00526 { 00527 CONTR(op)->afk = 1; 00528 CONTR(op)->stat_afk_used++; 00529 new_draw_info(0, COLOR_WHITE, op, "You are now AFK."); 00530 } 00531 00532 CONTR(op)->socket.ext_title_flag = 1; 00533 00534 return 1; 00535 } 00536 00542 int command_gsay(object *op, char *params) 00543 { 00544 char party_params[MAX_BUF]; 00545 00546 params = cleanup_chat_string(params); 00547 00548 if (!params || *params == '\0') 00549 { 00550 return 0; 00551 } 00552 00553 strcpy(party_params, "say "); 00554 strcat(party_params, params); 00555 command_party(op, party_params); 00556 return 0; 00557 } 00558 00565 int command_party(object *op, char *params) 00566 { 00567 char buf[MAX_BUF]; 00568 00569 if (!params) 00570 { 00571 if (!CONTR(op)->party) 00572 { 00573 new_draw_info(0, COLOR_WHITE, op, "You are not a member of any party."); 00574 new_draw_info(0, COLOR_WHITE, op, "For help try: /party help"); 00575 } 00576 else 00577 { 00578 new_draw_info_format(0, COLOR_WHITE, op, "You are a member of party %s (leader: %s).", CONTR(op)->party->name, CONTR(op)->party->leader); 00579 } 00580 00581 return 1; 00582 } 00583 00584 if (!strcmp(params, "help")) 00585 { 00586 new_draw_info(0, COLOR_WHITE, op, "To form a party type: /party form <partyname>"); 00587 new_draw_info(0, COLOR_WHITE, op, "To join a party type: /party join <partyname>"); 00588 new_draw_info(0, COLOR_WHITE, op, "If the party has a password, it will prompt you for it."); 00589 new_draw_info(0, COLOR_WHITE, op, "For a list of current parties type: /party list"); 00590 new_draw_info(0, COLOR_WHITE, op, "To leave a party type: /party leave"); 00591 new_draw_info(0, COLOR_WHITE, op, "To change a password for a party type: /party password <password>"); 00592 new_draw_info(0, COLOR_WHITE, op, "There is a 8 character max for password."); 00593 new_draw_info(0, COLOR_WHITE, op, "To talk to party members type: /party say <msg> or /gsay <msg>"); 00594 new_draw_info(0, COLOR_WHITE, op, "To see who is in your party: /party who"); 00595 new_draw_info(0, COLOR_WHITE, op, "To change the party's looting mode: /party loot mode"); 00596 new_draw_info(0, COLOR_WHITE, op, "To kick another player from your party: /party kick <name>"); 00597 new_draw_info(0, COLOR_WHITE, op, "To change party leader: /party leader <name>"); 00598 return 1; 00599 } 00600 else if (!strncmp(params, "say ", 4)) 00601 { 00602 if (!CONTR(op)->party) 00603 { 00604 new_draw_info(0, COLOR_WHITE, op, "You are not a member of any party."); 00605 return 1; 00606 } 00607 00608 params += 4; 00609 params = cleanup_chat_string(params); 00610 00611 if (!params || *params == '\0') 00612 { 00613 return 1; 00614 } 00615 00616 snprintf(buf, sizeof(buf), "[%s] %s says: %s", CONTR(op)->party->name, op->name, params); 00617 send_party_message(CONTR(op)->party, buf, PARTY_MESSAGE_CHAT, NULL); 00618 LOG(llevChat, "Party: %s [%s]: %s\n", op->name, CONTR(op)->party->name, params); 00619 return 1; 00620 } 00621 else if (!strcmp(params, "leave")) 00622 { 00623 if (!CONTR(op)->party) 00624 { 00625 new_draw_info(0, COLOR_WHITE, op, "You are not a member of any party."); 00626 return 1; 00627 } 00628 00629 new_draw_info_format(0, COLOR_WHITE, op, "You leave party %s.", CONTR(op)->party->name); 00630 snprintf(buf, sizeof(buf), "%s leaves party %s.", op->name, CONTR(op)->party->name); 00631 send_party_message(CONTR(op)->party, buf, PARTY_MESSAGE_STATUS, op); 00632 00633 remove_party_member(CONTR(op)->party, op); 00634 return 1; 00635 } 00636 else if (!strncmp(params, "password ", 9)) 00637 { 00638 if (!CONTR(op)->party) 00639 { 00640 new_draw_info(0, COLOR_RED, op, "You are not a member of any party."); 00641 return 1; 00642 } 00643 00644 if (CONTR(op)->party->leader != op->name) 00645 { 00646 new_draw_info(0, COLOR_RED, op, "Only the party's leader can change the password."); 00647 return 1; 00648 } 00649 00650 strncpy(CONTR(op)->party->passwd, params + 9, sizeof(CONTR(op)->party->passwd) - 1); 00651 snprintf(buf, sizeof(buf), "The password for party %s changed to '%s'.", CONTR(op)->party->name, CONTR(op)->party->passwd); 00652 send_party_message(CONTR(op)->party, buf, PARTY_MESSAGE_STATUS, NULL); 00653 return 1; 00654 } 00655 else if (!strncmp(params, "form ", 5)) 00656 { 00657 params = cleanup_chat_string(params + 5); 00658 00659 if (!params || *params == '\0') 00660 { 00661 new_draw_info(0, COLOR_RED, op, "Invalid party name to form."); 00662 return 1; 00663 } 00664 00665 if (CONTR(op)->party) 00666 { 00667 new_draw_info(0, COLOR_RED, op, "You must leave your current party before forming a new one."); 00668 return 1; 00669 } 00670 00671 if (find_party(params)) 00672 { 00673 new_draw_info_format(0, COLOR_WHITE, op, "The party %s already exists, pick another name.", params); 00674 return 1; 00675 } 00676 00677 form_party(op, params); 00678 return 1; 00679 } 00680 else if (!strncmp(params, "loot", 4)) 00681 { 00682 size_t i; 00683 00684 params += 4; 00685 00686 if (!CONTR(op)->party) 00687 { 00688 new_draw_info(0, COLOR_RED, op, "You are not a member of any party."); 00689 return 1; 00690 } 00691 00692 if (!params || !*params || !++params) 00693 { 00694 new_draw_info_format(0, COLOR_WHITE, op, "Current looting mode: <green>%s</green>.", party_loot_modes[CONTR(op)->party->loot]); 00695 return 1; 00696 } 00697 00698 if (CONTR(op)->party->leader != op->name) 00699 { 00700 new_draw_info(0, COLOR_RED, op, "Only the party's leader can change the looting mode."); 00701 return 1; 00702 } 00703 00704 for (i = 0; i < PARTY_LOOT_MAX; i++) 00705 { 00706 if (!strcmp(params, party_loot_modes[i])) 00707 { 00708 CONTR(op)->party->loot = i; 00709 snprintf(buf, sizeof(buf), "Party looting mode changed to '%s'.", party_loot_modes[i]); 00710 send_party_message(CONTR(op)->party, buf, PARTY_MESSAGE_STATUS, NULL); 00711 return 1; 00712 } 00713 } 00714 00715 new_draw_info(0, COLOR_WHITE, op, "Invalid looting mode. Valid modes are:"); 00716 00717 for (i = 0; i < PARTY_LOOT_MAX; i++) 00718 { 00719 new_draw_info_format(0, COLOR_WHITE, op, "<green>%s</green>: %s.", party_loot_modes[i], party_loot_modes_help[i]); 00720 } 00721 00722 return 1; 00723 } 00724 else if (!strncmp(params, "kick", 4)) 00725 { 00726 objectlink *ol; 00727 00728 if (!CONTR(op)->party) 00729 { 00730 new_draw_info(0, COLOR_RED, op, "You are not a member of any party."); 00731 return 1; 00732 } 00733 00734 if (CONTR(op)->party->leader != op->name) 00735 { 00736 new_draw_info(0, COLOR_RED, op, "Only the party's leader can kick other members of the party."); 00737 return 1; 00738 } 00739 00740 params = cleanup_chat_string(params + 4); 00741 00742 if (!params || *params == '\0') 00743 { 00744 new_draw_info(0, COLOR_WHITE, op, "Whom do you want to kick from the party?"); 00745 return 1; 00746 } 00747 00748 if (!strncasecmp(op->name, params, MAX_NAME)) 00749 { 00750 new_draw_info(0, COLOR_RED, op, "You cannot kick yourself."); 00751 return 1; 00752 } 00753 00754 for (ol = CONTR(op)->party->members; ol; ol = ol->next) 00755 { 00756 if (!strncasecmp(ol->objlink.ob->name, params, MAX_NAME)) 00757 { 00758 remove_party_member(CONTR(op)->party, ol->objlink.ob); 00759 snprintf(buf, sizeof(buf), "%s has been kicked from the party.", ol->objlink.ob->name); 00760 send_party_message(CONTR(op)->party, buf, PARTY_MESSAGE_STATUS, NULL); 00761 new_draw_info_format(0, COLOR_RED, ol->objlink.ob, "You have been kicked from the party '%s'.", CONTR(op)->party->name); 00762 return 1; 00763 } 00764 } 00765 00766 new_draw_info(0, COLOR_RED, op, "There's no player with that name in your party."); 00767 return 1; 00768 } 00769 else if (!strncmp(params, "leader ", 7)) 00770 { 00771 player *pl; 00772 00773 if (!CONTR(op)->party) 00774 { 00775 new_draw_info(0, COLOR_RED, op, "You are not a member of any party."); 00776 return 1; 00777 } 00778 00779 if (CONTR(op)->party->leader != op->name) 00780 { 00781 new_draw_info(0, COLOR_RED, op, "Only the party's leader can change the leader."); 00782 return 1; 00783 } 00784 00785 pl = find_player(params + 7); 00786 00787 if (!pl) 00788 { 00789 new_draw_info(0, COLOR_RED, op, "No such player."); 00790 return 1; 00791 } 00792 00793 if (pl->ob == op) 00794 { 00795 new_draw_info(0, COLOR_RED, op, "You are already the party leader."); 00796 return 1; 00797 } 00798 00799 if (!pl->party || pl->party != CONTR(op)->party) 00800 { 00801 new_draw_info(0, COLOR_RED, op, "That player is not a member of your party."); 00802 return 1; 00803 } 00804 00805 FREE_AND_ADD_REF_HASH(pl->party->leader, pl->ob->name); 00806 new_draw_info_format(0, COLOR_WHITE, pl->ob, "You are the new leader of party %s!", pl->party->name); 00807 new_draw_info_format(0, COLOR_GREEN, op, "%s is the new leader of your party.", pl->ob->name); 00808 return 1; 00809 } 00810 else 00811 { 00812 party_struct *party; 00813 SockList sl; 00814 unsigned char sock_buf[MAXSOCKBUF]; 00815 00816 sl.buf = sock_buf; 00817 SOCKET_SET_BINARY_CMD(&sl, BINARY_CMD_PARTY); 00818 00819 if (!strcmp(params, "list")) 00820 { 00821 SockList_AddChar(&sl, CMD_PARTY_LIST); 00822 00823 for (party = first_party; party; party = party->next) 00824 { 00825 SockList_AddString(&sl, party->name); 00826 SockList_AddString(&sl, party->leader); 00827 } 00828 } 00829 else if (!strcmp(params, "who")) 00830 { 00831 objectlink *ol; 00832 00833 if (!CONTR(op)->party) 00834 { 00835 new_draw_info(0, COLOR_RED, op, "You are not a member of any party."); 00836 return 1; 00837 } 00838 00839 SockList_AddChar(&sl, CMD_PARTY_WHO); 00840 00841 for (ol = CONTR(op)->party->members; ol; ol = ol->next) 00842 { 00843 if (CONTR(op)->socket.socket_version >= 1054) 00844 { 00845 SockList_AddString(&sl, ol->objlink.ob->name); 00846 SockList_AddChar(&sl, MAX(1, MIN((double) ol->objlink.ob->stats.hp / ol->objlink.ob->stats.maxhp * 100.0f, 100))); 00847 SockList_AddChar(&sl, MAX(1, MIN((double) ol->objlink.ob->stats.sp / ol->objlink.ob->stats.maxsp * 100.0f, 100))); 00848 SockList_AddChar(&sl, MAX(1, MIN((double) ol->objlink.ob->stats.grace / ol->objlink.ob->stats.maxgrace * 100.0f, 100))); 00849 } 00850 else 00851 { 00852 SockList_AddString(&sl, ol->objlink.ob->name); 00853 SockList_AddString(&sl, ol->objlink.ob->map->name); 00854 SockList_AddChar(&sl, (char) ol->objlink.ob->level); 00855 } 00856 } 00857 } 00858 else if (!strncmp(params, "join ", 5)) 00859 { 00860 char *party_name, *party_password; 00861 00862 if (CONTR(op)->party) 00863 { 00864 new_draw_info(0, COLOR_WHITE, op, "You must leave your current party before joining another."); 00865 return 1; 00866 } 00867 00868 params += 5; 00869 00870 if (!params) 00871 { 00872 return 1; 00873 } 00874 00875 party_name = strtok(params, "\t"); 00876 party_password = strtok(NULL, "\t"); 00877 00878 party = find_party(party_name); 00879 00880 if (!party) 00881 { 00882 new_draw_info(0, COLOR_WHITE, op, "No such party."); 00883 return 1; 00884 } 00885 00886 if (CONTR(op)->party != party) 00887 { 00888 /* If party password is not set or they've typed correct password... */ 00889 if (party->passwd[0] == '\0' || (party_password && !strcmp(party->passwd, party_password))) 00890 { 00891 add_party_member(party, op); 00892 CONTR(op)->stat_joined_party++; 00893 new_draw_info_format(0, COLOR_GREEN, op, "You have joined party: %s.", party->name); 00894 snprintf(buf, sizeof(buf), "%s joined party %s.", op->name, party->name); 00895 send_party_message(party, buf, PARTY_MESSAGE_STATUS, op); 00896 return 1; 00897 } 00898 /* Party password was typed but it wasn't correct. */ 00899 else if (party_password) 00900 { 00901 new_draw_info(0, COLOR_RED, op, "Incorrect party password."); 00902 return 1; 00903 } 00904 /* Otherwise ask them to type the password */ 00905 else 00906 { 00907 new_draw_info(0, COLOR_YELLOW, op, "That party requires a password. Type it now, or press ESC to cancel joining."); 00908 SockList_AddChar(&sl, CMD_PARTY_PASSWORD); 00909 SockList_AddString(&sl, party->name); 00910 } 00911 } 00912 } 00913 00914 if (sl.len > 1) 00915 { 00916 Send_With_Handling(&CONTR(op)->socket, &sl); 00917 } 00918 } 00919 00920 return 1; 00921 } 00922 00929 int command_whereami(object *op, char *params) 00930 { 00931 if (!op->map->region) 00932 { 00933 new_draw_info(0, COLOR_WHITE, op, "You appear to be lost somewhere..."); 00934 return 1; 00935 } 00936 00937 (void) params; 00938 00939 new_draw_info_format(0, COLOR_WHITE, op, "You are in %s.\n%s", get_region_longname(op->map->region), get_region_msg(op->map->region)); 00940 return 1; 00941 } 00942 00948 int command_ms_privacy(object *op, char *params) 00949 { 00950 if (CONTR(op)->ms_privacy) 00951 { 00952 CONTR(op)->ms_privacy = 0; 00953 new_draw_info(0, COLOR_WHITE, op, "Metaserver privacy turned off."); 00954 } 00955 else 00956 { 00957 CONTR(op)->ms_privacy = 1; 00958 new_draw_info(0, COLOR_WHITE, op, "Metaserver privacy turned on."); 00959 } 00960 00961 (void) params; 00962 return 1; 00963 } 00964 00970 int command_statistics(object *op, char *params) 00971 { 00972 size_t i; 00973 00974 (void) params; 00975 00976 new_draw_info_format(0, COLOR_WHITE, op, "Experience: %s", format_number_comma(op->stats.exp)); 00977 00978 if (op->level < MAXLEVEL) 00979 { 00980 char *cp = strdup_local(format_number_comma(level_exp(op->level + 1, 1.0))); 00981 00982 new_draw_info_format(0, COLOR_WHITE, op, "Next Level: %s (%s)", cp, format_number_comma(level_exp(op->level + 1, 1.0) - op->stats.exp)); 00983 free(cp); 00984 } 00985 00986 new_draw_info(0, COLOR_WHITE, op, "\nStat: Natural (Real)"); 00987 00988 for (i = 0; i < NUM_STATS; i++) 00989 { 00990 new_draw_info_format(0, COLOR_WHITE, op, "<green>%s:</green> %d (%d)", short_stat_name[i], get_attr_value(&CONTR(op)->orig_stats, i), get_attr_value(&op->stats, i)); 00991 } 00992 00993 new_draw_info_format(0, COLOR_WHITE, op, "\nYour equipped item power is %d out of %d.", CONTR(op)->item_power, op->level); 00994 00995 return 1; 00996 } 00997 01005 int command_region_map(object *op, char *params) 01006 { 01007 region *r; 01008 SockList sl; 01009 uint8 sock_buf[HUGE_BUF], params_check; 01010 01011 if (!op->map) 01012 { 01013 return 1; 01014 } 01015 01016 /* Server has not configured client maps URL. */ 01017 if (settings.client_maps_url[0] == '\0') 01018 { 01019 new_draw_info(0, COLOR_WHITE, op, "This server does not support that command."); 01020 return 1; 01021 } 01022 01023 /* Check if params were given and whether the player is allowed to 01024 * see map of any region they want. */ 01025 params_check = params && can_do_wiz_command(CONTR(op), "region_map"); 01026 01027 if (params_check) 01028 { 01029 /* Search for the region the player wants. */ 01030 for (r = first_region; r; r = r->next) 01031 { 01032 if (!strcasecmp(r->name, params)) 01033 { 01034 break; 01035 } 01036 } 01037 01038 /* Not found, try partial region names. */ 01039 if (!r) 01040 { 01041 size_t params_len = strlen(params); 01042 01043 for (r = first_region; r; r = r->next) 01044 { 01045 if (!strncasecmp(r->name, params, params_len)) 01046 { 01047 break; 01048 } 01049 } 01050 } 01051 01052 if (!r) 01053 { 01054 new_draw_info(0, COLOR_WHITE, op, "No such region."); 01055 return 1; 01056 } 01057 } 01058 else 01059 { 01060 r = op->map->region; 01061 } 01062 01063 /* Try to find a region that should have had a client map 01064 * generated. */ 01065 for (; r; r = r->parent) 01066 { 01067 if (r->map_first) 01068 { 01069 break; 01070 } 01071 } 01072 01073 if (!r) 01074 { 01075 if (params_check) 01076 { 01077 new_draw_info(0, COLOR_WHITE, op, "That region doesn't have a map."); 01078 } 01079 else 01080 { 01081 new_draw_info(0, COLOR_WHITE, op, "You cannot use that command here."); 01082 } 01083 01084 return 1; 01085 } 01086 01087 sl.buf = sock_buf; 01088 SOCKET_SET_BINARY_CMD(&sl, BINARY_CMD_REGION_MAP); 01089 SockList_AddString(&sl, op->map->path); 01090 SockList_AddShort(&sl, op->x); 01091 SockList_AddShort(&sl, op->y); 01092 SockList_AddString(&sl, r->name); 01093 SockList_AddString(&sl, settings.client_maps_url); 01094 Send_With_Handling(&CONTR(op)->socket, &sl); 01095 01096 return 1; 01097 }
1.7.4