diff --git a/doc/atcommands.txt b/doc/atcommands.txt index 7949f55359..a0c2326ba6 100644 --- a/doc/atcommands.txt +++ b/doc/atcommands.txt @@ -13,6 +13,10 @@ This file describes the usage of in-game commands and assumes that atcommand_symbol : "@" charcommand_symbol: "#" +Some commands cannot be used from console or script command to prevent map-server crashed. +See atcommand.c::atcommand_basecommands for restricted commands. Please tell us if any +other atcommand that causes map-server crashed executed by console or script commands. + To search for a command, write "@" before the command name (ex. @commands). The format of this file is as follows: 1. System Commands @@ -799,6 +803,9 @@ Warps to predefined locations in major cities. If no ID is given, all available maps will be displayed in the chat window. Locations and coordinates are stored in '/src/map/atcommand.c'. +Restriction: + - Used from console + --------------------------------------- @warp { } @@ -808,6 +815,9 @@ Locations and coordinates are stored in '/src/map/atcommand.c'. Warps to the specified map. If no coordinates are entered, a random location will be chosen. +Restriction: + - Used from console + --------------------------------------- @jumpto @@ -851,6 +861,9 @@ Allows other players to attack you outside of PvP. Changes base or job level by the specified amount. +Restriction: + - Used from console + --------------------------------------- @str <+/- amount> @@ -908,6 +921,9 @@ An 'upper' value can be specified with a job ID to produce its normal (0), advan If no job is given, a list of all available jobs will be returned. Note that jobs 22 (Wedding), 26 (Summer), 27 (Christmas), and 28 (Hanbok) are not available via @job. +Restriction: + - Used from console + --------------------------------------- @speed <0-1000> @@ -1224,6 +1240,14 @@ If a time is not specified (jailfor), the player will be jailed indefinitely. --------------------------------------- @kick + +Kick a player from the server. + +Restriction: + - Used from 'atcommand' or 'useatcmd' by autotrader + +--------------------------------------- + @kickall /killall @@ -1317,7 +1341,10 @@ Affected files: -- questdb: quest_db.txt -- script: /npc/*.txt, /npc/*.conf -- skilldb: skill_db.txt, const.txt, skill_require_db.txt, skill_cast_db.txt, skill_castnodex_db.txt, skill_nocast_db.txt, skill_copyable_db.txt, skill_improvise_db.txt, skill_changematerial_db.txt, skill_nonearnpc_db.txt, skill_damage_db.txt, skill_unit_db.txt, abra_db.txt, create_arrow_db.txt, produce_db.txt, spellbook_db.txt, magicmushroom_db.txt - -- statusdb: attr_fix.txt, size_fix.txt, refine_db.tx +-- statusdb: attr_fix.txt, size_fix.txt, refine_db.tx + +Restriction: + - Used from 'atcommand' or 'useatcmd'. For @reload & @reloadscript --------------------------------------- diff --git a/src/char/char_mapif.c b/src/char/char_mapif.c index 82e9a0341f..5756dd63c4 100644 --- a/src/char/char_mapif.c +++ b/src/char/char_mapif.c @@ -894,7 +894,7 @@ int chmapif_parse_save_scdata(int fd){ // Whatever comes from the mapserver, now is the time to drop previous entries if( Sql_Query( sql_handle, "DELETE FROM `%s` where `account_id` = %d and `char_id` = %d;", schema_config.scdata_db, aid, cid ) != SQL_SUCCESS ){ - Sql_ShowDebug( sql_handle ); + Sql_ShowDebug( sql_handle ); } else if( count > 0 ) { diff --git a/src/map/atcommand.c b/src/map/atcommand.c index 5145c5918e..06407c6da4 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -60,12 +60,19 @@ typedef struct AliasInfo AliasInfo; int atcmd_binding_count = 0; +/// Atcommand restriction usage +enum e_atcmd_restict { + ATCMD_NOCONSOLE = 0x1, /// Cannot be used via console (is_atcommand type 2) + ATCMD_NOSCRIPT = 0x2, /// Cannot be used via script command 'atcommand' or 'useatcmd' (is_atcommand type 0 and 3) + ATCMD_NOAUTOTRADE = 0x4, /// Like ATCMD_NOSCRIPT, but if the player is autotrader. Example: atcommand "@kick "+strcharinfo(0); +}; + struct AtCommandInfo { char command[ATCOMMAND_LENGTH]; AtCommandFunc func; - char* at_groups;/* quick @commands "can-use" lookup */ - char* char_groups;/* quick @charcommands "can-use" lookup */ - int restriction; //prevent : 1 console, 2 script... + char* at_groups; /// Quick @commands "can-use" lookup + char* char_groups; /// Quick @charcommands "can-use" lookup + uint8 restriction; /// Restrictions see enum e_restict }; struct AliasInfo { @@ -9136,7 +9143,7 @@ static inline void atcmd_channel_help(struct map_session_data *sd, const char *c { int fd = sd->fd; bool can_delete = pc_has_permission(sd, PC_PERM_CHANNEL_ADMIN); - bool can_create = (can_delete || Channel_Config.user_chenable); + bool can_create = (can_delete || channel_config.user_chenable); clif_displaymessage(fd, msg_txt(sd,1414));// ---- Available options: //option create @@ -9229,7 +9236,7 @@ ACMD_FUNC(channel) { return 0; } - if( strcmpi(key,"create") == 0 && ( Channel_Config.user_chenable || pc_has_permission(sd, PC_PERM_CHANNEL_ADMIN) ) ) { + if( strcmpi(key,"create") == 0 && ( channel_config.user_chenable || pc_has_permission(sd, PC_PERM_CHANNEL_ADMIN) ) ) { if(sub3[0] != '\0'){ clif_displaymessage(fd, msg_txt(sd,1408)); // Channel password may not contain spaces. return -1; @@ -9277,8 +9284,8 @@ ACMD_FUNC(fontcolor) sd->fontcolor = 0; } else { unsigned char k; - ARR_FIND(0,Channel_Config.colors_count,k,( strcmpi(message,Channel_Config.colors_name[k]) == 0 )); - if( k == Channel_Config.colors_count ) { + ARR_FIND(0,channel_config.colors_count,k,( strcmpi(message,channel_config.colors_name[k]) == 0 )); + if( k == channel_config.colors_count ) { sprintf(atcmd_output, msg_txt(sd,1411), message);// Unknown color '%s'. clif_displaymessage(fd, atcmd_output); return -1; @@ -9661,17 +9668,17 @@ ACMD_FUNC(clonestat) { **/ #define ACMD_DEF(x) { #x, atcommand_ ## x, NULL, NULL, 0 } #define ACMD_DEF2(x2, x) { x2, atcommand_ ## x, NULL, NULL, 0 } -//define with restriction +// Define with restriction #define ACMD_DEFR(x, r) { #x, atcommand_ ## x, NULL, NULL, r } #define ACMD_DEF2R(x2, x, r) { x2, atcommand_ ## x, NULL, NULL, r } void atcommand_basecommands(void) { /** * Command reference list, place the base of your commands here - * TODO : all restricted command are crashing case, please look into it + * TODO: List all commands that causing crash **/ AtCommandInfo atcommand_base[] = { #include "../custom/atcommand_def.inc" - ACMD_DEF2R("warp", mapmove, 1), + ACMD_DEF2R("warp", mapmove, ATCMD_NOCONSOLE), ACMD_DEF(where), ACMD_DEF(jumpto), ACMD_DEF(jump), @@ -9689,7 +9696,7 @@ void atcommand_basecommands(void) { ACMD_DEF(guildstorage), ACMD_DEF(option), ACMD_DEF(hide), // + /hide - ACMD_DEFR(jobchange, 1), + ACMD_DEFR(jobchange, ATCMD_NOCONSOLE), ACMD_DEF(kill), ACMD_DEF(alive), ACMD_DEF(kami), @@ -9705,7 +9712,7 @@ void atcommand_basecommands(void) { ACMD_DEF(clearstorage), ACMD_DEF(cleargstorage), ACMD_DEF(clearcart), - ACMD_DEF2R("blvl", baselevelup, 1), + ACMD_DEF2R("blvl", baselevelup, ATCMD_NOCONSOLE), ACMD_DEF2("jlvl", joblevelup), ACMD_DEF(help), ACMD_DEF(pvpoff), @@ -9713,7 +9720,7 @@ void atcommand_basecommands(void) { ACMD_DEF(gvgoff), ACMD_DEF(gvgon), ACMD_DEF(model), - ACMD_DEFR(go, 1), + ACMD_DEFR(go, ATCMD_NOCONSOLE), ACMD_DEF(monster), ACMD_DEF2("monstersmall", monster), ACMD_DEF2("monsterbig", monster), @@ -9746,7 +9753,7 @@ void atcommand_basecommands(void) { ACMD_DEF(doommap), ACMD_DEF(raise), ACMD_DEF(raisemap), - ACMD_DEF(kick), // + right click menu for GM "(name) force to quit" + ACMD_DEFR(kick,ATCMD_NOAUTOTRADE), // + right click menu for GM "(name) force to quit" ACMD_DEF(kickall), ACMD_DEF(allskill), ACMD_DEF(questskill), @@ -9762,11 +9769,11 @@ void atcommand_basecommands(void) { ACMD_DEF(broadcast), // + /b and /nb ACMD_DEF(localbroadcast), // + /lb and /nlb ACMD_DEF(recallall), - ACMD_DEFR(reload,2), + ACMD_DEFR(reload,ATCMD_NOSCRIPT), ACMD_DEF2("reloaditemdb", reload), ACMD_DEF2("reloadmobdb", reload), ACMD_DEF2("reloadskilldb", reload), - ACMD_DEF2R("reloadscript", reload,2), + ACMD_DEF2R("reloadscript", reload, ATCMD_NOSCRIPT), ACMD_DEF2("reloadatcommand", reload), ACMD_DEF2("reloadbattleconf", reload), ACMD_DEF2("reloadstatusdb", reload), @@ -10057,12 +10064,15 @@ static void atcommand_get_suggestions(struct map_session_data* sd, const char *n dbi_destroy(alias_iter); } -/* - * Executes an at-command - * \param type : +/** + * Executes an at-command + * @param fd + * @param sd + * @param message + * @param type * 0 : script call (atcommand) * 1 : normal player @atcommand - * 2 : console + * 2 : console (admin:@atcommand) * 3 : script call (useatcmd) */ bool is_atcommand(const int fd, struct map_session_data* sd, const char* message, int type) @@ -10143,7 +10153,7 @@ bool is_atcommand(const int fd, struct map_session_data* sd, const char* message if( x >= 1 || y >= 1 ) { /* we have command */ info = get_atcommandinfo_byname(atcommand_checkalias(command + 1)); if( !info || info->char_groups[sd->group_pos] == 0 ) /* if we can't use or doesn't exist: don't even display the command failed message */ - return false; + return false; } else return false;/* display as normal message */ } @@ -10211,17 +10221,20 @@ bool is_atcommand(const int fd, struct map_session_data* sd, const char* message } //check restriction - if(info->restriction){ - if(info->restriction&1 && type == 2) //console prevent + if (info->restriction) { + if (info->restriction&ATCMD_NOCONSOLE && type == 2) //console prevent return true; - if(info->restriction&2 && (type == 0 || type == 3) ) //scripts prevent + if (info->restriction&ATCMD_NOSCRIPT && (type == 0 || type == 3)) //scripts prevent + return true; + if (info->restriction&ATCMD_NOAUTOTRADE && (type == 0 || type == 3) + && ((*atcmd_msg == atcommand_symbol && sd && sd->state.autotrade) || (ssd && ssd->state.autotrade))) return true; } // type == 1 : player invoked if (type == 1) { if ((*command == atcommand_symbol && info->at_groups[sd->group_pos] == 0) || - (*command == charcommand_symbol && info->char_groups[sd->group_pos] == 0) ) { + (*command == charcommand_symbol && info->char_groups[sd->group_pos] == 0) ) { return false; } if( pc_isdead(sd) && pc_has_permission(sd,PC_PERM_DISABLE_CMD_DEAD) ) { @@ -10232,7 +10245,7 @@ bool is_atcommand(const int fd, struct map_session_data* sd, const char* message // Check if target is valid only if confirmed that player can use command. if (*message == charcommand_symbol && - (ssd = map_nick2sd(charname)) == NULL && (ssd = map_nick2sd(charname2)) == NULL ) { + (ssd = map_nick2sd(charname)) == NULL && (ssd = map_nick2sd(charname2)) == NULL ) { sprintf(output, msg_txt(sd,1389), command); // %s failed. Player not found. clif_displaymessage(fd, output); return true; diff --git a/src/map/channel.c b/src/map/channel.c index a154d8f84f..2fa65dfe84 100644 --- a/src/map/channel.c +++ b/src/map/channel.c @@ -18,8 +18,10 @@ #include static DBMap* channel_db; // channels -DBMap* channel_get_db(void){ return channel_db; } +struct Channel_Config channel_config; + +DBMap* channel_get_db(void){ return channel_db; } struct chan_banentry { int char_id; @@ -163,12 +165,12 @@ int channel_mjoin(struct map_session_data *sd) { if(!sd) return -1; if( !map[sd->bl.m].channel ) { - map[sd->bl.m].channel = channel_create(Channel_Config.map_chname,NULL,Channel_Config.map_chcolor,CHAN_TYPE_MAP,sd->bl.m); + map[sd->bl.m].channel = channel_create(channel_config.map_chname,NULL,channel_config.map_chcolor,CHAN_TYPE_MAP,sd->bl.m); } if( !( map[sd->bl.m].channel->opt & CHAN_OPT_ANNOUNCE_JOIN ) ) { char mout[60]; - sprintf(mout, msg_txt(sd,1435),Channel_Config.map_chname,map[sd->bl.m].name); // You're now in the '#%s' channel for '%s'. + sprintf(mout, msg_txt(sd,1435),channel_config.map_chname,map[sd->bl.m].name); // You're now in the '#%s' channel for '%s'. clif_disp_onlyself(sd, mout, strlen(mout)); } @@ -219,7 +221,7 @@ int channel_gjoin(struct map_session_data *sd, int flag){ channel = g->channel; if(!channel){ - channel = channel_create(Channel_Config.ally_chname,NULL,Channel_Config.ally_chcolor,CHAN_TYPE_ALLY,g->guild_id); + channel = channel_create(channel_config.ally_chname,NULL,channel_config.ally_chcolor,CHAN_TYPE_ALLY,g->guild_id); g->channel = channel; channel_ajoin(g); } @@ -299,7 +301,7 @@ int channel_pcquit(struct map_session_data *sd, int type){ if(!sd) return -1; // Leave all chat channels. - if(type&(1|2) && Channel_Config.ally_enable && sd->guild){ //quit guild and ally chan + if(type&(1|2) && channel_config.ally_enable && sd->guild){ //quit guild and ally chan struct guild *g = sd->guild; if(type&1 && channel_haspc(g->channel,sd)==1){ channel_clean(g->channel,sd,0); //leave guild chan @@ -315,7 +317,7 @@ int channel_pcquit(struct map_session_data *sd, int type){ } } } - if(type&4 && Channel_Config.map_enable && channel_haspc(map[sd->bl.m].channel,sd)==1){ //quit map chan + if(type&4 && channel_config.map_enable && channel_haspc(map[sd->bl.m].channel,sd)==1){ //quit map chan channel_clean(map[sd->bl.m].channel,sd,0); } if(type&8 && sd->channel_count ) { //quit all chan @@ -376,8 +378,8 @@ int channel_chk(char *chname, char *chpass, int type){ if ( strlen(chname) < 3 || strlen(chname) > CHAN_NAME_LENGTH ) return -2; if( (type&2) && ( - strcmpi(chname + 1,Channel_Config.map_chname) == 0 - || strcmpi(chname + 1,Channel_Config.ally_chname) == 0 + strcmpi(chname + 1,channel_config.map_chname) == 0 + || strcmpi(chname + 1,channel_config.ally_chname) == 0 || strdb_exists(channel_db, chname + 1) ) ) { return -4; @@ -402,16 +404,16 @@ int channel_chk(char *chname, char *chpass, int type){ struct Channel* channel_name2channel(char *chname, struct map_session_data *sd, int flag){ if(channel_chk(chname, NULL, 1)) return NULL; - if(sd && strcmpi(chname + 1,Channel_Config.map_chname) == 0){ + if(sd && strcmpi(chname + 1,channel_config.map_chname) == 0){ if(flag&1 && !map[sd->bl.m].channel) - map[sd->bl.m].channel = channel_create(Channel_Config.map_chname,NULL,Channel_Config.map_chcolor,CHAN_TYPE_MAP,sd->bl.m); + map[sd->bl.m].channel = channel_create(channel_config.map_chname,NULL,channel_config.map_chcolor,CHAN_TYPE_MAP,sd->bl.m); if(flag&2) channel_mjoin(sd); return map[sd->bl.m].channel; } - else if(sd && (strcmpi(chname + 1,Channel_Config.ally_chname) == 0) && sd->guild){ + else if(sd && (strcmpi(chname + 1,channel_config.ally_chname) == 0) && sd->guild){ if(flag&1 && !sd->guild->channel) - sd->guild->channel = channel_create(Channel_Config.ally_chname,NULL,Channel_Config.ally_chcolor,CHAN_TYPE_ALLY,sd->guild->guild_id); + sd->guild->channel = channel_create(channel_config.ally_chname,NULL,channel_config.ally_chcolor,CHAN_TYPE_ALLY,sd->guild->guild_id); if(flag&2) channel_gjoin(sd,3); return sd->guild->channel; @@ -472,9 +474,6 @@ int channel_pc_haschan(struct map_session_data *sd, struct Channel *channel){ * -1 : fail */ int channel_display_list(struct map_session_data *sd, char *options){ - struct Channel *channel; - char output[128]; - int k; if(!sd || !options) return -1; @@ -482,10 +481,13 @@ int channel_display_list(struct map_session_data *sd, char *options){ //display availaible colors if( options[0] != '\0' && strcmpi(options,"colors") == 0 ) { char msg[40]; + unsigned char k; clif_displaymessage(sd->fd, msg_txt(sd,1444)); // ---- Available Colors ---- - for( k = 0; k < Channel_Config.colors_count; k++ ) { - sprintf(msg, msg_txt(sd,1445),Channel_Config.colors_name[k]);// - '%s' - clif_colormes(sd,Channel_Config.colors[k],msg); + for( k = 0; k < channel_config.colors_count; k++ ) { + if (channel_config.colors[k]) { + sprintf(msg, msg_txt(sd,1445),channel_config.colors_name[k]);// - '%s' + clif_colormes(sd,channel_config.colors[k],msg); + } } } else if( options[0] != '\0' && strcmpi(options,"mine") == 0 ) { //display chan I'm into @@ -493,8 +495,12 @@ int channel_display_list(struct map_session_data *sd, char *options){ if(!sd->channel_count) clif_displaymessage(sd->fd, msg_txt(sd,1476)); // You have not joined any channels. else { + unsigned char k; + struct Channel *channel; for(k=0; kchannel_count; k++){ - channel = sd->channels[k]; + char output[128]; + if (!(channel = sd->channels[k])) + continue; sprintf(output, msg_txt(sd,1409), channel->name, db_size(channel->users));// - #%s (%d users) clif_displaymessage(sd->fd, output); } @@ -503,17 +509,20 @@ int channel_display_list(struct map_session_data *sd, char *options){ else { //display public chanels DBIterator *iter; bool has_perm = pc_has_permission(sd, PC_PERM_CHANNEL_ADMIN) ? true : false; + struct Channel *channel; + char output[128]; clif_displaymessage(sd->fd, msg_txt(sd,1410)); // ---- Public Channels ---- - if( Channel_Config.map_enable ) { - sprintf(output, msg_txt(sd,1409), Channel_Config.map_chname, map[sd->bl.m].channel ? db_size(map[sd->bl.m].channel->users) : 0);// - #%s (%d users) + if( channel_config.map_enable && map[sd->bl.m].channel ) { + sprintf(output, msg_txt(sd,1409), channel_config.map_chname, map[sd->bl.m].channel ? db_size(map[sd->bl.m].channel->users) : 0);// - #%s (%d users) clif_displaymessage(sd->fd, output); } - if( Channel_Config.ally_enable && sd->status.guild_id ) { + if( channel_config.ally_enable && sd->status.guild_id ) { struct guild *g = sd->guild; - if( !g ) return -1; //how can this happen if status.guild_id true ? - sprintf(output, msg_txt(sd,1409), Channel_Config.ally_chname, db_size(((struct Channel *)g->channel)->users));// - #%s (%d users) - clif_displaymessage(sd->fd, output); + if (g && g->channel) { + sprintf(output, msg_txt(sd,1409), channel_config.ally_chname, db_size(((struct Channel *)g->channel)->users));// - #%s (%d users) + clif_displaymessage(sd->fd, output); + } } iter = db_iterator(channel_db); for(channel = dbi_first(iter); dbi_exists(iter); channel = dbi_next(iter)) { @@ -618,7 +627,7 @@ int channel_pcleave(struct map_session_data *sd, char *chname){ return -2; //channel doesn't exist or player don't have it } - if( !Channel_Config.closing && (channel->opt & CHAN_OPT_ANNOUNCE_JOIN) ) { + if( !channel_config.closing && (channel->opt & CHAN_OPT_ANNOUNCE_JOIN) ) { char message[60]; sprintf(message, "#%s '%s' left",channel->name,sd->status.name); clif_channel_msg(channel,sd,message,channel->color); @@ -726,14 +735,14 @@ int channel_pccolor(struct map_session_data *sd, char *chname, char *color){ return -1; } - ARR_FIND(0,Channel_Config.colors_count,k,( strcmpi(color,Channel_Config.colors_name[k]) == 0 ) ); - if( k >= Channel_Config.colors_count ) { + ARR_FIND(0,channel_config.colors_count,k,( strcmpi(color,channel_config.colors_name[k]) == 0 ) ); + if( k >= channel_config.colors_count ) { sprintf(output, msg_txt(sd,1411), color);// Unknown color '%s'. clif_displaymessage(sd->fd, output); return -1; } channel->color = k; - sprintf(output, msg_txt(sd,1413),chname,Channel_Config.colors_name[k]);// '%s' channel color updated to '%s'. + sprintf(output, msg_txt(sd,1413),chname,channel_config.colors_name[k]);// '%s' channel color updated to '%s'. clif_displaymessage(sd->fd, output); return 0; } @@ -1031,74 +1040,74 @@ void channel_read_config(void) { if( !config_setting_lookup_string(settings, "map_local_channel_name", &map_chname) ) map_chname = "map"; - safestrncpy(Channel_Config.map_chname, map_chname, CHAN_NAME_LENGTH); + safestrncpy(channel_config.map_chname, map_chname, CHAN_NAME_LENGTH); if( !config_setting_lookup_string(settings, "ally_channel_name", &ally_chname) ) ally_chname = "ally"; - safestrncpy(Channel_Config.ally_chname, ally_chname, CHAN_NAME_LENGTH); + safestrncpy(channel_config.ally_chname, ally_chname, CHAN_NAME_LENGTH); config_setting_lookup_bool(settings, "map_local_channel", &local_enabled); config_setting_lookup_bool(settings, "ally_channel_enabled", &ally_enabled); if( local_enabled ) - Channel_Config.map_enable = true; + channel_config.map_enable = true; if( ally_enabled ) - Channel_Config.ally_enable = true; + channel_config.ally_enable = true; config_setting_lookup_bool(settings, "map_local_channel_autojoin", &local_autojoin); config_setting_lookup_bool(settings, "ally_channel_autojoin", &ally_autojoin); if( local_autojoin ) - Channel_Config.map_autojoin = true; + channel_config.map_autojoin = true; if( ally_autojoin ) - Channel_Config.ally_autojoin = true; + channel_config.ally_autojoin = true; config_setting_lookup_bool(settings, "allow_user_channel_creation", &allow_user_channel_creation); if( allow_user_channel_creation ) - Channel_Config.user_chenable = true; + channel_config.user_chenable = true; if( (colors = config_setting_get_member(settings, "colors")) != NULL ) { int color_count = config_setting_length(colors); - CREATE( Channel_Config.colors, unsigned long, color_count ); - CREATE( Channel_Config.colors_name, char *, color_count ); + CREATE( channel_config.colors, unsigned long, color_count ); + CREATE( channel_config.colors_name, char *, color_count ); for(i = 0; i < color_count; i++) { config_setting_t *color = config_setting_get_elem(colors, i); - CREATE( Channel_Config.colors_name[i], char, CHAN_NAME_LENGTH ); + CREATE( channel_config.colors_name[i], char, CHAN_NAME_LENGTH ); - safestrncpy(Channel_Config.colors_name[i], config_setting_name(color), CHAN_NAME_LENGTH); - Channel_Config.colors[i] = strtoul(config_setting_get_string_elem(colors,i),NULL,0); - Channel_Config.colors[i] = (Channel_Config.colors[i] & 0x0000FF) << 16 | (Channel_Config.colors[i] & 0x00FF00) | (Channel_Config.colors[i] & 0xFF0000) >> 16;//RGB to BGR + safestrncpy(channel_config.colors_name[i], config_setting_name(color), CHAN_NAME_LENGTH); + channel_config.colors[i] = strtoul(config_setting_get_string_elem(colors,i),NULL,0); + channel_config.colors[i] = (channel_config.colors[i] & 0x0000FF) << 16 | (channel_config.colors[i] & 0x00FF00) | (channel_config.colors[i] & 0xFF0000) >> 16;//RGB to BGR } - Channel_Config.colors_count = color_count; + channel_config.colors_count = color_count; } config_setting_lookup_string(settings, "map_local_channel_color", &map_color); - for (k = 0; k < Channel_Config.colors_count; k++) { - if( strcmpi(Channel_Config.colors_name[k],map_color) == 0 ) + for (k = 0; k < channel_config.colors_count; k++) { + if( strcmpi(channel_config.colors_name[k],map_color) == 0 ) break; } - if( k < Channel_Config.colors_count ) { - Channel_Config.map_chcolor = k; + if( k < channel_config.colors_count ) { + channel_config.map_chcolor = k; } else { ShowError("channels.conf: unknown color '%s' for 'map_local_channel_color', disabling '#%s'...\n",map_color,map_chname); - Channel_Config.map_enable = false; + channel_config.map_enable = false; } config_setting_lookup_string(settings, "ally_channel_color", &ally_color); - for (k = 0; k < Channel_Config.colors_count; k++) { - if( strcmpi(Channel_Config.colors_name[k],ally_color) == 0 ) + for (k = 0; k < channel_config.colors_count; k++) { + if( strcmpi(channel_config.colors_name[k],ally_color) == 0 ) break; } - if( k < Channel_Config.colors_count ) { - Channel_Config.ally_chcolor = k; + if( k < channel_config.colors_count ) { + channel_config.ally_chcolor = k; } else { ShowError("channels.conf: unknown color '%s' for 'ally_channel_color', disabling '#%s'...\n",ally_color,ally_chname); - Channel_Config.ally_enable = false; + channel_config.ally_enable = false; } if( (channels = config_setting_get_member(settings, "default_channels")) != NULL ) { @@ -1108,15 +1117,15 @@ void channel_read_config(void) { config_setting_t *channel = config_setting_get_elem(channels, i); const char *color = config_setting_get_string_elem(channels,i); char *name = config_setting_name(channel); - for (k = 0; k < Channel_Config.colors_count; k++) { - if( strcmpi(Channel_Config.colors_name[k],color) == 0 ) + for (k = 0; k < channel_config.colors_count; k++) { + if( strcmpi(channel_config.colors_name[k],color) == 0 ) break; } - if( k == Channel_Config.colors_count ) { + if( k == channel_config.colors_count ) { ShowError("channels.conf: unknown color '%s' for channel '%s', skipping channel...\n",color,name); continue; } - if( strcmpi(name,Channel_Config.map_chname) == 0 || strcmpi(name,Channel_Config.ally_chname) == 0 || strdb_exists(channel_db, name) ) { + if( strcmpi(name,channel_config.map_chname) == 0 || strcmpi(name,channel_config.ally_chname) == 0 || strdb_exists(channel_db, name) ) { ShowError("channels.conf: duplicate channel '%s', skipping channel...\n",name); continue; } @@ -1136,7 +1145,7 @@ void channel_read_config(void) { */ void do_init_channel(void) { channel_db = stridb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA, CHAN_NAME_LENGTH); - Channel_Config.ally_enable = Channel_Config.map_enable = Channel_Config.ally_autojoin = Channel_Config.map_autojoin = false; + channel_config.ally_enable = channel_config.map_enable = channel_config.ally_autojoin = channel_config.map_autojoin = false; channel_read_config(); } @@ -1158,12 +1167,12 @@ void do_final_channel(void) { db_destroy(channel_db); //delete all color thing - if( Channel_Config.colors_count ) { + if( channel_config.colors_count ) { int i=0; - for(i = 0; i < Channel_Config.colors_count; i++) { - aFree(Channel_Config.colors_name[i]); + for(i = 0; i < channel_config.colors_count; i++) { + aFree(channel_config.colors_name[i]); } - aFree(Channel_Config.colors_name); - aFree(Channel_Config.colors); + aFree(channel_config.colors_name); + aFree(channel_config.colors); } } diff --git a/src/map/channel.h b/src/map/channel.h index 9838c6718c..fb6f1eaf82 100644 --- a/src/map/channel.h +++ b/src/map/channel.h @@ -27,7 +27,7 @@ enum Channel_Type { CHAN_TYPE_ALLY = 3, //guild }; -struct { +struct Channel_Config { unsigned long *colors; //color avail int list char **colors_name; //colors avail name list unsigned char colors_count; //color avail count @@ -36,7 +36,8 @@ struct { bool map_autojoin, ally_autojoin; //do user auto join in mapchange, guildjoin ? char map_chname[CHAN_NAME_LENGTH], ally_chname[CHAN_NAME_LENGTH]; //channel name for map and ally bool closing; //server is closing -} Channel_Config; +}; +extern struct Channel_Config channel_config; struct Channel { char name[CHAN_NAME_LENGTH]; //channel name diff --git a/src/map/chrif.c b/src/map/chrif.c index 47523588c9..7c7966f5b0 100644 --- a/src/map/chrif.c +++ b/src/map/chrif.c @@ -286,7 +286,6 @@ int chrif_save(struct map_session_data *sd, int flag) { pc_makesavestatus(sd); if (flag && sd->state.active) { //Store player data which is quitting - //FIXME: SC are lost if there's no connection at save-time because of the way its related data is cleared immediately after this function. [Skotlex] if (chrif_isconnected()) { chrif_save_scdata(sd); chrif_skillcooldown_save(sd); diff --git a/src/map/clif.c b/src/map/clif.c index 1b8e638581..e5a0ebec3d 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -5657,7 +5657,7 @@ void clif_channel_msg(struct Channel *channel, struct map_session_data *sd, char WFIFOW(sd->fd,0) = 0x2C1; WFIFOW(sd->fd,2) = msg_len + 12; WFIFOL(sd->fd,4) = 0; - WFIFOL(sd->fd,8) = Channel_Config.colors[color]; + WFIFOL(sd->fd,8) = channel_config.colors[color]; safestrncpy((char*)WFIFOP(sd->fd,12), msg, msg_len); iter = db_iterator(channel->users); @@ -9784,7 +9784,7 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) sd->state.changemap = false; // Instances do not need their own channels - if( Channel_Config.map_enable && Channel_Config.map_autojoin && !map[sd->bl.m].flag.chmautojoin && !map[sd->bl.m].instance_id ) + if( channel_config.map_enable && channel_config.map_autojoin && !map[sd->bl.m].flag.chmautojoin && !map[sd->bl.m].instance_id ) channel_mjoin(sd); //join new map } else if (sd->guild && (battle_config.guild_notice_changemap == 2 || guild_notice)) clif_guild_notice(sd, sd->guild); // Displays at end diff --git a/src/map/guild.c b/src/map/guild.c index 333da6ed35..3987a093ba 100644 --- a/src/map/guild.c +++ b/src/map/guild.c @@ -511,7 +511,7 @@ int guild_recv_info(struct guild *sg) { if( sd==NULL ) continue; sd->guild = g; - if(Channel_Config.ally_autojoin ) { + if(channel_config.ally_autojoin ) { channel_gjoin(sd,3); //make all member join guildchan+allieschan } @@ -676,7 +676,7 @@ void guild_member_joined(struct map_session_data *sd) { g->member[i].sd = sd; sd->guild = g; - if( Channel_Config.ally_enable && Channel_Config.ally_autojoin ) { + if( channel_config.ally_enable && channel_config.ally_autojoin ) { channel_gjoin(sd,3); } } @@ -1673,7 +1673,7 @@ int guild_broken(int guild_id,int flag) { guild_db->foreach(guild_db,guild_broken_sub,guild_id); castle_db->foreach(castle_db,castle_guild_broken_sub,guild_id); guild_storage_delete(guild_id); - if( Channel_Config.ally_enable ) { + if( channel_config.ally_enable ) { channel_delete(g->channel); } idb_remove(guild_db,guild_id); diff --git a/src/map/map.c b/src/map/map.c index 1ee7cfbaba..94aba96f52 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -3832,7 +3832,7 @@ void do_final(void) struct s_mapiterator* iter; ShowStatus("Terminating...\n"); - Channel_Config.closing = true; + channel_config.closing = true; //Ladies and babies first. iter = mapit_getallusers(); diff --git a/src/map/map.h b/src/map/map.h index 12194dec49..a1325896bb 100644 --- a/src/map/map.h +++ b/src/map/map.h @@ -298,10 +298,19 @@ enum bl_type { BL_ALL = 0xFFF, }; -//For common mapforeach calls. Since pets cannot be affected, they aren't included here yet. +/// For common mapforeach calls. Since pets cannot be affected, they aren't included here yet. #define BL_CHAR (BL_PC|BL_MOB|BL_HOM|BL_MER|BL_ELEM) -enum npc_subtype { WARP, SHOP, SCRIPT, CASHSHOP, ITEMSHOP, POINTSHOP, TOMB }; +/// NPC Subtype +enum npc_subtype { + NPCTYPE_WARP, /// Warp + NPCTYPE_SHOP, /// Shop + NPCTYPE_SCRIPT, /// Script + NPCTYPE_CASHSHOP, /// Cashshop + NPCTYPE_ITEMSHOP, /// Itemshop + NPCTYPE_POINTSHOP, /// Pointshop + NPCTYPE_TOMB /// Monster tomb +}; enum e_race { RC_NONE_ = -1, //don't give us bonus diff --git a/src/map/mob.c b/src/map/mob.c index 4093fd76e6..06eaca6738 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -149,7 +149,7 @@ void mvptomb_create(struct mob_data *md, char *killer, time_t time) nd->class_ = 565; nd->speed = 200; - nd->subtype = TOMB; + nd->subtype = NPCTYPE_TOMB; nd->u.tomb.md = md; nd->u.tomb.kill_time = time; @@ -1192,7 +1192,7 @@ static int mob_warpchase_sub(struct block_list *bl,va_list ap) { nd = (TBL_NPC*) bl; - if(nd->subtype != WARP) + if(nd->subtype != NPCTYPE_WARP) return 0; //Not a warp if(nd->u.warp.mapindex != map[target->m].index) diff --git a/src/map/npc.c b/src/map/npc.c index 6b44c4db25..28e9f8fd6c 100644 --- a/src/map/npc.c +++ b/src/map/npc.c @@ -128,10 +128,10 @@ int npc_isnear_sub(struct block_list* bl, va_list args) { if (idx > 0 && skill_db[idx].unit_nonearnpc_type) { while (1) { - if (skill_db[idx].unit_nonearnpc_type&1 && nd->subtype == WARP) break; - if (skill_db[idx].unit_nonearnpc_type&2 && nd->subtype == SHOP) break; - if (skill_db[idx].unit_nonearnpc_type&4 && nd->subtype == SCRIPT) break; - if (skill_db[idx].unit_nonearnpc_type&8 && nd->subtype == TOMB) break; + if (skill_db[idx].unit_nonearnpc_type&1 && nd->subtype == NPCTYPE_WARP) break; + if (skill_db[idx].unit_nonearnpc_type&2 && nd->subtype == NPCTYPE_SHOP) break; + if (skill_db[idx].unit_nonearnpc_type&4 && nd->subtype == NPCTYPE_SCRIPT) break; + if (skill_db[idx].unit_nonearnpc_type&8 && nd->subtype == NPCTYPE_TOMB) break; return 0; } } @@ -944,11 +944,11 @@ int npc_touch_areanpc(struct map_session_data* sd, int16 m, int16 x, int16 y) } switch(map[m].npc[i]->subtype) { - case WARP: + case NPCTYPE_WARP: xs=map[m].npc[i]->u.warp.xs; ys=map[m].npc[i]->u.warp.ys; break; - case SCRIPT: + case NPCTYPE_SCRIPT: xs=map[m].npc[i]->u.scr.xs; ys=map[m].npc[i]->u.scr.ys; break; @@ -966,14 +966,14 @@ int npc_touch_areanpc(struct map_session_data* sd, int16 m, int16 x, int16 y) return 1; } switch(map[m].npc[i]->subtype) { - case WARP: + case NPCTYPE_WARP: if (pc_ishiding(sd) || (sd->sc.count && sd->sc.data[SC_CAMOUFLAGE]) || pc_isdead(sd)) break; // hidden or dead chars cannot use warps pc_setpos(sd,map[m].npc[i]->u.warp.mapindex,map[m].npc[i]->u.warp.x,map[m].npc[i]->u.warp.y,CLR_OUTSIGHT); break; - case SCRIPT: + case NPCTYPE_SCRIPT: for (j = i; j < map[m].npc_num; j++) { - if (map[m].npc[j]->subtype != WARP) { + if (map[m].npc[j]->subtype != NPCTYPE_WARP) { continue; } @@ -1023,13 +1023,13 @@ int npc_touch_areanpc2(struct mob_data *md) switch( map[m].npc[i]->subtype ) { - case WARP: + case NPCTYPE_WARP: if( !( battle_config.mob_warp&1 ) ) continue; xs = map[m].npc[i]->u.warp.xs; ys = map[m].npc[i]->u.warp.ys; break; - case SCRIPT: + case NPCTYPE_SCRIPT: xs = map[m].npc[i]->u.scr.xs; ys = map[m].npc[i]->u.scr.ys; break; @@ -1041,14 +1041,14 @@ int npc_touch_areanpc2(struct mob_data *md) { // In the npc touch area switch( map[m].npc[i]->subtype ) { - case WARP: + case NPCTYPE_WARP: xs = map_mapindex2mapid(map[m].npc[i]->u.warp.mapindex); if( m < 0 ) break; // Cannot Warp between map servers if( unit_warp(&md->bl, xs, map[m].npc[i]->u.warp.x, map[m].npc[i]->u.warp.y, CLR_OUTSIGHT) == 0 ) return 1; // Warped break; - case SCRIPT: + case NPCTYPE_SCRIPT: if( map[m].npc[i]->bl.id == md->areanpc_id ) break; // Already touch this NPC snprintf(eventname, ARRAYLENGTH(eventname), "%s::OnTouchNPC", map[m].npc[i]->exname); @@ -1102,13 +1102,13 @@ int npc_check_areanpc(int flag, int16 m, int16 x, int16 y, int16 range) switch(map[m].npc[i]->subtype) { - case WARP: + case NPCTYPE_WARP: if (!(flag&1)) continue; xs=map[m].npc[i]->u.warp.xs; ys=map[m].npc[i]->u.warp.ys; break; - case SCRIPT: + case NPCTYPE_SCRIPT: if (!(flag&2)) continue; xs=map[m].npc[i]->u.scr.xs; @@ -1218,18 +1218,18 @@ int npc_click(struct map_session_data* sd, struct npc_data* nd) return 1; switch(nd->subtype) { - case SHOP: - case ITEMSHOP: - case POINTSHOP: + case NPCTYPE_SHOP: + case NPCTYPE_ITEMSHOP: + case NPCTYPE_POINTSHOP: clif_npcbuysell(sd,nd->bl.id); break; - case CASHSHOP: + case NPCTYPE_CASHSHOP: clif_cashshop_show(sd,nd); break; - case SCRIPT: + case NPCTYPE_SCRIPT: run_script(nd->u.scr.script,0,sd->bl.id,nd->bl.id); break; - case TOMB: + case NPCTYPE_TOMB: run_tomb(sd,nd); break; } @@ -1289,7 +1289,7 @@ int npc_buysellsel(struct map_session_data* sd, int id, int type) if ((nd = npc_checknear(sd,map_id2bl(id))) == NULL) return 1; - if (nd->subtype != SHOP && nd->subtype != ITEMSHOP && nd->subtype != POINTSHOP) { + if (nd->subtype != NPCTYPE_SHOP && nd->subtype != NPCTYPE_ITEMSHOP && nd->subtype != NPCTYPE_POINTSHOP) { ShowError("no such shop npc : %d\n",id); if (sd->npc_id == id) sd->npc_id=0; @@ -1301,7 +1301,7 @@ int npc_buysellsel(struct map_session_data* sd, int id, int type) return 1; } - if (nd->subtype == ITEMSHOP) { + if (nd->subtype == NPCTYPE_ITEMSHOP) { char output[CHAT_SIZE_MAX]; struct item_data *itd = itemdb_exists(nd->u.shop.itemshop_nameid); memset(output,'\0',sizeof(output)); @@ -1309,7 +1309,7 @@ int npc_buysellsel(struct map_session_data* sd, int id, int type) sprintf(output,msg_txt(sd,714),itd->jname,itd->nameid); // Item Shop List: %s (%hu) clif_broadcast(&sd->bl,output,strlen(output) + 1,BC_BLUE,SELF); } - } else if (nd->subtype == POINTSHOP) { + } else if (nd->subtype == NPCTYPE_POINTSHOP) { char output[CHAT_SIZE_MAX]; memset(output,'\0',sizeof(output)); sprintf(output,msg_txt(sd,715),nd->u.shop.pointshop_str); // Point Shop List: '%s' @@ -1336,7 +1336,7 @@ int npc_cashshop_buylist(struct map_session_data *sd, int points, int count, uns unsigned short nameid; struct npc_data *nd = (struct npc_data *)map_id2bl(sd->npc_shopid); - if( !nd || nd->subtype != CASHSHOP ) + if( !nd || nd->subtype != NPCTYPE_CASHSHOP ) return 1; if( sd->state.trading ) @@ -1453,7 +1453,7 @@ int npc_cashshop_buy(struct map_session_data *sd, unsigned short nameid, int amo if( points < 0 ) return 6; - if( !nd || nd->subtype != CASHSHOP ) + if( !nd || nd->subtype != NPCTYPE_CASHSHOP ) return 1; if( sd->state.trading ) @@ -1538,7 +1538,7 @@ int npc_buylist(struct map_session_data* sd, int n, unsigned short* item_list) nd = npc_checknear(sd,map_id2bl(sd->npc_shopid)); if( nd == NULL ) return 3; - if( nd->subtype != SHOP && nd->subtype != ITEMSHOP && nd->subtype != POINTSHOP ) + if( nd->subtype != NPCTYPE_SHOP && nd->subtype != NPCTYPE_ITEMSHOP && nd->subtype != NPCTYPE_POINTSHOP ) return 3; z = 0; @@ -1602,11 +1602,11 @@ int npc_buylist(struct map_session_data* sd, int n, unsigned short* item_list) return npc_buylist_sub(sd,n,item_list,nd->master_nd); switch(nd->subtype) { - case SHOP: + case NPCTYPE_SHOP: if (z > (double)sd->status.zeny) return 1; // Not enough Zeny break; - case ITEMSHOP: + case NPCTYPE_ITEMSHOP: for (k = 0; k < MAX_INVENTORY; k++) { if (sd->status.inventory[k].nameid == nd->u.shop.itemshop_nameid) count += sd->status.inventory[k].amount; @@ -1619,7 +1619,7 @@ int npc_buylist(struct map_session_data* sd, int n, unsigned short* item_list) return 1; } break; - case POINTSHOP: + case NPCTYPE_POINTSHOP: switch(nd->u.shop.pointshop_str[0]) { case '#': if (nd->u.shop.pointshop_str[1] == '#') @@ -1646,13 +1646,13 @@ int npc_buylist(struct map_session_data* sd, int n, unsigned short* item_list) return 3; // Not enough space to store items switch(nd->subtype) { - case SHOP: + case NPCTYPE_SHOP: pc_payzeny(sd, (int)z, LOG_TYPE_NPC, NULL); break; - case ITEMSHOP: + case NPCTYPE_ITEMSHOP: pc_delitem(sd, pc_search_inventory(sd, nd->u.shop.itemshop_nameid), (int)z, 0, 0, LOG_TYPE_NPC); break; - case POINTSHOP: + case NPCTYPE_POINTSHOP: switch(nd->u.shop.pointshop_str[0]) { case '#': if (nd->u.shop.pointshop_str[1] == '#') @@ -1701,7 +1701,7 @@ int npc_buylist(struct map_session_data* sd, int n, unsigned short* item_list) } } - if (nd->subtype == POINTSHOP) { + if (nd->subtype == NPCTYPE_POINTSHOP) { sprintf(output,msg_txt(sd,716),nd->u.shop.pointshop_str,count - (int)z); // Your '%s' now: %d clif_disp_onlyself(sd,output,strlen(output)+1); } @@ -1782,7 +1782,7 @@ int npc_selllist(struct map_session_data* sd, int n, unsigned short* item_list) nullpo_retr(1, item_list); if( ( nd = npc_checknear(sd, map_id2bl(sd->npc_shopid)) ) == NULL - || ( nd->subtype != SHOP && nd->subtype != ITEMSHOP && nd->subtype != POINTSHOP ) ) + || ( nd->subtype != NPCTYPE_SHOP && nd->subtype != NPCTYPE_ITEMSHOP && nd->subtype != NPCTYPE_POINTSHOP ) ) { return 1; } @@ -1877,6 +1877,8 @@ int npc_remove_map(struct npc_data* nd) if(nd->bl.prev == NULL || nd->bl.m < 0) return 1; //Not assigned to a map. m = nd->bl.m; + if (nd->subtype == NPCTYPE_SCRIPT) + skill_clear_unitgroup(&nd->bl); clif_clearunit_area(&nd->bl,CLR_RESPAWN); npc_unsetcells(nd); map_delblock(&nd->bl); @@ -1955,9 +1957,9 @@ int npc_unload(struct npc_data* nd, bool single) { if( single && nd->bl.m != -1 ) map_remove_questinfo(nd->bl.m, nd); - if( (nd->subtype == SHOP || nd->subtype == CASHSHOP || nd->subtype == ITEMSHOP || nd->subtype == POINTSHOP) && nd->src_id == 0) //src check for duplicate shops [Orcao] + if( (nd->subtype == NPCTYPE_SHOP || nd->subtype == NPCTYPE_CASHSHOP || nd->subtype == NPCTYPE_ITEMSHOP || nd->subtype == NPCTYPE_POINTSHOP) && nd->src_id == 0) //src check for duplicate shops [Orcao] aFree(nd->u.shop.shop_item); - else if( nd->subtype == SCRIPT ) { + else if( nd->subtype == NPCTYPE_SCRIPT ) { struct s_mapiterator* iter; struct block_list* bl; @@ -2267,7 +2269,7 @@ struct npc_data* npc_add_warp(char* name, short from_mapid, short from_x, short nd->u.warp.xs = xs; nd->u.warp.ys = xs; nd->bl.type = BL_NPC; - nd->subtype = WARP; + nd->subtype = NPCTYPE_WARP; npc_setcells(nd); if(map_addblock(&nd->bl)) return NULL; @@ -2344,7 +2346,7 @@ static const char* npc_parse_warp(char* w1, char* w2, char* w3, char* w4, const nd->u.warp.ys = ys; npc_warp++; nd->bl.type = BL_NPC; - nd->subtype = WARP; + nd->subtype = NPCTYPE_WARP; npc_setcells(nd); if(map_addblock(&nd->bl)) //couldn't add on map return strchr(start,'\n'); @@ -2405,19 +2407,19 @@ static const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const } if( !strcasecmp(w2,"cashshop") ) - type = CASHSHOP; + type = NPCTYPE_CASHSHOP; else if( !strcasecmp(w2,"itemshop") ) - type = ITEMSHOP; + type = NPCTYPE_ITEMSHOP; else if( !strcasecmp(w2,"pointshop") ) - type = POINTSHOP; + type = NPCTYPE_POINTSHOP; else - type = SHOP; + type = NPCTYPE_SHOP; p = strchr(w4,','); memset(point_str,'\0',sizeof(point_str)); switch(type) { - case ITEMSHOP: { + case NPCTYPE_ITEMSHOP: { if (sscanf(p,",%hu:%d,",&nameid,&is_discount) < 1) { ShowError("npc_parse_shop: Invalid item cost definition in file '%s', line '%d'. Ignoring the rest of the line...\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4); return strchr(start,'\n'); // skip and continue @@ -2429,7 +2431,7 @@ static const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const p = strchr(p+1,','); break; } - case POINTSHOP: { + case NPCTYPE_POINTSHOP: { if (sscanf(p, ",%32[^,:]:%d,",point_str,&is_discount) < 1) { ShowError("npc_parse_shop: Invalid item cost definition in file '%s', line '%d'. Ignoring the rest of the line...\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4); return strchr(start,'\n'); // skip and continue @@ -2473,14 +2475,14 @@ static const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const continue; } if( value < 0 ) { - if( type == SHOP ) value = id->value_buy; + if( type == NPCTYPE_SHOP ) value = id->value_buy; else value = 0; // Cashshop doesn't have a "buy price" in the item_db } - if( (type == SHOP || type == ITEMSHOP || type == POINTSHOP) && value == 0 ) { // NPC selling items for free! + if( (type == NPCTYPE_SHOP || type == NPCTYPE_ITEMSHOP || type == NPCTYPE_POINTSHOP) && value == 0 ) { // NPC selling items for free! ShowWarning("npc_parse_shop: Item %s [%hu] is being sold for FREE in file '%s', line '%d'.\n", id->name, nameid2, filepath, strline(buffer,start-buffer)); } - if( type == SHOP && value*0.75 < id->value_sell*1.24 ) { // Exploit possible: you can buy and sell back with profit + if( type == NPCTYPE_SHOP && value*0.75 < id->value_sell*1.24 ) { // Exploit possible: you can buy and sell back with profit ShowWarning("npc_parse_shop: Item %s [%hu] discounted buying price (%d->%d) is less than overcharged selling price (%d->%d) at file '%s', line '%d'.\n", id->name, nameid2, value, (int)(value*0.75), id->value_sell, (int)(id->value_sell*1.24), filepath, strline(buffer,start-buffer)); } @@ -2504,9 +2506,9 @@ static const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const return strchr(start,'\n');// continue } - if (type != SHOP) { - if (type == ITEMSHOP) nd->u.shop.itemshop_nameid = nameid; // Item shop currency - else if (type == POINTSHOP) safestrncpy(nd->u.shop.pointshop_str,point_str,strlen(point_str)+1); // Point shop currency + if (type != NPCTYPE_SHOP) { + if (type == NPCTYPE_ITEMSHOP) nd->u.shop.itemshop_nameid = nameid; // Item shop currency + else if (type == NPCTYPE_POINTSHOP) safestrncpy(nd->u.shop.pointshop_str,point_str,strlen(point_str)+1); // Point shop currency nd->u.shop.discount = is_discount; } nd->bl.prev = nd->bl.next = NULL; @@ -2547,11 +2549,11 @@ static const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const * @return bool 'true' is discountable, 'false' otherwise */ bool npc_shop_discount(enum npc_subtype type, bool discount) { - if (type == SHOP || (type != SHOP && discount)) + if (type == NPCTYPE_SHOP || (type != NPCTYPE_SHOP && discount)) return true; - if( (type == ITEMSHOP && battle_config.discount_item_point_shop&1) || - (type == POINTSHOP && battle_config.discount_item_point_shop&2) ) + if( (type == NPCTYPE_ITEMSHOP && battle_config.discount_item_point_shop&1) || + (type == NPCTYPE_POINTSHOP && battle_config.discount_item_point_shop&2) ) return true; return false; } @@ -2754,7 +2756,7 @@ static const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, cons ++npc_script; nd->bl.type = BL_NPC; - nd->subtype = SCRIPT; + nd->subtype = NPCTYPE_SCRIPT; if( m >= 0 ) { @@ -2847,7 +2849,7 @@ const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const ch type = dnd->subtype; // get placement - if( (type == SHOP || type == CASHSHOP || type == ITEMSHOP || type == POINTSHOP || type == SCRIPT) && strcmp(w1, "-") == 0 ) {// floating shop/chashshop/itemshop/pointshop/script + if( (type == NPCTYPE_SHOP || type == NPCTYPE_CASHSHOP || type == NPCTYPE_ITEMSHOP || type == NPCTYPE_POINTSHOP || type == NPCTYPE_SCRIPT) && strcmp(w1, "-") == 0 ) {// floating shop/chashshop/itemshop/pointshop/script x = y = dir = 0; m = -1; } else { @@ -2864,9 +2866,9 @@ const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const ch ShowError("npc_parse_duplicate: coordinates %d/%d are out of bounds in map %s(%dx%d), in file '%s', line '%d'\n", x, y, map[m].name, map[m].xs, map[m].ys,filepath,strline(buffer,start-buffer)); } - if( type == WARP && sscanf(w4, "%d,%d", &xs, &ys) == 2 );// , - else if( type == SCRIPT && sscanf(w4, "%*[^,],%d,%d", &xs, &ys) == 2);// ,, - else if( type == WARP ) { + if( type == NPCTYPE_WARP && sscanf(w4, "%d,%d", &xs, &ys) == 2 );// , + else if( type == NPCTYPE_SCRIPT && sscanf(w4, "%*[^,],%d,%d", &xs, &ys) == 2);// ,, + else if( type == NPCTYPE_WARP ) { ShowError("npc_parse_duplicate: Invalid span format for duplicate warp in file '%s', line '%d'. Skipping line...\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4); return end;// next line, try to continue } @@ -2885,7 +2887,7 @@ const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const ch nd->bl.type = BL_NPC; nd->subtype = (enum npc_subtype)type; switch( type ) { - case SCRIPT: + case NPCTYPE_SCRIPT: ++npc_script; nd->u.scr.xs = xs; nd->u.scr.ys = ys; @@ -2894,16 +2896,16 @@ const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const ch nd->u.scr.label_list_num = dnd->u.scr.label_list_num; break; - case SHOP: - case CASHSHOP: - case ITEMSHOP: - case POINTSHOP: + case NPCTYPE_SHOP: + case NPCTYPE_CASHSHOP: + case NPCTYPE_ITEMSHOP: + case NPCTYPE_POINTSHOP: ++npc_shop; nd->u.shop.shop_item = dnd->u.shop.shop_item; nd->u.shop.count = dnd->u.shop.count; break; - case WARP: + case NPCTYPE_WARP: ++npc_warp; if( !battle_config.warp_point_debug ) nd->class_ = WARP_CLASS; @@ -2937,7 +2939,7 @@ const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const ch } strdb_put(npcname_db, nd->exname, nd); - if( type != SCRIPT ) + if( type != NPCTYPE_SCRIPT ) return end; //----------------------------------------- @@ -2970,7 +2972,7 @@ int npc_duplicate4instance(struct npc_data *snd, int16 m) { return 1; } - if( snd->subtype == WARP ) { // Adjust destination, if instanced + if( snd->subtype == NPCTYPE_WARP ) { // Adjust destination, if instanced struct npc_data *wnd = NULL; // New NPC struct instance_data *im = &instance_data[map[m].instance_id]; int dm = map_mapindex2mapid(snd->u.warp.mapindex), imap = 0, i; @@ -3007,7 +3009,7 @@ int npc_duplicate4instance(struct npc_data *snd, int16 m) { wnd->u.warp.xs = snd->u.warp.xs; wnd->u.warp.ys = snd->u.warp.ys; wnd->bl.type = BL_NPC; - wnd->subtype = WARP; + wnd->subtype = NPCTYPE_WARP; npc_setcells(wnd); if(map_addblock(&wnd->bl)) return 1; @@ -3057,11 +3059,11 @@ void npc_setcells(struct npc_data* nd) switch(nd->subtype) { - case WARP: + case NPCTYPE_WARP: xs = nd->u.warp.xs; ys = nd->u.warp.ys; break; - case SCRIPT: + case NPCTYPE_SCRIPT: xs = nd->u.scr.xs; ys = nd->u.scr.ys; break; @@ -3095,7 +3097,7 @@ void npc_unsetcells(struct npc_data* nd) int16 m = nd->bl.m, x = nd->bl.x, y = nd->bl.y, xs, ys; int i,j, x0, x1, y0, y1; - if (nd->subtype == WARP) { + if (nd->subtype == NPCTYPE_WARP) { xs = nd->u.warp.xs; ys = nd->u.warp.ys; } else { @@ -4167,7 +4169,7 @@ void do_final_npc(void) { static void npc_debug_warps_sub(struct npc_data* nd) { int16 m; - if (nd->bl.type != BL_NPC || nd->subtype != WARP || nd->bl.m < 0) + if (nd->bl.type != BL_NPC || nd->subtype != NPCTYPE_WARP || nd->bl.m < 0) return; m = map_mapindex2mapid(nd->u.warp.mapindex); @@ -4256,7 +4258,7 @@ void do_init_npc(void){ npc_script++; fake_nd->bl.type = BL_NPC; - fake_nd->subtype = SCRIPT; + fake_nd->subtype = NPCTYPE_SCRIPT; strdb_put(npcname_db, fake_nd->exname, fake_nd); fake_nd->u.scr.timerid = INVALID_TIMER; diff --git a/src/map/pc_groups.c b/src/map/pc_groups.c index 2dacf88623..c5f79c04e3 100644 --- a/src/map/pc_groups.c +++ b/src/map/pc_groups.c @@ -467,6 +467,4 @@ void pc_groups_reload(void) { pc_group_pc_load(sd); } mapit_free(iter); - - } diff --git a/src/map/script.c b/src/map/script.c index ad5eaf332c..fdf4ef9bbd 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -11814,7 +11814,7 @@ BUILDIN_FUNC(flagemblem) nd = (TBL_NPC*)map_id2nd(st->oid); if( nd == NULL ) { ShowError("script:flagemblem: npc %d not found\n", st->oid); - } else if( nd->subtype != SCRIPT ) { + } else if( nd->subtype != NPCTYPE_SCRIPT ) { ShowError("script:flagemblem: unexpected subtype %d for npc %d '%s'\n", nd->subtype, st->oid, nd->exname); } else { bool changed = ( nd->u.scr.guild_id != g_id )?true:false; @@ -13242,10 +13242,9 @@ BUILDIN_FUNC(nude) } int atcommand_sub(struct script_state* st,int type) { - TBL_PC dummy_sd; - TBL_PC* sd; + TBL_PC *sd, dummy_sd; int fd; - const char* cmd; + const char *cmd; cmd = script_getstr(st,2); @@ -13257,19 +13256,23 @@ int atcommand_sub(struct script_state* st,int type) { fd = 0; memset(&dummy_sd, 0, sizeof(TBL_PC)); - if (st->oid) - { + if (st->oid) { struct block_list* bl = map_id2bl(st->oid); memcpy(&dummy_sd.bl, bl, sizeof(struct block_list)); if (bl->type == BL_NPC) safestrncpy(dummy_sd.status.name, ((TBL_NPC*)bl)->name, NAME_LENGTH); + sd->mapindex = (bl->m > 0) ? bl->m : mapindex_name2id(MAP_DEFAULT); } + + // Init Group ID, Level, & permissions + sd->group_id = sd->group_level = 99; + sd->permissions |= PC_PERM_ALLPERMISSION; } if (!is_atcommand(fd, sd, cmd, type)) { - ShowWarning("script: buildin_atcommand: failed to execute command '%s'\n", cmd); + ShowWarning("buildin_atcommand: failed to execute command '%s'\n", cmd); script_reportsrc(st); - return 1; + return SCRIPT_CMD_FAILURE; } return SCRIPT_CMD_SUCCESS; } @@ -15473,14 +15476,14 @@ BUILDIN_FUNC(callshop) if( script_hasdata(st,3) ) flag = script_getnum(st,3); nd = npc_name2id(shopname); - if( !nd || nd->bl.type != BL_NPC || (nd->subtype != SHOP && nd->subtype != CASHSHOP && nd->subtype != ITEMSHOP && nd->subtype != POINTSHOP) ) + if( !nd || nd->bl.type != BL_NPC || (nd->subtype != NPCTYPE_SHOP && nd->subtype != NPCTYPE_CASHSHOP && nd->subtype != NPCTYPE_ITEMSHOP && nd->subtype != NPCTYPE_POINTSHOP) ) { ShowError("buildin_callshop: Shop [%s] not found (or NPC is not shop type)\n", shopname); script_pushint(st,0); return 1; } - if( nd->subtype == SHOP || nd->subtype == ITEMSHOP || nd->subtype == POINTSHOP ) + if( nd->subtype == NPCTYPE_SHOP || nd->subtype == NPCTYPE_ITEMSHOP || nd->subtype == NPCTYPE_POINTSHOP ) { // flag the user as using a valid script call for opening the shop (for floating NPCs) sd->state.callshop = 1; @@ -15507,7 +15510,7 @@ BUILDIN_FUNC(npcshopitem) int n, i; int amount; - if( !nd || ( nd->subtype != SHOP && nd->subtype != CASHSHOP && nd->subtype != ITEMSHOP && nd->subtype != POINTSHOP ) ) + if( !nd || ( nd->subtype != NPCTYPE_SHOP && nd->subtype != NPCTYPE_CASHSHOP && nd->subtype != NPCTYPE_ITEMSHOP && nd->subtype != NPCTYPE_POINTSHOP ) ) { //Not found. script_pushint(st,0); return 0; @@ -15536,7 +15539,7 @@ BUILDIN_FUNC(npcshopadditem) int n, i; int amount; - if( !nd || ( nd->subtype != SHOP && nd->subtype != CASHSHOP && nd->subtype != ITEMSHOP && nd->subtype != POINTSHOP ) ) + if( !nd || ( nd->subtype != NPCTYPE_SHOP && nd->subtype != NPCTYPE_CASHSHOP && nd->subtype != NPCTYPE_ITEMSHOP && nd->subtype != NPCTYPE_POINTSHOP ) ) { //Not found. script_pushint(st,0); return 0; @@ -15567,7 +15570,7 @@ BUILDIN_FUNC(npcshopdelitem) int amount; int size; - if( !nd || ( nd->subtype != SHOP && nd->subtype != CASHSHOP && nd->subtype != ITEMSHOP && nd->subtype != POINTSHOP ) ) + if( !nd || ( nd->subtype != NPCTYPE_SHOP && nd->subtype != NPCTYPE_CASHSHOP && nd->subtype != NPCTYPE_ITEMSHOP && nd->subtype != NPCTYPE_POINTSHOP ) ) { //Not found. script_pushint(st,0); return 0; @@ -15606,7 +15609,7 @@ BUILDIN_FUNC(npcshopattach) if( script_hasdata(st,3) ) flag = script_getnum(st,3); - if( !nd || ( nd->subtype != SHOP && nd->subtype != CASHSHOP && nd->subtype != ITEMSHOP && nd->subtype != POINTSHOP ) ) + if( !nd || ( nd->subtype != NPCTYPE_SHOP && nd->subtype != NPCTYPE_CASHSHOP && nd->subtype != NPCTYPE_ITEMSHOP && nd->subtype != NPCTYPE_POINTSHOP ) ) { //Not found. script_pushint(st,0); return 0; @@ -16426,7 +16429,7 @@ BUILDIN_FUNC(getvariableofnpc) } nd = npc_name2id(script_getstr(st,3)); - if( nd == NULL || nd->subtype != SCRIPT || nd->u.scr.script == NULL ) + if( nd == NULL || nd->subtype != NPCTYPE_SCRIPT || nd->u.scr.script == NULL ) {// NPC not found or has no script ShowError("script:getvariableofnpc: can't find npc %s\n", script_getstr(st,3)); script_pushnil(st); @@ -16455,10 +16458,9 @@ BUILDIN_FUNC(warpportal) struct block_list* bl; bl = map_id2bl(st->oid); - if( bl == NULL ) - { - ShowError("script:warpportal: npc is needed\n"); - return 1; + if( bl == NULL ) { + ShowError("buildin_warpportal: NPC is needed\n"); + return SCRIPT_CMD_FAILURE; } spx = script_getnum(st,2); @@ -16467,12 +16469,14 @@ BUILDIN_FUNC(warpportal) tpx = script_getnum(st,5); tpy = script_getnum(st,6); - if( mapindex == 0 ) - return 0;// map not found + if( mapindex == 0 ) { + ShowError("buildin_warpportal: Target map not found %s.\n", script_getstr(st, 4)); + return SCRIPT_CMD_FAILURE; + } group = skill_unitsetting(bl, AL_WARP, 4, spx, spy, 0); if( group == NULL ) - return 0;// failed + return SCRIPT_CMD_FAILURE;// failed group->val1 = (group->val1<<16)|(short)0; group->val2 = (tpx<<16) | tpy; group->val3 = mapindex; diff --git a/src/map/status.c b/src/map/status.c index 4d8fb1235d..bcc88a717b 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -6734,7 +6734,7 @@ int status_get_guild_id(struct block_list *bl) return ((TBL_MER*)bl)->master->status.guild_id; break; case BL_NPC: - if (((TBL_NPC*)bl)->subtype == SCRIPT) + if (((TBL_NPC*)bl)->subtype == NPCTYPE_SCRIPT) return ((TBL_NPC*)bl)->u.scr.guild_id; break; case BL_SKILL: @@ -6781,7 +6781,7 @@ int status_get_emblem_id(struct block_list *bl) return ((TBL_MER*)bl)->master->guild_emblem_id; break; case BL_NPC: - if (((TBL_NPC*)bl)->subtype == SCRIPT && ((TBL_NPC*)bl)->u.scr.guild_id > 0) { + if (((TBL_NPC*)bl)->subtype == NPCTYPE_SCRIPT && ((TBL_NPC*)bl)->u.scr.guild_id > 0) { struct guild *g = guild_search(((TBL_NPC*)bl)->u.scr.guild_id); if (g) return g->emblem_id; diff --git a/src/map/unit.h b/src/map/unit.h index 45cf12f34d..1655ab00b8 100644 --- a/src/map/unit.h +++ b/src/map/unit.h @@ -18,7 +18,7 @@ extern const short dirx[8]; ///lookup to know where will move to x according dir extern const short diry[8]; ///lookup to know where will move to y according dir struct unit_data { - struct block_list *bl; ///link to owner object BL_CHAR (BL_PC|BL_HOM|BL_PET|BL_ELE|BL_MER) + struct block_list *bl; ///link to owner object BL_PC|BL_MOB|BL_PET|BL_NPC|BL_HOM|BL_MER|BL_ELEM struct walkpath_data walkpath; struct skill_timerskill *skilltimerskill[MAX_SKILLTIMERSKILL]; struct skill_unit_group *skillunit[MAX_SKILLUNITGROUP]; diff --git a/src/map/vending.c b/src/map/vending.c index c43937994a..87f017151d 100755 --- a/src/map/vending.c +++ b/src/map/vending.c @@ -297,6 +297,7 @@ void vending_purchasereq(struct map_session_data* sd, int aid, int uid, const ui * @param data : itemlist data \n * data := {.w .w .l}[count] * @param count : number of different items + * @return 0 If success, 1 - Cannot open (die, not state.prevend, trading), 2 - No cart, 3 - Count issue, 4 - Cart data isn't saved yet, 5 - No valid item found */ char vending_openvending(struct map_session_data* sd, const char* message, const uint8* data, int count) { int i, j;