/src/map/atcommand.c
C | 10340 lines | 8018 code | 1401 blank | 921 comment | 2647 complexity | 60a1d92ffe0296710d30b4bd5c365bc9 MD5 | raw file
Possible License(s): GPL-3.0, LGPL-2.0
Large files files are truncated, but you can click here to view the full file
- /**
- * This file is part of Hercules.
- * http://herc.ws - http://github.com/HerculesWS/Hercules
- *
- * Copyright (C) 2012-2016 Hercules Dev Team
- * Copyright (C) Athena Dev Teams
- *
- * Hercules is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
- #define HERCULES_CORE
- #include "config/core.h" // AUTOLOOTITEM_SIZE, AUTOTRADE_PERSISTENCY, MAX_SUGGESTIONS, MOB_FLEE(), MOB_HIT(), RENEWAL, RENEWAL_DROP, RENEWAL_EXP
- #include "atcommand.h"
- #include "map/HPMmap.h"
- #include "map/battle.h"
- #include "map/channel.h"
- #include "map/chat.h"
- #include "map/chrif.h"
- #include "map/clif.h"
- #include "map/duel.h"
- #include "map/elemental.h"
- #include "map/guild.h"
- #include "map/homunculus.h"
- #include "map/intif.h"
- #include "map/itemdb.h"
- #include "map/log.h"
- #include "map/mail.h"
- #include "map/map.h"
- #include "map/mapreg.h"
- #include "map/mercenary.h"
- #include "map/mob.h"
- #include "map/npc.h"
- #include "map/party.h"
- #include "map/pc.h"
- #include "map/pc_groups.h" // groupid2name
- #include "map/pet.h"
- #include "map/quest.h"
- #include "map/script.h"
- #include "map/searchstore.h"
- #include "map/skill.h"
- #include "map/status.h"
- #include "map/storage.h"
- #include "map/trade.h"
- #include "map/unit.h"
- #include "common/cbasetypes.h"
- #include "common/conf.h"
- #include "common/core.h"
- #include "common/memmgr.h"
- #include "common/mmo.h" // MAX_CARTS
- #include "common/nullpo.h"
- #include "common/random.h"
- #include "common/showmsg.h"
- #include "common/socket.h"
- #include "common/strlib.h"
- #include "common/sysinfo.h"
- #include "common/timer.h"
- #include "common/utils.h"
- #include <math.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- struct atcommand_interface atcommand_s;
- struct atcommand_interface *atcommand;
- static char atcmd_output[CHAT_SIZE_MAX];
- static char atcmd_player_name[NAME_LENGTH];
- // @commands (script-based)
- struct atcmd_binding_data* get_atcommandbind_byname(const char* name) {
- int i = 0;
- nullpo_retr(NULL, name);
- if( *name == atcommand->at_symbol || *name == atcommand->char_symbol )
- name++; // for backwards compatibility
- ARR_FIND( 0, atcommand->binding_count, i, strcmpi(atcommand->binding[i]->command, name) == 0 );
- return ( i < atcommand->binding_count ) ? atcommand->binding[i] : NULL;
- }
- const char* atcommand_msgsd(struct map_session_data *sd, int msg_number) {
- Assert_retr("??", msg_number >= 0 && msg_number < MAX_MSG && atcommand->msg_table[0][msg_number] != NULL);
- if (!sd || sd->lang_id >= atcommand->max_message_table || !atcommand->msg_table[sd->lang_id][msg_number])
- return atcommand->msg_table[0][msg_number];
- return atcommand->msg_table[sd->lang_id][msg_number];
- }
- const char* atcommand_msgfd(int fd, int msg_number) {
- struct map_session_data *sd = sockt->session_is_valid(fd) ? sockt->session[fd]->session_data : NULL;
- Assert_retr("??", msg_number >= 0 && msg_number < MAX_MSG && atcommand->msg_table[0][msg_number] != NULL);
- if (!sd || sd->lang_id >= atcommand->max_message_table || !atcommand->msg_table[sd->lang_id][msg_number])
- return atcommand->msg_table[0][msg_number];
- return atcommand->msg_table[sd->lang_id][msg_number];
- }
- //-----------------------------------------------------------
- // Return the message string of the specified number by [Yor]
- //-----------------------------------------------------------
- const char* atcommand_msg(int msg_number) {
- Assert_retr("??", msg_number >= 0 && msg_number < MAX_MSG);
- if (atcommand->msg_table[map->default_lang_id][msg_number] != NULL && atcommand->msg_table[map->default_lang_id][msg_number][0] != '\0')
- return atcommand->msg_table[map->default_lang_id][msg_number];
- if(atcommand->msg_table[0][msg_number] != NULL && atcommand->msg_table[0][msg_number][0] != '\0')
- return atcommand->msg_table[0][msg_number];
- return "??";
- }
- /**
- * Reads Message Data
- *
- * @param[in] cfg_name configuration filename to read.
- * @param[in] allow_override whether to allow duplicate message IDs to override the original value.
- * @return success state.
- */
- bool msg_config_read(const char *cfg_name, bool allow_override) {
- int msg_number;
- char line[1024], w1[1024], w2[1024];
- FILE *fp;
- static int called = 1;
- nullpo_retr(false, cfg_name);
- if ((fp = fopen(cfg_name, "r")) == NULL) {
- ShowError("Messages file not found: %s\n", cfg_name);
- return false;
- }
- if( !atcommand->max_message_table )
- atcommand->expand_message_table();
- while(fgets(line, sizeof(line), fp)) {
- if (line[0] == '/' && line[1] == '/')
- continue;
- if (sscanf(line, "%1023[^:]: %1023[^\r\n]", w1, w2) != 2)
- continue;
- if (strcmpi(w1, "import") == 0) {
- atcommand->msg_read(w2, true);
- } else {
- msg_number = atoi(w1);
- if (msg_number >= 0 && msg_number < MAX_MSG) {
- if (atcommand->msg_table[0][msg_number] != NULL) {
- if (!allow_override) {
- ShowError("Duplicate message: ID '%d' was already used for '%s'. Message '%s' will be ignored.\n",
- msg_number, w2, atcommand->msg_table[0][msg_number]);
- continue;
- }
- aFree(atcommand->msg_table[0][msg_number]);
- }
- /* this could easily become consecutive memory like get_str() and save the malloc overhead for over 1k calls [Ind] */
- atcommand->msg_table[0][msg_number] = (char *)aMalloc((strlen(w2) + 1)*sizeof (char));
- strcpy(atcommand->msg_table[0][msg_number],w2);
- }
- }
- }
- fclose(fp);
- if( ++called == 1 ) { //Original
- if( script->lang_export_fp ) {
- int i;
- for(i = 0; i < MAX_MSG;i++) {
- if( atcommand->msg_table[0][i] != NULL ) {
- fprintf(script->lang_export_fp, "msgctxt \"messages.conf\"\n"
- "msgid \"%s\"\n"
- "msgstr \"\"\n",
- atcommand->msg_table[0][i]
- );
- }
- }
- }
- }
- return true;
- }
- /*==========================================
- * Cleanup Message Data
- *------------------------------------------*/
- void do_final_msg(void) {
- int i, j;
- for(i = 0; i < atcommand->max_message_table; i++) {
- for (j = 0; j < MAX_MSG; j++) {
- if( atcommand->msg_table[i][j] )
- aFree(atcommand->msg_table[i][j]);
- }
- aFree(atcommand->msg_table[i]);
- }
- if( atcommand->msg_table )
- aFree(atcommand->msg_table);
- }
- /**
- * retrieves the help string associated with a given command.
- */
- static inline const char* atcommand_help_string(AtCommandInfo *info) {
- return info->help;
- }
- /*==========================================
- * @send (used for testing packet sends from the client)
- *------------------------------------------*/
- ACMD(send)
- {
- int len=0,type;
- long num;
- // read message type as hex number (without the 0x)
- if (!*message
- || !((sscanf(message, "len %x", &type)==1 && (len=1, true))
- || sscanf(message, "%x", &type)==1)
- ) {
- clif->message(fd, msg_fd(fd,900)); // Usage:
- clif->message(fd, msg_fd(fd,901)); // @send len <packet hex number>
- clif->message(fd, msg_fd(fd,902)); // @send <packet hex number> {<value>}*
- clif->message(fd, msg_fd(fd,903)); // Value: <type=B(default),W,L><number> or S<length>"<string>"
- return false;
- }
- #define PARSE_ERROR(error,p) do {\
- clif->message(fd, (error));\
- safesnprintf(atcmd_output, sizeof(atcmd_output), ">%s", (p));\
- clif->message(fd, atcmd_output);\
- } while(0) //define PARSE_ERROR
- #define CHECK_EOS(p) do { \
- if(*(p) == 0){ \
- clif->message(fd, "Unexpected end of string");\
- return false;\
- } \
- } while(0) //define CHECK_EOS
- #define SKIP_VALUE(p) do { \
- while(*(p) && !ISSPACE(*(p))) ++(p); /* non-space */\
- while(*(p) && ISSPACE(*(p))) ++(p); /* space */\
- } while(0) //define SKIP_VALUE
- #define GET_VALUE(p,num) do { \
- if(sscanf((p), "x%lx", &(num)) < 1 && sscanf((p), "%ld ", &(num)) < 1){\
- PARSE_ERROR("Invalid number in:",(p));\
- return false;\
- }\
- } while(0) //define GET_VALUE
- if (type >= MIN_PACKET_DB && type <= MAX_PACKET_DB) {
- int off = 2;
- if (len) {
- // show packet length
- safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,904), type, clif->packet(type)->len); // Packet 0x%x length: %d
- clif->message(fd, atcmd_output);
- return true;
- }
- len = clif->packet(type)->len;
- if (len == 0) {
- // unknown packet - ERROR
- safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,905), type); // Unknown packet: 0x%x
- clif->message(fd, atcmd_output);
- return false;
- } else if (len == -1) {
- // dynamic packet
- len = SHRT_MAX-4; // maximum length
- off = 4;
- }
- WFIFOHEAD(sd->fd, len);
- WFIFOW(sd->fd,0)=TOW(type);
- // parse packet contents
- SKIP_VALUE(message);
- while(*message != 0 && off < len){
- if(ISDIGIT(*message) || *message == '-' || *message == '+')
- {// default (byte)
- GET_VALUE(message,num);
- WFIFOB(sd->fd,off)=TOB(num);
- ++off;
- } else if(TOUPPER(*message) == 'B')
- {// byte
- ++message;
- GET_VALUE(message,num);
- WFIFOB(sd->fd,off)=TOB(num);
- ++off;
- } else if(TOUPPER(*message) == 'W')
- {// word (2 bytes)
- ++message;
- GET_VALUE(message,num);
- WFIFOW(sd->fd,off)=TOW(num);
- off+=2;
- } else if(TOUPPER(*message) == 'L')
- {// long word (4 bytes)
- ++message;
- GET_VALUE(message,num);
- WFIFOL(sd->fd,off)=TOL(num);
- off+=4;
- } else if(TOUPPER(*message) == 'S')
- {// string - escapes are valid
- // get string length - num <= 0 means not fixed length (default)
- int end;
- ++message;
- if(*message == '"'){
- num=0;
- } else {
- GET_VALUE(message,num);
- while(*message != '"')
- {// find start of string
- if(*message == 0 || ISSPACE(*message)){
- PARSE_ERROR(msg_fd(fd,906),message); // Not a string:
- return false;
- }
- ++message;
- }
- }
- // parse string
- ++message;
- CHECK_EOS(message);
- end=(num<=0? 0: min(off+((int)num),len));
- for(; *message != '"' && (off < end || end == 0); ++off){
- if(*message == '\\'){
- ++message;
- CHECK_EOS(message);
- switch(*message){
- case 'a': num=0x07; break; // Bell
- case 'b': num=0x08; break; // Backspace
- case 't': num=0x09; break; // Horizontal tab
- case 'n': num=0x0A; break; // Line feed
- case 'v': num=0x0B; break; // Vertical tab
- case 'f': num=0x0C; break; // Form feed
- case 'r': num=0x0D; break; // Carriage return
- case 'e': num=0x1B; break; // Escape
- default: num=*message; break;
- case 'x': // Hexadecimal
- {
- ++message;
- CHECK_EOS(message);
- if(!ISXDIGIT(*message)){
- PARSE_ERROR(msg_fd(fd,907),message); // Not a hexadecimal digit:
- return false;
- }
- num=(ISDIGIT(*message)?*message-'0':TOLOWER(*message)-'a'+10);
- if(ISXDIGIT(*message)){
- ++message;
- CHECK_EOS(message);
- num<<=8;
- num+=(ISDIGIT(*message)?*message-'0':TOLOWER(*message)-'a'+10);
- }
- WFIFOB(sd->fd,off)=TOB(num);
- ++message;
- CHECK_EOS(message);
- continue;
- }
- case '0':
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7': // Octal
- {
- num=*message-'0'; // 1st octal digit
- ++message;
- CHECK_EOS(message);
- if(ISDIGIT(*message) && *message < '8'){
- num<<=3;
- num+=*message-'0'; // 2nd octal digit
- ++message;
- CHECK_EOS(message);
- if(ISDIGIT(*message) && *message < '8'){
- num<<=3;
- num+=*message-'0'; // 3rd octal digit
- ++message;
- CHECK_EOS(message);
- }
- }
- WFIFOB(sd->fd,off)=TOB(num);
- continue;
- }
- }
- } else
- num=*message;
- WFIFOB(sd->fd,off)=TOB(num);
- ++message;
- CHECK_EOS(message);
- }//for
- while(*message != '"')
- {// ignore extra characters
- ++message;
- CHECK_EOS(message);
- }
- // terminate the string
- if(off < end)
- {// fill the rest with 0's
- memset(WFIFOP(sd->fd,off),0,end-off);
- off=end;
- }
- } else
- {// unknown
- PARSE_ERROR(msg_fd(fd,908),message); // Unknown type of value in:
- return false;
- }
- SKIP_VALUE(message);
- }
- if (clif->packet(type)->len == -1) { // send dynamic packet
- WFIFOW(sd->fd,2)=TOW(off);
- WFIFOSET(sd->fd,off);
- } else {// send static packet
- if(off < len)
- memset(WFIFOP(sd->fd,off),0,len-off);
- WFIFOSET(sd->fd,len);
- }
- } else {
- clif->message(fd, msg_fd(fd,259)); // Invalid packet
- return false;
- }
- sprintf (atcmd_output, msg_fd(fd,258), type, type); // Sent packet 0x%x (%d)
- clif->message(fd, atcmd_output);
- return true;
- #undef PARSE_ERROR
- #undef CHECK_EOS
- #undef SKIP_VALUE
- #undef GET_VALUE
- }
- /*==========================================
- * @rura, @warp, @mapmove
- *------------------------------------------*/
- ACMD(mapmove) {
- char map_name[MAP_NAME_LENGTH_EXT];
- unsigned short map_index;
- short x = 0, y = 0;
- int16 m = -1;
- memset(map_name, '\0', sizeof(map_name));
- if (!*message ||
- (sscanf(message, "%15s %5hd %5hd", map_name, &x, &y) < 3 &&
- sscanf(message, "%15[^,],%5hd,%5hd", map_name, &x, &y) < 1)) {
- clif->message(fd, msg_fd(fd,909)); // Please enter a map (usage: @warp/@rura/@mapmove <mapname> <x> <y>).
- return false;
- }
- map_index = mapindex->name2id(map_name);
- if (map_index)
- m = map->mapindex2mapid(map_index);
- if (!map_index || m < 0) { // m < 0 means on different server or that map is disabled! [Kevin]
- clif->message(fd, msg_fd(fd,1)); // Map not found.
- return false;
- }
- if( sd->bl.m == m && sd->bl.x == x && sd->bl.y == y ) {
- clif->message(fd, msg_fd(fd,253)); // You already are at your destination!
- return false;
- }
- if ((x || y) && map->getcell(m, &sd->bl, x, y, CELL_CHKNOPASS) && pc_get_group_level(sd) < battle_config.gm_ignore_warpable_area) {
- //This is to prevent the pc->setpos call from printing an error.
- clif->message(fd, msg_fd(fd,2));
- if (!map->search_freecell(NULL, m, &x, &y, 10, 10, 1))
- x = y = 0; //Invalid cell, use random spot.
- }
- if (map->list[m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
- clif->message(fd, msg_fd(fd,247));
- return false;
- }
- if (sd->bl.m >= 0 && map->list[sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
- clif->message(fd, msg_fd(fd,248));
- return false;
- }
- if (pc->setpos(sd, map_index, x, y, CLR_TELEPORT) != 0) {
- clif->message(fd, msg_fd(fd,1)); // Map not found.
- return false;
- }
- clif->message(fd, msg_fd(fd,0)); // Warped.
- return true;
- }
- /*==========================================
- * Displays where a character is. Corrected version by Silent. [Skotlex]
- *------------------------------------------*/
- ACMD(where) {
- struct map_session_data* pl_sd;
- memset(atcmd_player_name, '\0', sizeof atcmd_player_name);
- if (!*message || sscanf(message, "%23[^\n]", atcmd_player_name) < 1) {
- clif->message(fd, msg_fd(fd,910)); // Please enter a player name (usage: @where <char name>).
- return false;
- }
- pl_sd = map->nick2sd(atcmd_player_name);
- if (pl_sd == NULL ||
- strncmp(pl_sd->status.name, atcmd_player_name, NAME_LENGTH) != 0 ||
- (pc_has_permission(pl_sd, PC_PERM_HIDE_SESSION) && pc_get_group_level(pl_sd) > pc_get_group_level(sd) && !pc_has_permission(sd, PC_PERM_WHO_DISPLAY_AID))
- ) {
- clif->message(fd, msg_fd(fd,3)); // Character not found.
- return false;
- }
- snprintf(atcmd_output, sizeof atcmd_output, "%s %s %d %d", pl_sd->status.name, mapindex_id2name(pl_sd->mapindex), pl_sd->bl.x, pl_sd->bl.y);
- clif->message(fd, atcmd_output);
- return true;
- }
- /*==========================================
- *
- *------------------------------------------*/
- ACMD(jumpto) {
- struct map_session_data *pl_sd = NULL;
- if (!*message) {
- clif->message(fd, msg_fd(fd,911)); // Please enter a player name (usage: @jumpto/@warpto/@goto <char name/ID>).
- return false;
- }
- if (sd->bl.m >= 0 && map->list[sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
- clif->message(fd, msg_fd(fd,248)); // You are not authorized to warp from your current map.
- return false;
- }
- if( pc_isdead(sd) ) {
- clif->message(fd, msg_fd(fd,864)); // "You cannot use this command when dead."
- return false;
- }
- if((pl_sd=map->nick2sd((char *)message)) == NULL && (pl_sd=map->charid2sd(atoi(message))) == NULL) {
- clif->message(fd, msg_fd(fd,3)); // Character not found.
- return false;
- }
- if (pl_sd->bl.m >= 0 && map->list[pl_sd->bl.m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
- clif->message(fd, msg_fd(fd,247)); // You are not authorized to warp to this map.
- return false;
- }
- if( pl_sd->bl.m == sd->bl.m && pl_sd->bl.x == sd->bl.x && pl_sd->bl.y == sd->bl.y ) {
- clif->message(fd, msg_fd(fd,253)); // You already are at your destination!
- return false;
- }
- pc->setpos(sd, pl_sd->mapindex, pl_sd->bl.x, pl_sd->bl.y, CLR_TELEPORT);
- safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,4), pl_sd->status.name); // Jumped to %s
- clif->message(fd, atcmd_output);
- return true;
- }
- /*==========================================
- *
- *------------------------------------------*/
- ACMD(jump)
- {
- short x = 0, y = 0;
- memset(atcmd_output, '\0', sizeof(atcmd_output));
- sscanf(message, "%5hd %5hd", &x, &y);
- if (map->list[sd->bl.m].flag.noteleport && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
- clif->message(fd, msg_fd(fd,248)); // You are not authorized to warp from your current map.
- return false;
- }
- if( pc_isdead(sd) ) {
- clif->message(fd, msg_fd(fd,864)); // "You cannot use this command when dead."
- return false;
- }
- if ((x || y) && map->getcell(sd->bl.m, &sd->bl, x, y, CELL_CHKNOPASS)) {
- //This is to prevent the pc->setpos call from printing an error.
- clif->message(fd, msg_fd(fd,2));
- if (!map->search_freecell(NULL, sd->bl.m, &x, &y, 10, 10, 1))
- x = y = 0; //Invalid cell, use random spot.
- }
- if (x && y && sd->bl.x == x && sd->bl.y == y) {
- clif->message(fd, msg_fd(fd,253)); // You already are at your destination!
- return false;
- }
- pc->setpos(sd, sd->mapindex, x, y, CLR_TELEPORT);
- safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,5), sd->bl.x, sd->bl.y); // Jumped to %d %d
- clif->message(fd, atcmd_output);
- return true;
- }
- /*==========================================
- * Display list of online characters with
- * various info.
- *------------------------------------------*/
- ACMD(who) {
- const struct map_session_data *pl_sd = NULL;
- struct s_mapiterator *iter = NULL;
- char player_name[NAME_LENGTH] = "";
- int count = 0;
- int level = 0;
- StringBuf buf;
- /**
- * 1 = @who : Player name, [Title], [Party name], [Guild name]
- * 2 = @who2 : Player name, [Title], BLvl, JLvl, Job
- * 3 = @who3 : [CID/AID] Player name [Title], Map, X, Y
- */
- int display_type = 1;
- int map_id = -1;
- if (stristr(info->command, "map") != NULL) {
- char map_name[MAP_NAME_LENGTH_EXT] = "";
- if (sscanf(message, "%15s %23s", map_name, player_name) < 1 || (map_id = map->mapname2mapid(map_name)) < 0)
- map_id = sd->bl.m;
- } else {
- sscanf(message, "%23s", player_name);
- }
- if (stristr(info->command, "2") != NULL)
- display_type = 2;
- else if (stristr(info->command, "3") != NULL)
- display_type = 3;
- level = pc_get_group_level(sd);
- StrBuf->Init(&buf);
- iter = mapit_getallusers();
- for (pl_sd = BL_UCCAST(BL_PC, mapit->first(iter)); mapit->exists(iter); pl_sd = BL_UCCAST(BL_PC, mapit->next(iter))) {
- if (!((pc_has_permission(pl_sd, PC_PERM_HIDE_SESSION) || pc_isinvisible(pl_sd)) && pc_get_group_level(pl_sd) > level)) { // you can look only lower or same level
- if (stristr(pl_sd->status.name, player_name) == NULL // search with no case sensitive
- || (map_id >= 0 && pl_sd->bl.m != map_id))
- continue;
- switch (display_type) {
- case 2: {
- StrBuf->Printf(&buf, msg_fd(fd,343), pl_sd->status.name); // "Name: %s "
- if (pc_get_group_id(pl_sd) > 0) // Player title, if exists
- StrBuf->Printf(&buf, msg_fd(fd,344), pcg->get_name(pl_sd->group)); // "(%s) "
- StrBuf->Printf(&buf, msg_fd(fd,347), pl_sd->status.base_level, pl_sd->status.job_level,
- pc->job_name(pl_sd->status.class_)); // "| Lv:%d/%d | Job: %s"
- break;
- }
- case 3: {
- if (pc_has_permission(sd, PC_PERM_WHO_DISPLAY_AID))
- StrBuf->Printf(&buf, msg_fd(fd,912), pl_sd->status.char_id, pl_sd->status.account_id); // "(CID:%d/AID:%d) "
- StrBuf->Printf(&buf, msg_fd(fd,343), pl_sd->status.name); // "Name: %s "
- if (pc_get_group_id(pl_sd) > 0) // Player title, if exists
- StrBuf->Printf(&buf, msg_fd(fd,344), pcg->get_name(pl_sd->group)); // "(%s) "
- StrBuf->Printf(&buf, msg_fd(fd,348), mapindex_id2name(pl_sd->mapindex), pl_sd->bl.x, pl_sd->bl.y); // "| Location: %s %d %d"
- break;
- }
- default: {
- struct party_data *p = party->search(pl_sd->status.party_id);
- struct guild *g = pl_sd->guild;
- StrBuf->Printf(&buf, msg_fd(fd,343), pl_sd->status.name); // "Name: %s "
- if (pc_get_group_id(pl_sd) > 0) // Player title, if exists
- StrBuf->Printf(&buf, msg_fd(fd,344), pcg->get_name(pl_sd->group)); // "(%s) "
- if (p != NULL)
- StrBuf->Printf(&buf, msg_fd(fd,345), p->party.name); // " | Party: '%s'"
- if (g != NULL)
- StrBuf->Printf(&buf, msg_fd(fd,346), g->name); // " | Guild: '%s'"
- break;
- }
- }
- clif->messagecolor_self(fd, COLOR_DEFAULT, StrBuf->Value(&buf));/** for whatever reason clif->message crashes with some patterns, see bugreport:8186 **/
- StrBuf->Clear(&buf);
- count++;
- }
- }
- mapit->free(iter);
- if (map_id < 0) {
- if (count == 0)
- StrBuf->AppendStr(&buf, msg_fd(fd,28)); // No player found.
- else if (count == 1)
- StrBuf->AppendStr(&buf, msg_fd(fd,29)); // 1 player found.
- else
- StrBuf->Printf(&buf, msg_fd(fd,30), count); // %d players found.
- } else {
- if (count == 0)
- StrBuf->Printf(&buf, msg_fd(fd,54), map->list[map_id].name); // No player found in map '%s'.
- else if (count == 1)
- StrBuf->Printf(&buf, msg_fd(fd,55), map->list[map_id].name); // 1 player found in map '%s'.
- else
- StrBuf->Printf(&buf, msg_fd(fd,56), count, map->list[map_id].name); // %d players found in map '%s'.
- }
- clif->message(fd, StrBuf->Value(&buf));
- StrBuf->Destroy(&buf);
- return true;
- }
- /*==========================================
- *
- *------------------------------------------*/
- ACMD(whogm)
- {
- const struct map_session_data *pl_sd;
- struct s_mapiterator* iter;
- int j, count;
- int level;
- char match_text[CHAT_SIZE_MAX];
- char player_name[NAME_LENGTH];
- struct guild *g;
- struct party_data *p;
- memset(atcmd_output, '\0', sizeof(atcmd_output));
- memset(match_text, '\0', sizeof(match_text));
- memset(player_name, '\0', sizeof(player_name));
- if (sscanf(message, "%199[^\n]", match_text) < 1)
- strcpy(match_text, "");
- for (j = 0; match_text[j]; j++)
- match_text[j] = TOLOWER(match_text[j]);
- count = 0;
- level = pc_get_group_level(sd);
- iter = mapit_getallusers();
- for (pl_sd = BL_UCCAST(BL_PC, mapit->first(iter)); mapit->exists(iter); pl_sd = BL_UCCAST(BL_PC, mapit->next(iter))) {
- int pl_level = pc_get_group_level(pl_sd);
- if (!pl_level)
- continue;
- if (match_text[0]) {
- memcpy(player_name, pl_sd->status.name, NAME_LENGTH);
- for (j = 0; player_name[j]; j++)
- player_name[j] = TOLOWER(player_name[j]);
- // search with no case sensitive
- if (strstr(player_name, match_text) == NULL)
- continue;
- }
- if (pl_level > level) {
- if (pc_isinvisible(pl_sd))
- continue;
- safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,913), pl_sd->status.name); // Name: %s (GM)
- clif->message(fd, atcmd_output);
- count++;
- continue;
- }
- safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,914), // Name: %s (GM:%d) | Location: %s %d %d
- pl_sd->status.name, pl_level,
- mapindex_id2name(pl_sd->mapindex), pl_sd->bl.x, pl_sd->bl.y);
- clif->message(fd, atcmd_output);
- safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,915), // BLvl: %d | Job: %s (Lvl: %d)
- pl_sd->status.base_level,
- pc->job_name(pl_sd->status.class_), pl_sd->status.job_level);
- clif->message(fd, atcmd_output);
- p = party->search(pl_sd->status.party_id);
- g = pl_sd->guild;
- safesnprintf(atcmd_output, sizeof(atcmd_output),msg_fd(fd,916), // Party: '%s' | Guild: '%s'
- p?p->party.name:msg_fd(fd,917), g?g->name:msg_fd(fd,917)); // None.
- clif->message(fd, atcmd_output);
- count++;
- }
- mapit->free(iter);
- if (count == 0)
- clif->message(fd, msg_fd(fd,150)); // No GM found.
- else if (count == 1)
- clif->message(fd, msg_fd(fd,151)); // 1 GM found.
- else {
- safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,152), count); // %d GMs found.
- clif->message(fd, atcmd_output);
- }
- return true;
- }
- /*==========================================
- *
- *------------------------------------------*/
- ACMD(save)
- {
- pc->setsavepoint(sd, sd->mapindex, sd->bl.x, sd->bl.y);
- if (sd->status.pet_id > 0 && sd->pd)
- intif->save_petdata(sd->status.account_id, &sd->pd->pet);
- chrif->save(sd,0);
- clif->message(fd, msg_fd(fd,6)); // Your save point has been changed.
- return true;
- }
- /*==========================================
- *
- *------------------------------------------*/
- ACMD(load) {
- int16 m;
- m = map->mapindex2mapid(sd->status.save_point.map);
- if (m >= 0 && map->list[m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
- clif->message(fd, msg_fd(fd,249)); // You are not authorized to warp to your save map.
- return false;
- }
- if (sd->bl.m >= 0 && map->list[sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
- clif->message(fd, msg_fd(fd,248)); // You are not authorized to warp from your current map.
- return false;
- }
- pc->setpos(sd, sd->status.save_point.map, sd->status.save_point.x, sd->status.save_point.y, CLR_OUTSIGHT);
- clif->message(fd, msg_fd(fd,7)); // Warping to save point..
- return true;
- }
- /*==========================================
- *
- *------------------------------------------*/
- ACMD(speed)
- {
- int speed;
- memset(atcmd_output, '\0', sizeof(atcmd_output));
- if (!*message || sscanf(message, "%12d", &speed) < 1) {
- safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,918), MIN_WALK_SPEED, MAX_WALK_SPEED); // Please enter a speed value (usage: @speed <%d-%d>).
- clif->message(fd, atcmd_output);
- return false;
- }
- sd->state.permanent_speed = 0;
- if (speed < 0)
- sd->base_status.speed = DEFAULT_WALK_SPEED;
- else
- sd->base_status.speed = cap_value(speed, MIN_WALK_SPEED, MAX_WALK_SPEED);
- if( sd->base_status.speed != DEFAULT_WALK_SPEED ) {
- sd->state.permanent_speed = 1; // Set lock when set to non-default speed.
- clif->message(fd, msg_fd(fd,8)); // Speed changed.
- } else
- clif->message(fd, msg_fd(fd,172)); //Speed returned to normal.
- status_calc_bl(&sd->bl, SCB_SPEED);
- return true;
- }
- /*==========================================
- *
- *------------------------------------------*/
- ACMD(storage)
- {
- if (sd->npc_id || sd->state.vending || sd->state.buyingstore || sd->state.trading || sd->state.storage_flag)
- return false;
- if (storage->open(sd) == 1) { //Already open.
- clif->message(fd, msg_fd(fd,250));
- return false;
- }
- clif->message(fd, msg_fd(fd,919)); // Storage opened.
- return true;
- }
- /*==========================================
- *
- *------------------------------------------*/
- ACMD(guildstorage)
- {
- if (!sd->status.guild_id) {
- clif->message(fd, msg_fd(fd,252));
- return false;
- }
- if (sd->npc_id || sd->state.vending || sd->state.buyingstore || sd->state.trading)
- return false;
- if (sd->state.storage_flag == STORAGE_FLAG_NORMAL) {
- clif->message(fd, msg_fd(fd,250));
- return false;
- }
- if (sd->state.storage_flag == STORAGE_FLAG_GUILD) {
- clif->message(fd, msg_fd(fd,251));
- return false;
- }
- if( gstorage->open(sd) ) {
- clif->message(fd, msg_fd(fd,1201)); // Your guild's storage has already been opened by another member, try again later.
- return false;
- }
- clif->message(fd, msg_fd(fd,920)); // Guild storage opened.
- return true;
- }
- /*==========================================
- *
- *------------------------------------------*/
- ACMD(option)
- {
- int param1 = 0, param2 = 0, param3 = 0;
- if (!*message || sscanf(message, "%12d %12d %12d", ¶m1, ¶m2, ¶m3) < 1 || param1 < 0 || param2 < 0 || param3 < 0)
- {// failed to match the parameters so inform the user of the options
- const char* text;
- // attempt to find the setting information for this command
- text = atcommand_help_string( info );
- // notify the user of the requirement to enter an option
- clif->message(fd, msg_fd(fd,921)); // Please enter at least one option.
- if( text ) {// send the help text associated with this command
- clif->messageln( fd, text );
- }
- return false;
- }
- sd->sc.opt1 = param1;
- sd->sc.opt2 = param2;
- pc->setoption(sd, param3);
- clif->message(fd, msg_fd(fd,9)); // Options changed.
- return true;
- }
- /*==========================================
- *
- *------------------------------------------*/
- ACMD(hide) {
- if (pc_isinvisible(sd)) {
- sd->sc.option &= ~OPTION_INVISIBLE;
- if (sd->disguise != -1 )
- status->set_viewdata(&sd->bl, sd->disguise);
- else
- status->set_viewdata(&sd->bl, sd->status.class_);
- clif->message(fd, msg_fd(fd,10)); // Invisible: Off
- // increment the number of pvp players on the map
- map->list[sd->bl.m].users_pvp++;
- if( map->list[sd->bl.m].flag.pvp && !map->list[sd->bl.m].flag.pvp_nocalcrank ) {
- // register the player for ranking calculations
- sd->pvp_timer = timer->add( timer->gettick() + 200, pc->calc_pvprank_timer, sd->bl.id, 0 );
- }
- //bugreport:2266
- map->foreachinmovearea(clif->insight, &sd->bl, AREA_SIZE, sd->bl.x, sd->bl.y, BL_ALL, &sd->bl);
- } else {
- sd->sc.option |= OPTION_INVISIBLE;
- sd->vd.class_ = INVISIBLE_CLASS;
- clif->message(fd, msg_fd(fd,11)); // Invisible: On
- // decrement the number of pvp players on the map
- map->list[sd->bl.m].users_pvp--;
- if( map->list[sd->bl.m].flag.pvp && !map->list[sd->bl.m].flag.pvp_nocalcrank && sd->pvp_timer != INVALID_TIMER ) {
- // unregister the player for ranking
- timer->delete( sd->pvp_timer, pc->calc_pvprank_timer );
- sd->pvp_timer = INVALID_TIMER;
- }
- }
- clif->changeoption(&sd->bl);
- return true;
- }
- /*==========================================
- * Changes a character's class
- *------------------------------------------*/
- ACMD(jobchange)
- {
- int job = 0, upper = 0;
- bool found = false;
- if (*message == '\0') { // No message, just show the list
- found = false;
- } else if (sscanf(message, "%12d %12d", &job, &upper) >= 1) { // Numeric job ID
- found = true;
- } else { // Job name
- int i;
- // Normal Jobs
- for (i = JOB_NOVICE; !found && i < JOB_MAX_BASIC; i++) {
- if (strncmpi(message, pc->job_name(i), 16) == 0) {
- job = i;
- found = true;
- break;
- }
- }
- // High Jobs, Babies and Third
- for (i = JOB_NOVICE_HIGH; !found && i < JOB_MAX; i++) {
- if (strncmpi(message, pc->job_name(i), 16) == 0) {
- job = i;
- found = true;
- break;
- }
- }
- }
- if (!found || !pc->db_checkid(job)) {
- const char *text = atcommand_help_string(info);
- if (text)
- clif->messageln(fd, text);
- return false;
- }
- // Deny direct transformation into dummy jobs
- if (job == JOB_KNIGHT2 || job == JOB_CRUSADER2
- || job == JOB_WEDDING || job == JOB_XMAS || job == JOB_SUMMER
- || job == JOB_LORD_KNIGHT2 || job == JOB_PALADIN2
- || job == JOB_BABY_KNIGHT2 || job == JOB_BABY_CRUSADER2
- || job == JOB_STAR_GLADIATOR2
- || (job >= JOB_RUNE_KNIGHT2 && job <= JOB_MECHANIC_T2)
- || (job >= JOB_BABY_RUNE2 && job <= JOB_BABY_MECHANIC2)
- ) {
- /* WHY DO WE LIST THEM THEN? */
- clif->message(fd, msg_fd(fd,923)); //"You can not change to this job by command."
- return true;
- }
- if (pc->jobchange(sd, job, upper) != 0) {
- clif->message(fd, msg_fd(fd,155)); // You are unable to change your job.
- return false;
- }
- clif->message(fd, msg_fd(fd,12)); // Your job has been changed.
- return true;
- }
- /*==========================================
- *
- *------------------------------------------*/
- ACMD(kill)
- {
- status_kill(&sd->bl);
- clif->message(sd->fd, msg_fd(fd,13)); // A pity! You've died.
- if (fd != sd->fd)
- clif->message(fd, msg_fd(fd,14)); // Character killed.
- return true;
- }
- /*==========================================
- *
- *------------------------------------------*/
- ACMD(alive)
- {
- if (!status->revive(&sd->bl, 100, 100)) {
- clif->message(fd, msg_fd(fd,867)); // "You're not dead."
- return false;
- }
- clif->skill_nodamage(&sd->bl,&sd->bl,ALL_RESURRECTION,4,1);
- clif->message(fd, msg_fd(fd,16)); // You've been revived! It's a miracle!
- return true;
- }
- /*==========================================
- * +kamic [LuzZza]
- *------------------------------------------*/
- ACMD(kami)
- {
- unsigned int color=0;
- memset(atcmd_output, '\0', sizeof(atcmd_output));
- if(*(info->command + 4) != 'c' && *(info->command + 4) != 'C') {
- if (!*message) {
- clif->message(fd, msg_fd(fd,980)); // Please enter a message (usage: @kami <message>).
- return false;
- }
- sscanf(message, "%199[^\n]", atcmd_output);
- if (stristr(info->command, "l") != NULL)
- clif->broadcast(&sd->bl, atcmd_output, strlen(atcmd_output) + 1, BC_DEFAULT, ALL_SAMEMAP);
- else
- intif->broadcast(atcmd_output, strlen(atcmd_output) + 1, (*(info->command + 4) == 'b' || *(info->command + 4) == 'B') ? BC_BLUE : BC_YELLOW);
- } else {
- if(!*message || (sscanf(message, "%10u %199[^\n]", &color, atcmd_output) < 2)) {
- clif->message(fd, msg_fd(fd,981)); // Please enter color and message (usage: @kamic <color> <message>).
- return false;
- }
- if(color > 0xFFFFFF) {
- clif->message(fd, msg_fd(fd,982)); // Invalid color.
- return false;
- }
- intif->broadcast2(atcmd_output, strlen(atcmd_output) + 1, color, 0x190, 12, 0, 0);
- }
- return true;
- }
- /*==========================================
- *
- *------------------------------------------*/
- ACMD(heal)
- {
- int hp = 0, sp = 0; // [Valaris] thanks to fov
- sscanf(message, "%12d %12d", &hp, &sp);
- // some overflow checks
- if( hp == INT_MIN ) hp++;
- if( sp == INT_MIN ) sp++;
- if ( hp == 0 && sp == 0 ) {
- if (!status_percent_heal(&sd->bl, 100, 100))
- clif->message(fd, msg_fd(fd,157)); // HP and SP have already been recovered.
- else
- clif->message(fd, msg_fd(fd,17)); // HP, SP recovered.
- return true;
- }
- if ( hp > 0 && sp >= 0 ) {
- if(!status->heal(&sd->bl, hp, sp, 0))
- clif->message(fd, msg_fd(fd,157)); // HP and SP are already with the good value.
- else
- clif->message(fd, msg_fd(fd,17)); // HP, SP recovered.
- return true;
- }
- if ( hp < 0 && sp <= 0 ) {
- status->damage(NULL, &sd->bl, -hp, -sp, 0, 0);
- clif->damage(&sd->bl,&sd->bl, 0, 0, -hp, 0, BDT_ENDURE, 0);
- clif->message(fd, msg_fd(fd,156)); // HP or/and SP modified.
- return true;
- }
- //Opposing signs.
- if ( hp ) {
- if (hp > 0)
- status->heal(&sd->bl, hp, 0, 0);
- else {
- status->damage(NULL, &sd->bl, -hp, 0, 0, 0);
- clif->damage(&sd->bl,&sd->bl, 0, 0, -hp, 0, BDT_ENDURE, 0);
- }
- }
- if ( sp ) {
- if (sp > 0)
- status->heal(&sd->bl, 0, sp, 0);
- else
- status->damage(NULL, &sd->bl, 0, -sp, 0, 0);
- }
- clif->message(fd, msg_fd(fd,156)); // HP or/and SP modified.
- return true;
- }
- /*==========================================
- * @item command (usage: @item <name/id_of_item> <quantity>) (modified by [Yor] for pet_egg)
- * @itembound command (usage: @itembound <name/id_of_item> <quantity> <bound type>) (revised by [Mhalicot])
- *------------------------------------------*/
- ACMD(item)
- {
- char item_name[100];
- int number = 0, item_id, flag = 0, bound = 0;
- struct item item_tmp;
- struct item_data *item_data;
- int get_count, i;
- memset(item_name, '\0', sizeof(item_name));
- if (!strcmpi(info->command,"itembound") && (!*message || (
- sscanf(message, "\"%99[^\"]\" %12d %12d", item_name, &number, &bound) < 2 &&
- sscanf(message, "%99s %12d %12d", item_name, &number, &bound) < 2
- ))) {
- clif->message(fd, msg_fd(fd,295)); // Please enter an item name or ID (usage: @itembound <item name/ID> <quantity> <bound_type>).
- return false;
- } else if (!*message
- || ( sscanf(message, "\"%99[^\"]\" %12d", item_name, &number) < 1
- && sscanf(message, "%99s %12d", item_name, &number) < 1
- )) {
- clif->message(fd, msg_fd(fd,983)); // Please enter an item name or ID (usage: @item <item name/ID> <quantity>).
- return false;
- }
- if (number <= 0)
- number = 1;
- if ((item_data = itemdb->search_name(item_name)) == NULL &&
- (item_data = itemdb->exists(atoi(item_name))) == NULL)
- {
- clif->message(fd, msg_fd(fd,19)); // Invalid item ID or name.
- return false;
- }
- if(!strcmpi(info->command,"itembound") ) {
- if( !(bound >= IBT_MIN && bound <= IBT_MAX) ) {
- clif->message(fd, msg_fd(fd,298)); // Invalid bound type
- return false;
- }
- switch( (enum e_item_bound_type)bound ) {
- case IBT_CHARACTER:
- case IBT_ACCOUNT:
- break; /* no restrictions */
- case IBT_PARTY:
- if( !sd->status.party_id ) {
- clif->message(fd, msg_fd(fd,1498)); //You can't add a party bound item to a character without party!
- return false;
- }
- break;
- case IBT_GUILD:
- if( !sd->status.guild_id ) {
- clif->message(fd, msg_fd(fd,1499)); //You can't add a guild bound item to a character without guild!
- return false;
- }
- break;
- }
- }
- item_id = item_data->nameid;
- get_count = number;
- //Check if it's stackable.
- if (!itemdb->isstackable2(item_data)) {
- if( bound && (item_data->type == IT_PETEGG || item_data->type == IT_PETARMOR) ) {
- clif->message(fd, msg_fd(fd,498)); // Cannot create bounded pet eggs or pet armors.
- return false;
- }
- get_count = 1;
- }
- for (i = 0; i < number; i += get_count) {
- // if not pet egg
- if (!pet->create_egg(sd, item_id)) {
- memset(&item_tmp, 0, sizeof(item_tmp));
- item_tmp.nameid = item_id;
- item_tmp.identify = 1;
- item_tmp.bound = (unsigned char)bound;
- if ((flag = pc->additem(sd, &item_tmp, get_count, LOG_TYPE_COMMAND)))
- clif->additem(sd, 0, 0, flag);
- }
- }
- if (flag == 0)
- clif->message(fd, msg_fd(fd,18)); // Item created.
- return true;
- }
- /*==========================================
- * @item2 and @itembound2 command (revised by [Mhalicot])
- *------------------------------------------*/
- ACMD(item2)
- {
- struct item item_tmp;
- struct item_data *item_data;
- char item_name[100];
- int item_id, number = 0, bound = 0;
- int identify = 0, refine = 0, attr = 0;
- int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
- memset(item_name, '\0', sizeof(item_name));
- if (!strcmpi(info->command,"itembound2") && (!*message || (
- sscanf(message, "\"%99[^\"]\" %12d %12d %12d %12d %12d %12d %12d %12d %12d", item_name, &number, &identify, &refine, &attr, &c1, &c2, &c3, &c4, &bound) < 10 &&
- sscanf(message, "%99s %12d %12d %12d %12d %12d %12d %12d %12d %12d", item_name, &number, &identify, &refine, &attr, &c1, &c2, &c3, &c4, &bound) < 10 ))) {
- clif->message(fd, msg_fd(fd,296)); // Please enter all parameters (usage: @itembound2 <item name/ID> <quantity>
- clif->message(fd, msg_fd(fd,297)); // <identify_flag> <refine> <attribute> <card1> <card2> <card3> <card4> <bound_type>).
- return false;
- } else if (!*message
- || ( sscanf(message, "\"%99[^\"]\" %12d %12d %12d %12d %12d %12d %12d %12d", item_name, &number, &identify, &refine, &attr, &c1, &c2, &c3, &c4) < 9
- && sscanf(message, "%99s %12d %12d %12d %12d %12d %12d %12d %12d", item_name, &number, &identify, &refine, &attr, &c1, &c2, &c3, &c4) < 9
- )) {
- clif->message(fd, msg_fd(fd,984)); // Please enter all parameters (usage: @item2 <item name/ID> <quantity>
- clif->message(fd, msg_fd(fd,985)); // <identify_flag> <refine> <attribute> <card1> <card2> <card3> <card4>).
- return false;
- }
- if (number <= 0)
- number = 1;
- if( !strcmpi(info->command,"itembound2") && !(bound >= IBT_MIN && bound <= IBT_MAX) ) {
- clif->message(fd, msg_fd(fd,298)); // Invalid bound type
- return false;
- }
- item_id = 0;
- if ((item_data = itemdb->search_name(item_name)) != NULL ||
- (item_data = itemdb->exists(atoi(item_name))) != NULL)
- item_id = item_data->nameid;
- if (item_id > 500) {
- int flag = 0;
- int loop, get_count, i;
- loop = 1;
- get_count = number;
- if( !strcmpi(info->command,"itembound2") )
- bound = 1;
- if( !itemdb->isstackable2(item_data) ) {
- if( bound && (item_data->type == IT_PETEGG || item_data->type == IT_PETARMOR) ) {
- clif->message(fd, msg_fd(fd,498)); // Cannot create bounded pet eggs or pet armors.
- return false;
- }
- loop = number;
- get_count = 1;
- if (item_data->type == IT_PETEGG) {
- identify = 1;
- refine = 0;
- }
- if (item_data->type == IT_PETARMOR)
- refine = 0;
- } else {
- identify = 1;
- refine = attr = 0;
- }
- refine = cap_value(refine, 0, MAX_REFINE);
- for (i = 0; i < loop; i++) {
- memset(&item_tmp, 0, sizeof(item_tmp));
- item_tmp.nameid = item_id;
- item_tmp.identify = identify;
- item_tmp.refine = refine;
- item_tmp.attribute = attr;
- item_tmp.bound = (unsigned char)bound;
- item_tmp.card[0] = c1;
- item_tmp.card[1] = c2;
- item_tmp.card[2] = c3;
- item_tmp.card[3] = c4;
- if ((flag = pc->additem(sd, &item_tmp, get_count, LOG_TYPE_COMMAND)))
- clif->additem(sd, 0, 0, flag);
- }
- if (flag == 0)
- clif->message(fd, msg_fd(fd,18)); // Item created.
- } else {
- clif->message(fd, msg_fd(fd,19)); // Invalid item ID or name.
- return false;
- }
- return true;
- }
- /*==========================================
- *
- *------------------------------------------*/
- ACMD(itemreset)
- {
- int i;
- for (i = 0; i < MAX_INVENTORY; i++) {
- if (sd->status.inventory[i].amount && sd->status.inventory[i].equip == 0) {
- pc->delitem(sd, i, sd->status.inventory[i].amount, 0, DELITEM_NORMAL, LOG_TYPE_COMMAND);
- }
- }
- clif->message(fd, msg_fd(fd,20)); // All of your items have been removed.
- return true;
- }
- /*==========================================
- * Atcommand @lvlup
- *------------------------------------------*/
- ACMD(baselevelup)
- {
- int level=0, i=0, status_point=0;
- if (!*message || !(level = atoi(message))) {
- clif->message(fd, msg_fd(fd,986)); // Please enter a level adjustment (usage: @lvup/@blevel/@baselvlup <number of levels>).
- return false;
- }
- if (level > 0) {
- if (sd->status.base_level >= pc->maxbaselv(sd)) { // check for max level by Valaris
- clif->message(fd, msg_fd(fd,47)); // Base level can't go any higher.
- return false;
- } // End Addition
- if ((unsigned int)level > pc->maxbaselv(sd) || (unsigned int)level > pc->maxbaselv(sd) - sd->status.base_level) // fix positive overflow
- level = pc->maxbaselv(sd) - sd->status.base_level;
- for (i = 0; i < level; i++)
- status_point += pc->gets_status_point(sd->status.base_level + i);
- sd->status.status_point += status_point;
- sd->status.base_level += (unsigned int)level;
- status_calc_pc(sd, SCO_FORCE);
- status_percent_heal(&sd->bl, 100, 100);
- clif->misceffect(&sd->bl, 0);
- clif->message(fd, msg_fd(fd,21)); // Base level raised.
- } else {
- if (sd->status.base_level == 1) {
- clif->message(fd, msg_fd(fd,158)); // Base level can't go any lower.
- return false;
- }
- level*=-1;
- if ((unsigned int)level >= sd->status.base_level)
- level = sd->status.base_level-1;
- for (i = 0; i > -level; i--)
- status_point += pc->gets_status_point(sd->status.base_level + i - 1);
- if (sd->status.status_point < status_point)
- pc->resetstate(sd);
- if (sd->status.status_point < status_point)
- sd->status.status_point = 0;
- else
- sd->status.status_point -= status_point;
- sd->status.base_level -= (unsigned int)level;
- clif->message(fd, msg_fd(fd,22)); // Base level lowered.
- status_calc_pc(sd, SCO_FORCE);
- }
- sd->status.base_exp = 0;
- clif->updatestatus(sd, SP_STATUSPOINT);
- clif->updatestatus(sd, SP_BASELEVEL);
- clif->updatestatus(sd, SP_BASEEXP);
- clif->updatestatus(sd, SP_NEXTBASEEXP);
- pc->baselevelchanged(sd);
- if(sd->status.party_id)
- party->send_levelup(sd);
- return true;
- }
- /*==========================================
- *
- *------------------------------------------*/
- ACMD(joblevelup)
- {
- int level=0;
- if (!*message || !(level = atoi(message))) {
- clif->message(fd, msg_fd(fd,987)); // Please enter a level adjustment (usage: @joblvup/@jlevel/@joblvlup <number of levels>).
- return false;
- }
- if (level > 0) {
- if (sd->status.job_level >= pc->maxjoblv(sd)) {
- clif->message(fd, msg_fd(fd,23)); // Job level can't go any higher.
- return false;
- }
- if ((unsigned int)level > pc->maxjoblv(sd) || (unsigned int)level > pc->maxjoblv(sd) - sd->status.job_level) // fix positive overflow
- level = pc->maxjoblv(sd) - sd->status.job_level;
- sd->status.job_level += (unsigned int)level;
- sd->status.skill_point += level;
- clif->misceffect(&sd->bl, 1);
- clif->message(fd, msg_fd(fd,24)); // Job level raised.
- } else {
- if (sd->status.job_level == 1) {
- clif->message(fd, msg_fd(fd,159)); // Job level can't go any lower.
- return false;
- }
- level *=-1;
- if ((unsigned int)level >= sd->status.job_level) // fix negative overflow
- level = sd->status.job_level-1;
- sd->status.job_level -= (unsigned int)level;
- if (sd->status.skill_point < level)
- pc->resetskill(sd, PCRESETSKILL_NONE); //Reset skills since we need to subtract more points.
- if (sd->status.skill_point < level)
- sd->status.skill_point = 0;
- else
- sd->status.skill_point -= level;
- clif->message(fd, msg_fd(fd,25)); // Job level lowered.
- }
- sd->status.job_exp = 0;
- clif->updatestatus(sd, SP_JOBLEVEL);
- clif->updatestatus(sd, SP_JOBEXP);
- clif->updatestatus(sd, SP_NEXTJOBEXP);
- clif->updatestatus(sd, SP_SKILLPOINT);
- status_calc_pc(sd, SCO_FORCE);
- return true;
- }
- /*==========================================
- * @help
- *------------------------------------------*/
- ACMD(help) {
- const char *command_name = NULL;
- char *default_command = "help";
- AtCommandInfo *tinfo = NULL;
- if (!*message) {
- command_name = default_command; // If no command_name specified, display help for @help.
- } else {
- if (*message == atcommand->at_symbol || *message == atcommand->char_symbol)
- ++message;
- command_name = atcommand->check_alias(message);
- }
- if (!atcommand->can_use2(sd, command_name, COMMAND_ATCOMMAND)) {
- safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,153), message); // "%s is Unknown Command"
- clif->message(fd, atcmd_output);
- atcommand->get_suggestions(sd, command_name, true);
- return false;
- }
- tinfo = atcommand->get_info_byname(atcommand->check_alias(command_name));
- if ( !tinfo || tinfo->help == NULL ) {
- safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,988), atcommand->at_symbol, command_name); // There is no help for %c%s.
- clif->message(fd, atcmd_output);
- atcommand->get_suggestions(sd, command_name, true);
- return false;
- }
- safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,989), atcommand->at_symbol, command_name); // Help for command %c%s:
- clif->message(fd, atcmd_output);
- { // Display aliases
- DBIterator* iter;
- AtCommandInfo *command_info;
- AliasInfo *alias_info = NULL;
- StringBuf buf;
- bool has_aliases = false;
- StrBuf->Init(&buf);
- StrBuf->AppendStr(&buf, msg_fd(fd,990)); // Available aliases:
- command_info = atcommand->get_info_byname(command_name);
- iter = db_iterator(atcommand->alias_db);
- for (alias_info = dbi_first(iter); dbi_exists(iter); alias_info = dbi_next(iter)) {
- if (alias_info->command == command_info) {
- StrBuf->Printf(&buf, " %s", alias_info->alias);
- has_aliases = true;
- }
- }
- dbi_destroy(iter);
- if (has_aliases)
- clif->message(fd, StrBuf->Value(&buf));
- StrBuf->Destroy(&buf);
- }
- // Display help contents
- clif->messageln(fd, tinfo->help);
- return true;
- }
- /**
- * Helper function, used in foreach calls to stop auto-attack timers.
- *
- * @see map_foreachinmap
- *
- * Arglist parameters:
- * - (int) id: If 0, stop any attacks. Otherwise, the target block list id to stop attacking.
- */
- int atcommand_stopattack(struct block_list *bl,va_list ap)
- {
- struct unit_data *ud = NULL;
- int id = 0;
- nullpo_ret(bl);
- ud = unit->bl2ud(bl);
- id = va_arg(ap, int);
- if (ud && ud->attacktimer != INVALID_TIMER && (!id || id == ud->target)) {
- unit->stop_attack(bl);
- return 1;
- }
- return 0;
- }
- /*==========================================
- *
- *------------------------------------------*/
- int atcommand_pvpoff_sub(struct block_list *bl,va_list ap)
- {
- struct map_session_data *sd = NULL;
- nullpo_ret(bl);
- Assert_ret(bl->type == BL_PC);
- sd = BL_UCAST(BL_PC, bl);
- clif->pvpset(sd, 0, 0, 2);
- if (sd->pvp_timer != INVALID_TIMER) {
- timer->delete(sd->pvp_timer, pc->calc_pvprank_timer);
- sd->pvp_timer = INVALID_TIMER;
- }
- return 0;
- }
- ACMD(pvpoff)
- {
- if (!map->list[sd->bl.m].flag.pvp) {
- clif->message(fd, msg_fd(fd,160)); // PvP is already Off.
- return false;
- }
- map->zone_change2(sd->bl.m,map->list[sd->bl.m].prev_zone);
- map->list[sd->bl.m].flag.pvp = 0;
- if (!battle_config.pk_mode) {
- clif->map_property_mapall(sd->bl.m, MAPPROPERTY_NOTHING);
- clif->maptypeproperty2(&sd->bl,ALL_SAMEMAP);
- }
- map->foreachinmap(atcommand->pvpoff_sub,sd->bl.m, BL_PC);
- map->foreachinmap(atcommand->stopattack,sd->bl.m, BL_CHAR, 0);
- clif->message(fd, msg_fd(fd,31)); // PvP: Off.
- return true;
- }
- /*==========================================
- *
- *------------------------------------------*/
- int atcommand_pvpon_sub(struct block_list *bl,va_list ap)
- {
- struct map_session_data *sd = NULL;
- nullpo_ret(bl);
- Assert_ret(bl->type == BL_PC);
- sd = BL_UCAST(BL_PC, bl);
- if (sd->pvp_timer == INVALID_TIMER) {
- sd->pvp_timer = timer->add(timer->gettick() + 200, pc->calc_pvprank_timer, sd->bl.id, 0);
- sd->pvp_rank = 0;
- sd->pvp_lastusers = 0;
- sd->pvp_point = 5;
- sd->pvp_won = 0;
- sd->pvp_lost = 0;
- }
- return 0;
- }
- ACMD(pvpon)
- {
- if (map->list[sd->bl.m].flag.pvp) {
- clif->message(fd, msg_fd(fd,161)); // PvP is already On.
- return false;
- }
- map->zone_change2(sd->bl.m,strdb_get(map->zone_db, MAP_ZONE_PVP_NAME));
- map-…
Large files files are truncated, but you can click here to view the full file