diff options
Diffstat (limited to 'src/map')
55 files changed, 3032 insertions, 2150 deletions
diff --git a/src/map/Makefile.in b/src/map/Makefile.in index 60d87522e..b5a3d4461 100644 --- a/src/map/Makefile.in +++ b/src/map/Makefile.in @@ -116,13 +116,13 @@ map-server: ../../map-server@EXEEXT@ ../../map-server@EXEEXT@: $(MAP_SERVER_SQL_DEPENDS) Makefile @echo " LD $(notdir $@)" @$(CC) @STATIC@ @LDFLAGS@ -o ../../map-server@EXEEXT@ $(MAP_OBJ) $(COMMON_D)/obj_sql/common_sql.a \ - $(COMMON_D)/obj_all/common.a $(MT19937AR_OBJ) $(LIBCONFIG_OBJ) @LIBS@ @PCRE_LIBS@ @MYSQL_LIBS@ + $(COMMON_D)/obj_all/common.a $(MT19937AR_OBJ) $(LIBCONFIG_OBJ) @LIBS@ @MYSQL_LIBS@ # map object files obj_sql/%.o: %.c $(MAP_H) $(COMMON_H) $(CONFIG_H) $(MT19937AR_H) $(LIBCONFIG_H) | obj_sql @echo " CC $<" - @$(CC) @CFLAGS@ @DEFS@ $(COMMON_INCLUDE) $(THIRDPARTY_INCLUDE) @PCRE_CFLAGS@ @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $< + @$(CC) @CFLAGS@ @DEFS@ $(COMMON_INCLUDE) $(THIRDPARTY_INCLUDE) @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $< # missing object files $(COMMON_D)/obj_all/common.a: diff --git a/src/map/atcommand.c b/src/map/atcommand.c index 9d03dd057..e422a5de4 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -223,8 +223,8 @@ ACMD(send) // 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) + || !((sscanf(message, "len %x", (unsigned int*)&type)==1 && (len=1, true)) + || sscanf(message, "%x", (unsigned int*)&type)==1) ) { clif->message(fd, msg_fd(fd,900)); // Usage: clif->message(fd, msg_fd(fd,901)); // @send len <packet hex number> @@ -252,7 +252,7 @@ ACMD(send) } while(0) //define SKIP_VALUE #define GET_VALUE(p,num) do { \ - if(sscanf((p), "x%lx", &(num)) < 1 && sscanf((p), "%ld ", &(num)) < 1){\ + if(sscanf((p), "x%lx", (long unsigned int*)&(num)) < 1 && sscanf((p), "%ld ", &(num)) < 1){\ PARSE_ERROR("Invalid number in:",(p));\ return false;\ }\ @@ -260,24 +260,28 @@ ACMD(send) if (type >= MIN_PACKET_DB && type <= MAX_PACKET_DB) { int off = 2; + if (clif->packet(type) == NULL) { + // 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; + } + 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) { + + if (len == -1) { // dynamic packet len = SHRT_MAX-4; // maximum length off = 4; } + WFIFOHEAD(sd->fd, len); WFIFOW(sd->fd,0)=TOW(type); @@ -543,7 +547,7 @@ ACMD(jumpto) { return false; } - if((pl_sd=map->nick2sd((char *)message)) == NULL && (pl_sd=map->charid2sd(atoi(message))) == NULL) { + if((pl_sd=map->nick2sd((const char *)message)) == NULL && (pl_sd=map->charid2sd(atoi(message))) == NULL) { clif->message(fd, msg_fd(fd,3)); // Character not found. return false; } @@ -2268,11 +2272,11 @@ ACMD(gat) { for (y = 2; y >= -2; y--) { safesnprintf(atcmd_output, sizeof(atcmd_output), "%s (x= %d, y= %d) %02X %02X %02X %02X %02X", map->list[sd->bl.m].name, sd->bl.x - 2, sd->bl.y + y, - map->getcell(sd->bl.m, &sd->bl, sd->bl.x - 2, sd->bl.y + y, CELL_GETTYPE), - map->getcell(sd->bl.m, &sd->bl, sd->bl.x - 1, sd->bl.y + y, CELL_GETTYPE), - map->getcell(sd->bl.m, &sd->bl, sd->bl.x, sd->bl.y + y, CELL_GETTYPE), - map->getcell(sd->bl.m, &sd->bl, sd->bl.x + 1, sd->bl.y + y, CELL_GETTYPE), - map->getcell(sd->bl.m, &sd->bl, sd->bl.x + 2, sd->bl.y + y, CELL_GETTYPE)); + (unsigned int)map->getcell(sd->bl.m, &sd->bl, sd->bl.x - 2, sd->bl.y + y, CELL_GETTYPE), + (unsigned int)map->getcell(sd->bl.m, &sd->bl, sd->bl.x - 1, sd->bl.y + y, CELL_GETTYPE), + (unsigned int)map->getcell(sd->bl.m, &sd->bl, sd->bl.x, sd->bl.y + y, CELL_GETTYPE), + (unsigned int)map->getcell(sd->bl.m, &sd->bl, sd->bl.x + 1, sd->bl.y + y, CELL_GETTYPE), + (unsigned int)map->getcell(sd->bl.m, &sd->bl, sd->bl.x + 2, sd->bl.y + y, CELL_GETTYPE)); clif->message(fd, atcmd_output); } @@ -2743,7 +2747,7 @@ ACMD(recall) { return false; } - if((pl_sd=map->nick2sd((char *)message)) == NULL && (pl_sd=map->charid2sd(atoi(message))) == NULL) { + if((pl_sd=map->nick2sd((const char *)message)) == NULL && (pl_sd=map->charid2sd(atoi(message))) == NULL) { clif->message(fd, msg_fd(fd,3)); // Character not found. return false; } @@ -3068,7 +3072,7 @@ ACMD(kick) return false; } - if((pl_sd=map->nick2sd((char *)message)) == NULL && (pl_sd=map->charid2sd(atoi(message))) == NULL) { + if((pl_sd=map->nick2sd((const char *)message)) == NULL && (pl_sd=map->charid2sd(atoi(message))) == NULL) { clif->message(fd, msg_fd(fd,3)); // Character not found. return false; } @@ -3609,16 +3613,16 @@ ACMD(reloadskilldb) * @reloadatcommand - reloads conf/atcommand.conf conf/groups.conf *------------------------------------------*/ ACMD(reloadatcommand) { - config_t run_test; + struct config_t run_test; - if (libconfig->read_file(&run_test, "conf/groups.conf")) { + if (!libconfig->load_file(&run_test, "conf/groups.conf")) { clif->message(fd, msg_fd(fd,1036)); // Error reading groups.conf, reload failed. return false; } libconfig->destroy(&run_test); - if (libconfig->read_file(&run_test, map->ATCOMMAND_CONF_FILENAME)) { + if (!libconfig->load_file(&run_test, map->ATCOMMAND_CONF_FILENAME)) { clif->message(fd, msg_fd(fd,1037)); // Error reading atcommand.conf, reload failed. return false; } @@ -3639,6 +3643,8 @@ ACMD(reloadbattleconf) memcpy(&prev_config, &battle_config, sizeof(prev_config)); battle->config_read(map->BATTLE_CONF_FILENAME); + if (prev_config.feature_roulette == 0 && battle_config.feature_roulette == 1 && !clif->parse_roulette_db()) + battle_config.feature_roulette = 0; if( prev_config.item_rate_mvp != battle_config.item_rate_mvp || prev_config.item_rate_common != battle_config.item_rate_common @@ -3917,7 +3923,7 @@ ACMD(mapinfo) strcat(atcmd_output, msg_fd(fd,1096)); // PartyLock | if (map->list[m_id].flag.guildlock) strcat(atcmd_output, msg_fd(fd,1097)); // GuildLock | - if (map->list[m_id].flag.noviewid) + if (map->list[m_id].flag.noviewid != EQP_NONE) strcat(atcmd_output, msg_fd(fd,1079)); // NoViewID | clif->message(fd, atcmd_output); @@ -5119,7 +5125,7 @@ ACMD(follow) { return true; } - if ((pl_sd = map->nick2sd((char *)message)) == NULL) + if ((pl_sd = map->nick2sd((const char *)message)) == NULL) { clif->message(fd, msg_fd(fd,3)); // Character not found. return false; @@ -5258,7 +5264,7 @@ ACMD(clearcart) for( i = 0; i < MAX_CART; i++ ) if(sd->status.cart[i].nameid > 0) - pc->cart_delitem(sd, i, sd->status.cart[i].amount, 1, LOG_TYPE_OTHER); + pc->cart_delitem(sd, i, sd->status.cart[i].amount, 1, LOG_TYPE_COMMAND); clif->clearcart(fd); clif->updatestatus(sd,SP_CARTINFO); @@ -5597,7 +5603,7 @@ ACMD(changegm) { return false; } - if ((pl_sd=map->nick2sd((char *) message)) == NULL || pl_sd->status.guild_id != sd->status.guild_id) { + if ((pl_sd=map->nick2sd((const char *) message)) == NULL || pl_sd->status.guild_id != sd->status.guild_id) { clif->message(fd, msg_fd(fd,1184)); // Target character must be online and be a guild member. return false; } @@ -5617,7 +5623,7 @@ ACMD(changeleader) { return false; } - if (party->changeleader(sd, map->nick2sd((char *) message))) + if (party->changeleader(sd, map->nick2sd((const char *) message))) return true; return false; } @@ -6376,7 +6382,7 @@ ACMD(trade) { return false; } - if ( (pl_sd = map->nick2sd((char *)message)) == NULL ) { + if ( (pl_sd = map->nick2sd((const char *)message)) == NULL ) { clif->message(fd, msg_fd(fd,3)); // Character not found. return false; } @@ -6419,7 +6425,7 @@ ACMD(unmute) { return false; } - if ((pl_sd = map->nick2sd((char *)message)) == NULL) + if ((pl_sd = map->nick2sd((const char *)message)) == NULL) { clif->message(fd, msg_fd(fd,3)); // Character not found. return false; @@ -7663,7 +7669,7 @@ ACMD(showdelay) *------------------------------------------*/ ACMD(invite) { unsigned int did = sd->duel_group; - struct map_session_data *target_sd = map->nick2sd((char *)message); + struct map_session_data *target_sd = map->nick2sd((const char *)message); if (did == 0) { @@ -7736,7 +7742,7 @@ ACMD(duel) { duel->create(sd, maxpl); } else { struct map_session_data *target_sd; - target_sd = map->nick2sd((char *)message); + target_sd = map->nick2sd((const char *)message); if (target_sd != NULL) { unsigned int newduel; if ((newduel = duel->create(sd, 2)) != -1) { @@ -7878,7 +7884,7 @@ ACMD(clone) { return false; } - if ((pl_sd=map->nick2sd((char *)message)) == NULL && (pl_sd=map->charid2sd(atoi(message))) == NULL) { + if ((pl_sd=map->nick2sd((const char *)message)) == NULL && (pl_sd=map->charid2sd(atoi(message))) == NULL) { clif->message(fd, msg_fd(fd,3)); // Character not found. return false; } @@ -7915,7 +7921,7 @@ ACMD(clone) { y = sd->bl.y; } - if ((x = mob->clone_spawn(pl_sd, sd->bl.m, x, y, "", master, 0, flag?1:0, 0)) > 0) { + if ((x = mob->clone_spawn(pl_sd, sd->bl.m, x, y, "", master, MD_NONE, flag?1:0, 0)) > 0) { clif->message(fd, msg_fd(fd,128+flag*2)); // Evil Clone spawned. Clone spawned. Slave clone spawned. return true; } @@ -8414,6 +8420,7 @@ ACMD(charcommands) atcommand->commands_sub(sd, fd, COMMAND_CHARCOMMAND); return true; } + /* for new mounts */ ACMD(cashmount) { @@ -8425,7 +8432,7 @@ ACMD(cashmount) clif->message(sd->fd,msg_fd(fd,1362)); // NOTICE: If you crash with mount your LUA is outdated. if (!sd->sc.data[SC_ALL_RIDING]) { clif->message(sd->fd,msg_fd(fd,1363)); // You have mounted. - sc_start(NULL,&sd->bl,SC_ALL_RIDING,100,0,-1); + sc_start(NULL, &sd->bl, SC_ALL_RIDING, 100, 25, INFINITE_DURATION); } else { clif->message(sd->fd,msg_fd(fd,1364)); // You have released your mount. status_change_end(&sd->bl, SC_ALL_RIDING, INVALID_TIMER); @@ -9294,7 +9301,7 @@ ACMD(costume){ return false; } - sc_start(NULL,&sd->bl, name2id[k], 100, 0, -1); + sc_start(NULL, &sd->bl, name2id[k], 100, 0, INFINITE_DURATION); return true; } @@ -9795,143 +9802,124 @@ void atcommand_get_suggestions(struct map_session_data* sd, const char *name, bo } /** - * Executes an at-command + * Executes an at-command. + * * @param fd fd associated to the invoking character * @param sd sd associated to the invoking character * @param message atcommand arguments * @param player_invoked true if the command was invoked by a player, false if invoked by the server (bypassing any restrictions) + * + * @retval true if the message was recognized as atcommand. + * @retval false if the message should be considered a non-command message. */ -bool atcommand_exec(const int fd, struct map_session_data *sd, const char *message, bool player_invoked) { - char charname[NAME_LENGTH], params[100]; - char charname2[NAME_LENGTH]; - char command[100]; +bool atcommand_exec(const int fd, struct map_session_data *sd, const char *message, bool player_invoked) +{ + char params[100], command[100]; char output[CHAT_SIZE_MAX]; - //Reconstructed message + // Reconstructed message char atcmd_msg[CHAT_SIZE_MAX]; struct map_session_data *ssd = NULL; //sd for target - AtCommandInfo * info; + AtCommandInfo *info; + + bool is_atcommand = true; // false if it's a charcommand nullpo_retr(false, sd); - //Shouldn't happen - if ( !message || !*message ) + // Shouldn't happen + if (message == NULL || *message == '\0') return false; - //Block NOCHAT but do not display it as a normal message + // Block NOCHAT but do not display it as a normal message if (pc_ismuted(&sd->sc, MANNER_NOCOMMAND)) return true; // skip 10/11-langtype's codepage indicator, if detected - if ( message[0] == '|' && strlen(message) >= 4 && (message[3] == atcommand->at_symbol || message[3] == atcommand->char_symbol) ) + if (message[0] == '|' && strlen(message) >= 4 && (message[3] == atcommand->at_symbol || message[3] == atcommand->char_symbol)) message += 3; - //Should display as a normal message - if ( *message != atcommand->at_symbol && *message != atcommand->char_symbol ) + // Should display as a normal message + if (*message != atcommand->at_symbol && *message != atcommand->char_symbol) return false; if (player_invoked) { - //Commands are disabled on maps flagged as 'nocommand' - if ( map->list[sd->bl.m].nocommand && pc_get_group_level(sd) < map->list[sd->bl.m].nocommand ) { + // Commands are disabled on maps flagged as 'nocommand' + if (map->list[sd->bl.m].nocommand && pc_get_group_level(sd) < map->list[sd->bl.m].nocommand) { clif->message(fd, msg_fd(fd,143)); return false; } } - if (*message == atcommand->char_symbol) { - do { - char params2[100]; - int x, y, z; - - //Checks to see if #command has a name or a name + parameters. - x = sscanf(message, "%99s \"%23[^\"]\" %99[^\n]", command, charname, params); - y = sscanf(message, "%99s %23s %99[^\n]", command, charname2, params2); + if (*message == atcommand->char_symbol) + is_atcommand = false; - //z always has the value of the scan that was successful - z = ( x > 1 ) ? x : y; - - //#command + name means the sufficient target was used and anything else after - //can be looked at by the actual command function since most scan to see if the - //right parameters are used. - if ( x > 2 ) { - sprintf(atcmd_msg, "%s %s", command, params); - break; - } - else if ( y > 2 ) { - sprintf(atcmd_msg, "%s %s", command, params2); - break; - } - //Regardless of what style the #command is used, if it's correct, it will always have - //this value if there is no parameter. Send it as just the #command - else if ( z == 2 ) { - sprintf(atcmd_msg, "%s", command); - break; - } + if (is_atcommand) { // #command + sprintf(atcmd_msg, "%s", message); + ssd = sd; + } else { // @command + char charname[NAME_LENGTH]; + int n; + + // Checks to see if #command has a name or a name + parameters. + if ((n = sscanf(message, "%99s \"%23[^\"]\" %99[^\n]", command, charname, params)) < 2 + && (n = sscanf(message, "%99s %23s %99[^\n]", command, charname, params)) < 2 + ) { + if (pc_get_group_level(sd) == 0) { + if (n < 1) + return false; // no command found. Display as normal message - if( !pc_get_group_level(sd) ) { - if( x >= 1 || y >= 1 ) { /* we have command */ - info = atcommand->get_info_byname(atcommand->check_alias(command + 1)); - if( !info || info->char_groups[pcg->get_idx(sd->group)] == 0 ) /* if we can't use or doesn't exist: don't even display the command failed message */ - return false; - } else - return false;/* display as normal message */ + info = atcommand->get_info_byname(atcommand->check_alias(command + 1)); + if (info == NULL || info->char_groups[pcg->get_idx(sd->group)] == 0) { + /* if we can't use or doesn't exist: don't even display the command failed message */ + return false; + } } sprintf(output, msg_fd(fd,1388), atcommand->char_symbol); // Charcommand failed (usage: %c<command> <char name> <parameters>). clif->message(fd, output); return true; - } while(0); - } - else /*if (*message == atcommand->at_symbol)*/ { - //atcmd_msg is constructed above differently for charcommands - //it's copied from message if not a charcommand so it can - //pass through the rest of the code compatible with both symbols - sprintf(atcmd_msg, "%s", message); + } + + ssd = map->nick2sd(charname); + if (ssd == NULL) { + sprintf(output, msg_fd(fd,1389), command); // %s failed. Player not found. + clif->message(fd, output); + return true; + } + + if (n > 2) + sprintf(atcmd_msg, "%s %s", command, params); + else + sprintf(atcmd_msg, "%s", command); } pc->update_idle_time(sd, BCIDLE_ATCOMMAND); //Clearing these to be used once more. - memset(command, '\0', sizeof(command)); - memset(params, '\0', sizeof(params)); + memset(command, '\0', sizeof command); + memset(params, '\0', sizeof params); //check to see if any params exist within this command - if( sscanf(atcmd_msg, "%99s %99[^\n]", command, params) < 2 ) + if (sscanf(atcmd_msg, "%99s %99[^\n]", command, params) < 2) params[0] = '\0'; // @commands (script based) - if(player_invoked && atcommand->binding_count > 0) { - struct atcmd_binding_data * binding; - + if (player_invoked && atcommand->binding_count > 0) { // Get atcommand binding - binding = atcommand->get_bind_byname(command); + struct atcmd_binding_data *binding = atcommand->get_bind_byname(command); // Check if the binding isn't NULL and there is a NPC event, level of usage met, et cetera - if( binding != NULL - && binding->npc_event[0] + if (binding != NULL && binding->npc_event[0] != '\0' && ( - (*atcmd_msg == atcommand->at_symbol && pc_get_group_level(sd) >= binding->group_lv) - || (*atcmd_msg == atcommand->char_symbol && pc_get_group_level(sd) >= binding->group_lv_char) + (is_atcommand && pc_get_group_level(sd) >= binding->group_lv) + || (!is_atcommand && pc_get_group_level(sd) >= binding->group_lv_char) ) ) { - // Check if self or character invoking; if self == character invoked, then self invoke. - bool invokeFlag = ((*atcmd_msg == atcommand->at_symbol) ? 1 : 0); - - // Check if the command initiated is a character command - if (*message == atcommand->char_symbol - && (ssd = map->nick2sd(charname)) == NULL - && (ssd = map->nick2sd(charname2)) == NULL - ) { - sprintf(output, msg_fd(fd,1389), command); // %s failed. Player not found. - clif->message(fd, output); - return true; - } - - if( binding->log ) /* log only if this command should be logged [Ind/Hercules] */ + if (binding->log) /* log only if this command should be logged [Ind/Hercules] */ logs->atcommand(sd, atcmd_msg); - npc->do_atcmd_event((invokeFlag ? sd : ssd), command, params, binding->npc_event); + npc->do_atcmd_event(ssd, command, params, binding->npc_event); return true; } } @@ -9939,51 +9927,40 @@ bool atcommand_exec(const int fd, struct map_session_data *sd, const char *messa //Grab the command information and check for the proper GM level required to use it or if the command exists info = atcommand->get_info_byname(atcommand->check_alias(command + 1)); if (info == NULL) { - if( pc_get_group_level(sd) ) { // TODO: remove or replace with proper permission - sprintf(output, msg_fd(fd,153), command); // "%s is Unknown Command." - clif->message(fd, output); - atcommand->get_suggestions(sd, command + 1, *message == atcommand->at_symbol); - return true; - } else + if (pc_get_group_level(sd) == 0) // TODO: remove or replace with proper permission return false; + + sprintf(output, msg_fd(fd,153), command); // "%s is Unknown Command." + clif->message(fd, output); + atcommand->get_suggestions(sd, command + 1, is_atcommand); + return true; } if (player_invoked) { int i; - if ((*command == atcommand->at_symbol && info->at_groups[pcg->get_idx(sd->group)] == 0) || - (*command == atcommand->char_symbol && info->char_groups[pcg->get_idx(sd->group)] == 0) ) { + if ((is_atcommand && info->at_groups[pcg->get_idx(sd->group)] == 0) + || (!is_atcommand && info->char_groups[pcg->get_idx(sd->group)] == 0)) return false; - } - if( pc_isdead(sd) && pc_has_permission(sd,PC_PERM_DISABLE_CMD_DEAD) ) { + + if (pc_isdead(sd) && pc_has_permission(sd,PC_PERM_DISABLE_CMD_DEAD)) { clif->message(fd, msg_fd(fd,1393)); // You can't use commands while dead return true; } - for(i = 0; i < map->list[sd->bl.m].zone->disabled_commands_count; i++) { - if( info->func == map->list[sd->bl.m].zone->disabled_commands[i]->cmd ) { + for (i = 0; i < map->list[sd->bl.m].zone->disabled_commands_count; i++) { + if (info->func == map->list[sd->bl.m].zone->disabled_commands[i]->cmd) { if (pc_get_group_level(sd) < map->list[sd->bl.m].zone->disabled_commands[i]->group_lv) { clif->messagecolor_self(sd->fd, COLOR_RED, "This command is disabled in this area"); return true; - } else { - break;/* already found the matching command, no need to keep checking -- just go on */ } + break; /* already found the matching command, no need to keep checking -- just go on */ } } } - // Check if target is valid only if confirmed that player can use command. - if (*message == atcommand->char_symbol - && (ssd = map->nick2sd(charname)) == NULL - && (ssd = map->nick2sd(charname2)) == NULL - ) { - sprintf(output, msg_fd(fd,1389), command); // %s failed. Player not found. - clif->message(fd, output); - return true; - } - //Attempt to use the command - if ( (info->func(fd, (*atcmd_msg == atcommand->at_symbol) ? sd : ssd, command, params,info) != true) ) { + if ((info->func(fd, ssd, command, params,info) != true)) { #ifdef AUTOTRADE_PERSISTENCY - if( info->func == atcommand_autotrade ) /** autotrade deletes caster, so we got nothing more to do here **/ + if (info->func == atcommand_autotrade) /* autotrade deletes caster, so we got nothing more to do here */ return true; #endif sprintf(output,msg_fd(fd,154), command); // %s failed. @@ -9991,8 +9968,8 @@ bool atcommand_exec(const int fd, struct map_session_data *sd, const char *messa return true; } - if( info->log ) /* log only if this command should be logged [Ind/Hercules] */ - logs->atcommand(sd, *atcmd_msg == atcommand->at_symbol ? atcmd_msg : message); + if (info->log) /* log only if this command should be logged [Ind/Hercules] */ + logs->atcommand(sd, is_atcommand ? atcmd_msg : message); return true; } @@ -10001,13 +9978,13 @@ bool atcommand_exec(const int fd, struct map_session_data *sd, const char *messa * *------------------------------------------*/ void atcommand_config_read(const char* config_filename) { - config_t atcommand_config; - config_setting_t *aliases = NULL, *help = NULL, *nolog = NULL; + struct config_t atcommand_config; + struct config_setting_t *aliases = NULL, *help = NULL, *nolog = NULL; const char *symbol = NULL; int num_aliases = 0; nullpo_retv(config_filename); - if (libconfig->read_file(&atcommand_config, config_filename)) + if (!libconfig->load_file(&atcommand_config, config_filename)) return; // Command symbols @@ -10036,7 +10013,7 @@ void atcommand_config_read(const char* config_filename) { int count = libconfig->setting_length(aliases); for (i = 0; i < count; ++i) { - config_setting_t *command; + struct config_setting_t *command; const char *commandname = NULL; int j = 0, alias_count = 0; AtCommandInfo *commandinfo = NULL; @@ -10074,7 +10051,7 @@ void atcommand_config_read(const char* config_filename) { int count = libconfig->setting_length(nolog); for (i = 0; i < count; ++i) { - config_setting_t *command; + struct config_setting_t *command; const char *commandname = NULL; AtCommandInfo *commandinfo = NULL; @@ -10096,7 +10073,7 @@ void atcommand_config_read(const char* config_filename) { int i; for (i = 0; i < count; ++i) { - config_setting_t *command; + struct config_setting_t *command; const char *commandname; AtCommandInfo *commandinfo = NULL; @@ -10139,7 +10116,7 @@ static inline int atcommand_command_type2idx(AtCommandType type) * Loads permissions for groups to use commands. * */ -void atcommand_db_load_groups(GroupSettings **groups, config_setting_t **commands_, size_t sz) +void atcommand_db_load_groups(GroupSettings **groups, struct config_setting_t **commands_, size_t sz) { DBIterator *iter = db_iterator(atcommand->db); AtCommandInfo *atcmd; @@ -10152,7 +10129,7 @@ void atcommand_db_load_groups(GroupSettings **groups, config_setting_t **command CREATE(atcmd->char_groups, char, sz); for (i = 0; i < sz; i++) { GroupSettings *group = groups[i]; - config_setting_t *commands = commands_[i]; + struct config_setting_t *commands = commands_[i]; int result = 0; int idx = -1; @@ -10173,7 +10150,7 @@ void atcommand_db_load_groups(GroupSettings **groups, config_setting_t **command } if (commands != NULL) { - config_setting_t *cmd = NULL; + struct config_setting_t *cmd = NULL; // <commandname> : <bool> (only atcommand) if (config_setting_lookup_bool(commands, atcmd->command, &result) && result) { diff --git a/src/map/atcommand.h b/src/map/atcommand.h index 5c4acdf01..a4f9afce7 100644 --- a/src/map/atcommand.h +++ b/src/map/atcommand.h @@ -23,7 +23,6 @@ #include "map/pc_groups.h" #include "common/hercules.h" -#include "common/conf.h" #include "common/db.h" #include <stdarg.h> @@ -34,6 +33,7 @@ struct map_session_data; struct AtCommandInfo; struct block_list; +struct config_setting_t; /** * Defines @@ -110,7 +110,7 @@ struct atcommand_interface { bool (*create) (char *name, AtCommandFunc func); bool (*can_use) (struct map_session_data *sd, const char *command); bool (*can_use2) (struct map_session_data *sd, const char *command, AtCommandType type); - void (*load_groups) (GroupSettings **groups, config_setting_t **commands_, size_t sz); + void (*load_groups) (GroupSettings **groups, struct config_setting_t **commands_, size_t sz); AtCommandInfo* (*exists) (const char* name); bool (*msg_read) (const char *cfg_name, bool allow_override); void (*final_msg) (void); diff --git a/src/map/battle.c b/src/map/battle.c index 3b3ea2047..a7a6f4719 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -2717,15 +2717,16 @@ void battle_calc_skillratio_weapon_unknown(int *attack_type, struct block_list * * After this we apply bg/gvg reduction *------------------------------------------*/ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damage *d,int64 damage,uint16 skill_id,uint16 skill_lv) { - struct map_session_data *sd = NULL; - struct status_change *sc, *tsc; + struct map_session_data *s_sd, *t_sd; + struct status_change *s_sc, *sc; struct status_change_entry *sce; int div_, flag; nullpo_ret(bl); nullpo_ret(d); - sd = BL_CAST(BL_PC, bl); + s_sd = BL_CAST(BL_PC, src); + t_sd = BL_CAST(BL_PC, bl); div_ = d->div_; flag = d->flag; @@ -2735,22 +2736,22 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam return 0; if( battle_config.ksprotection && mob->ksprotected(src, bl) ) return 0; - if (sd != NULL) { + if (t_sd != NULL) { //Special no damage states - if(flag&BF_WEAPON && sd->special_state.no_weapon_damage) - damage -= damage * sd->special_state.no_weapon_damage / 100; + if(flag&BF_WEAPON && t_sd->special_state.no_weapon_damage) + damage -= damage * t_sd->special_state.no_weapon_damage / 100; - if(flag&BF_MAGIC && sd->special_state.no_magic_damage) - damage -= damage * sd->special_state.no_magic_damage / 100; + if(flag&BF_MAGIC && t_sd->special_state.no_magic_damage) + damage -= damage * t_sd->special_state.no_magic_damage / 100; - if(flag&BF_MISC && sd->special_state.no_misc_damage) - damage -= damage * sd->special_state.no_misc_damage / 100; + if(flag&BF_MISC && t_sd->special_state.no_misc_damage) + damage -= damage * t_sd->special_state.no_misc_damage / 100; if(!damage) return 0; } + s_sc = status->get_sc(src); sc = status->get_sc(bl); - tsc = status->get_sc(src); if( sc && sc->data[SC_INVINCIBLE] && !sc->data[SC_INVINCIBLEOFF] ) return 1; @@ -2838,7 +2839,7 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam } if( sc->data[SC__MAELSTROM] && (flag&BF_MAGIC) && skill_id && (skill->get_inf(skill_id)&INF_GROUND_SKILL) ) { // {(Maelstrom Skill LevelxAbsorbed Skill Level)+(Caster's Job/5)}/2 - int sp = (sc->data[SC__MAELSTROM]->val1 * skill_lv + (sd ? sd->status.job_level / 5 : 0)) / 2; + int sp = (sc->data[SC__MAELSTROM]->val1 * skill_lv + (t_sd ? t_sd->status.job_level / 5 : 0)) / 2; status->heal(bl, 0, sp, 3); d->dmg_lv = ATK_BLOCK; return 0; @@ -2916,7 +2917,7 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam if(sc->data[SC_DODGE_READY] && ( !sc->opt1 || sc->opt1 == OPT1_BURNING ) && (flag&BF_LONG || sc->data[SC_STRUP]) && rnd()%100 < 20) { - if (sd && pc_issit(sd)) pc->setstand(sd); //Stand it to dodge. + if (t_sd && pc_issit(t_sd)) pc->setstand(t_sd); //Stand it to dodge. clif->skill_nodamage(bl,bl,TK_DODGE,1,1); if (!sc->data[SC_COMBOATTACK]) sc_start4(src, bl, SC_COMBOATTACK, 100, TK_JUMPKICK, src->id, 1, 0, 2000); @@ -2987,13 +2988,12 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam #endif if( damage ) { - struct map_session_data *tsd = BL_CAST(BL_PC, src); if( sc->data[SC_DEEP_SLEEP] ) { damage += damage / 2; // 1.5 times more damage while in Deep Sleep. status_change_end(bl,SC_DEEP_SLEEP,INVALID_TIMER); } - if( tsd && sd && sc->data[SC_COLD] && flag&BF_WEAPON ){ - switch(tsd->status.weapon){ + if( s_sd && t_sd && sc->data[SC_COLD] && flag&BF_WEAPON ){ + switch(s_sd->status.weapon){ case W_MACE: case W_2HMACE: case W_1HAXE: @@ -3002,7 +3002,7 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam break; case W_MUSICAL: case W_WHIP: - if(!sd->state.arrow_atk) + if(!t_sd->state.arrow_atk) break; case W_BOW: case W_REVOLVER: @@ -3131,8 +3131,7 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam if( (sce = sc->data[SC_STONEHARDSKIN]) && flag&(BF_SHORT|BF_WEAPON) && damage > 0 ) { sce->val2 -= (int)cap_value(damage,INT_MIN,INT_MAX); if( src->type == BL_PC ) { - struct map_session_data *ssd = BL_CAST(BL_PC, src); - if (ssd && ssd->status.weapon != W_BOW) + if (s_sd && s_sd->status.weapon != W_BOW) skill->break_equip(src, EQP_WEAPON, 3000, BCT_SELF); } else skill->break_equip(src, EQP_WEAPON, 3000, BCT_SELF); @@ -3209,31 +3208,31 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam if( sc->data[SC__DEADLYINFECT] && flag&BF_SHORT && damage > 0 && rnd()%100 < 30 + 10 * sc->data[SC__DEADLYINFECT]->val1 && !is_boss(src) ) status->change_spread(bl, src); // Deadly infect attacked side - if (sd && damage > 0 && (sce = sc->data[SC_GENTLETOUCH_ENERGYGAIN]) != NULL) { + if (t_sd && damage > 0 && (sce = sc->data[SC_GENTLETOUCH_ENERGYGAIN]) != NULL) { if ( rnd() % 100 < sce->val2 ) - pc->addspiritball(sd, skill->get_time(MO_CALLSPIRITS, 1), pc->getmaxspiritball(sd, 0)); + pc->addspiritball(t_sd, skill->get_time(MO_CALLSPIRITS, 1), pc->getmaxspiritball(t_sd, 0)); } } //SC effects from caster side. - if (tsc && tsc->count) { - if( tsc->data[SC_INVINCIBLE] && !tsc->data[SC_INVINCIBLEOFF] ) + if (s_sc && s_sc->count) { + if( s_sc->data[SC_INVINCIBLE] && !s_sc->data[SC_INVINCIBLEOFF] ) damage += damage * 75 / 100; // [Epoque] if (bl->type == BL_MOB) { const struct mob_data *md = BL_UCCAST(BL_MOB, bl); int i; - if (((sce=tsc->data[SC_MANU_ATK]) != NULL && (flag&BF_WEAPON)) - || ((sce=tsc->data[SC_MANU_MATK]) != NULL && (flag&BF_MAGIC))) { + if (((sce=s_sc->data[SC_MANU_ATK]) != NULL && (flag&BF_WEAPON)) + || ((sce=s_sc->data[SC_MANU_MATK]) != NULL && (flag&BF_MAGIC))) { for (i = 0; i < ARRAYLENGTH(mob->manuk); i++) if (md->class_ == mob->manuk[i]) { damage += damage * sce->val1 / 100; break; } } - if (((sce=tsc->data[SC_SPL_ATK]) != NULL && (flag&BF_WEAPON)) - || ((sce=tsc->data[SC_SPL_MATK]) != NULL && (flag&BF_MAGIC))) { + if (((sce=s_sc->data[SC_SPL_ATK]) != NULL && (flag&BF_WEAPON)) + || ((sce=s_sc->data[SC_SPL_MATK]) != NULL && (flag&BF_MAGIC))) { for (i = 0; i < ARRAYLENGTH(mob->splendide); i++) if (md->class_ == mob->splendide[i]) { damage += damage * sce->val1 / 100; @@ -3241,31 +3240,30 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam } } } - if( tsc->data[SC_POISONINGWEAPON] ) { + if( s_sc->data[SC_POISONINGWEAPON] ) { struct status_data *tstatus = status->get_status_data(bl); - if ( !(flag&BF_SKILL) && (flag&BF_WEAPON) && damage > 0 && rnd()%100 < tsc->data[SC_POISONINGWEAPON]->val3 ) { + if ( !(flag&BF_SKILL) && (flag&BF_WEAPON) && damage > 0 && rnd()%100 < s_sc->data[SC_POISONINGWEAPON]->val3 ) { short rate = 100; - if ( tsc->data[SC_POISONINGWEAPON]->val1 == 9 ) // Oblivion Curse gives a 2nd success chance after the 1st one passes which is reducible. [Rytech] + if ( s_sc->data[SC_POISONINGWEAPON]->val1 == 9 ) // Oblivion Curse gives a 2nd success chance after the 1st one passes which is reducible. [Rytech] rate = 100 - tstatus->int_ * 4 / 5; - sc_start(src,bl,tsc->data[SC_POISONINGWEAPON]->val2,rate,tsc->data[SC_POISONINGWEAPON]->val1,skill->get_time2(GC_POISONINGWEAPON,1) - (tstatus->vit + tstatus->luk) / 2 * 1000); + sc_start(src,bl,s_sc->data[SC_POISONINGWEAPON]->val2,rate,s_sc->data[SC_POISONINGWEAPON]->val1,skill->get_time2(GC_POISONINGWEAPON,1) - (tstatus->vit + tstatus->luk) / 2 * 1000); } } - if( tsc->data[SC__DEADLYINFECT] && flag&BF_SHORT && damage > 0 && rnd()%100 < 30 + 10 * tsc->data[SC__DEADLYINFECT]->val1 && !is_boss(src) ) + if( s_sc->data[SC__DEADLYINFECT] && flag&BF_SHORT && damage > 0 && rnd()%100 < 30 + 10 * s_sc->data[SC__DEADLYINFECT]->val1 && !is_boss(src) ) status->change_spread(src, bl); - if (tsc->data[SC_SHIELDSPELL_REF] && tsc->data[SC_SHIELDSPELL_REF]->val1 == 1 && damage > 0) + if (s_sc->data[SC_SHIELDSPELL_REF] && s_sc->data[SC_SHIELDSPELL_REF]->val1 == 1 && damage > 0) skill->break_equip(bl,EQP_ARMOR,10000,BCT_ENEMY ); - if (tsc->data[SC_STYLE_CHANGE] && rnd()%2) { + if (s_sc->data[SC_STYLE_CHANGE] && rnd()%2) { struct homun_data *hd = BL_CAST(BL_HOM,bl); if (hd) homun->addspiritball(hd, 10); } - if (src->type == BL_PC && damage > 0 && (sce = tsc->data[SC_GENTLETOUCH_ENERGYGAIN]) != NULL) { - struct map_session_data *tsd = BL_UCAST(BL_PC, src); - if (tsd != NULL && rnd() % 100 < sce->val2) - pc->addspiritball(tsd, skill->get_time(MO_CALLSPIRITS, 1), pc->getmaxspiritball(tsd, 0)); + if (src->type == BL_PC && damage > 0 && (sce = s_sc->data[SC_GENTLETOUCH_ENERGYGAIN]) != NULL) { + if (s_sd != NULL && rnd() % 100 < sce->val2) + pc->addspiritball(s_sd, skill->get_time(MO_CALLSPIRITS, 1), pc->getmaxspiritball(s_sd, 0)); } } /* no data claims these settings affect anything other than players */ - if( damage && sd && bl->type == BL_PC ) { + if( damage && t_sd && bl->type == BL_PC ) { switch( skill_id ) { //case PA_PRESSURE: /* pressure also belongs to this list but it doesn't reach this area -- so don't worry about it */ case HW_GRAVITATION: @@ -3307,14 +3305,13 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam if (skill_id) mob->skill_event(md, src, timer->gettick(), MSC_SKILLUSED|(skill_id<<16)); } - if (sd && pc_ismadogear(sd) && rnd()%100 < 50) { + if (t_sd && pc_ismadogear(t_sd) && rnd()%100 < 50) { int element = -1; if (!skill_id || (element = skill->get_ele(skill_id, skill_lv)) == -1) { // Take weapon's element struct status_data *sstatus = NULL; - struct map_session_data *ssd = BL_CAST(BL_PC, src); - if (src->type == BL_PC && ssd->bonus.arrow_ele != 0) { - element = ssd->bonus.arrow_ele; + if (s_sd != NULL && s_sd->bonus.arrow_ele != 0) { + element = s_sd->bonus.arrow_ele; } else if ((sstatus = status->get_status_data(src)) != NULL) { element = sstatus->rhw.ele; } @@ -3326,9 +3323,9 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam element = rnd()%ELE_MAX; } if (element == ELE_FIRE) - pc->overheat(sd, 1); + pc->overheat(t_sd, 1); else if (element == ELE_WATER) - pc->overheat(sd, -1); + pc->overheat(t_sd, -1); } return damage; @@ -4118,7 +4115,8 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list * #else short totaldef = tstatus->def2 + (short)status->get_def(target); #endif - if ( sd ) wd.damage += sd->bonus.arrow_atk; + if (sd != NULL) + wd.damage += sd->bonus.arrow_atk; md.damage = (int)(3 * (1 + wd.damage) * (5 + skill_lv) / 5.0f); md.damage -= totaldef; @@ -4583,7 +4581,7 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list skill_id == NJ_KIRIKAGE)) { short cri = sstatus->cri; - if (sd) { + if (sd != NULL) { // if show_katar_crit_bonus is enabled, it already done the calculation in status.c if (!battle_config.show_katar_crit_bonus && sd->status.weapon == W_KATAR) { cri <<= 1; @@ -4782,12 +4780,10 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list //Assuming that 99% of the cases we will not need to check for the flag.rh... we don't. //ATK_RATE scales the damage. 100 = no change. 50 is halved, 200 is doubled, etc #define ATK_RATE( a ) do { int64 temp__ = (a); wd.damage= wd.damage*temp__/100 ; if(flag.lh) wd.damage2= wd.damage2*temp__/100; } while(0) -#define ATK_RATE2( a , b ) do { wd.damage= wd.damage*(a)/100 ; if(flag.lh) wd.damage2= wd.damage2*(b)/100; } while(0) #define ATK_RATER(a) ( wd.damage = wd.damage*(a)/100 ) #define ATK_RATEL(a) ( wd.damage2 = wd.damage2*(a)/100 ) //Adds dmg%. 100 = +100% (double) damage. 10 = +10% damage #define ATK_ADDRATE( a ) do { int64 temp__ = (a); wd.damage+= wd.damage*temp__/100; if(flag.lh) wd.damage2+= wd.damage2*temp__/100; } while(0) -#define ATK_ADDRATE2( a , b ) do { wd.damage+= wd.damage*(a)/100 ; if(flag.lh) wd.damage2+= wd.damage2*(b)/100; } while(0) //Adds an absolute value to damage. 100 = +100 damage #define ATK_ADD( a ) do { int64 temp__ = (a); wd.damage += temp__; if (flag.lh) wd.damage2 += temp__; } while(0) #define ATK_ADD2( a , b ) do { wd.damage += (a); if (flag.lh) wd.damage2 += (b); } while(0) @@ -6372,11 +6368,9 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t return wd.dmg_lv; } #undef ATK_RATE -#undef ATK_RATE2 #undef ATK_RATER #undef ATK_RATEL #undef ATK_ADDRATE -#undef ATK_ADDRATE2 #undef ATK_ADD #undef ATK_ADD2 #undef GET_NORMAL_ATTACK @@ -7382,19 +7376,19 @@ void Hercules_report(char* date, char *time_c) { WBUFW(buf,2) = 262 + ( bd_size * ( BFLAG_LENGTH + 4 ) ); WBUFW(buf,4) = 0x9f; - safestrncpy((char*)WBUFP(buf,6), date, 12); - safestrncpy((char*)WBUFP(buf,18), time_c, 9); - safestrncpy((char*)WBUFP(buf,27), timestring, 24); + safestrncpy(WBUFP(buf,6), date, 12); + safestrncpy(WBUFP(buf,18), time_c, 9); + safestrncpy(WBUFP(buf,27), timestring, 24); - safestrncpy((char*)WBUFP(buf,51), sysinfo->platform(), 16); - safestrncpy((char*)WBUFP(buf,67), sysinfo->osversion(), 50); - safestrncpy((char*)WBUFP(buf,117), sysinfo->cpu(), 32); + safestrncpy(WBUFP(buf,51), sysinfo->platform(), 16); + safestrncpy(WBUFP(buf,67), sysinfo->osversion(), 50); + safestrncpy(WBUFP(buf,117), sysinfo->cpu(), 32); WBUFL(buf,149) = sysinfo->cpucores(); - safestrncpy((char*)WBUFP(buf,153), sysinfo->arch(), 8); + safestrncpy(WBUFP(buf,153), sysinfo->arch(), 8); WBUFB(buf,161) = sysinfo->vcstypeid(); WBUFB(buf,162) = sysinfo->is64bit(); - safestrncpy((char*)WBUFP(buf,163), sysinfo->vcsrevision_src(), 41); - safestrncpy((char*)WBUFP(buf,204), sysinfo->vcsrevision_scripts(), 41); + safestrncpy(WBUFP(buf,163), sysinfo->vcsrevision_src(), 41); + safestrncpy(WBUFP(buf,204), sysinfo->vcsrevision_scripts(), 41); WBUFB(buf,245) = (sysinfo->is_superuser()? 1 : 0); WBUFL(buf,246) = map->getusers(); @@ -7403,7 +7397,7 @@ void Hercules_report(char* date, char *time_c) { WBUFL(buf,258) = bd_size; for( i = 0; i < bd_size; i++ ) { - safestrncpy((char*)WBUFP(buf,262 + ( i * ( BFLAG_LENGTH + 4 ) ) ), battle_data[i].str, BFLAG_LENGTH); + safestrncpy(WBUFP(buf,262 + ( i * ( BFLAG_LENGTH + 4 ) ) ), battle_data[i].str, BFLAG_LENGTH); WBUFL(buf,262 + BFLAG_LENGTH + ( i * ( BFLAG_LENGTH + 4 ) ) ) = *battle_data[i].val; } diff --git a/src/map/battleground.c b/src/map/battleground.c index e3fedbf34..311690ec3 100644 --- a/src/map/battleground.c +++ b/src/map/battleground.c @@ -330,18 +330,18 @@ enum bg_queue_types bg_str2teamtype (const char *str) { } void bg_config_read(void) { - config_t bg_conf; - config_setting_t *data = NULL; + struct config_t bg_conf; + struct config_setting_t *data = NULL; const char *config_filename = "conf/battlegrounds.conf"; // FIXME hardcoded name - if (libconfig->read_file(&bg_conf, config_filename)) + if (!libconfig->load_file(&bg_conf, config_filename)) return; data = libconfig->lookup(&bg_conf, "battlegrounds"); if (data != NULL) { - config_setting_t *settings = libconfig->setting_get_elem(data, 0); - config_setting_t *arenas; + struct config_setting_t *settings = libconfig->setting_get_elem(data, 0); + struct config_setting_t *arenas; const char *delay_var; int offline = 0; @@ -361,8 +361,8 @@ void bg_config_read(void) { int arena_count = libconfig->setting_length(arenas); CREATE( bg->arena, struct bg_arena *, arena_count ); for(i = 0; i < arena_count; i++) { - config_setting_t *arena = libconfig->setting_get_elem(arenas, i); - config_setting_t *reward; + struct config_setting_t *arena = libconfig->setting_get_elem(arenas, i); + struct config_setting_t *reward; const char *aName, *aEvent, *aDelayVar, *aTeamTypes; int minLevel = 0, maxLevel = 0; int prizeWin, prizeLoss, prizeDraw; @@ -495,7 +495,8 @@ void bg_config_read(void) { } libconfig->destroy(&bg_conf); } -struct bg_arena *bg_name2arena (char *name) { +struct bg_arena *bg_name2arena(const char *name) +{ int i; nullpo_retr(NULL, name); for(i = 0; i < bg->arenas; i++) { @@ -827,9 +828,9 @@ enum BATTLEGROUNDS_QUEUE_ACK bg_canqueue(struct map_session_data *sd, struct bg_ if ( ( tick = pc_readglobalreg(sd, script->add_str(bg->gdelay_var)) ) && tsec < tick ) { char response[100]; if( (tick-tsec) > 60 ) - sprintf(response, "You are a deserter! Wait %d minute(s) before you can apply again",(tick-tsec)/60); + sprintf(response, "You are a deserter! Wait %u minute(s) before you can apply again", (tick - tsec) / 60); else - sprintf(response, "You are a deserter! Wait %d seconds before you can apply again",(tick-tsec)); + sprintf(response, "You are a deserter! Wait %u seconds before you can apply again", (tick - tsec)); clif->messagecolor_self(sd->fd, COLOR_RED, response); return BGQA_FAIL_DESERTER; } @@ -837,9 +838,9 @@ enum BATTLEGROUNDS_QUEUE_ACK bg_canqueue(struct map_session_data *sd, struct bg_ if ( ( tick = pc_readglobalreg(sd, script->add_str(arena->delay_var)) ) && tsec < tick ) { char response[100]; if( (tick-tsec) > 60 ) - sprintf(response, "You can't reapply to this arena so fast. Apply to the different arena or wait %d minute(s)",(tick-tsec)/60); + sprintf(response, "You can't reapply to this arena so fast. Apply to the different arena or wait %u minute(s)", (tick - tsec) / 60); else - sprintf(response, "You can't reapply to this arena so fast. Apply to the different arena or wait %d seconds",(tick-tsec)); + sprintf(response, "You can't reapply to this arena so fast. Apply to the different arena or wait %u seconds", (tick - tsec)); clif->messagecolor_self(sd->fd, COLOR_RED, response); return BGQA_FAIL_COOLDOWN; } @@ -906,7 +907,7 @@ enum BATTLEGROUNDS_QUEUE_ACK bg_canqueue(struct map_session_data *sd, struct bg_ case BGQT_INDIVIDUAL:/* already did */ break; default: - ShowDebug("bg_canqueue: unknown/unsupported type %d\n",type); + ShowDebug("bg_canqueue: unknown/unsupported type %u\n", type); return BGQA_DUPLICATE_REQUEST; } return BGQA_SUCCESS; diff --git a/src/map/battleground.h b/src/map/battleground.h index 639d91635..bb77db125 100644 --- a/src/map/battleground.h +++ b/src/map/battleground.h @@ -108,7 +108,7 @@ struct battleground_interface { void (*init) (bool minimal); void (*final) (void); /* */ - struct bg_arena *(*name2arena) (char *name); + struct bg_arena *(*name2arena) (const char *name); void (*queue_add) (struct map_session_data *sd, struct bg_arena *arena, enum bg_queue_types type); enum BATTLEGROUNDS_QUEUE_ACK (*can_queue) (struct map_session_data *sd, struct bg_arena *arena, enum bg_queue_types type); int (*id2pos) (int queue_id, int account_id); diff --git a/src/map/channel.c b/src/map/channel.c index d778b355d..28ef854da 100644 --- a/src/map/channel.c +++ b/src/map/channel.c @@ -589,19 +589,19 @@ void channel_quit_guild(struct map_session_data *sd) void read_channels_config(void) { - config_t channels_conf; - config_setting_t *chsys = NULL; + struct config_t channels_conf; + struct config_setting_t *chsys = NULL; const char *config_filename = "conf/channels.conf"; // FIXME hardcoded name - if (libconfig->read_file(&channels_conf, config_filename)) + if (!libconfig->load_file(&channels_conf, config_filename)) return; chsys = libconfig->lookup(&channels_conf, "chsys"); if (chsys != NULL) { - config_setting_t *settings = libconfig->setting_get_elem(chsys, 0); - config_setting_t *channels; - config_setting_t *colors; + struct config_setting_t *settings = libconfig->setting_get_elem(chsys, 0); + struct config_setting_t *channels; + struct config_setting_t *colors; int i,k; const char *local_name, *ally_name, *local_color, *ally_color, @@ -710,7 +710,7 @@ void read_channels_config(void) CREATE(channel->config->colors, unsigned int, color_count); CREATE(channel->config->colors_name, char *, color_count); for(i = 0; i < color_count; i++) { - config_setting_t *color = libconfig->setting_get_elem(colors, i); + struct config_setting_t *color = libconfig->setting_get_elem(colors, i); CREATE(channel->config->colors_name[i], char, HCS_NAME_LENGTH); @@ -771,7 +771,7 @@ void read_channels_config(void) int channel_count = libconfig->setting_length(channels); for(i = 0; i < channel_count; i++) { - config_setting_t *chan = libconfig->setting_get_elem(channels, i); + struct config_setting_t *chan = libconfig->setting_get_elem(channels, i); const char *name = config_setting_name(chan); const char *color = libconfig->setting_get_string_elem(channels,i); @@ -792,7 +792,7 @@ void read_channels_config(void) } } - ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' channels in '"CL_WHITE"%s"CL_RESET"'.\n", db_size(channel->db), config_filename); + ShowStatus("Done reading '"CL_WHITE"%u"CL_RESET"' channels in '"CL_WHITE"%s"CL_RESET"'.\n", db_size(channel->db), config_filename); } libconfig->destroy(&channels_conf); } diff --git a/src/map/chrif.c b/src/map/chrif.c index 1f7fbe96e..70339c378 100644 --- a/src/map/chrif.c +++ b/src/map/chrif.c @@ -110,7 +110,9 @@ struct chrif_interface *chrif; #define chrif_check(a) do { if(!chrif->isconnected()) return a; } while(0) /// Resets all the data. -void chrif_reset(void) { +void chrif_reset(void) __attribute__ ((noreturn)); +void chrif_reset(void) +{ // TODO kick everyone out and reset everything [FlavioJS] exit(EXIT_FAILURE); } @@ -362,7 +364,7 @@ void chrif_recvmap(int fd) { } if (battle_config.etc_log) - ShowStatus("Received maps from %d.%d.%d.%d:%d (%d maps)\n", CONVIP(ip), port, j); + ShowStatus("Received maps from %u.%u.%u.%u:%u (%d maps)\n", CONVIP(ip), port, j); chrif->other_mapserver_count++; } @@ -379,7 +381,7 @@ void chrif_removemap(int fd) { chrif->other_mapserver_count--; if(battle_config.etc_log) - ShowStatus("remove map of server %d.%d.%d.%d:%d (%d maps)\n", CONVIP(ip), port, j); + ShowStatus("remove map of server %u.%u.%u.%u:%u (%d maps)\n", CONVIP(ip), port, j); } // received after a character has been "final saved" on the char-server @@ -592,7 +594,7 @@ void chrif_authok(int fd) { int account_id, group_id, char_id; uint32 login_id1,login_id2; time_t expiration_time; - struct mmo_charstatus* charstatus; + const struct mmo_charstatus *charstatus; struct auth_node *node; bool changing_mapservers; struct map_session_data *sd = NULL; @@ -609,7 +611,7 @@ void chrif_authok(int fd) { expiration_time = (time_t)(int32)RFIFOL(fd,16); group_id = RFIFOL(fd,20); changing_mapservers = (RFIFOB(fd,24)); - charstatus = (struct mmo_charstatus*)RFIFOP(fd,25); + charstatus = RFIFOP(fd,25); char_id = charstatus->char_id; //Check if we don't already have player data in our server @@ -794,7 +796,7 @@ bool chrif_char_ask_name(int acc, const char* character_name, unsigned short ope WFIFOHEAD(chrif->fd,44); WFIFOW(chrif->fd,0) = 0x2b0e; WFIFOL(chrif->fd,2) = acc; - safestrncpy((char*)WFIFOP(chrif->fd,6), character_name, NAME_LENGTH); + safestrncpy(WFIFOP(chrif->fd,6), character_name, NAME_LENGTH); WFIFOW(chrif->fd,30) = operation_type; if (operation_type == CHAR_ASK_NAME_BAN || operation_type == CHAR_ASK_NAME_CHARBAN) { @@ -825,7 +827,7 @@ bool chrif_changesex(struct map_session_data *sd, bool change_account) WFIFOHEAD(chrif->fd,44); WFIFOW(chrif->fd,0) = 0x2b0e; WFIFOL(chrif->fd,2) = sd->status.account_id; - safestrncpy((char*)WFIFOP(chrif->fd,6), sd->status.name, NAME_LENGTH); + safestrncpy(WFIFOP(chrif->fd,6), sd->status.name, NAME_LENGTH); WFIFOW(chrif->fd,30) = change_account ? CHAR_ASK_NAME_CHANGESEX : CHAR_ASK_NAME_CHANGECHARSEX; if (!change_account) WFIFOB(chrif->fd,32) = sd->status.sex == SEX_MALE ? SEX_FEMALE : SEX_MALE; @@ -931,14 +933,14 @@ bool chrif_divorceack(int char_id, int partner_id) { sd->status.partner_id = 0; for(i = 0; i < MAX_INVENTORY; i++) if (sd->status.inventory[i].nameid == WEDDING_RING_M || sd->status.inventory[i].nameid == WEDDING_RING_F) - pc->delitem(sd, i, 1, 0, DELITEM_NORMAL, LOG_TYPE_OTHER); + pc->delitem(sd, i, 1, 0, DELITEM_NORMAL, LOG_TYPE_DIVORCE); } if( ( sd = map->charid2sd(partner_id) ) != NULL && sd->status.partner_id == char_id ) { sd->status.partner_id = 0; for(i = 0; i < MAX_INVENTORY; i++) if (sd->status.inventory[i].nameid == WEDDING_RING_M || sd->status.inventory[i].nameid == WEDDING_RING_F) - pc->delitem(sd, i, 1, 0, DELITEM_NORMAL, LOG_TYPE_OTHER); + pc->delitem(sd, i, 1, 0, DELITEM_NORMAL, LOG_TYPE_DIVORCE); } return true; @@ -1171,8 +1173,9 @@ bool chrif_save_scdata(struct map_session_data *sd) { //parses the sc_data of th data.tick = DIFF_TICK32(td->tick,tick); //Duration that is left before ending. else data.tick = 0; //Negative tick does not necessarily mean that sc has expired - } else - data.tick = -1; //Infinite duration + } else { + data.tick = INFINITE_DURATION; + } data.type = i; data.val1 = sc->data[i]->val1; data.val2 = sc->data[i]->val2; @@ -1219,7 +1222,7 @@ bool chrif_load_scdata(int fd) { count = RFIFOW(fd,12); //sc_count for (i = 0; i < count; i++) { - struct status_change_data *data = (struct status_change_data*)RFIFOP(fd,14 + i*sizeof(struct status_change_data)); + const struct status_change_data *data = RFIFOP(fd,14 + i*sizeof(struct status_change_data)); status->change_start(NULL, &sd->bl, (sc_type)data->type, 10000, data->val1, data->val2, data->val3, data->val4, data->tick, SCFLAG_NOAVOID|SCFLAG_FIXEDTICK|SCFLAG_LOADED|SCFLAG_FIXEDRATE); } @@ -1394,23 +1397,23 @@ int chrif_parse(int fd) { } while (RFIFOREST(fd) >= 2) { + cmd = RFIFOW(fd,0); + if (VECTOR_LENGTH(HPM->packets[hpChrif_Parse]) > 0) { - int result = HPM->parse_packets(fd,hpChrif_Parse); + int result = HPM->parse_packets(fd,cmd,hpChrif_Parse); if (result == 1) continue; if (result == 2) return 0; } - cmd = RFIFOW(fd,0); - if (cmd < 0x2af8 || cmd >= 0x2af8 + ARRAYLENGTH(chrif->packet_len_table) || chrif->packet_len_table[cmd-0x2af8] == 0) { int result = intif->parse(fd); // Passed on to the intif if (result == 1) continue; // Treated in intif if (result == 2) return 0; // Didn't have enough data (len==-1) - ShowWarning("chrif_parse: session #%d, intif->parse failed (unrecognized command 0x%.4x).\n", fd, cmd); + ShowWarning("chrif_parse: session #%d, intif->parse failed (unrecognized command 0x%.4x).\n", fd, (unsigned int)cmd); sockt->eof(fd); return 0; } @@ -1434,10 +1437,10 @@ int chrif_parse(int fd) { case 0x2b03: clif->charselectok(RFIFOL(fd,2), RFIFOB(fd,6)); break; case 0x2b04: chrif->recvmap(fd); break; case 0x2b06: chrif->changemapserverack(RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10), RFIFOL(fd,14), RFIFOW(fd,18), RFIFOW(fd,20), RFIFOW(fd,22), RFIFOL(fd,24), RFIFOW(fd,28)); break; - case 0x2b09: map->addnickdb(RFIFOL(fd,2), (char*)RFIFOP(fd,6)); break; + case 0x2b09: map->addnickdb(RFIFOL(fd,2), RFIFOP(fd,6)); break; case 0x2b0a: sockt->datasync(fd, false); break; case 0x2b0d: chrif->changedsex(fd); break; - case 0x2b0f: chrif->char_ask_name_answer(RFIFOL(fd,2), (char*)RFIFOP(fd,6), RFIFOW(fd,30), RFIFOW(fd,32)); break; + case 0x2b0f: chrif->char_ask_name_answer(RFIFOL(fd,2), RFIFOP(fd,6), RFIFOW(fd,30), RFIFOW(fd,32)); break; case 0x2b12: chrif->divorceack(RFIFOL(fd,2), RFIFOL(fd,6)); break; case 0x2b14: chrif->idbanned(fd); break; case 0x2b1b: chrif->recvfamelist(fd); break; @@ -1451,7 +1454,7 @@ int chrif_parse(int fd) { case 0x2b25: chrif->deadopt(RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10)); break; case 0x2b27: chrif->authfail(fd); break; default: - ShowError("chrif_parse : unknown packet (session #%d): 0x%x. Disconnecting.\n", fd, cmd); + ShowError("chrif_parse : unknown packet (session #%d): 0x%x. Disconnecting.\n", fd, (unsigned int)cmd); sockt->eof(fd); return 0; } diff --git a/src/map/clif.c b/src/map/clif.c index 827f57c45..69d9b6779 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -198,22 +198,6 @@ static inline bool disguised(struct block_list* bl) return true; } -//Guarantees that the given string does not exceeds the allowed size, as well as making sure it's null terminated. [Skotlex] -static inline unsigned int mes_len_check(char* mes, unsigned int len, unsigned int max) { - nullpo_retr(0, mes); - if (len <= 0) - { - mes[0] = '\0'; - Assert_retr(0, len > 0); - } - if( len > max ) - len = max; - - mes[len-1] = '\0'; - - return len; -} - /*========================================== * Ip setting of map-server *------------------------------------------*/ @@ -645,7 +629,7 @@ bool clif_send(const void* buf, int len, struct block_list* bl, enum send_target break; default: - ShowError("clif_send: Unrecognized type %d\n",type); + ShowError("clif_send: Unrecognized type %u\n", type); return false; } @@ -1010,7 +994,7 @@ void clif_set_unit_idle(struct block_list* bl, struct map_session_data *tsd, enu #endif #if PACKETVER >= 20131223 p.AID = bl->id; - p.GID = (sd) ? sd->status.char_id : 0; // CCODE + p.GID = (sd) ? sd->status.char_id : 0; // CCODE #else p.GID = bl->id; #endif @@ -1065,6 +1049,7 @@ void clif_set_unit_idle(struct block_list* bl, struct map_session_data *tsd, enu #endif #if PACKETVER >= 20150513 p.body = vd->body_style; + safestrncpy(p.name, clif->get_bl_name(bl), NAME_LENGTH); #endif clif->send(&p,sizeof(p),tsd?&tsd->bl:bl,target); @@ -1151,7 +1136,7 @@ void clif_spawn_unit(struct block_list* bl, enum send_target target) { #endif #if PACKETVER >= 20131223 p.AID = bl->id; - p.GID = (sd) ? sd->status.char_id : 0; // CCODE + p.GID = (sd) ? sd->status.char_id : 0; // CCODE #else p.GID = bl->id; #endif @@ -1205,6 +1190,7 @@ void clif_spawn_unit(struct block_list* bl, enum send_target target) { #endif #if PACKETVER >= 20150513 p.body = vd->body_style; + safestrncpy(p.name, clif->get_bl_name(bl), NAME_LENGTH); #endif if( disguised(bl) ) { nullpo_retv(sd); @@ -1246,7 +1232,7 @@ void clif_set_unit_walking(struct block_list* bl, struct map_session_data *tsd, #endif #if PACKETVER >= 20131223 p.AID = bl->id; - p.GID = (tsd) ? tsd->status.char_id : 0; // CCODE + p.GID = (tsd) ? tsd->status.char_id : 0; // CCODE #else p.GID = bl->id; #endif @@ -1296,6 +1282,7 @@ void clif_set_unit_walking(struct block_list* bl, struct map_session_data *tsd, #endif #if PACKETVER >= 20150513 p.body = vd->body_style; + safestrncpy(p.name, clif->get_bl_name(bl), NAME_LENGTH); #endif clif->send(&p,sizeof(p),tsd?&tsd->bl:bl,target); @@ -1612,7 +1599,7 @@ void clif_homskillinfoblock(struct map_session_data *sd) { WFIFOW(fd, len + 8) = 0; WFIFOW(fd, len + 10) = 0; } - safestrncpy((char*)WFIFOP(fd, len + 12), skill->get_name(id), NAME_LENGTH); + safestrncpy(WFIFOP(fd, len + 12), skill->get_name(id), NAME_LENGTH); WFIFOB(fd, len + 36) = (hd->homunculus.hskill[j].lv < homun->skill_tree_get_max(id, hd->homunculus.class_)) ? 1 : 0; len += 37; } @@ -1816,7 +1803,7 @@ void clif_changemap(struct map_session_data *sd, short m, int x, int y) { WFIFOHEAD(fd,packet_len(0x91)); WFIFOW(fd,0) = 0x91; - mapindex->getmapname_ext(map->list[m].custom_name ? map->list[map->list[m].instance_src_map].name : map->list[m].name, (char*)WFIFOP(fd,2)); + mapindex->getmapname_ext(map->list[m].custom_name ? map->list[map->list[m].instance_src_map].name : map->list[m].name, WFIFOP(fd,2)); WFIFOW(fd,18) = x; WFIFOW(fd,20) = y; WFIFOSET(fd,packet_len(0x91)); @@ -1831,7 +1818,7 @@ void clif_changemapserver(struct map_session_data* sd, unsigned short map_index, WFIFOHEAD(fd,packet_len(0x92)); WFIFOW(fd,0) = 0x92; - mapindex->getmapname_ext(mapindex_id2name(map_index), (char*)WFIFOP(fd,2)); + mapindex->getmapname_ext(mapindex_id2name(map_index), WFIFOP(fd,2)); WFIFOW(fd,18) = x; WFIFOW(fd,20) = y; WFIFOL(fd,22) = htonl(ip); @@ -1984,7 +1971,7 @@ void clif_scriptmes(struct map_session_data *sd, int npcid, const char *mes) { WFIFOW(fd,0)=0xb4; WFIFOW(fd,2)=slen; WFIFOL(fd,4)=npcid; - memcpy((char*)WFIFOP(fd,8), mes, slen-8); + memcpy(WFIFOP(fd,8), mes, slen-8); WFIFOSET(fd,WFIFOW(fd,2)); } @@ -2103,7 +2090,7 @@ void clif_scriptmenu(struct map_session_data* sd, int npcid, const char* mes) { WFIFOW(fd,0)=0xb7; WFIFOW(fd,2)=slen; WFIFOL(fd,4)=npcid; - memcpy((char*)WFIFOP(fd,8), mes, slen-8); + memcpy(WFIFOP(fd,8), mes, slen-8); WFIFOSET(fd,WFIFOW(fd,2)); } @@ -2211,7 +2198,7 @@ void clif_cutin(struct map_session_data* sd, const char* image, int type) fd=sd->fd; WFIFOHEAD(fd, packet_len(0x1b3)); WFIFOW(fd,0)=0x1b3; - strncpy((char*)WFIFOP(fd,2),image,64); + strncpy(WFIFOP(fd,2),image,64); WFIFOB(fd,66)=type; WFIFOSET(fd,packet_len(0x1b3)); } @@ -2333,9 +2320,9 @@ void clif_add_random_options(unsigned char* buf, struct item* item) int i; nullpo_retv(buf); for (i = 0; i < 5; i++){ - WBUFW(buf,i*5+0) = 0; // OptIndex - WBUFW(buf,i*5+2) = 0; // Value - WBUFB(buf,i*5+4) = 0; // Param1 + WBUFW(buf,i*5+0) = 0; // OptIndex + WBUFW(buf,i*5+2) = 0; // Value + WBUFB(buf,i*5+4) = 0; // Param1 } } @@ -3642,7 +3629,7 @@ void clif_dispchat(struct chat_data* cd, int fd) WBUFW(buf,12) = cd->limit; WBUFW(buf,14) = (cd->owner->type == BL_NPC) ? cd->users+1 : cd->users; WBUFB(buf,16) = type; - memcpy((char*)WBUFP(buf,17), cd->title, strlen(cd->title)); // not zero-terminated + memcpy(WBUFP(buf,17), cd->title, strlen(cd->title)); // not zero-terminated if( fd ) { WFIFOHEAD(fd,WBUFW(buf,2)); @@ -3679,7 +3666,7 @@ void clif_changechatstatus(struct chat_data* cd) WBUFW(buf,12) = cd->limit; WBUFW(buf,14) = (cd->owner->type == BL_NPC) ? cd->users+1 : cd->users; WBUFB(buf,16) = type; - memcpy((char*)WBUFP(buf,17), cd->title, strlen(cd->title)); // not zero-terminated + memcpy(WBUFP(buf,17), cd->title, strlen(cd->title)); // not zero-terminated clif->send(buf,WBUFW(buf,2),cd->owner,CHAT); } @@ -3841,7 +3828,7 @@ void clif_traderequest(struct map_session_data *sd, const char *name) #if PACKETVER < 6 WFIFOHEAD(fd,packet_len(0xe5)); WFIFOW(fd,0) = 0xe5; - safestrncpy((char*)WFIFOP(fd,2), name, NAME_LENGTH); + safestrncpy(WFIFOP(fd,2), name, NAME_LENGTH); WFIFOSET(fd,packet_len(0xe5)); #else // PACKETVER >= 6 tsd = map->id2sd(sd->trade_partner); @@ -3850,7 +3837,7 @@ void clif_traderequest(struct map_session_data *sd, const char *name) WFIFOHEAD(fd,packet_len(0x1f4)); WFIFOW(fd,0) = 0x1f4; - safestrncpy((char*)WFIFOP(fd,2), name, NAME_LENGTH); + safestrncpy(WFIFOP(fd,2), name, NAME_LENGTH); WFIFOL(fd,26) = tsd->status.char_id; WFIFOW(fd,30) = tsd->status.base_level; WFIFOSET(fd,packet_len(0x1f4)); @@ -4330,7 +4317,7 @@ int clif_damage(struct block_list* src, struct block_list* dst, int sdelay, int p.leftDamage = damage2; } #if PACKETVER >= 20131223 - p.is_sp_damaged = 0; // [ToDo] IsSPDamage - Displays blue digits. + p.is_sp_damaged = 0; // TODO: IsSPDamage - Displays blue digits. #endif if(disguised(dst)) { @@ -4425,7 +4412,7 @@ void clif_changemapcell(int fd, int16 m, int x, int y, int type, enum send_targe WBUFW(buf,2) = x; WBUFW(buf,4) = y; WBUFW(buf,6) = type; - mapindex->getmapname_ext(map->list[m].custom_name ? map->list[map->list[m].instance_src_map].name : map->list[m].name,(char*)WBUFP(buf,8)); + mapindex->getmapname_ext(map->list[m].custom_name ? map->list[map->list[m].instance_src_map].name : map->list[m].name, WBUFP(buf,8)); if( fd ) { WFIFOHEAD(fd,packet_len(0x192)); @@ -4735,7 +4722,7 @@ void clif_skillinfoblock(struct map_session_data *sd) WFIFOW(fd, len + 8) = 0; WFIFOW(fd, len + 10)= 0; } - safestrncpy((char*)WFIFOP(fd,len+12), skill->get_name(id), NAME_LENGTH); + safestrncpy(WFIFOP(fd,len+12), skill->get_name(id), NAME_LENGTH); if(sd->status.skill[i].flag == SKILL_FLAG_PERMANENT) WFIFOB(fd,len+36) = (sd->status.skill[i].lv < skill->tree_get_max(id, sd->status.class_))? 1:0; else @@ -4786,7 +4773,7 @@ void clif_addskill(struct map_session_data *sd, int id) WFIFOW(fd,10) = 0; WFIFOW(fd,12) = 0; } - safestrncpy((char*)WFIFOP(fd,14), skill->get_name(id), NAME_LENGTH); + safestrncpy(WFIFOP(fd,14), skill->get_name(id), NAME_LENGTH); if (sd->status.skill[idx].flag == SKILL_FLAG_PERMANENT) WFIFOB(fd,38) = (skill_lv < skill->tree_get_max(id, sd->status.class_))? 1:0; else @@ -5078,7 +5065,7 @@ int clif_skill_damage(struct block_list *src, struct block_list *dst, int64 tick // type 6 (ACTION_SKILL) skills. So we have to do a small // hack to set all type 6 to be sent as type 8 ACTION_ATTACK_MULTIPLE #if PACKETVER < 20131223 - WBUFB(buf, 32) = type; + WBUFB(buf, 32) = type; #else WBUFB(buf, 32) = (type == BDT_SKILL) ? BDT_MULTIHIT : type; #endif @@ -5227,12 +5214,12 @@ void clif_skill_warppoint(struct map_session_data* sd, uint16 skill_id, uint16 s WFIFOW(fd,0) = 0x11c; WFIFOW(fd,2) = skill_id; memset(WFIFOP(fd,4), 0x00, 4*MAP_NAME_LENGTH_EXT); - if (map1 == (unsigned short)-1) strcpy((char*)WFIFOP(fd,4), "Random"); + if (map1 == (unsigned short)-1) strcpy(WFIFOP(fd,4), "Random"); else // normal map name - if (map1 > 0) mapindex->getmapname_ext(mapindex_id2name(map1), (char*)WFIFOP(fd,4)); - if (map2 > 0) mapindex->getmapname_ext(mapindex_id2name(map2), (char*)WFIFOP(fd,20)); - if (map3 > 0) mapindex->getmapname_ext(mapindex_id2name(map3), (char*)WFIFOP(fd,36)); - if (map4 > 0) mapindex->getmapname_ext(mapindex_id2name(map4), (char*)WFIFOP(fd,52)); + if (map1 > 0) mapindex->getmapname_ext(mapindex_id2name(map1), WFIFOP(fd,4)); + if (map2 > 0) mapindex->getmapname_ext(mapindex_id2name(map2), WFIFOP(fd,20)); + if (map3 > 0) mapindex->getmapname_ext(mapindex_id2name(map3), WFIFOP(fd,36)); + if (map4 > 0) mapindex->getmapname_ext(mapindex_id2name(map4), WFIFOP(fd,52)); WFIFOSET(fd,packet_len(0x11c)); sd->menuskill_id = skill_id; @@ -5508,7 +5495,7 @@ void clif_displaymessage(const int fd, const char* mes) { WFIFOHEAD(fd, 5 + len); WFIFOW(fd,0) = 0x8e; WFIFOW(fd,2) = 5 + len; // 4 + len + NULL terminate - safestrncpy((char *)WFIFOP(fd,4), mes, len + 1); + safestrncpy(WFIFOP(fd,4), mes, len + 1); WFIFOSET(fd, 5 + len); } #endif @@ -5538,7 +5525,7 @@ void clif_displaymessage2(const int fd, const char* mes) { WFIFOHEAD(fd, 5 + len); WFIFOW(fd,0) = 0x8e; WFIFOW(fd,2) = 5 + len; // 4 + len + NULL terminate - safestrncpy((char *)WFIFOP(fd,4), line, len + 1); + safestrncpy(WFIFOP(fd,4), line, len + 1); WFIFOSET(fd, 5 + len); } } @@ -5567,11 +5554,11 @@ void clif_displaymessage_sprintf(const int fd, const char *mes, ...) { /* process */ va_start(ap,mes); - len += vsnprintf((char *)WFIFOP(fd,4), 255, mes, ap); + len += vsnprintf(WFIFOP(fd,4), 255, mes, ap); va_end(ap); /* adjusting */ - ptr = (char *)WFIFOP(fd,4); + ptr = WFIFOP(fd,4); ptr[len - 1] = '\0'; /* */ @@ -5625,7 +5612,7 @@ void clif_GlobalMessage(struct block_list* bl, const char* message) { WBUFW(buf,0)=0x8d; WBUFW(buf,2)=len+8; WBUFL(buf,4)=bl->id; - safestrncpy((char *) WBUFP(buf,8),message,len); + safestrncpy(WBUFP(buf,8),message,len); clif->send((unsigned char *) buf,WBUFW(buf,2),bl,ALL_CLIENT); } @@ -5818,8 +5805,8 @@ void clif_wis_message(int fd, const char *nick, const char *mes, size_t mes_len) WFIFOHEAD(fd, mes_len + NAME_LENGTH + 4); WFIFOW(fd,0) = 0x97; WFIFOW(fd,2) = mes_len + NAME_LENGTH + 4; - safestrncpy((char*)WFIFOP(fd,4), nick, NAME_LENGTH); - safestrncpy((char*)WFIFOP(fd,28), mes, mes_len); + safestrncpy(WFIFOP(fd,4), nick, NAME_LENGTH); + safestrncpy(WFIFOP(fd,28), mes, mes_len); WFIFOSET(fd,WFIFOW(fd,2)); #else ssd = map->nick2sd(nick); @@ -5827,9 +5814,9 @@ void clif_wis_message(int fd, const char *nick, const char *mes, size_t mes_len) WFIFOHEAD(fd, mes_len + NAME_LENGTH + 8); WFIFOW(fd,0) = 0x97; WFIFOW(fd,2) = mes_len + NAME_LENGTH + 8; - safestrncpy((char*)WFIFOP(fd,4), nick, NAME_LENGTH); + safestrncpy(WFIFOP(fd,4), nick, NAME_LENGTH); WFIFOL(fd,28) = (ssd && pc_get_group_level(ssd) == 99) ? 1 : 0; // isAdmin; if nonzero, also displays text above char - safestrncpy((char*)WFIFOP(fd,32), mes, mes_len); + safestrncpy(WFIFOP(fd,32), mes, mes_len); WFIFOSET(fd,WFIFOW(fd,2)); #endif } @@ -5865,7 +5852,7 @@ void clif_solved_charname(int fd, int charid, const char* name) WFIFOHEAD(fd,packet_len(0x194)); WFIFOW(fd,0)=0x194; WFIFOL(fd,2)=charid; - safestrncpy((char*)WFIFOP(fd,6), name, NAME_LENGTH); + safestrncpy(WFIFOP(fd,6), name, NAME_LENGTH); WFIFOSET(fd,packet_len(0x194)); } @@ -6089,7 +6076,7 @@ void clif_item_skill(struct map_session_data *sd,uint16 skill_id,uint16 skill_lv WFIFOW(fd, 8)=skill_lv; WFIFOW(fd,10)=skill->get_sp(skill_id,skill_lv); WFIFOW(fd,12)=skill->get_range2(&sd->bl, skill_id,skill_lv); - safestrncpy((char*)WFIFOP(fd,14),skill->get_name(skill_id),NAME_LENGTH); + safestrncpy(WFIFOP(fd,14),skill->get_name(skill_id),NAME_LENGTH); WFIFOB(fd,38)=0; WFIFOSET(fd,packet_len(0x147)); } @@ -6176,7 +6163,7 @@ void clif_showvendingboard(struct block_list* bl, const char* message, int fd) WBUFW(buf,0) = 0x131; WBUFL(buf,2) = bl->id; - safestrncpy((char*)WBUFP(buf,6), message, 80); + safestrncpy(WBUFP(buf,6), message, 80); if( fd ) { WFIFOHEAD(fd,packet_len(0x131)); @@ -6404,7 +6391,7 @@ void clif_party_member_info(struct party_data *p, struct map_session_data *sd) WBUFB(buf,14) = (p->party.member[i].online)?0:1; memcpy(WBUFP(buf,15), p->party.name, NAME_LENGTH); memcpy(WBUFP(buf,39), sd->status.name, NAME_LENGTH); - mapindex->getmapname_ext(map->list[sd->bl.m].custom_name ? map->list[map->list[sd->bl.m].instance_src_map].name : map->list[sd->bl.m].name, (char*)WBUFP(buf,63)); + mapindex->getmapname_ext(map->list[sd->bl.m].custom_name ? map->list[map->list[sd->bl.m].instance_src_map].name : map->list[sd->bl.m].name, WBUFP(buf,63)); WBUFB(buf,79) = (p->party.item&1)?1:0; WBUFB(buf,80) = (p->party.item&2)?1:0; clif->send(buf,packet_len(0x1e9),&sd->bl,PARTY); @@ -6437,7 +6424,7 @@ void clif_party_info(struct party_data* p, struct map_session_data *sd) WBUFL(buf,28+c*46) = m->account_id; memcpy(WBUFP(buf,28+c*46+4), m->name, NAME_LENGTH); - mapindex->getmapname_ext(mapindex_id2name(m->map), (char*)WBUFP(buf,28+c*46+28)); + mapindex->getmapname_ext(mapindex_id2name(m->map), WBUFP(buf,28+c*46+28)); WBUFB(buf,28+c*46+44) = (m->leader) ? 0 : 1; WBUFB(buf,28+c*46+45) = (m->online) ? 0 : 1; c++; @@ -6525,13 +6512,13 @@ void clif_party_inviteack(struct map_session_data* sd, const char* nick, int res #if PACKETVER < 20070821 WFIFOHEAD(fd,packet_len(0xfd)); WFIFOW(fd,0) = 0xfd; - safestrncpy((char*)WFIFOP(fd,2),nick,NAME_LENGTH); + safestrncpy(WFIFOP(fd,2),nick,NAME_LENGTH); WFIFOB(fd,26) = result; WFIFOSET(fd,packet_len(0xfd)); #else WFIFOHEAD(fd,packet_len(0x2c5)); WFIFOW(fd,0) = 0x2c5; - safestrncpy((char*)WFIFOP(fd,2),nick,NAME_LENGTH); + safestrncpy(WFIFOP(fd,2),nick,NAME_LENGTH); WFIFOL(fd,26) = result; WFIFOSET(fd,packet_len(0x2c5)); #endif @@ -6637,7 +6624,7 @@ void clif_party_message(struct party_data* p, int account_id, const char* mes, i WBUFW(buf,0)=0x109; WBUFW(buf,2)=len+8; WBUFL(buf,4)=account_id; - safestrncpy((char *)WBUFP(buf,8), mes, len); + safestrncpy(WBUFP(buf,8), mes, len); clif->send(buf,len+8,&sd->bl,PARTY); } } @@ -7303,7 +7290,7 @@ void clif_guild_basicinfo(struct map_session_data *sd) { memcpy(WFIFOP(fd,46),g->name, NAME_LENGTH); memcpy(WFIFOP(fd,70),g->master, NAME_LENGTH); - safestrncpy((char*)WFIFOP(fd,94),msg_sd(sd,300+guild->checkcastles(g)),16); // "'N' castles" + safestrncpy(WFIFOP(fd,94),msg_sd(sd,300+guild->checkcastles(g)),16); // "'N' castles" WFIFOL(fd,110) = 0; // zeny WFIFOSET(fd,packet_len(0x1b6)); @@ -7546,7 +7533,7 @@ void clif_guild_skillinfo(struct map_session_data* sd) WFIFOW(fd, p + 8) = 0; WFIFOW(fd, p + 10) = 0; } - safestrncpy((char*)WFIFOP(fd,p+12), skill->get_name(id), NAME_LENGTH); + safestrncpy(WFIFOP(fd,p+12), skill->get_name(id), NAME_LENGTH); WFIFOB(fd,p+36)= (g->skill[i].lv < guild->skill_get_max(id) && sd == g->member[0].sd) ? 1 : 0; c++; } @@ -7647,8 +7634,8 @@ void clif_guild_expulsion(struct map_session_data* sd, const char* name, const c nullpo_retv(mes); WBUFW(buf,0) = cmd; - safestrncpy((char*)WBUFP(buf,2), name, NAME_LENGTH); - safestrncpy((char*)WBUFP(buf,26), mes, 40); + safestrncpy(WBUFP(buf,2), name, NAME_LENGTH); + safestrncpy(WBUFP(buf,26), mes, 40); #if PACKETVER < 20100803 memset(WBUFP(buf,66), 0, NAME_LENGTH); // account name (not used for security reasons) #endif @@ -7715,7 +7702,7 @@ void clif_guild_message(struct guild *g,int account_id,const char *mes,int len) WBUFW(buf, 0) = 0x17f; WBUFW(buf, 2) = len + 5; - safestrncpy((char*)WBUFP(buf,4), mes, len+1); + safestrncpy(WBUFP(buf,4), mes, len+1); if ((sd = guild->getavailablesd(g)) != NULL) clif->send(buf, WBUFW(buf,2), &sd->bl, GUILD_NOBG); @@ -7859,7 +7846,7 @@ void clif_talkiebox(struct block_list* bl, const char* talkie) WBUFW(buf,0) = 0x191; WBUFL(buf,2) = bl->id; - safestrncpy((char*)WBUFP(buf,6),talkie,MESSAGE_SIZE); + safestrncpy(WBUFP(buf,6),talkie,MESSAGE_SIZE); clif->send(buf,packet_len(0x191),bl,AREA); } @@ -7942,7 +7929,7 @@ void clif_marriage_proposal(int fd, struct map_session_data *sd, struct map_sess WFIFOW(fd,0) = 0x1e2; WFIFOL(fd,2) = ssd->status.account_id; WFIFOL(fd,6) = ssd->status.char_id; - safestrncpy((char*)WFIFOP(fd,10), ssd->status.name, NAME_LENGTH); + safestrncpy(WFIFOP(fd,10), ssd->status.name, NAME_LENGTH); WFIFOSET(fd, packet_len(0x1e2)); } */ @@ -7967,7 +7954,7 @@ void clif_disp_message(struct block_list* src, const char* mes, size_t len, enum WBUFW(buf, 0) = 0x17f; WBUFW(buf, 2) = len + 5; - safestrncpy((char*)WBUFP(buf,4), mes, len+1); + safestrncpy(WBUFP(buf,4), mes, len+1); clif->send(buf, WBUFW(buf,2), src, target); } @@ -8041,7 +8028,7 @@ void clif_GM_silence(struct map_session_data* sd, struct map_session_data* tsd, WFIFOHEAD(fd,packet_len(0x14b)); WFIFOW(fd,0) = 0x14b; WFIFOB(fd,2) = type; - safestrncpy((char*)WFIFOP(fd,3), sd->status.name, NAME_LENGTH); + safestrncpy(WFIFOP(fd,3), sd->status.name, NAME_LENGTH); WFIFOSET(fd, packet_len(0x14b)); } @@ -8099,7 +8086,7 @@ void clif_playBGM(struct map_session_data* sd, const char* name) fd = sd->fd; WFIFOHEAD(fd,packet_len(0x7fe)); WFIFOW(fd,0) = 0x7fe; - safestrncpy((char*)WFIFOP(fd,2), name, NAME_LENGTH); + safestrncpy(WFIFOP(fd,2), name, NAME_LENGTH); WFIFOSET(fd,packet_len(0x7fe)); } @@ -8127,7 +8114,7 @@ void clif_soundeffect(struct map_session_data* sd, struct block_list* bl, const fd = sd->fd; WFIFOHEAD(fd,packet_len(0x1d3)); WFIFOW(fd,0) = 0x1d3; - safestrncpy((char*)WFIFOP(fd,2), name, NAME_LENGTH); + safestrncpy(WFIFOP(fd,2), name, NAME_LENGTH); WFIFOB(fd,26) = type; WFIFOL(fd,27) = 0; WFIFOL(fd,31) = bl->id; @@ -8142,7 +8129,7 @@ void clif_soundeffectall(struct block_list* bl, const char* name, int type, enum nullpo_retv(name); WBUFW(buf,0) = 0x1d3; - safestrncpy((char*)WBUFP(buf,2), name, NAME_LENGTH); + safestrncpy(WBUFP(buf,2), name, NAME_LENGTH); WBUFB(buf,26) = type; WBUFL(buf,27) = 0; WBUFL(buf,31) = bl->id; @@ -8226,7 +8213,7 @@ void clif_messagecolor_self(int fd, uint32 color, const char *msg) WFIFOW(fd,2) = msg_len + 12; WFIFOL(fd,4) = 0; WFIFOL(fd,8) = RGB2BGR(color); - safestrncpy((char*)WFIFOP(fd,12), msg, msg_len); + safestrncpy(WFIFOP(fd,12), msg, msg_len); WFIFOSET(fd, msg_len + 12); } @@ -8475,7 +8462,7 @@ void clif_charnameack (int fd, struct block_list *bl) memcpy(WBUFP(buf,6), BL_UCCAST(BL_ELEM, bl)->db->name, NAME_LENGTH); break; default: - ShowError("clif_charnameack: bad type %d(%d)\n", bl->type, bl->id); + ShowError("clif_charnameack: bad type %u(%d)\n", bl->type, bl->id); return; } @@ -8586,14 +8573,14 @@ void clif_disp_overhead(struct block_list *bl, const char* mes) WBUFW(buf,0) = 0x8d; WBUFW(buf,2) = len_mes + 8; // len of message + 8 (command+len+id) WBUFL(buf,4) = bl->id; - safestrncpy((char*)WBUFP(buf,8), mes, len_mes); + safestrncpy(WBUFP(buf,8), mes, len_mes); clif->send(buf, WBUFW(buf,2), bl, AREA_CHAT_WOC); // send back message to the speaker if( bl->type == BL_PC ) { WBUFW(buf,0) = 0x8e; WBUFW(buf, 2) = len_mes + 4; - safestrncpy((char*)WBUFP(buf,4), mes, len_mes); + safestrncpy(WBUFP(buf,4), mes, len_mes); clif->send(buf, WBUFW(buf,2), bl, SELF); } @@ -8680,7 +8667,7 @@ void clif_starskill(struct map_session_data* sd, const char* mapname, int monste WFIFOHEAD(fd,packet_len(0x20e)); WFIFOW(fd,0) = 0x20e; - safestrncpy((char*)WFIFOP(fd,2), mapname, NAME_LENGTH); + safestrncpy(WFIFOP(fd,2), mapname, NAME_LENGTH); WFIFOL(fd,26) = monster_id; WFIFOB(fd,30) = star; WFIFOB(fd,31) = result; @@ -8884,8 +8871,9 @@ void clif_msgtable_skill(struct map_session_data* sd, uint16 skill_id, int msg_i /// Returns true if the packet was parsed successfully. /// Formats: 0 - <packet id>.w <packet len>.w (<name> : <message>).?B 00 /// 1 - <packet id>.w <packet len>.w <name>.24B <message>.?B 00 -bool clif_process_message(struct map_session_data *sd, int format, char **name_, size_t *namelen_, char **message_, size_t *messagelen_) { - char *text, *name, *message; +bool clif_process_message(struct map_session_data *sd, int format, const char **name_, size_t *namelen_, const char **message_, size_t *messagelen_) +{ + const char *text, *name, *message; unsigned int packetlen, textlen; size_t namelen, messagelen; int fd = sd->fd; @@ -8909,7 +8897,7 @@ bool clif_process_message(struct map_session_data *sd, int format, char **name_, return false; } - text = (char*)RFIFOP(fd,4); + text = RFIFOP(fd,4); textlen = packetlen - 4; // process <name> part of the packet @@ -9000,7 +8988,7 @@ void clif_channel_msg(struct channel_data *chan, struct map_session_data *sd, ch WFIFOW(sd->fd,2) = msg_len + 12; WFIFOL(sd->fd,4) = 0; WFIFOL(sd->fd,8) = RGB2BGR(color); - safestrncpy((char*)WFIFOP(sd->fd,12), msg, msg_len); + safestrncpy(WFIFOP(sd->fd,12), msg, msg_len); for (user = dbi_first(iter); dbi_exists(iter); user = dbi_next(iter)) { if( user->fd == sd->fd ) @@ -9033,7 +9021,7 @@ void clif_channel_msg2(struct channel_data *chan, char *msg) WBUFW(buf,2) = msg_len + 12; WBUFL(buf,4) = 0; WBUFL(buf,8) = RGB2BGR(color); - safestrncpy((char*)WBUFP(buf,12), msg, msg_len); + safestrncpy(WBUFP(buf,12), msg, msg_len); for (user = dbi_first(iter); dbi_exists(iter); user = dbi_next(iter)) { WFIFOHEAD(user->fd,msg_len + 12); @@ -9730,10 +9718,11 @@ void clif_parse_GlobalMessage(int fd, struct map_session_data* sd) __attribute__ /// There are various variants of this packet. void clif_parse_GlobalMessage(int fd, struct map_session_data* sd) { - const char* text = (char*)RFIFOP(fd,4); + const char *text = RFIFOP(fd,4); size_t textlen = RFIFOW(fd,2) - 4; - char *name, *message, *fakename = NULL; + const char *name = NULL, *message = NULL; + char *fakename = NULL; size_t namelen, messagelen; bool is_fake; @@ -9818,7 +9807,7 @@ void clif_parse_GlobalMessage(int fd, struct map_session_data* sd) WFIFOW(fd,2) = mylen + 12; WFIFOL(fd,4) = sd->bl.id; WFIFOL(fd,8) = RGB2BGR(color); - safestrncpy((char*)WFIFOP(fd,12), mout, mylen); + safestrncpy(WFIFOP(fd,12), mout, mylen); clif->send(WFIFOP(fd,0), WFIFOW(fd,2), &sd->bl, AREA_WOS); WFIFOL(fd,4) = -sd->bl.id; WFIFOSET(fd, mylen + 12); @@ -9840,7 +9829,7 @@ void clif_parse_GlobalMessage(int fd, struct map_session_data* sd) WFIFOW(fd,0) = 0x8d; WFIFOW(fd,2) = 8 + textlen; WFIFOL(fd,4) = sd->bl.id; - safestrncpy((char*)WFIFOP(fd,8), is_fake ? fakename : text, textlen); + safestrncpy(WFIFOP(fd,8), is_fake ? fakename : text, textlen); //FIXME: chat has range of 9 only clif->send(WFIFOP(fd,0), WFIFOW(fd,2), &sd->bl, sd->chatID ? CHAT_WOS : AREA_CHAT_WOC); @@ -9848,7 +9837,7 @@ void clif_parse_GlobalMessage(int fd, struct map_session_data* sd) if( is_fake ) { WFIFOW(fd,0) = 0x8e; WFIFOW(fd,2) = textlen + 4; - safestrncpy((char*)WFIFOP(fd,4), fakename, textlen); + safestrncpy(WFIFOP(fd,4), fakename, textlen); aFree(fakename); } else { memcpy(WFIFOP(fd,0), RFIFOP(fd,0), RFIFOW(fd,2)); @@ -9859,10 +9848,8 @@ void clif_parse_GlobalMessage(int fd, struct map_session_data* sd) // Chat logging type 'O' / Global Chat logs->chat(LOG_CHAT_GLOBAL, 0, sd->status.char_id, sd->status.account_id, mapindex_id2name(sd->mapindex), sd->bl.x, sd->bl.y, NULL, message); -#ifdef PCRE_SUPPORT // trigger listening npcs map->foreachinrange(npc_chat->sub, &sd->bl, AREA_SIZE, BL_NPC, text, textlen, &sd->bl); -#endif } void clif_parse_MapMove(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); @@ -9872,10 +9859,9 @@ void clif_parse_MapMove(int fd, struct map_session_data *sd) __attribute__((nonn void clif_parse_MapMove(int fd, struct map_session_data *sd) { char command[MAP_NAME_LENGTH_EXT+25]; - char* map_name; + char map_name[MAP_NAME_LENGTH_EXT]; - map_name = (char*)RFIFOP(fd,2); - map_name[MAP_NAME_LENGTH_EXT-1]='\0'; + safestrncpy(map_name, RFIFOP(fd,2), MAP_NAME_LENGTH_EXT); sprintf(command, "%cmapmove %s %d %d", atcommand->at_symbol, map_name, RFIFOW(fd,18), RFIFOW(fd,20)); atcommand->exec(fd, sd, command, true); } @@ -10144,7 +10130,7 @@ void clif_parse_WisMessage(int fd, struct map_session_data* sd) struct map_session_data* dstsd; int i; - char *target, *message; + const char *target, *message; size_t namelen, messagelen; // validate packet and retrieve name and message @@ -10174,7 +10160,7 @@ void clif_parse_WisMessage(int fd, struct map_session_data* sd) // Lordalfa - Paperboy - To whisper NPC commands // //-------------------------------------------------------// if (target[0] && (strncasecmp(target,"NPC:",4) == 0) && (strlen(target) > 4)) { - char* str = target+4; //Skip the NPC: string part. + const char *str = target+4; //Skip the NPC: string part. struct npc_data *nd; if ((nd = npc->name2id(str))) { char split_data[NUM_WHISPER_VAR][CHAT_SIZE_MAX]; @@ -10209,7 +10195,7 @@ void clif_parse_WisMessage(int fd, struct map_session_data* sd) return; } } else if( target[0] == '#' ) { - char *chname = target; + const char *chname = target; struct channel_data *chan = channel->search(chname, sd); if (chan) { @@ -10273,19 +10259,26 @@ void clif_parse_WisMessage(int fd, struct map_session_data* sd) clif->wis_message(dstsd->fd, sd->status.name, message, messagelen); } -void clif_parse_Broadcast(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); +void clif_parse_Broadcast(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// /b /nb (CZ_BROADCAST). /// Request to broadcast a message on whole server. /// 0099 <packet len>.W <text>.?B 00 -void clif_parse_Broadcast(int fd, struct map_session_data* sd) { - char command[CHAT_SIZE_MAX+11]; - char* msg = (char*)RFIFOP(fd,4); - unsigned int len = RFIFOW(fd,2)-4; +void clif_parse_Broadcast(int fd, struct map_session_data *sd) +{ + const char commandname[] = "kami"; + char command[sizeof commandname + 2 + CHAT_SIZE_MAX] = ""; // '@' command + ' ' + message + NUL + int len = (int)RFIFOW(fd,2) - 4; - // as the length varies depending on the command used, just block unreasonably long strings - mes_len_check(msg, len, CHAT_SIZE_MAX); + if (len < 0) + return; - sprintf(command, "%ckami %s", atcommand->at_symbol, msg); + sprintf(command, "%c%s ", atcommand->at_symbol, commandname); + + // as the length varies depending on the command used, truncate unreasonably long strings + if (len >= (int)(sizeof command - strlen(command))) + len = (int)(sizeof command - strlen(command)) - 1; + + strncat(command, RFIFOP(fd,4), len); atcommand->exec(fd, sd, command, true); } @@ -10397,16 +10390,18 @@ void clif_parse_EquipItem(int fd,struct map_session_data *sd) __attribute__((non /// Request to equip an item (CZ_REQ_WEAR_EQUIP). /// 00a9 <index>.W <position>.W /// 0998 <index>.W <position>.L -void clif_parse_EquipItem(int fd,struct map_session_data *sd) { - struct packet_equip_item *p = P2PTR(fd); +void clif_parse_EquipItem(int fd,struct map_session_data *sd) +{ + const struct packet_equip_item *p = RP2PTR(fd); + int index = 0; if(pc_isdead(sd)) { clif->clearunit_area(&sd->bl,CLR_DEAD); return; } - p->index = p->index - 2; - if (p->index >= MAX_INVENTORY) + index = p->index - 2; + if (index >= MAX_INVENTORY) return; //Out of bounds check. if( sd->npc_id ) { @@ -10417,26 +10412,26 @@ void clif_parse_EquipItem(int fd,struct map_session_data *sd) { else if ( pc_cant_act2(sd) || sd->state.prerefining ) return; - if(!sd->status.inventory[p->index].identify) { - clif->equipitemack(sd,p->index,0,EIA_FAIL);// fail + if(!sd->status.inventory[index].identify) { + clif->equipitemack(sd, index, 0, EIA_FAIL);// fail return; } - if(!sd->inventory_data[p->index]) + if(!sd->inventory_data[index]) return; - if(sd->inventory_data[p->index]->type == IT_PETARMOR){ - pet->equipitem(sd,p->index); + if(sd->inventory_data[index]->type == IT_PETARMOR){ + pet->equipitem(sd, index); return; } pc->update_idle_time(sd, BCIDLE_USEITEM); //Client doesn't send the position for ammo. - if(sd->inventory_data[p->index]->type == IT_AMMO) - pc->equipitem(sd,p->index,EQP_AMMO); + if(sd->inventory_data[index]->type == IT_AMMO) + pc->equipitem(sd, index, EQP_AMMO); else - pc->equipitem(sd,p->index,p->wearLocation); + pc->equipitem(sd, index, p->wearLocation); } void clif_parse_UnequipItem(int fd,struct map_session_data *sd) __attribute__((nonnull (2))); @@ -10542,14 +10537,30 @@ void clif_parse_NpcBuyListSend(int fd, struct map_session_data* sd) __attribute_ /// 00c8 <packet len>.W { <amount>.W <name id>.W }* void clif_parse_NpcBuyListSend(int fd, struct map_session_data* sd) { - int n = (RFIFOW(fd,2)-4) /4; - unsigned short* item_list = (unsigned short*)RFIFOP(fd,4); + int n = ((int)RFIFOW(fd,2)-4) / 4; int result; - if( sd->state.trading || !sd->npc_shopid || pc_has_permission(sd,PC_PERM_DISABLE_STORE) ) + Assert_retv(n >= 0); + + if( sd->state.trading || !sd->npc_shopid || pc_has_permission(sd,PC_PERM_DISABLE_STORE) ) { result = 1; - else - result = npc->buylist(sd,n,item_list); + } else { + struct itemlist item_list = { 0 }; + int i; + + VECTOR_INIT(item_list); + VECTOR_ENSURE(item_list, n, 1); + for (i = 0; i < n; i++) { + struct itemlist_entry entry = { 0 }; + + entry.amount = RFIFOW(fd, 4 + 4 * i); + entry.id = RFIFOW(fd, 4 + 4 * i + 2); + + VECTOR_PUSH(item_list, entry); + } + result = npc->buylist(sd, &item_list); + VECTOR_CLEAR(item_list); + } sd->npc_shopid = 0; //Clear shop data. @@ -10578,15 +10589,32 @@ void clif_parse_NpcSellListSend(int fd,struct map_session_data *sd) __attribute_ void clif_parse_NpcSellListSend(int fd,struct map_session_data *sd) { int fail=0,n; - unsigned short *item_list; - n = (RFIFOW(fd,2)-4) /4; - item_list = (unsigned short*)RFIFOP(fd,4); + n = ((int)RFIFOW(fd,2)-4) /4; + + Assert_retv(n >= 0); - if (sd->state.trading || !sd->npc_shopid) + if (sd->state.trading || !sd->npc_shopid) { fail = 1; - else - fail = npc->selllist(sd,n,item_list); + } else { + struct itemlist item_list = { 0 }; + int i; + + VECTOR_INIT(item_list); + VECTOR_ENSURE(item_list, n, 1); + + for (i = 0; i < n; i++) { + struct itemlist_entry entry = { 0 }; + + entry.id = (int)RFIFOW(fd, 4 + 4 * i) - 2; + entry.amount = RFIFOW(fd, 4 + 4 * i + 2); + + VECTOR_PUSH(item_list, entry); + } + fail = npc->selllist(sd, &item_list); + + VECTOR_CLEAR(item_list); + } sd->npc_shopid = 0; //Clear shop data. @@ -10604,8 +10632,8 @@ void clif_parse_CreateChatRoom(int fd, struct map_session_data* sd) int len = RFIFOW(fd,2)-15; int limit = RFIFOW(fd,4); bool pub = (RFIFOB(fd,6) != 0); - const char* password = (char*)RFIFOP(fd,7); //not zero-terminated - const char* title = (char*)RFIFOP(fd,15); // not zero-terminated + const char *password = RFIFOP(fd,7); //not zero-terminated + const char *title = RFIFOP(fd,15); // not zero-terminated char s_password[CHATROOM_PASS_SIZE]; char s_title[CHATROOM_TITLE_SIZE]; @@ -10639,7 +10667,7 @@ void clif_parse_ChatAddMember(int fd, struct map_session_data* sd) __attribute__ void clif_parse_ChatAddMember(int fd, struct map_session_data* sd) { int chatid = RFIFOL(fd,2); - const char* password = (char*)RFIFOP(fd,6); // not zero-terminated + const char *password = RFIFOP(fd,6); // not zero-terminated chat->join(sd,chatid,password); } @@ -10655,8 +10683,8 @@ void clif_parse_ChatRoomStatusChange(int fd, struct map_session_data* sd) int len = RFIFOW(fd,2)-15; int limit = RFIFOW(fd,4); bool pub = (RFIFOB(fd,6) != 0); - const char* password = (char*)RFIFOP(fd,7); // not zero-terminated - const char* title = (char*)RFIFOP(fd,15); // not zero-terminated + const char *password = RFIFOP(fd,7); // not zero-terminated + const char *title = RFIFOP(fd,15); // not zero-terminated char s_password[CHATROOM_PASS_SIZE]; char s_title[CHATROOM_TITLE_SIZE]; @@ -10677,7 +10705,7 @@ void clif_parse_ChangeChatOwner(int fd, struct map_session_data* sd) __attribute /// 1 = normal void clif_parse_ChangeChatOwner(int fd, struct map_session_data* sd) { - chat->change_owner(sd,(char*)RFIFOP(fd,6)); + chat->change_owner(sd, RFIFOP(fd,6)); } void clif_parse_KickFromChat(int fd,struct map_session_data *sd) __attribute__((nonnull (2))); @@ -10685,7 +10713,7 @@ void clif_parse_KickFromChat(int fd,struct map_session_data *sd) __attribute__(( /// 00e2 <name>.24B void clif_parse_KickFromChat(int fd,struct map_session_data *sd) { - chat->kick(sd,(char*)RFIFOP(fd,2)); + chat->kick(sd, RFIFOP(fd,2)); } void clif_parse_ChatLeave(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); @@ -10853,7 +10881,7 @@ void clif_parse_ChangeCart(int fd,struct map_session_data *sd) } #endif - type = (int)RFIFOW(fd,2); + type = RFIFOW(fd,2); #ifdef NEW_CARTS if( (type == 9 && sd->status.base_level > 131) || (type == 8 && sd->status.base_level > 121) || @@ -10874,6 +10902,25 @@ void clif_parse_ChangeCart(int fd,struct map_session_data *sd) pc->setcart(sd,type); } +/// Request to select cart's visual look for new cart design (CZ_SELECTCART). +/// 0980 <identity>.L <type>.B +void clif_parse_SelectCart(int fd, struct map_session_data *sd) +{ +#if PACKETVER >= 20150805 // RagexeRE + int type; + + if (!sd || !pc->checkskill(sd, MC_CARTDECORATE) || RFIFOL(fd, 2) != sd->status.account_id) + return; + + type = RFIFOB(fd, 6); + + if (type <= MAX_BASE_CARTS || type > MAX_CARTS) + return; + + pc->setcart(sd, type); +#endif +} + void clif_parse_StatusUp(int fd,struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to increase status (CZ_STATUS_CHANGE). /// 00bb <status id>.W <amount>.B @@ -11154,7 +11201,7 @@ void clif_parse_UseSkillToPosSub(int fd, struct map_session_data *sd, uint16 ski return; } //You can't use Graffiti/TalkieBox AND have a vending open, so this is safe. - safestrncpy(sd->message, (char*)RFIFOP(fd,skillmoreinfo), MESSAGE_SIZE); + safestrncpy(sd->message, RFIFOP(fd,skillmoreinfo), MESSAGE_SIZE); } if( sd->ud.skilltimer != INVALID_TIMER ) @@ -11247,7 +11294,7 @@ void clif_parse_UseSkillMap(int fd, struct map_session_data* sd) uint16 skill_id = RFIFOW(fd,2); char map_name[MAP_NAME_LENGTH]; - mapindex->getmapname((char*)RFIFOP(fd,4), map_name); + mapindex->getmapname(RFIFOP(fd,4), map_name); sd->state.workinprogress = 0; if(skill_id != sd->menuskill_id) @@ -11408,7 +11455,7 @@ void clif_parse_NpcAmountInput(int fd,struct map_session_data *sd) __attribute__ void clif_parse_NpcAmountInput(int fd,struct map_session_data *sd) { int npcid = RFIFOL(fd,2); - int amount = (int)RFIFOL(fd,6); + int amount = RFIFOL(fd,6); if (amount >= 0) sd->npc_amount = amount; @@ -11424,7 +11471,7 @@ void clif_parse_NpcStringInput(int fd, struct map_session_data* sd) { int message_len = RFIFOW(fd,2)-8; int npcid = RFIFOL(fd,4); - const char* message = (char*)RFIFOP(fd,8); + const char *message = RFIFOP(fd,8); if( message_len <= 0 ) return; // invalid input @@ -11465,6 +11512,22 @@ void clif_parse_ItemIdentify(int fd,struct map_session_data *sd) clif_menuskill_clear(sd); } +/// Identifying item with right-click (CZ_REQ_ONECLICK_ITEMIDENTIFY). +/// 0A35 <index>.W +void clif_parse_OneClick_ItemIdentify(int fd, struct map_session_data *sd) +{ + int cmd = RFIFOW(fd,0); + short idx = RFIFOW(fd, packet_db[cmd].pos[0]) - 2; + int n; + + if (idx < 0 || idx >= MAX_INVENTORY || sd->inventory_data[idx] == NULL || sd->status.inventory[idx].nameid <= 0) + return; + + if ((n = pc->have_magnifier(sd) ) != INDEX_NOT_FOUND && + pc->delitem(sd, n, 1, 0, DELITEM_NORMAL, LOG_TYPE_CONSUME) == 0) + skill->identify(sd, idx); +} + void clif_parse_SelectArrow(int fd,struct map_session_data *sd) __attribute__((nonnull (2))); /// Answer to arrow crafting item selection dialog (CZ_REQ_MAKINGARROW). /// 01ae <name id>.W @@ -11562,20 +11625,26 @@ void clif_parse_ResetChar(int fd, struct map_session_data *sd) { atcommand->exec(fd, sd, cmd, true); } -void clif_parse_LocalBroadcast(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); +void clif_parse_LocalBroadcast(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// /lb /nlb (CZ_LOCALBROADCAST). /// Request to broadcast a message on current map. /// 019c <packet len>.W <text>.?B -void clif_parse_LocalBroadcast(int fd, struct map_session_data* sd) +void clif_parse_LocalBroadcast(int fd, struct map_session_data *sd) { - char command[CHAT_SIZE_MAX+16]; - char* msg = (char*)RFIFOP(fd,4); - unsigned int len = RFIFOW(fd,2)-4; + const char commandname[] = "lkami"; + char command[sizeof commandname + 2 + CHAT_SIZE_MAX] = ""; // '@' + command + ' ' + message + NUL + int len = (int)RFIFOW(fd,2) - 4; - // as the length varies depending on the command used, just block unreasonably long strings - mes_len_check(msg, len, CHAT_SIZE_MAX); + if (len < 0) + return; - sprintf(command, "%clkami %s", atcommand->at_symbol, msg); + sprintf(command, "%c%s ", atcommand->at_symbol, commandname); + + // as the length varies depending on the command used, truncate unreasonably long strings + if (len >= (int)(sizeof command - strlen(command))) + len = (int)(sizeof command - strlen(command)) - 1; + + strncat(command, RFIFOP(fd,4), len); atcommand->exec(fd, sd, command, true); } @@ -11722,9 +11791,11 @@ void clif_parse_CreateParty(int fd, struct map_session_data *sd) __attribute__(( /// Party creation request /// 00f9 <party name>.24B (CZ_MAKE_GROUP) /// 01e8 <party name>.24B <item pickup rule>.B <item share rule>.B (CZ_MAKE_GROUP2) -void clif_parse_CreateParty(int fd, struct map_session_data *sd) { - char* name = (char*)RFIFOP(fd,2); - name[NAME_LENGTH-1] = '\0'; +void clif_parse_CreateParty(int fd, struct map_session_data *sd) +{ + char name[NAME_LENGTH]; + + safestrncpy(name, RFIFOP(fd,2), NAME_LENGTH); if( map->list[sd->bl.m].flag.partylock ) { // Party locked. @@ -11740,11 +11811,13 @@ void clif_parse_CreateParty(int fd, struct map_session_data *sd) { } void clif_parse_CreateParty2(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); -void clif_parse_CreateParty2(int fd, struct map_session_data *sd) { - char* name = (char*)RFIFOP(fd,2); +void clif_parse_CreateParty2(int fd, struct map_session_data *sd) +{ + char name[NAME_LENGTH]; int item1 = RFIFOB(fd,26); int item2 = RFIFOB(fd,27); - name[NAME_LENGTH-1] = '\0'; + + safestrncpy(name, RFIFOP(fd,2), NAME_LENGTH); if( map->list[sd->bl.m].flag.partylock ) { // Party locked. @@ -11783,10 +11856,12 @@ void clif_parse_PartyInvite(int fd, struct map_session_data *sd) { } void clif_parse_PartyInvite2(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); -void clif_parse_PartyInvite2(int fd, struct map_session_data *sd) { +void clif_parse_PartyInvite2(int fd, struct map_session_data *sd) +{ struct map_session_data *t_sd; - char *name = (char*)RFIFOP(fd,2); - name[NAME_LENGTH-1] = '\0'; + char name[NAME_LENGTH]; + + safestrncpy(name, RFIFOP(fd,2), NAME_LENGTH); if(map->list[sd->bl.m].flag.partylock) { // Party locked. @@ -11843,7 +11918,7 @@ void clif_parse_RemovePartyMember(int fd, struct map_session_data *sd) { clif->message(fd, msg_fd(fd,227)); return; } - party->removemember(sd,RFIFOL(fd,2),(char*)RFIFOP(fd,6)); + party->removemember(sd, RFIFOL(fd,2), RFIFOP(fd,6)); } void clif_parse_PartyChangeOption(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); @@ -11882,10 +11957,10 @@ void clif_parse_PartyMessage(int fd, struct map_session_data* sd) __attribute__( /// 0108 <packet len>.W <text>.?B (<name> : <message>) 00 void clif_parse_PartyMessage(int fd, struct map_session_data* sd) { - const char* text = (char*)RFIFOP(fd,4); + const char *text = RFIFOP(fd,4); int textlen = RFIFOW(fd,2) - 4; - char *name, *message; + const char *name, *message; size_t namelen, messagelen; // validate packet and retrieve name and message @@ -12140,7 +12215,7 @@ void clif_parse_PartyRecruitRegisterReq(int fd, struct map_session_data* sd) { #ifdef PARTY_RECRUIT short level = RFIFOW(fd,2); - const char *notice = (const char*)RFIFOP(fd, 4); + const char *notice = RFIFOP(fd, 4); party->recruit_register(sd, level, notice); #else @@ -12263,9 +12338,7 @@ void clif_parse_PartyRecruitUpdateReq(int fd, struct map_session_data *sd) __att void clif_parse_PartyRecruitUpdateReq(int fd, struct map_session_data *sd) { #ifdef PARTY_RECRUIT - const char *notice; - - notice = (const char*)RFIFOP(fd, 2); + const char *notice = RFIFOP(fd, 2); party->recruit_update(sd, notice); #else @@ -12566,8 +12639,8 @@ void clif_parse_PurchaseReq(int fd, struct map_session_data* sd) __attribute__(( void clif_parse_PurchaseReq(int fd, struct map_session_data* sd) { int len = (int)RFIFOW(fd,2) - 8; - int id = (int)RFIFOL(fd,4); - const uint8* data = (uint8*)RFIFOP(fd,8); + int id = RFIFOL(fd,4); + const uint8 *data = RFIFOP(fd,8); vending->purchase(sd, id, sd->vended_id, data, len/4); @@ -12581,9 +12654,9 @@ void clif_parse_PurchaseReq2(int fd, struct map_session_data* sd) __attribute__( void clif_parse_PurchaseReq2(int fd, struct map_session_data* sd) { int len = (int)RFIFOW(fd,2) - 12; - int aid = (int)RFIFOL(fd,4); - int uid = (int)RFIFOL(fd,8); - const uint8* data = (uint8*)RFIFOP(fd,12); + int aid = RFIFOL(fd,4); + int uid = RFIFOL(fd,8); + const uint8 *data = RFIFOP(fd,12); vending->purchase(sd, aid, uid, data, len/4); @@ -12600,9 +12673,9 @@ void clif_parse_OpenVending(int fd, struct map_session_data* sd) __attribute__(( /// 1 = open void clif_parse_OpenVending(int fd, struct map_session_data* sd) { short len = (short)RFIFOW(fd,2) - 85; - const char* message = (char*)RFIFOP(fd,4); - bool flag = (bool)RFIFOB(fd,84); - const uint8* data = (uint8*)RFIFOP(fd,85); + const char *message = RFIFOP(fd,4); + bool flag = (RFIFOB(fd,84) != 0) ? true : false; + const uint8 *data = RFIFOP(fd,85); if( !flag ) sd->state.prevend = sd->state.workinprogress = 0; @@ -12627,9 +12700,10 @@ void clif_parse_OpenVending(int fd, struct map_session_data* sd) { void clif_parse_CreateGuild(int fd,struct map_session_data *sd) __attribute__((nonnull (2))); /// Guild creation request (CZ_REQ_MAKE_GUILD). /// 0165 <char id>.L <guild name>.24B -void clif_parse_CreateGuild(int fd,struct map_session_data *sd) { - char* name = (char*)RFIFOP(fd,6); - name[NAME_LENGTH-1] = '\0'; +void clif_parse_CreateGuild(int fd,struct map_session_data *sd) +{ + char name[NAME_LENGTH]; + safestrncpy(name, RFIFOP(fd,6), NAME_LENGTH); if(map->list[sd->bl.m].flag.guildlock) { //Guild locked. @@ -12684,7 +12758,7 @@ void clif_parse_GuildRequestInfo(int fd, struct map_session_data *sd) clif->guild_expulsionlist(sd); break; default: - ShowError("clif: guild request info: unknown type %d\n", RFIFOL(fd,2)); + ShowError("clif: guild request info: unknown type %u\n", RFIFOL(fd,2)); break; } } @@ -12700,7 +12774,7 @@ void clif_parse_GuildChangePositionInfo(int fd, struct map_session_data *sd) return; for(i = 4; i < RFIFOW(fd,2); i += 40 ){ - guild->change_position(sd->status.guild_id, RFIFOL(fd,i), RFIFOL(fd,i+4), RFIFOL(fd,i+12), (char*)RFIFOP(fd,i+16)); + guild->change_position(sd->status.guild_id, RFIFOL(fd,i), RFIFOL(fd,i+4), RFIFOL(fd,i+12), RFIFOP(fd,i+16)); } } @@ -12815,8 +12889,8 @@ bool clif_validate_emblem(const uint8 *emblem, unsigned long emblem_len) { switch( RBUFW(buf,28) ) { case 8: // palette indexes { - const uint8 *indexes = (const uint8 *)RBUFP(buf,offbits); - const uint32 *palette = (const uint32 *)RBUFP(buf,BITMAPFILEHEADER_SIZE + BITMAPINFOHEADER_SIZE); + const uint8 *indexes = RBUFP(buf,offbits); + const uint32 *palette = RBUFP(buf,BITMAPFILEHEADER_SIZE + BITMAPINFOHEADER_SIZE); for (i = 0; i < BITMAP_WIDTH * BITMAP_HEIGHT; i++) { if( indexes[i] >= palettesize ) // Invalid color @@ -12834,7 +12908,7 @@ bool clif_validate_emblem(const uint8 *emblem, unsigned long emblem_len) { } case 24: // full colors { - const struct s_bitmaptripple *pixels = (const struct s_bitmaptripple*)RBUFP(buf,offbits); + const struct s_bitmaptripple *pixels = RBUFP(buf,offbits); for (i = 0; i < BITMAP_WIDTH * BITMAP_HEIGHT; i++) { // if( pixels[i].r < 0xF8 || pixels[i].g > 0x07 || pixels[i].b < 0xF8 ) @@ -12882,18 +12956,22 @@ void clif_parse_GuildChangeNotice(int fd, struct map_session_data* sd) __attribu void clif_parse_GuildChangeNotice(int fd, struct map_session_data* sd) { int guild_id = RFIFOL(fd,2); - char* msg1 = (char*)RFIFOP(fd,6); - char* msg2 = (char*)RFIFOP(fd,66); + char *msg1 = NULL, *msg2 = NULL; - if(!sd->state.gmaster_flag) + if (!sd->state.gmaster_flag) return; + msg1 = aStrndup(RFIFOP(fd,6), MAX_GUILDMES1-1); + msg2 = aStrndup(RFIFOP(fd,66), MAX_GUILDMES2-1); + // compensate for some client defects when using multilingual mode if (msg1[0] == '|' && msg1[3] == '|') msg1+= 3; // skip duplicate marker if (msg2[0] == '|' && msg2[3] == '|') msg2+= 3; // skip duplicate marker if (msg2[0] == '|') msg2[strnlen(msg2, MAX_GUILDMES2)-1] = '\0'; // delete extra space at the end of string guild->change_notice(sd, guild_id, msg1, msg2); + aFree(msg1); + aFree(msg2); } // Helper function for guild invite functions @@ -12931,14 +13009,15 @@ void clif_parse_GuildInvite(int fd,struct map_session_data *sd) { void clif_parse_GuildInvite2(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Guild invite request (/guildinvite) (CZ_REQ_JOIN_GUILD2). /// 0916 <char name>.24B -void clif_parse_GuildInvite2(int fd, struct map_session_data *sd) { - char *nick = (char*)RFIFOP(fd, 2); - struct map_session_data *t_sd = map->nick2sd(nick); +void clif_parse_GuildInvite2(int fd, struct map_session_data *sd) +{ + char nick[NAME_LENGTH]; + struct map_session_data *t_sd = NULL; - nick[NAME_LENGTH - 1] = '\0'; + safestrncpy(nick, RFIFOP(fd, 2), NAME_LENGTH); + t_sd = map->nick2sd(nick); - if (!clif_sub_guild_invite(fd, sd, t_sd)) - return; + clif_sub_guild_invite(fd, sd, t_sd); } void clif_parse_GuildReplyInvite(int fd,struct map_session_data *sd) __attribute__((nonnull (2))); @@ -12966,7 +13045,7 @@ void clif_parse_GuildLeave(int fd,struct map_session_data *sd) { return; } - guild->leave(sd,RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),(char*)RFIFOP(fd,14)); + guild->leave(sd,RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10), RFIFOP(fd,14)); } void clif_parse_GuildExpulsion(int fd,struct map_session_data *sd) __attribute__((nonnull (2))); @@ -12978,7 +13057,7 @@ void clif_parse_GuildExpulsion(int fd,struct map_session_data *sd) { clif->message(fd, msg_fd(fd,228)); return; } - guild->expulsion(sd,RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),(char*)RFIFOP(fd,14)); + guild->expulsion(sd, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10), RFIFOP(fd,14)); } void clif_parse_GuildMessage(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); @@ -12986,10 +13065,10 @@ void clif_parse_GuildMessage(int fd, struct map_session_data* sd) __attribute__( /// 017e <packet len>.W <text>.?B (<name> : <message>) 00 void clif_parse_GuildMessage(int fd, struct map_session_data* sd) { - const char* text = (char*)RFIFOP(fd,4); + const char *text = RFIFOP(fd,4); int textlen = RFIFOW(fd,2) - 4; - char *name, *message; + const char *name, *message; size_t namelen, messagelen; // validate packet and retrieve name and message @@ -13109,7 +13188,7 @@ void clif_parse_GuildBreak(int fd, struct map_session_data *sd) { clif->message(fd, msg_fd(fd,228)); return; } - guild->dobreak(sd,(char*)RFIFOP(fd,2)); + guild->dobreak(sd, RFIFOP(fd,2)); } /// Pet @@ -13185,7 +13264,7 @@ void clif_parse_ChangePetName(int fd, struct map_session_data *sd) __attribute__ /// 01a5 <name>.24B void clif_parse_ChangePetName(int fd, struct map_session_data *sd) { - pet->change_name(sd,(char*)RFIFOP(fd,2)); + pet->change_name(sd, RFIFOP(fd,2)); } void clif_parse_GMKick(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); @@ -13208,7 +13287,7 @@ void clif_parse_GMKick(int fd, struct map_session_data *sd) { case BL_PC: { char command[NAME_LENGTH+6]; - sprintf(command, "%ckick %s", atcommand->at_symbol, status->get_name(target)); + sprintf(command, "%ckick %s", atcommand->at_symbol, clif->get_bl_name(target)); atcommand->exec(fd, sd, command, true); } break; @@ -13223,7 +13302,7 @@ void clif_parse_GMKick(int fd, struct map_session_data *sd) { clif->GM_kickack(sd, 0); return; } - sprintf(command, "/kick %s (%d)", status->get_name(target), status->get_class(target)); + sprintf(command, "/kick %s (%d)", clif->get_bl_name(target), status->get_class(target)); logs->atcommand(sd, command); status_percent_damage(&sd->bl, target, 100, 0, true); // can invalidate 'target' } @@ -13266,12 +13345,12 @@ void clif_parse_GMShift(int fd, struct map_session_data *sd) __attribute__((nonn /// Request to warp to a character with given name. /// 01bb <char name>.24B void clif_parse_GMShift(int fd, struct map_session_data *sd) -{// FIXME: remove is supposed to receive account name for clients prior 20100803RE - char *player_name; +{ + // FIXME: remove is supposed to receive account name for clients prior 20100803RE + char player_name[NAME_LENGTH]; char command[NAME_LENGTH+8]; - player_name = (char*)RFIFOP(fd,2); - player_name[NAME_LENGTH-1] = '\0'; + safestrncpy(player_name, RFIFOP(fd,2), NAME_LENGTH); sprintf(command, "%cjumpto %s", atcommand->at_symbol, player_name); atcommand->exec(fd, sd, command, true); @@ -13302,12 +13381,12 @@ void clif_parse_GMRecall(int fd, struct map_session_data *sd) __attribute__((non /// Request to summon a player with given name to own position. /// 01bd <char name>.24B void clif_parse_GMRecall(int fd, struct map_session_data *sd) -{// FIXME: recall is supposed to receive account name for clients prior 20100803RE - char *player_name; - char command [NAME_LENGTH+8]; +{ + // FIXME: recall is supposed to receive account name for clients prior 20100803RE + char player_name[NAME_LENGTH]; + char command[NAME_LENGTH+8]; - player_name = (char*)RFIFOP(fd,2); - player_name[NAME_LENGTH-1] = '\0'; + safestrncpy(player_name, RFIFOP(fd,2), NAME_LENGTH); sprintf(command, "%crecall %s", atcommand->at_symbol, player_name); atcommand->exec(fd, sd, command, true); @@ -13343,16 +13422,16 @@ void clif_parse_GM_Monster_Item(int fd, struct map_session_data *sd) __attribute /// /item agitinvest - reset current global agit investments.(not yet implemented) /// 013f <item/mob name>.24B /// 09ce <item/mob name>.100B [Ind/Yommy<3] -void clif_parse_GM_Monster_Item(int fd, struct map_session_data *sd) { - struct packet_gm_monster_item *p = P2PTR(fd); +void clif_parse_GM_Monster_Item(int fd, struct map_session_data *sd) +{ + const struct packet_gm_monster_item *p = RP2PTR(fd); int i, count; - char *item_monster_name; + char item_monster_name[sizeof p->str]; struct item_data *item_array[10]; struct mob_db *mob_array[10]; char command[256]; - item_monster_name = p->str; - item_monster_name[(sizeof(struct packet_gm_monster_item)-2)-1] = '\0'; + safestrncpy(item_monster_name, p->str, sizeof(item_monster_name)); if ( (count=itemdb->search_name_array(item_array, 10, item_monster_name, 1)) > 0 ) { for(i = 0; i < count; i++) { @@ -13473,9 +13552,10 @@ void clif_parse_GMRc(int fd, struct map_session_data* sd) __attribute__((nonnull void clif_parse_GMRc(int fd, struct map_session_data* sd) { char command[NAME_LENGTH+15]; - char *name = (char*)RFIFOP(fd,2); + char name[NAME_LENGTH]; + + safestrncpy(name, RFIFOP(fd,2), NAME_LENGTH); - name[NAME_LENGTH-1] = '\0'; sprintf(command, "%cmute %d %s", atcommand->at_symbol, 60, name); atcommand->exec(fd, sd, command, true); } @@ -13490,7 +13570,7 @@ void clif_account_name(struct map_session_data* sd, int account_id, const char* WFIFOHEAD(fd,packet_len(0x1e0)); WFIFOW(fd,0) = 0x1e0; WFIFOL(fd,2) = account_id; - safestrncpy((char*)WFIFOP(fd,6), accname, NAME_LENGTH); + safestrncpy(WFIFOP(fd,6), accname, NAME_LENGTH); WFIFOSET(fd,packet_len(0x1e0)); } @@ -13534,13 +13614,14 @@ void clif_parse_PMIgnore(int fd, struct map_session_data* sd) __attribute__((non /// type: /// 0 = (/ex nick) deny speech from nick /// 1 = (/in nick) allow speech from nick -void clif_parse_PMIgnore(int fd, struct map_session_data* sd) { - char* nick; +void clif_parse_PMIgnore(int fd, struct map_session_data* sd) +{ + char nick[NAME_LENGTH]; uint8 type; int i; - nick = (char*)RFIFOP(fd,2); // speed up - nick[NAME_LENGTH-1] = '\0'; // to be sure that the player name has at most 23 characters + safestrncpy(nick, RFIFOP(fd,2), NAME_LENGTH); + type = RFIFOB(fd,26); if( type == 0 ) { // Add name to ignore list (block) @@ -13798,12 +13879,14 @@ void clif_friendlist_req(struct map_session_data* sd, int account_id, int char_i void clif_parse_FriendsListAdd(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to add a player as friend (CZ_ADD_FRIENDS). /// 0202 <name>.24B -void clif_parse_FriendsListAdd(int fd, struct map_session_data *sd) { +void clif_parse_FriendsListAdd(int fd, struct map_session_data *sd) +{ struct map_session_data *f_sd; int i; - char *nick = (char*)RFIFOP(fd,2); + char nick[NAME_LENGTH]; + + safestrncpy(nick, RFIFOP(fd,2), NAME_LENGTH); - nick[NAME_LENGTH - 1] = '\0'; f_sd = map->nick2sd(nick); // ensure that the request player's friend list is not full @@ -14022,17 +14105,17 @@ void clif_ranklist_sub(unsigned char *buf, enum fame_list_type type) { for( i = 0; i < 10 && i < MAX_FAME_LIST; i++ ) { if( list[i].id > 0 ) { if( strcmp(list[i].name, "-") == 0 && (name = map->charid2nick(list[i].id)) != NULL ) { - strncpy((char *)(WBUFP(buf, 24 * i)), name, NAME_LENGTH); + strncpy(WBUFP(buf, 24 * i), name, NAME_LENGTH); } else { - strncpy((char *)(WBUFP(buf, 24 * i)), list[i].name, NAME_LENGTH); + strncpy(WBUFP(buf, 24 * i), list[i].name, NAME_LENGTH); } } else { - strncpy((char *)(WBUFP(buf, 24 * i)), "None", 5); + strncpy(WBUFP(buf, 24 * i), "None", 5); } WBUFL(buf, 24 * 10 + i * 4) = list[i].fame; //points } for( ;i < 10; i++ ) { // In case the MAX is less than 10. - strncpy((char *)(WBUFP(buf, 24 * i)), "Unavailable", 12); + strncpy(WBUFP(buf, 24 * i), "Unavailable", 12); WBUFL(buf, 24 * 10 + i * 4) = 0; } } @@ -14215,7 +14298,7 @@ void clif_ranking_pk(struct map_session_data* sd) { WFIFOHEAD(fd,packet_len(0x238)); WFIFOW(fd,0) = 0x238; for (i = 0; i < 10;i ++) { - strncpy((char*)WFIFOP(fd, i * 24 + 2), "Unknown", NAME_LENGTH); + strncpy(WFIFOP(fd, i * 24 + 2), "Unknown", NAME_LENGTH); WFIFOL(fd,i*4+242) = 0; } WFIFOSET(fd, packet_len(0x238)); @@ -14275,8 +14358,9 @@ void clif_feel_req(int fd, struct map_session_data *sd, uint16 skill_lv) void clif_parse_ChangeHomunculusName(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// Request to change homunculus' name (CZ_RENAME_MER). /// 0231 <name>.24B -void clif_parse_ChangeHomunculusName(int fd, struct map_session_data *sd) { - homun->change_name(sd,(char*)RFIFOP(fd,2)); +void clif_parse_ChangeHomunculusName(int fd, struct map_session_data *sd) +{ + homun->change_name(sd, RFIFOP(fd,2)); } void clif_parse_HomMoveToMaster(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); @@ -14443,7 +14527,7 @@ void clif_parse_Check(int fd, struct map_session_data *sd) if(!pc_has_permission(sd, PC_PERM_USE_CHECK)) return; - safestrncpy(charname, (const char*)RFIFOP(fd,packet_db[RFIFOW(fd,0)].pos[0]), sizeof(charname)); + safestrncpy(charname, RFIFOP(fd,packet_db[RFIFOW(fd,0)].pos[0]), sizeof(charname)); if( ( pl_sd = map->nick2sd(charname) ) == NULL || pc_get_group_level(sd) < pc_get_group_level(pl_sd) ) { return; @@ -14534,8 +14618,8 @@ void clif_Mail_new(int fd, int mail_id, const char *sender, const char *title) WFIFOHEAD(fd,packet_len(0x24a)); WFIFOW(fd,0) = 0x24a; WFIFOL(fd,2) = mail_id; - safestrncpy((char*)WFIFOP(fd,6), title, MAIL_TITLE_LENGTH); - safestrncpy((char*)WFIFOP(fd,46), sender, NAME_LENGTH); + safestrncpy(WFIFOP(fd,6), title, MAIL_TITLE_LENGTH); + safestrncpy(WFIFOP(fd,46), sender, NAME_LENGTH); WFIFOSET(fd,packet_len(0x24a)); } @@ -14641,8 +14725,8 @@ void clif_Mail_read(struct map_session_data *sd, int mail_id) WFIFOW(fd,0) = 0x242; WFIFOW(fd,2) = len; WFIFOL(fd,4) = msg->id; - safestrncpy((char*)WFIFOP(fd,8), msg->title, MAIL_TITLE_LENGTH + 1); - safestrncpy((char*)WFIFOP(fd,48), msg->send_name, NAME_LENGTH + 1); + safestrncpy(WFIFOP(fd,8), msg->title, MAIL_TITLE_LENGTH + 1); + safestrncpy(WFIFOP(fd,48), msg->send_name, NAME_LENGTH + 1); WFIFOL(fd,72) = 0; WFIFOL(fd,76) = msg->zeny; @@ -14661,7 +14745,7 @@ void clif_Mail_read(struct map_session_data *sd, int mail_id) memset(WFIFOP(fd,80), 0x00, 19); WFIFOB(fd,99) = (unsigned char)msg_len; - safestrncpy((char*)WFIFOP(fd,100), msg->body, msg_len + 1); + safestrncpy(WFIFOP(fd,100), msg->body, msg_len + 1); WFIFOSET(fd,len); if (msg->status == MAIL_UNREAD) { @@ -14886,15 +14970,15 @@ void clif_parse_Mail_send(int fd, struct map_session_data *sd) msg.send_id = sd->status.char_id; msg.dest_id = 0; // will attempt to resolve name safestrncpy(msg.send_name, sd->status.name, NAME_LENGTH); - safestrncpy(msg.dest_name, (char*)RFIFOP(fd,4), NAME_LENGTH); - safestrncpy(msg.title, (char*)RFIFOP(fd,28), MAIL_TITLE_LENGTH); + safestrncpy(msg.dest_name, RFIFOP(fd,4), NAME_LENGTH); + safestrncpy(msg.title, RFIFOP(fd,28), MAIL_TITLE_LENGTH); if (msg.title[0] == '\0') { return; // Message has no length and somehow client verification was skipped. } if (body_len) - safestrncpy(msg.body, (char*)RFIFOP(fd,69), body_len + 1); + safestrncpy(msg.body, RFIFOP(fd,69), body_len + 1); else memset(msg.body, 0x00, MAIL_BODY_LENGTH); @@ -14934,7 +15018,7 @@ void clif_Auction_openwindow(struct map_session_data *sd) /// Returns auction item search results (ZC_AUCTION_ITEM_REQ_SEARCH). /// 0252 <packet len>.W <pages>.L <count>.L { <auction id>.L <seller name>.24B <name id>.W <type>.L <amount>.W <identified>.B <damaged>.B <refine>.B <card1>.W <card2>.W <card3>.W <card4>.W <now price>.L <max price>.L <buyer name>.24B <delete time>.L }* -void clif_Auction_results(struct map_session_data *sd, short count, short pages, uint8 *buf) +void clif_Auction_results(struct map_session_data *sd, short count, short pages, const uint8 *buf) { int i, fd, len = sizeof(struct auction_data); struct auction_data auction; @@ -14953,7 +15037,7 @@ void clif_Auction_results(struct map_session_data *sd, short count, short pages, memcpy(&auction, RBUFP(buf,i * len), len); WFIFOL(fd,k) = auction.auction_id; - safestrncpy((char*)WFIFOP(fd,4+k), auction.seller_name, NAME_LENGTH); + safestrncpy(WFIFOP(fd,4+k), auction.seller_name, NAME_LENGTH); if( (item = itemdb->exists(auction.item.nameid)) != NULL && item->view_id > 0 ) WFIFOW(fd,28+k) = item->view_id; @@ -14971,7 +15055,7 @@ void clif_Auction_results(struct map_session_data *sd, short count, short pages, WFIFOW(fd,45+k) = auction.item.card[3]; WFIFOL(fd,47+k) = auction.price; WFIFOL(fd,51+k) = auction.buynow; - safestrncpy((char*)WFIFOP(fd,55+k), auction.buyer_name, NAME_LENGTH); + safestrncpy(WFIFOP(fd,55+k), auction.buyer_name, NAME_LENGTH); WFIFOL(fd,79+k) = (uint32)auction.timestamp; } WFIFOSET(fd,WFIFOW(fd,2)); @@ -15245,7 +15329,7 @@ void clif_parse_Auction_search(int fd, struct map_session_data* sd) clif->pAuction_cancelreg(fd, sd); - safestrncpy(search_text, (char*)RFIFOP(fd,8), sizeof(search_text)); + safestrncpy(search_text, RFIFOP(fd,8), sizeof(search_text)); intif->Auction_requestlist(sd->status.char_id, type, price, search_text, page); } @@ -15381,13 +15465,25 @@ void clif_parse_cashshop_buy(int fd, struct map_session_data *sd) int len = RFIFOW(fd,2); int points = RFIFOL(fd,4); int count = RFIFOW(fd,8); - unsigned short* item_list = (unsigned short*)RFIFOP(fd,10); + struct itemlist item_list = { 0 }; + int i; if( len < 10 || len != 10 + count * 4) { - ShowWarning("Player %u sent incorrect cash shop buy packet (len %u:%u)!\n", sd->status.char_id, len, 10 + count * 4); + ShowWarning("Player %d sent incorrect cash shop buy packet (len %d:%d)!\n", sd->status.char_id, len, 10 + count * 4); return; } - fail = npc->cashshop_buylist(sd,points,count,item_list); + VECTOR_INIT(item_list); + VECTOR_ENSURE(item_list, count, 1); + for (i = 0; i < count; i++) { + struct itemlist_entry entry = { 0 }; + + entry.amount = RFIFOW(fd, 10 + 4 * i); + entry.id = RFIFOW(fd, 10 + 4 * i + 2); // Nameid + + VECTOR_PUSH(item_list, entry); + } + fail = npc->cashshop_buylist(sd, points, &item_list); + VECTOR_CLEAR(item_list); #endif } @@ -15506,7 +15602,7 @@ void clif_bossmapinfo(int fd, struct mob_data *md, short flag) WFIFOW(fd,11) = hours; // Hours WFIFOW(fd,13) = minutes; // Minutes } - safestrncpy((char*)WFIFOP(fd,19), md->db->jname, NAME_LENGTH); + safestrncpy(WFIFOP(fd,19), md->db->jname, NAME_LENGTH); } WFIFOSET(fd,70); @@ -15538,7 +15634,7 @@ void clif_parse_EquipTick(int fd, struct map_session_data* sd) __attribute__((no /// 1 = enabled void clif_parse_EquipTick(int fd, struct map_session_data* sd) { - bool flag = (bool)RFIFOL(fd,6); + bool flag = (RFIFOL(fd,6) != 0) ? true : false; sd->status.show_equip = flag; clif->equiptickack(sd, flag); } @@ -15572,7 +15668,7 @@ void clif_quest_send_list(struct map_session_data *sd) + sd->avail_quests * (sizeof(struct packet_quest_list_info) + MAX_QUEST_OBJECTIVES * sizeof(struct packet_mission_info_sub)); // >= than the actual length buf = aMalloc(len); - packet = (struct packet_quest_list_header *)WBUFP(buf, 0); + packet = WBUFP(buf, 0); real_len = sizeof(*packet); packet->PacketType = questListType; @@ -15882,7 +15978,7 @@ void clif_mercenary_info(struct map_session_data *sd) { #endif WFIFOW(fd,18) = mstatus->flee; WFIFOW(fd,20) = mstatus->amotion; - safestrncpy((char*)WFIFOP(fd,22), md->db->name, NAME_LENGTH); + safestrncpy(WFIFOP(fd,22), md->db->name, NAME_LENGTH); WFIFOW(fd,46) = md->db->lv; WFIFOL(fd,48) = mstatus->hp; WFIFOL(fd,52) = mstatus->max_hp; @@ -15924,7 +16020,7 @@ void clif_mercenary_skillblock(struct map_session_data *sd) WFIFOW(fd, len + 8) = 0; WFIFOW(fd, len + 10) = 0; } - safestrncpy((char*)WFIFOP(fd,len+12), skill->get_name(id), NAME_LENGTH); + safestrncpy(WFIFOP(fd,len+12), skill->get_name(id), NAME_LENGTH); WFIFOB(fd,len+36) = 0; // Skillable for Mercenary? len += 37; } @@ -16083,10 +16179,10 @@ void clif_parse_BattleChat(int fd, struct map_session_data* sd) __attribute__((n /// 0x2db <packet len>.W <text>.?B (<name> : <message>) 00 void clif_parse_BattleChat(int fd, struct map_session_data* sd) { - const char* text = (char*)RFIFOP(fd,4); + const char *text = RFIFOP(fd,4); int textlen = RFIFOW(fd,2) - 4; - char *name, *message; + const char *name, *message; size_t namelen, messagelen; if( !clif->process_message(sd, 0, &name, &namelen, &message, &messagelen) ) @@ -16146,7 +16242,7 @@ void clif_sendbgemblem_area(struct map_session_data *sd) WBUFW(buf, 0) = 0x2dd; WBUFL(buf,2) = sd->bl.id; - safestrncpy((char*)WBUFP(buf,6), sd->status.name, NAME_LENGTH); // name don't show in screen. + safestrncpy(WBUFP(buf,6), sd->status.name, NAME_LENGTH); // name don't show in screen. WBUFW(buf,30) = sd->bg_id; clif->send(buf,packet_len(0x2dd), &sd->bl, AREA); } @@ -16157,7 +16253,7 @@ void clif_sendbgemblem_single(int fd, struct map_session_data *sd) WFIFOHEAD(fd,32); WFIFOW(fd,0) = 0x2dd; WFIFOL(fd,2) = sd->bl.id; - safestrncpy((char*)WFIFOP(fd,6), sd->status.name, NAME_LENGTH); + safestrncpy(WFIFOP(fd,6), sd->status.name, NAME_LENGTH); WFIFOW(fd,30) = sd->bg_id; WFIFOSET(fd,packet_len(0x2dd)); } @@ -16369,36 +16465,51 @@ void clif_parse_LessEffect(int fd, struct map_session_data* sd) sd->state.lesseffect = ( isLess != 0 ); } -void clif_parse_ItemListWindowSelected(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); +void clif_parse_ItemListWindowSelected(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); /// S 07e4 <length>.w <option>.l <val>.l {<index>.w <amount>.w).4b* -void clif_parse_ItemListWindowSelected(int fd, struct map_session_data* sd) { - int n = (RFIFOW(fd,2)-12) / 4; +void clif_parse_ItemListWindowSelected(int fd, struct map_session_data *sd) +{ + int n = ((int)RFIFOW(fd,2) - 12) / 4; int type = RFIFOL(fd,4); int flag = RFIFOL(fd,8); // Button clicked: 0 = Cancel, 1 = OK - unsigned short* item_list = (unsigned short*)RFIFOP(fd,12); + struct itemlist item_list = { 0 }; + int i; if( sd->state.trading || sd->npc_shopid ) return; - if( flag == 0 || n == 0) { + if (flag == 0 || n <= 0) { clif_menuskill_clear(sd); return; // Canceled by player. } - if( sd->menuskill_id != SO_EL_ANALYSIS && sd->menuskill_id != GN_CHANGEMATERIAL ) { + if (n > MAX_INVENTORY) + n = MAX_INVENTORY; // It should be impossible to have more than that. + + if (sd->menuskill_id != SO_EL_ANALYSIS && sd->menuskill_id != GN_CHANGEMATERIAL) { clif_menuskill_clear(sd); return; // Prevent hacking. } + VECTOR_INIT(item_list); + VECTOR_ENSURE(item_list, n, 1); + for (i = 0; i < n; i++) { + struct itemlist_entry entry = { 0 }; + entry.id = (int)RFIFOW(fd, 12 + 4 * i) - 2; // Inventory index + entry.amount = RFIFOW(fd, 12 + 4 * i + 2); + VECTOR_PUSH(item_list, entry); + } + switch( type ) { case 0: // Change Material - skill->changematerial(sd,n,item_list); + skill->changematerial(sd, &item_list); break; case 1: // Level 1: Pure to Rough case 2: // Level 2: Rough to Pure - skill->elementalanalysis(sd,n,type,item_list); + skill->elementalanalysis(sd, type, &item_list); break; } + VECTOR_CLEAR(item_list); clif_menuskill_clear(sd); return; @@ -16483,7 +16594,7 @@ void clif_parse_ReqOpenBuyingStore(int fd, struct map_session_data* sd) __attrib /// 1 = open void clif_parse_ReqOpenBuyingStore(int fd, struct map_session_data* sd) { const unsigned int blocksize = 8; - uint8* itemlist; + const uint8 *itemlist; char storename[MESSAGE_SIZE]; unsigned char result; int zenylimit; @@ -16495,13 +16606,13 @@ void clif_parse_ReqOpenBuyingStore(int fd, struct map_session_data* sd) { // TODO: Make this check global for all variable length packets. if( packet_len < 89 ) {// minimum packet length - ShowError("clif_parse_ReqOpenBuyingStore: Malformed packet (expected length=%u, length=%u, account_id=%d).\n", 89, packet_len, sd->bl.id); + ShowError("clif_parse_ReqOpenBuyingStore: Malformed packet (expected length=%u, length=%u, account_id=%d).\n", 89U, packet_len, sd->bl.id); return; } zenylimit = RFIFOL(fd,info->pos[1]); result = RFIFOL(fd,info->pos[2]); - safestrncpy(storename, (const char*)RFIFOP(fd,info->pos[3]), sizeof(storename)); + safestrncpy(storename, RFIFOP(fd,info->pos[3]), sizeof(storename)); itemlist = RFIFOP(fd,info->pos[4]); // so that buyingstore_create knows, how many elements it has access to @@ -16665,7 +16776,7 @@ void clif_parse_ReqTradeBuyingStore(int fd, struct map_session_data* sd) __attri /// 0819 <packet len>.W <account id>.L <store id>.L { <index>.W <name id>.W <amount>.W }* void clif_parse_ReqTradeBuyingStore(int fd, struct map_session_data* sd) { const unsigned int blocksize = 6; - uint8* itemlist; + const uint8 *itemlist; int account_id; unsigned int count, packet_len, buyer_id; struct s_packet_db* info = &packet_db[RFIFOW(fd,0)]; @@ -16674,7 +16785,7 @@ void clif_parse_ReqTradeBuyingStore(int fd, struct map_session_data* sd) { if( packet_len < 12 ) {// minimum packet length - ShowError("clif_parse_ReqTradeBuyingStore: Malformed packet (expected length=%u, length=%u, account_id=%d).\n", 12, packet_len, sd->bl.id); + ShowError("clif_parse_ReqTradeBuyingStore: Malformed packet (expected length=%u, length=%u, account_id=%d).\n", 12U, packet_len, sd->bl.id); return; } @@ -16687,7 +16798,7 @@ void clif_parse_ReqTradeBuyingStore(int fd, struct map_session_data* sd) { if( packet_len%blocksize ) { - ShowError("clif_parse_ReqTradeBuyingStore: Unexpected item list size %u (account_id=%d, buyer_id=%u, block size=%u)\n", packet_len, sd->bl.id, account_id, blocksize); + ShowError("clif_parse_ReqTradeBuyingStore: Unexpected item list size %u (account_id=%d, buyer_id=%d, block size=%u)\n", packet_len, sd->bl.id, account_id, blocksize); return; } count = packet_len/blocksize; @@ -16794,7 +16905,7 @@ void clif_parse_SearchStoreInfo(int fd, struct map_session_data* sd) { if( packet_len < 15 ) {// minimum packet length - ShowError("clif_parse_SearchStoreInfo: Malformed packet (expected length=%u, length=%u, account_id=%d).\n", 15, packet_len, sd->bl.id); + ShowError("clif_parse_SearchStoreInfo: Malformed packet (expected length=%u, length=%u, account_id=%d).\n", 15U, packet_len, sd->bl.id); return; } @@ -16976,10 +17087,10 @@ void clif_parse_debug(int fd,struct map_session_data *sd) { if( packet_len == -1 ) {// variable length packet_len = RFIFOW(fd,2); // clif_parse ensures, that this amount of data is already received } - ShowDebug("Packet debug of 0x%04X (length %d), %s session #%d, %d/%d (AID/CID)\n", cmd, packet_len, sd->state.active ? "authed" : "unauthed", fd, sd->status.account_id, sd->status.char_id); + ShowDebug("Packet debug of 0x%04X (length %d), %s session #%d, %d/%d (AID/CID)\n", (unsigned int)cmd, packet_len, sd->state.active ? "authed" : "unauthed", fd, sd->status.account_id, sd->status.char_id); } else { packet_len = (int)RFIFOREST(fd); - ShowDebug("Packet debug of 0x%04X (length %d), session #%d\n", cmd, packet_len, fd); + ShowDebug("Packet debug of 0x%04X (length %d), session #%d\n", (unsigned int)cmd, packet_len, fd); } ShowDump(RFIFOP(fd,0), packet_len); @@ -17275,8 +17386,8 @@ void clif_parse_MoveItem(int fd, struct map_session_data *sd) { /* [Ind/Hercules] */ void clif_cashshop_db(void) { - config_t cashshop_conf; - config_setting_t *cashshop = NULL, *cats = NULL; + struct config_t cashshop_conf; + struct config_setting_t *cashshop = NULL, *cats = NULL; const char *config_filename = "db/cashshop_db.conf"; // FIXME hardcoded name int i, item_count_t = 0; for( i = 0; i < CASHSHOP_TAB_MAX; i++ ) { @@ -17284,16 +17395,14 @@ void clif_cashshop_db(void) { clif->cs.item_count[i] = 0; } - if (libconfig->read_file(&cashshop_conf, config_filename)) { - ShowError("can't read %s\n", config_filename); + if (!libconfig->load_file(&cashshop_conf, config_filename)) return; - } cashshop = libconfig->lookup(&cashshop_conf, "cash_shop"); if( cashshop != NULL && (cats = libconfig->setting_get_elem(cashshop, 0)) != NULL ) { for(i = 0; i < CASHSHOP_TAB_MAX; i++) { - config_setting_t *cat; + struct config_setting_t *cat; char entry_name[10]; sprintf(entry_name,"cat_%d",i); @@ -17302,7 +17411,7 @@ void clif_cashshop_db(void) { int k, item_count = libconfig->setting_length(cat); for(k = 0; k < item_count; k++) { - config_setting_t *entry = libconfig->setting_get_elem(cat,k); + struct config_setting_t *entry = libconfig->setting_get_elem(cat,k); const char *name = config_setting_name(entry); int price = libconfig->setting_get_int(entry); struct item_data * data = NULL; @@ -17547,18 +17656,18 @@ void clif_maptypeproperty2(struct block_list *bl,enum send_target t) { p.PacketType = maptypeproperty2Type; p.type = 0x28; - p.flag.party = map->list[bl->m].flag.pvp ? 1 : 0; //PARTY - p.flag.guild = (map->list[bl->m].flag.battleground || map_flag_gvg(bl->m)) ? 1 : 0; // GUILD - p.flag.siege = (map->list[bl->m].flag.battleground || map_flag_gvg2(bl->m)) ? 1: 0; // SIEGE - p.flag.mineffect = map_flag_gvg(bl->m) ? 1 : ( (sd && sd->state.lesseffect) ? 1 : 0); // USE_SIMPLE_EFFECT - Forcing /mineffect in castles during WoE (probably redundant? I'm not sure) + p.flag.party = map->list[bl->m].flag.pvp ? 1 : 0; //PARTY + p.flag.guild = (map->list[bl->m].flag.battleground || map_flag_gvg(bl->m)) ? 1 : 0; // GUILD + p.flag.siege = (map->list[bl->m].flag.battleground || map_flag_gvg2(bl->m)) ? 1: 0; // SIEGE + p.flag.mineffect = map_flag_gvg(bl->m) ? 1 : ( (sd && sd->state.lesseffect) ? 1 : 0); // USE_SIMPLE_EFFECT - Forcing /mineffect in castles during WoE (probably redundant? I'm not sure) p.flag.nolockon = 0; // DISABLE_LOCKON - TODO - p.flag.countpk = map->list[bl->m].flag.pvp ? 1 : 0; // COUNT_PK - p.flag.nopartyformation = map->list[bl->m].flag.partylock ? 1 : 0; // NO_PARTY_FORMATION - p.flag.bg = map->list[bl->m].flag.battleground ? 1 : 0; // BATTLEFIELD + p.flag.countpk = map->list[bl->m].flag.pvp ? 1 : 0; // COUNT_PK + p.flag.nopartyformation = map->list[bl->m].flag.partylock ? 1 : 0; // NO_PARTY_FORMATION + p.flag.bg = map->list[bl->m].flag.battleground ? 1 : 0; // BATTLEFIELD p.flag.nocostume = (map->list[bl->m].flag.noviewid & EQP_COSTUME) ? 1 : 0; // DISABLE_COSTUMEITEM - Disables Costume Sprite p.flag.usecart = 1; // USECART - TODO p.flag.summonstarmiracle = 0; // SUNMOONSTAR_MIRACLE - TODO - p.flag.SpareBits = 0; // UNUSED + p.flag.SpareBits = 0; // UNUSED clif->send(&p,sizeof(p),bl,t); #endif @@ -17606,7 +17715,7 @@ void clif_ShowScript(struct block_list* bl, const char* message) { WBUFW(buf,0)=0x8b3; WBUFW(buf,2)=len+8; WBUFL(buf,4)=bl->id; - safestrncpy((char *) WBUFP(buf,8),message,len); + safestrncpy(WBUFP(buf,8),message,len); clif->send((unsigned char *) buf,WBUFW(buf,2),bl,ALL_CLIENT); } @@ -17646,7 +17755,8 @@ void clif_bgqueue_ack(struct map_session_data *sd, enum BATTLEGROUNDS_QUEUE_ACK } } -void clif_bgqueue_notice_delete(struct map_session_data *sd, enum BATTLEGROUNDS_QUEUE_NOTICE_DELETED response, char *name) { +void clif_bgqueue_notice_delete(struct map_session_data *sd, enum BATTLEGROUNDS_QUEUE_NOTICE_DELETED response, const char *name) +{ struct packet_bgqueue_notice_delete p; nullpo_retv(sd); @@ -17658,8 +17768,9 @@ void clif_bgqueue_notice_delete(struct map_session_data *sd, enum BATTLEGROUNDS_ } void clif_parse_bgqueue_register(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); -void clif_parse_bgqueue_register(int fd, struct map_session_data *sd) { - struct packet_bgqueue_register *p = P2PTR(fd); +void clif_parse_bgqueue_register(int fd, struct map_session_data *sd) +{ + const struct packet_bgqueue_register *p = RP2PTR(fd); struct bg_arena *arena = NULL; if( !bg->queue_on ) return; /* temp, until feature is complete */ @@ -17696,19 +17807,22 @@ void clif_bgqueue_update_info(struct map_session_data *sd, unsigned char arena_i } void clif_parse_bgqueue_checkstate(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); -void clif_parse_bgqueue_checkstate(int fd, struct map_session_data *sd) { - struct packet_bgqueue_checkstate *p = P2PTR(fd); +void clif_parse_bgqueue_checkstate(int fd, struct map_session_data *sd) +{ + const struct packet_bgqueue_checkstate *p = RP2PTR(fd); nullpo_retv(sd); - if ( sd->bg_queue.arena && sd->bg_queue.type ) { + if (sd->bg_queue.arena && sd->bg_queue.type) { clif->bgqueue_update_info(sd,sd->bg_queue.arena->id,bg->id2pos(sd->bg_queue.arena->queue_id,sd->status.account_id)); - } else + } else { clif->bgqueue_notice_delete(sd, BGQND_FAIL_NOT_QUEUING,p->bg_name); + } } void clif_parse_bgqueue_revoke_req(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); -void clif_parse_bgqueue_revoke_req(int fd, struct map_session_data *sd) { - struct packet_bgqueue_revoke_req *p = P2PTR(fd); +void clif_parse_bgqueue_revoke_req(int fd, struct map_session_data *sd) +{ + const struct packet_bgqueue_revoke_req *p = RP2PTR(fd); if( sd->bg_queue.arena ) bg->queue_pc_cleanup(sd); @@ -17717,8 +17831,9 @@ void clif_parse_bgqueue_revoke_req(int fd, struct map_session_data *sd) { } void clif_parse_bgqueue_battlebegin_ack(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); -void clif_parse_bgqueue_battlebegin_ack(int fd, struct map_session_data *sd) { - struct packet_bgqueue_battlebegin_ack *p = P2PTR(fd); +void clif_parse_bgqueue_battlebegin_ack(int fd, struct map_session_data *sd) +{ + const struct packet_bgqueue_battlebegin_ack *p = RP2PTR(fd); struct bg_arena *arena; if( !bg->queue_on ) return; /* temp, until feature is complete */ @@ -17854,10 +17969,11 @@ void clif_cart_additem_ack(struct map_session_data *sd, int flag) { clif->send(&p,sizeof(p), &sd->bl, SELF); } -void clif_parse_BankDeposit(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); /* Bank System [Yommy/Hercules] */ -void clif_parse_BankDeposit(int fd, struct map_session_data* sd) { - struct packet_banking_deposit_req *p = P2PTR(fd); +void clif_parse_BankDeposit(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); +void clif_parse_BankDeposit(int fd, struct map_session_data *sd) +{ + const struct packet_banking_deposit_req *p = RP2PTR(fd); int money; if (!battle_config.feature_banking) { @@ -17870,9 +17986,10 @@ void clif_parse_BankDeposit(int fd, struct map_session_data* sd) { pc->bank_deposit(sd,money); } -void clif_parse_BankWithdraw(int fd, struct map_session_data* sd) __attribute__((nonnull (2))); -void clif_parse_BankWithdraw(int fd, struct map_session_data* sd) { - struct packet_banking_withdraw_req *p = P2PTR(fd); +void clif_parse_BankWithdraw(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); +void clif_parse_BankWithdraw(int fd, struct map_session_data *sd) +{ + const struct packet_banking_withdraw_req *p = RP2PTR(fd); int money; if (!battle_config.feature_banking) { @@ -18107,32 +18224,30 @@ void clif_parse_NPCMarketClosed(int fd, struct map_session_data *sd) { sd->npc_shopid = 0; } -void clif_npc_market_purchase_ack(struct map_session_data *sd, struct packet_npc_market_purchase *req, unsigned char response) { +void clif_npc_market_purchase_ack(struct map_session_data *sd, const struct itemlist *item_list, unsigned char response) +{ #if PACKETVER >= 20131223 unsigned short c = 0; nullpo_retv(sd); - nullpo_retv(req); + nullpo_retv(item_list); npcmarket_result.PacketType = npcmarketresultackType; npcmarket_result.result = response == 0 ? 1 : 0;/* find other values */ - if( npcmarket_result.result ) { - unsigned short i, list_size = (req->PacketLength - 4) / sizeof(req->list[0]), j; - struct npc_data* nd; - struct npc_item_list *shop = NULL; - unsigned short shop_size = 0; - - nd = map->id2nd(sd->npc_shopid); - - shop = nd->u.scr.shop->item; - shop_size = nd->u.scr.shop->items; + if (npcmarket_result.result) { + struct npc_data *nd = map->id2nd(sd->npc_shopid); + struct npc_item_list *shop = nd->u.scr.shop->item; + unsigned short shop_size = nd->u.scr.shop->items; + int i; - for(i = 0; i < list_size; i++) { + for (i = 0; i < VECTOR_LENGTH(*item_list); i++) { + const struct itemlist_entry *entry = &VECTOR_INDEX(*item_list, i); + int j; - npcmarket_result.list[i].ITID = req->list[i].ITID; - npcmarket_result.list[i].qty = req->list[i].qty; + npcmarket_result.list[i].ITID = entry->id; + npcmarket_result.list[i].qty = entry->amount; - ARR_FIND( 0, shop_size, j, req->list[i].ITID == shop[j].nameid ); + ARR_FIND( 0, shop_size, j, entry->id == shop[j].nameid); npcmarket_result.list[i].price = (j != shop_size) ? shop[j].value : 0; @@ -18147,11 +18262,32 @@ void clif_npc_market_purchase_ack(struct map_session_data *sd, struct packet_npc } void clif_parse_NPCMarketPurchase(int fd, struct map_session_data *sd) __attribute__((nonnull (2))); -void clif_parse_NPCMarketPurchase(int fd, struct map_session_data *sd) { +void clif_parse_NPCMarketPurchase(int fd, struct map_session_data *sd) +{ #if PACKETVER >= 20131223 - struct packet_npc_market_purchase *p = P2PTR(fd); + const struct packet_npc_market_purchase *p = RP2PTR(fd); + int response = 0, i; + int count = (p->PacketLength - 4) / sizeof p->list[0]; + struct itemlist item_list; + + Assert_retv(count >= 0 && count <= MAX_INVENTORY); + + VECTOR_INIT(item_list); + VECTOR_ENSURE(item_list, count, 1); + + for (i = 0; i < count; i++) { + struct itemlist_entry entry = { 0 }; + + entry.id = p->list[i].ITID; + entry.amount = p->list[i].qty; + + VECTOR_PUSH(item_list, entry); + } - clif->npc_market_purchase_ack(sd,p,npc->market_buylist(sd,(p->PacketLength - 4) / sizeof(p->list[0]),p)); + response = npc->market_buylist(sd, &item_list); + clif->npc_market_purchase_ack(sd, &item_list, response); + + VECTOR_CLEAR(item_list); #endif } @@ -18271,7 +18407,7 @@ void clif_parse_RouletteGenerate(int fd, struct map_session_data* sd) { it.nameid = clif->rd.nameid[stage][0]; it.identify = 1; - pc->additem(sd, &it, clif->rd.qty[stage][0], LOG_TYPE_OTHER);/** TODO maybe a new log type for roulette items? **/ + pc->additem(sd, &it, clif->rd.qty[stage][0], LOG_TYPE_ROULETTE);/** TODO maybe a new log type for roulette items? **/ sd->roulette.stage = 0; result = GENERATE_ROULETTE_LOSING; @@ -18306,7 +18442,7 @@ void clif_parse_RouletteRecvItem(int fd, struct map_session_data* sd) { it.nameid = clif->rd.nameid[sd->roulette.prizeStage][sd->roulette.prizeIdx]; it.identify = 1; - switch (pc->additem(sd, &it, clif->rd.qty[sd->roulette.prizeStage][sd->roulette.prizeIdx], LOG_TYPE_OTHER)) { + switch (pc->additem(sd, &it, clif->rd.qty[sd->roulette.prizeStage][sd->roulette.prizeIdx], LOG_TYPE_ROULETTE)) { case 0: p.Result = RECV_ITEM_SUCCESS; sd->roulette.claimPrize = false; @@ -18335,8 +18471,8 @@ void clif_parse_RouletteRecvItem(int fd, struct map_session_data* sd) { } bool clif_parse_roulette_db(void) { - config_t roulette_conf; - config_setting_t *roulette = NULL, *levels = NULL; + struct config_t roulette_conf; + struct config_setting_t *roulette = NULL, *levels = NULL; const char *config_filename = "db/roulette_db.conf"; // FIXME hardcoded name int i, j, item_count_t = 0; @@ -18344,15 +18480,13 @@ bool clif_parse_roulette_db(void) { clif->rd.items[i] = 0; } - if (libconfig->read_file(&roulette_conf, config_filename)) { - ShowError("can't read %s\n", config_filename); + if (!libconfig->load_file(&roulette_conf, config_filename)) return false; - } roulette = libconfig->lookup(&roulette_conf, "roulette"); if( roulette != NULL && (levels = libconfig->setting_get_elem(roulette, 0)) != NULL ) { for(i = 0; i < MAX_ROULETTE_LEVEL; i++) { - config_setting_t *level; + struct config_setting_t *level; char entry_name[10]; sprintf(entry_name,"level_%d",i+1); @@ -18361,7 +18495,7 @@ bool clif_parse_roulette_db(void) { int k, item_count = libconfig->setting_length(level); for(k = 0; k < item_count; k++) { - config_setting_t *entry = libconfig->setting_get_elem(level,k); + struct config_setting_t *entry = libconfig->setting_get_elem(level,k); const char *name = config_setting_name(entry); int qty = libconfig->setting_get_int(entry); struct item_data * data = NULL; @@ -18607,6 +18741,44 @@ void clif_dressroom_open(struct map_session_data *sd, int view) WFIFOSET(fd,packet_len(0xa02)); } +/// Request to select cart's visual look for new cart design (ZC_SELECTCART). +/// 097f <Length>.W <identity>.L <type>.B +void clif_selectcart(struct map_session_data *sd) +{ +#if PACKETVER >= 20150805 + int i = 0, fd; + + fd = sd->fd; + + WFIFOHEAD(fd, 8 + MAX_CARTDECORATION_CARTS); + WFIFOW(fd, 0) = 0x97f; + WFIFOW(fd, 2) = 8 + MAX_CARTDECORATION_CARTS; + WFIFOL(fd, 4) = sd->status.account_id; + + for (i = 0; i < MAX_CARTDECORATION_CARTS; i++) { + WFIFOB(fd, 8 + i) = MAX_BASE_CARTS + 1 + i; + } + + WFIFOSET(fd, 8 + MAX_CARTDECORATION_CARTS); +#endif +} + +/** + * Returns the name of the given bl, in a client-friendly format. + * + * @param bl The requested bl. + * @return The bl's name (guaranteed to be non-NULL). + */ +const char *clif_get_bl_name(const struct block_list *bl) +{ + const char *name = status->get_name(bl); + + if (name == NULL) + return "Unknown"; + + return name; +} + /* */ unsigned short clif_decrypt_cmd( int cmd, struct map_session_data *sd ) { if( sd ) { @@ -18688,25 +18860,25 @@ int clif_parse(int fd) { if (RFIFOREST(fd) < 2) return 0; + if (sd) + parse_cmd_func = sd->parse_cmd_func; + else + parse_cmd_func = clif->parse_cmd; + + cmd = parse_cmd_func(fd,sd); + if (VECTOR_LENGTH(HPM->packets[hpClif_Parse]) > 0) { - int result = HPM->parse_packets(fd,hpClif_Parse); + int result = HPM->parse_packets(fd,cmd,hpClif_Parse); if (result == 1) continue; if (result == 2) return 0; } - if( sd ) - parse_cmd_func = sd->parse_cmd_func; - else - parse_cmd_func = clif->parse_cmd; - - cmd = parse_cmd_func(fd,sd); - // filter out invalid / unsupported packets if (cmd > MAX_PACKET_DB || cmd < MIN_PACKET_DB || packet_db[cmd].len == 0) { ShowWarning("clif_parse: Received unsupported packet (packet 0x%04x (0x%04x), %"PRIuS" bytes received), disconnecting session #%d.\n", - cmd, RFIFOW(fd,0), RFIFOREST(fd), fd); + (unsigned int)cmd, RFIFOW(fd,0), RFIFOREST(fd), fd); #ifdef DUMP_INVALID_PACKET ShowDump(RFIFOP(fd,0), RFIFOREST(fd)); #endif @@ -18722,7 +18894,7 @@ int clif_parse(int fd) { packet_len = RFIFOW(fd,2); if (packet_len < 4 || packet_len > 32768) { - ShowWarning("clif_parse: Received packet 0x%04x specifies invalid packet_len (%d), disconnecting session #%d.\n", cmd, packet_len, fd); + ShowWarning("clif_parse: Received packet 0x%04x specifies invalid packet_len (%d), disconnecting session #%d.\n", (unsigned int)cmd, packet_len, fd); #ifdef DUMP_INVALID_PACKET ShowDump(RFIFOP(fd,0), RFIFOREST(fd)); #endif @@ -18736,7 +18908,11 @@ int clif_parse(int fd) { return 0; // not enough data received to form the packet if( battle_config.packet_obfuscation == 2 || cmd != RFIFOW(fd, 0) || (sd && sd->parse_cmd_func == clif_parse_cmd_decrypt) ) { - RFIFOW(fd, 0) = cmd; + // Note: Overriding const qualifier to re-inject the decoded packet ID. +#define RFIFOP_mutable(fd, pos) ((void *)(sockt->session[fd]->rdata + sockt->session[fd]->rdata_pos + (pos))) + int16 *packet_id = RFIFOP_mutable(fd, 0); +#undef RFIFOP_mutable + *packet_id = cmd; if( sd ) { sd->cryptKey = (( sd->cryptKey * clif->cryptKey[1] ) + clif->cryptKey[2]) & 0xFFFFFFFF; // Update key for the next packet } @@ -18810,7 +18986,12 @@ static void __attribute__ ((unused)) packetdb_addpacket(short cmd, int len, ...) pFunc func; if (cmd > MAX_PACKET_DB) { - ShowError("Packet Error: packet 0x%x is greater than the maximum allowed (0x%x), skipping...\n", cmd, MAX_PACKET_DB); + ShowError("Packet Error: packet 0x%x is greater than the maximum allowed (0x%x), skipping...\n", (unsigned int)cmd, (unsigned int)MAX_PACKET_DB); + return; + } + + if (cmd < MIN_PACKET_DB) { + ShowError("Packet Error: packet 0x%x is lower than the minimum allowed (0x%x), skipping...\n", (unsigned int)cmd, (unsigned int)MIN_PACKET_DB); return; } @@ -19419,6 +19600,8 @@ void clif_defaults(void) { clif->cancelmergeitem = clif_cancelmergeitem; clif->comparemergeitem = clif_comparemergeitem; clif->ackmergeitems = clif_ackmergeitems; + /* Cart Deco */ + clif->selectcart = clif_selectcart; /*------------------------ *- Parse Incoming Packet @@ -19467,6 +19650,7 @@ void clif_defaults(void) { clif->pGetItemFromCart = clif_parse_GetItemFromCart; clif->pRemoveOption = clif_parse_RemoveOption; clif->pChangeCart = clif_parse_ChangeCart; + clif->pSelectCart = clif_parse_SelectCart; clif->pStatusUp = clif_parse_StatusUp; clif->pSkillUp = clif_parse_SkillUp; clif->pUseSkillToId = clif_parse_UseSkillToId; @@ -19663,4 +19847,6 @@ void clif_defaults(void) { clif->add_random_options = clif_add_random_options; clif->pHotkeyRowShift = clif_parse_HotkeyRowShift; clif->dressroom_open = clif_dressroom_open; + clif->pOneClick_ItemIdentify = clif_parse_OneClick_ItemIdentify; + clif->get_bl_name = clif_get_bl_name; } diff --git a/src/map/clif.h b/src/map/clif.h index 5a6b01d31..f930e4ca1 100644 --- a/src/map/clif.h +++ b/src/map/clif.h @@ -40,6 +40,7 @@ struct guild; struct homun_data; struct item; struct item_data; +struct itemlist; // map/itemdb.h struct map_session_data; struct mercenary_data; struct mob_data; @@ -58,12 +59,11 @@ struct view_data; * Defines **/ #define packet_len(cmd) packet_db[cmd].len -#define P2PTR(fd) RFIFO2PTR(fd) #define clif_menuskill_clear(sd) ((sd)->menuskill_id = (sd)->menuskill_val = (sd)->menuskill_val2 = 0) #define clif_disp_onlyself(sd,mes,len) clif->disp_message( &(sd)->bl, (mes), (len), SELF ) #define MAX_ROULETTE_LEVEL 7 /** client-defined value **/ #define MAX_ROULETTE_COLUMNS 9 /** client-defined value **/ -#define RGB2BGR(c) ((c & 0x0000FF) << 16 | (c & 0x00FF00) | (c & 0xFF0000) >> 16) +#define RGB2BGR(c) (((c) & 0x0000FF) << 16 | ((c) & 0x00FF00) | ((c) & 0xFF0000) >> 16) #define COLOR_RED 0xff0000U #define COLOR_GREEN 0x00ff00U @@ -73,12 +73,6 @@ struct view_data; /** * Enumerations **/ -enum {// packet DB - MIN_PACKET_DB = 0x0064, - MAX_PACKET_DB = 0x0F00, - MAX_PACKET_POS = 20, -}; - typedef enum send_target { ALL_CLIENT, ALL_SAMEMAP, @@ -862,7 +856,7 @@ struct clif_interface { void (*messageln) (const int fd, const char* mes); /* message+s(printf) */ void (*messages) (const int fd, const char *mes, ...) __attribute__((format(printf, 2, 3))); - bool (*process_message) (struct map_session_data *sd, int format, char **name_, size_t *namelen_, char **message_, size_t *messagelen_); + bool (*process_message) (struct map_session_data *sd, int format, const char **name_, size_t *namelen_, const char **message_, size_t *messagelen_); void (*wisexin) (struct map_session_data *sd,int type,int flag); void (*wisall) (struct map_session_data *sd,int type,int flag); void (*PMIgnoreList) (struct map_session_data* sd); @@ -1004,7 +998,7 @@ struct clif_interface { void (*mail_setattachment) (int fd, int index, uint8 flag); /* auction-related */ void (*auction_openwindow) (struct map_session_data *sd); - void (*auction_results) (struct map_session_data *sd, short count, short pages, uint8 *buf); + void (*auction_results) (struct map_session_data *sd, short count, short pages, const uint8 *buf); void (*auction_message) (int fd, unsigned char flag); void (*auction_close) (int fd, unsigned char flag); void (*auction_setitem) (int fd, int index, bool fail); @@ -1058,7 +1052,7 @@ struct clif_interface { void (*elemental_updatestatus) (struct map_session_data *sd, int type); /* bgqueue */ void (*bgqueue_ack) (struct map_session_data *sd, enum BATTLEGROUNDS_QUEUE_ACK response, unsigned char arena_id); - void (*bgqueue_notice_delete) (struct map_session_data *sd, enum BATTLEGROUNDS_QUEUE_NOTICE_DELETED response, char *name); + void (*bgqueue_notice_delete) (struct map_session_data *sd, enum BATTLEGROUNDS_QUEUE_NOTICE_DELETED response, const char *name); void (*bgqueue_update_info) (struct map_session_data *sd, unsigned char arena_id, int position); void (*bgqueue_joined) (struct map_session_data *sd, int pos); void (*bgqueue_pcleft) (struct map_session_data *sd); @@ -1087,7 +1081,7 @@ struct clif_interface { int (*delay_damage_sub) (int tid, int64 tick, int id, intptr_t data); /* NPC Market */ void (*npc_market_open) (struct map_session_data *sd, struct npc_data *nd); - void (*npc_market_purchase_ack) (struct map_session_data *sd, struct packet_npc_market_purchase *req, unsigned char response); + void (*npc_market_purchase_ack) (struct map_session_data *sd, const struct itemlist *item_list, unsigned char response); /* */ bool (*parse_roulette_db) (void); void (*roulette_generate_ack) (struct map_session_data *sd, unsigned char result, short stage, short prizeIdx, short bonusItemID); @@ -1338,6 +1332,12 @@ struct clif_interface { void (*add_random_options) (unsigned char* buf, struct item* item); void (*pHotkeyRowShift) (int fd, struct map_session_data *sd); void (*dressroom_open) (struct map_session_data *sd, int view); + void (*pOneClick_ItemIdentify) (int fd,struct map_session_data *sd); + /* Cart Deco */ + void (*selectcart) (struct map_session_data *sd); + void (*pSelectCart) (int fd, struct map_session_data *sd); + + const char *(*get_bl_name) (const struct block_list *bl); }; #ifdef HERCULES_CORE diff --git a/src/map/elemental.c b/src/map/elemental.c index a87deb7d7..b6297c2cf 100644 --- a/src/map/elemental.c +++ b/src/map/elemental.c @@ -254,7 +254,8 @@ void elemental_summon_init(struct elemental_data *ed) { ed->regen.state.block = 0; } -int elemental_data_received(struct s_elemental *ele, bool flag) { +int elemental_data_received(const struct s_elemental *ele, bool flag) +{ struct map_session_data *sd; struct elemental_data *ed; struct s_elemental_db *db; @@ -544,28 +545,38 @@ int elemental_change_mode_ack(struct elemental_data *ed, int mode) { return 1; } -/*=============================================================== - * Change elemental mode. - *-------------------------------------------------------------*/ -int elemental_change_mode(struct elemental_data *ed, int mode) { +/** + * Changes elemental mode. + * + * @param ed The elemental data. + * @param mode The new mode. + * @retval 1 in case of success. + */ +int elemental_change_mode(struct elemental_data *ed, uint32 mode) +{ + int skillmode = EL_SKILLMODE_PASIVE; nullpo_ret(ed); // Remove target elemental->unlocktarget(ed); // Removes the effects of the previous mode. - if(ed->elemental.mode != mode ) elemental->clean_effect(ed); + if (ed->elemental.mode != mode) + elemental->clean_effect(ed); ed->battle_status.mode = ed->elemental.mode = mode; // Normalize elemental mode to elemental skill mode. - if( mode == EL_MODE_AGGRESSIVE ) mode = EL_SKILLMODE_AGGRESSIVE; // Aggressive spirit mode -> Aggressive spirit skill. - else if( mode == EL_MODE_ASSIST ) mode = EL_SKILLMODE_ASSIST; // Assist spirit mode -> Assist spirit skill. - else mode = EL_SKILLMODE_PASIVE; // Passive spirit mode -> Passive spirit skill. + if (mode == EL_MODE_AGGRESSIVE) + skillmode = EL_SKILLMODE_AGGRESSIVE; // Aggressive spirit mode -> Aggressive spirit skill. + else if (mode == EL_MODE_ASSIST) + skillmode = EL_SKILLMODE_ASSIST; // Assist spirit mode -> Assist spirit skill. + else + skillmode = EL_SKILLMODE_PASIVE; // Passive spirit mode -> Passive spirit skill. // Use a skill immediately after every change mode. - if( mode != EL_SKILLMODE_AGGRESSIVE ) - elemental->change_mode_ack(ed,mode); + if (skillmode != EL_SKILLMODE_AGGRESSIVE) + elemental->change_mode_ack(ed, skillmode); return 1; } @@ -680,7 +691,8 @@ int elemental_ai_sub_timer_activesearch(struct block_list *bl, va_list ap) { int elemental_ai_sub_timer(struct elemental_data *ed, struct map_session_data *sd, int64 tick) { struct block_list *target = NULL; - int master_dist, view_range, mode; + int master_dist, view_range; + uint32 mode; nullpo_ret(ed); nullpo_ret(sd); @@ -759,7 +771,7 @@ int elemental_ai_sub_timer(struct elemental_data *ed, struct map_session_data *s return 0; } - if( mode == EL_MODE_AGGRESSIVE ) { + if (mode == EL_MODE_AGGRESSIVE) { target = map->id2bl(ed->ud.target); if( !target ) diff --git a/src/map/elemental.h b/src/map/elemental.h index 1a98670e0..cdd83fd21 100644 --- a/src/map/elemental.h +++ b/src/map/elemental.h @@ -122,11 +122,11 @@ struct elemental_interface { struct view_data * (*get_viewdata) (int class_); int (*create) (struct map_session_data *sd, int class_, unsigned int lifetime); - int (*data_received) (struct s_elemental *ele, bool flag); + int (*data_received) (const struct s_elemental *ele, bool flag); int (*save) (struct elemental_data *ed); int (*change_mode_ack) (struct elemental_data *ed, int mode); - int (*change_mode) (struct elemental_data *ed, int mode); + int (*change_mode) (struct elemental_data *ed, uint32 mode); void (*heal) (struct elemental_data *ed, int hp, int sp); int (*dead) (struct elemental_data *ed); diff --git a/src/map/guild.c b/src/map/guild.c index cba05638f..13acfc0db 100644 --- a/src/map/guild.c +++ b/src/map/guild.c @@ -230,15 +230,18 @@ struct map_session_data* guild_getavailablesd(struct guild* g) } /// lookup: player AID/CID -> member index -int guild_getindex(struct guild *g,int account_id,int char_id) +int guild_getindex(const struct guild *g, int account_id, int char_id) { int i; if( g == NULL ) - return -1; + return INDEX_NOT_FOUND; ARR_FIND( 0, g->max_member, i, g->member[i].account_id == account_id && g->member[i].char_id == char_id ); - return( i < g->max_member ) ? i : -1; + if (i == g->max_member) + return INDEX_NOT_FOUND; + + return i; } /// lookup: player sd -> member position @@ -286,9 +289,8 @@ int guild_payexp_timer_sub(DBKey key, DBData *data, va_list ap) { c = DB->data2ptr(data); - if ( - (g = guild->search(c->guild_id)) == NULL || - (i = guild->getindex(g, c->account_id, c->char_id)) < 0 + if ((g = guild->search(c->guild_id)) == NULL + || (i = guild->getindex(g, c->account_id, c->char_id)) == INDEX_NOT_FOUND ) { ers_free(guild->expcache_ers, c); return 0; @@ -433,7 +435,7 @@ int guild_npc_request_info(int guild_id,const char *event) } //Confirmation of the character belongs to guild -int guild_check_member(struct guild *g) +int guild_check_member(const struct guild *g) { int i; struct map_session_data *sd; @@ -447,7 +449,7 @@ int guild_check_member(struct guild *g) continue; i = guild->getindex(g,sd->status.account_id,sd->status.char_id); - if (i < 0) { + if (i == INDEX_NOT_FOUND) { sd->status.guild_id=0; sd->guild_emblem_id=0; ShowWarning("guild: check_member %d[%s] is not member\n",sd->status.account_id,sd->status.name); @@ -475,7 +477,8 @@ int guild_recv_noinfo(int guild_id) } //Get and display information for all member -int guild_recv_info(struct guild *sg) { +int guild_recv_info(const struct guild *sg) +{ struct guild *g,before; int i,bm,m; DBData data; @@ -753,9 +756,9 @@ void guild_member_joined(struct map_session_data *sd) guild->block_skill(sd, 300000); } i = guild->getindex(g, sd->status.account_id, sd->status.char_id); - if (i == -1) + if (i == INDEX_NOT_FOUND) { sd->status.guild_id = 0; - else { + } else { g->member[i].sd = sd; sd->guild = g; @@ -875,7 +878,7 @@ int guild_expulsion(struct map_session_data* sd, int guild_id, int account_id, i // find the member and perform expulsion i = guild->getindex(g, account_id, char_id); - if( i != -1 && strcmp(g->member[i].name,g->master) != 0 ) //Can't expel the GL! + if (i != INDEX_NOT_FOUND && strcmp(g->member[i].name,g->master) != 0) //Can't expel the GL! intif->guild_leave(g->guild_id,account_id,char_id,1,mes); return 0; @@ -892,7 +895,7 @@ int guild_member_withdraw(int guild_id, int account_id, int char_id, int flag, c return 0; // no such guild (error!) i = guild->getindex(g, account_id, char_id); - if( i == -1 ) + if (i == INDEX_NOT_FOUND) return 0; // not a member (inconsistency!) online_member_sd = guild->getavailablesd(g); @@ -975,8 +978,8 @@ int guild_send_memberinfoshort(struct map_session_data *sd,int online) sd->status.account_id,sd->status.char_id,online,sd->status.base_level,sd->status.class_); if(!online){ - int i=guild->getindex(g,sd->status.account_id,sd->status.char_id); - if(i>=0) + int i = guild->getindex(g,sd->status.account_id,sd->status.char_id); + if (i != INDEX_NOT_FOUND) g->member[i].sd=NULL; else ShowError("guild_send_memberinfoshort: Failed to locate member %d:%d in guild %d!\n", sd->status.account_id, sd->status.char_id, g->guild_id); @@ -993,7 +996,7 @@ int guild_send_memberinfoshort(struct map_session_data *sd,int online) int guild_recv_memberinfoshort(int guild_id,int account_id,int char_id,int online,int lv,int class_) { // cleaned up [LuzZza] - int i,alv,c,idx=-1,om=0,oldonline=-1; + int i, alv, c, idx = INDEX_NOT_FOUND, om = 0, oldonline = -1; struct guild *g = guild->search(guild_id); if(g == NULL) @@ -1015,7 +1018,7 @@ int guild_recv_memberinfoshort(int guild_id,int account_id,int char_id,int onlin om++; } - if(idx == -1 || c == 0) { + if (idx == INDEX_NOT_FOUND || c == 0) { //Treat char_id who doesn't match guild_id (not found as member) struct map_session_data *sd = map->id2sd(account_id); if(sd && sd->status.char_id == char_id) { @@ -1117,7 +1120,7 @@ int guild_change_position(int guild_id,int idx,int mode,int exp_mode,const char nullpo_ret(name); exp_mode = cap_value(exp_mode, 0, battle_config.guild_exp_limit); - p.mode=mode&GPERM_BOTH; // Invite and Expel + p.mode=mode&GPERM_MASK; p.exp_mode=exp_mode; safestrncpy(p.name,name,NAME_LENGTH); return intif->guild_position(guild_id,idx,&p); @@ -1126,7 +1129,7 @@ int guild_change_position(int guild_id,int idx,int mode,int exp_mode,const char /*==================================================== * Notification of member has changed his guild title *---------------------------------------------------*/ -int guild_position_changed(int guild_id,int idx,struct guild_position *p) +int guild_position_changed(int guild_id, int idx, const struct guild_position *p) { struct guild *g=guild->search(guild_id); int i; @@ -1883,7 +1886,8 @@ int guild_gm_changed(int guild_id, int account_id, int char_id) /*==================================================== * Guild disbanded *---------------------------------------------------*/ -int guild_break(struct map_session_data *sd,char *name) { +int guild_break(struct map_session_data *sd, const char *name) +{ struct guild *g; struct unit_data *ud; int i; @@ -2064,7 +2068,7 @@ void guild_castle_reconnect(int castle_id, int index, int value) } // Load castle data then invoke OnAgitInit* on last -int guild_castledataloadack(int len, struct guild_castle *gc) +int guild_castledataloadack(int len, const struct guild_castle *gc) { int i; int n = (len-4) / sizeof(struct guild_castle); diff --git a/src/map/guild.h b/src/map/guild.h index 10749f8ad..cd796adb3 100644 --- a/src/map/guild.h +++ b/src/map/guild.h @@ -98,7 +98,7 @@ struct guild_interface { struct guild_castle *(*mapindex2gc) (short map_index); /* */ struct map_session_data *(*getavailablesd) (struct guild *g); - int (*getindex) (struct guild *g,int account_id,int char_id); + int (*getindex) (const struct guild *g, int account_id, int char_id); int (*getposition) (struct guild *g, struct map_session_data *sd); unsigned int (*payexp) (struct map_session_data *sd,unsigned int exp); int (*getexp) (struct map_session_data *sd,int exp); // [Celest] @@ -107,7 +107,7 @@ struct guild_interface { int (*created) (int account_id,int guild_id); int (*request_info) (int guild_id); int (*recv_noinfo) (int guild_id); - int (*recv_info) (struct guild *sg); + int (*recv_info) (const struct guild *sg); int (*npc_request_info) (int guild_id,const char *ev); int (*invite) (struct map_session_data *sd,struct map_session_data *tsd); int (*reply_invite) (struct map_session_data *sd,int guild_id,int flag); @@ -130,7 +130,7 @@ struct guild_interface { int (*change_memberposition) (int guild_id,int account_id,int char_id,short idx); int (*memberposition_changed) (struct guild *g,int idx,int pos); int (*change_position) (int guild_id,int idx,int mode,int exp_mode,const char *name); - int (*position_changed) (int guild_id,int idx,struct guild_position *p); + int (*position_changed) (int guild_id, int idx, const struct guild_position *p); int (*change_notice) (struct map_session_data *sd,int guild_id,const char *mes1,const char *mes2); int (*notice_changed) (int guild_id,const char *mes1,const char *mes2); int (*change_emblem) (struct map_session_data *sd,int len,const char *data); @@ -139,14 +139,14 @@ struct guild_interface { int (*recv_message) (int guild_id,int account_id,const char *mes,int len); int (*send_dot_remove) (struct map_session_data *sd); int (*skillupack) (int guild_id,uint16 skill_id,int account_id); - int (*dobreak) (struct map_session_data *sd,char *name); + int (*dobreak) (struct map_session_data *sd, const char *name); int (*broken) (int guild_id,int flag); int (*gm_change) (int guild_id, struct map_session_data *sd); int (*gm_changed) (int guild_id, int account_id, int char_id); /* */ void (*castle_map_init) (void); int (*castledatasave) (int castle_id,int index,int value); - int (*castledataloadack) (int len, struct guild_castle *gc); + int (*castledataloadack) (int len, const struct guild_castle *gc); void (*castle_reconnect) (int castle_id, int index, int value); /* */ void (*agit_start) (void); @@ -176,7 +176,7 @@ struct guild_interface { int (*broken_sub) (DBKey key, DBData *data, va_list ap); int (*castle_broken_sub) (DBKey key, DBData *data, va_list ap); void (*makemember) (struct guild_member *m,struct map_session_data *sd); - int (*check_member) (struct guild *g); + int (*check_member) (const struct guild *g); int (*get_alliance_count) (struct guild *g,int flag); void (*castle_reconnect_sub) (void *key, void *data, va_list ap); }; diff --git a/src/map/homunculus.c b/src/map/homunculus.c index b642c197f..bda8fd9e6 100644 --- a/src/map/homunculus.c +++ b/src/map/homunculus.c @@ -399,7 +399,7 @@ bool homunculus_levelup(struct homun_data *hd) { int homunculus_change_class(struct homun_data *hd, short class_) { int i = homun->db_search(class_,HOMUNCULUS_CLASS); nullpo_retr(0, hd); - if(i < 0) + if (i == INDEX_NOT_FOUND) return 0; hd->homunculusDB = &homun->dbs->db[i]; hd->homunculus.class_ = class_; @@ -705,7 +705,8 @@ void homunculus_hunger_timer_delete(struct homun_data *hd) { } } -int homunculus_change_name(struct map_session_data *sd,char *name) { +int homunculus_change_name(struct map_session_data *sd, const char *name) +{ int i; struct homun_data *hd; nullpo_retr(1, sd); @@ -725,21 +726,26 @@ int homunculus_change_name(struct map_session_data *sd,char *name) { return intif_rename_hom(sd, name); } -bool homunculus_change_name_ack(struct map_session_data *sd, char* name, int flag) { +bool homunculus_change_name_ack(struct map_session_data *sd, const char *name, int flag) +{ struct homun_data *hd; + char *newname = NULL; nullpo_retr(false, sd); nullpo_retr(false, name); hd = sd->hd; nullpo_retr(false, hd); if (!homun_alive(hd)) return false; - normalize_name(name," ");//bugreport:3032 + newname = aStrndup(name, NAME_LENGTH-1); + normalize_name(newname, " ");//bugreport:3032 // FIXME[Haru]: This should be normalized by the inter-server (so that it's const here) - if ( !flag || !strlen(name) ) { + if (flag == 0 || strlen(newname) == 0) { clif->message(sd->fd, msg_sd(sd,280)); // You cannot use this name + aFree(newname); return false; } - safestrncpy(hd->homunculus.name,name,NAME_LENGTH); + safestrncpy(hd->homunculus.name, newname, NAME_LENGTH); + aFree(newname); clif->charnameack (0,&hd->bl); hd->homunculus.rename_flag = 1; clif->hominfo(sd,hd,0); @@ -763,14 +769,25 @@ int homunculus_db_search(int key,int type) { return i; break; default: - return -1; + return INDEX_NOT_FOUND; } } - return -1; + return INDEX_NOT_FOUND; } -// Create homunc structure -bool homunculus_create(struct map_session_data *sd, struct s_homunculus *hom) { +/** + * Creates and initializes an homunculus. + * + * @remark + * The char_id field in the source homunculus data is ignored (the sd's + * character ID is used instead). + * + * @param sd The owner character. + * @param hom The homunculus source data. + * @retval false in case of errors. + */ +bool homunculus_create(struct map_session_data *sd, const struct s_homunculus *hom) +{ struct homun_data *hd; int i = 0; @@ -780,7 +797,7 @@ bool homunculus_create(struct map_session_data *sd, struct s_homunculus *hom) { Assert_retr(false, sd->status.hom_id == 0 || sd->hd == 0 || sd->hd->master == sd); i = homun->db_search(hom->class_,HOMUNCULUS_CLASS); - if(i < 0) { + if (i == INDEX_NOT_FOUND) { ShowError("homunculus_create: unknown class [%d] for homunculus '%s', requesting deletion.\n", hom->class_, hom->name); sd->status.hom_id = 0; intif->homunculus_requestdelete(hom->hom_id); @@ -794,6 +811,7 @@ bool homunculus_create(struct map_session_data *sd, struct s_homunculus *hom) { hd->master = sd; hd->homunculusDB = &homun->dbs->db[i]; memcpy(&hd->homunculus, hom, sizeof(struct s_homunculus)); + hd->homunculus.char_id = sd->status.char_id; // Fix character ID if necessary. hd->exp_next = homun->dbs->exptable[hd->homunculus.level - 1]; status->set_viewdata(&hd->bl, hd->homunculus.class_); @@ -863,35 +881,38 @@ bool homunculus_call(struct map_session_data *sd) { } // Receive homunculus data from char server -bool homunculus_recv_data(int account_id, struct s_homunculus *sh, int flag) { +bool homunculus_recv_data(int account_id, const struct s_homunculus *sh, int flag) +{ struct map_session_data *sd; struct homun_data *hd; nullpo_retr(false, sh); + sd = map->id2sd(account_id); - if(!sd) + if (sd == NULL) return false; - if (sd->status.char_id != sh->char_id) { - if (sd->status.hom_id == sh->hom_id) - sh->char_id = sd->status.char_id; //Correct char id. - else - return false; - } - if(!flag) { // Failed to load + + if (flag == 0) { // Failed to load sd->status.hom_id = 0; return false; } - if (!sd->status.hom_id) //Hom just created. + if (sd->status.char_id != sh->char_id && sd->status.hom_id != sh->hom_id) + return false; + + if (sd->status.hom_id == 0) //Hom just created. sd->status.hom_id = sh->hom_id; - if (sd->hd) //uh? Overwrite the data. - memcpy(&sd->hd->homunculus, sh, sizeof(struct s_homunculus)); - else + if (sd->hd != NULL) { + //uh? Overwrite the data. + memcpy(&sd->hd->homunculus, sh, sizeof sd->hd->homunculus); + sd->hd->homunculus.char_id = sd->status.char_id; // Correct char id if necessary. + } else { homun->create(sd, sh); + } hd = sd->hd; - if(hd && hd->homunculus.hp && hd->homunculus.vaporize == HOM_ST_ACTIVE && hd->bl.prev == NULL && sd->bl.prev != NULL) { + if(hd != NULL && hd->homunculus.hp && hd->homunculus.vaporize == HOM_ST_ACTIVE && hd->bl.prev == NULL && sd->bl.prev != NULL) { enum homun_type htype = homun->class2type(hd->homunculus.class_); map->addblock(&hd->bl); @@ -927,7 +948,8 @@ bool homunculus_creation_request(struct map_session_data *sd, int class_) { nullpo_retr(false, sd); i = homun->db_search(class_,HOMUNCULUS_CLASS); - if(i < 0) return false; + if (i == INDEX_NOT_FOUND) + return false; memset(&hom, 0, sizeof(struct s_homunculus)); //Initial data diff --git a/src/map/homunculus.h b/src/map/homunculus.h index 1712c98a9..3dd9e4772 100644 --- a/src/map/homunculus.h +++ b/src/map/homunculus.h @@ -63,14 +63,15 @@ enum homun_id { #define homun_alive(x) ((x) && (x)->homunculus.vaporize == HOM_ST_ACTIVE && (x)->battle_status.hp > 0) #ifdef RENEWAL -#define HOMUN_LEVEL_STATWEIGHT_VALUE 0 -#define APPLY_HOMUN_LEVEL_STATWEIGHT()( \ - hom->str_value = hom->agi_value = \ - hom->vit_value = hom->int_value = \ - hom->dex_value = hom->luk_value = hom->level / 10 - HOMUN_LEVEL_STATWEIGHT_VALUE \ - ) +#define HOMUN_LEVEL_STATWEIGHT_VALUE 0 +#define APPLY_HOMUN_LEVEL_STATWEIGHT() \ + do { \ + hom->str_value = hom->agi_value = \ + hom->vit_value = hom->int_value = \ + hom->dex_value = hom->luk_value = hom->level / 10 - HOMUN_LEVEL_STATWEIGHT_VALUE; \ + } while (false) #else -#define APPLY_HOMUN_LEVEL_STATWEIGHT() +#define APPLY_HOMUN_LEVEL_STATWEIGHT() (void)0 #endif struct h_stats { @@ -185,13 +186,13 @@ struct homunculus_interface { bool (*feed) (struct map_session_data *sd, struct homun_data *hd); int (*hunger_timer) (int tid, int64 tick, int id, intptr_t data); void (*hunger_timer_delete) (struct homun_data *hd); - int (*change_name) (struct map_session_data *sd,char *name); - bool (*change_name_ack) (struct map_session_data *sd, char* name, int flag); + int (*change_name) (struct map_session_data *sd, const char *name); + bool (*change_name_ack) (struct map_session_data *sd, const char *name, int flag); int (*db_search) (int key,int type); - bool (*create) (struct map_session_data *sd, struct s_homunculus *hom); + bool (*create) (struct map_session_data *sd, const struct s_homunculus *hom); void (*init_timers) (struct homun_data * hd); bool (*call) (struct map_session_data *sd); - bool (*recv_data) (int account_id, struct s_homunculus *sh, int flag); + bool (*recv_data) (int account_id, const struct s_homunculus *sh, int flag); bool (*creation_request) (struct map_session_data *sd, int class_); bool (*ressurect) (struct map_session_data* sd, unsigned char per, short x, short y); void (*revive) (struct homun_data *hd, unsigned int hp, unsigned int sp); diff --git a/src/map/instance.c b/src/map/instance.c index 5e8256c88..a6700d486 100644 --- a/src/map/instance.c +++ b/src/map/instance.c @@ -106,7 +106,7 @@ int instance_create(int owner_id, const char *name, enum instance_owner_type typ icptr = &g->instances; break; default: - ShowError("instance_create: unknown type %d for owner_id %d and name %s.\n", type,owner_id,name); + ShowError("instance_create: unknown type %u for owner_id %d and name %s.\n", type, owner_id, name); return -1; } @@ -591,7 +591,7 @@ void instance_destroy(int instance_id) { icptr = &g->instances; break; default: - ShowError("instance_destroy: unknown type %d for owner_id %d and name '%s'.\n", instance->list[instance_id].owner_type,instance->list[instance_id].owner_id,instance->list[instance_id].name); + ShowError("instance_destroy: unknown type %u for owner_id %d and name '%s'.\n", instance->list[instance_id].owner_type, instance->list[instance_id].owner_id, instance->list[instance_id].name); break; } diff --git a/src/map/intif.c b/src/map/intif.c index 1968ebe67..7d2493d46 100644 --- a/src/map/intif.c +++ b/src/map/intif.c @@ -132,7 +132,7 @@ int intif_delete_petdata(int pet_id) return 1; } -int intif_rename(struct map_session_data *sd, int type, char *name) +int intif_rename(struct map_session_data *sd, int type, const char *name) { if (intif->CheckForCharServer()) return 1; @@ -231,7 +231,7 @@ int intif_main_message(struct map_session_data* sd, const char* message) } // The transmission of Wisp/Page to inter-server (player not found on this server) -int intif_wis_message(struct map_session_data *sd, char *nick, char *mes, size_t mes_len) +int intif_wis_message(struct map_session_data *sd, const char *nick, const char *mes, size_t mes_len) { if (intif->CheckForCharServer()) return 0; @@ -350,7 +350,7 @@ int intif_saveregistry(struct map_session_data *sd) { WFIFOB(inter_fd, plen) = (unsigned char)len;/* won't be higher; the column size is 32 */ plen += 1; - safestrncpy((char*)WFIFOP(inter_fd,plen), varname, len); + safestrncpy(WFIFOP(inter_fd,plen), varname, len); plen += len; WFIFOL(inter_fd, plen) = script_getvaridx(key.i64); @@ -368,7 +368,7 @@ int intif_saveregistry(struct map_session_data *sd) { WFIFOB(inter_fd, plen) = (unsigned char)len;/* won't be higher; the column size is 254 */ plen += 1; - safestrncpy((char*)WFIFOP(inter_fd,plen), p->value, len); + safestrncpy(WFIFOP(inter_fd,plen), p->value, len); plen += len; } else { script->reg_destroy_single(sd,key.i64,&p->flag); @@ -463,7 +463,7 @@ int intif_send_guild_storage(int account_id,struct guild_storage *gstor) } // Party creation request -int intif_create_party(struct party_member *member,char *name,int item,int item2) +int intif_create_party(struct party_member *member, const char *name, int item, int item2) { if (intif->CheckForCharServer()) return 0; @@ -684,7 +684,7 @@ int intif_guild_leave(int guild_id,int account_id,int char_id,int flag,const cha WFIFOL(inter_fd, 6) = account_id; WFIFOL(inter_fd,10) = char_id; WFIFOB(inter_fd,14) = flag; - safestrncpy((char*)WFIFOP(inter_fd,15),mes,40); + safestrncpy(WFIFOP(inter_fd,15),mes,40); WFIFOSET(inter_fd,55); return 0; } @@ -837,8 +837,8 @@ int intif_guild_notice(int guild_id,const char *mes1,const char *mes2) WFIFOHEAD(inter_fd,186); WFIFOW(inter_fd,0)=0x303e; WFIFOL(inter_fd,2)=guild_id; - memcpy(WFIFOP(inter_fd,6),mes1,MAX_GUILDMES1); - memcpy(WFIFOP(inter_fd,66),mes2,MAX_GUILDMES2); + safestrncpy(WFIFOP(inter_fd, 6), mes1, MAX_GUILDMES1); + safestrncpy(WFIFOP(inter_fd, 66), mes2, MAX_GUILDMES2); WFIFOSET(inter_fd,186); return 0; } @@ -956,13 +956,13 @@ int intif_homunculus_requestdelete(int homun_id) // Wisp/Page reception // rewritten by [Yor] void intif_parse_WisMessage(int fd) { struct map_session_data* sd; - char *wisp_source; + const char *wisp_source; char name[NAME_LENGTH]; int id, i; id=RFIFOL(fd,4); - safestrncpy(name, (char*)RFIFOP(fd,32), NAME_LENGTH); + safestrncpy(name, RFIFOP(fd,32), NAME_LENGTH); sd = map->nick2sd(name); if(sd == NULL || strcmp(sd->status.name, name) != 0) { //Not found @@ -973,7 +973,7 @@ void intif_parse_WisMessage(int fd) { intif_wis_replay(id, 2); return; } - wisp_source = (char *) RFIFOP(fd,8); // speed up [Yor] + wisp_source = RFIFOP(fd,8); // speed up [Yor] for(i=0; i < MAX_IGNORE_LIST && sd->ignore[i].name[0] != '\0' && strcmp(sd->ignore[i].name, wisp_source) != 0 @@ -985,17 +985,19 @@ void intif_parse_WisMessage(int fd) { return; } //Success to send whisper. - clif->wis_message(sd->fd, wisp_source, (char*)RFIFOP(fd,56),RFIFOW(fd,2)-56); + clif->wis_message(sd->fd, wisp_source, RFIFOP(fd,56),RFIFOW(fd,2)-56); intif_wis_replay(id,0); // success } // Wisp/page transmission result reception -void intif_parse_WisEnd(int fd) { +void intif_parse_WisEnd(int fd) +{ struct map_session_data* sd; + const char *playername = RFIFOP(fd, 2); if (battle_config.etc_log) - ShowInfo("intif_parse_wisend: player: %s, flag: %d\n", RFIFOP(fd,2), RFIFOB(fd,26)); // flag: 0: success to send whisper, 1: target character is not logged in?, 2: ignored by target - sd = map->nick2sd((char *)RFIFOP(fd,2)); + ShowInfo("intif_parse_wisend: player: %s, flag: %d\n", playername, RFIFOB(fd,26)); // flag: 0: success to send whisper, 1: target character is not logged in?, 2: ignored by target + sd = map->nick2sd(playername); if (sd != NULL) clif->wis_end(sd->fd, RFIFOB(fd,26)); @@ -1032,8 +1034,8 @@ void mapif_parse_WisToGM(int fd) message = (char *) (mes_len >= 255 ? (char *) aMalloc(mes_len) : mbuf); permission = RFIFOL(fd,28); - safestrncpy(Wisp_name, (char*)RFIFOP(fd,4), NAME_LENGTH); - safestrncpy(message, (char*)RFIFOP(fd,32), mes_len); + safestrncpy(Wisp_name, RFIFOP(fd,4), NAME_LENGTH); + safestrncpy(message, RFIFOP(fd,32), mes_len); // information is sent to all online GM map->foreachpc(mapif_parse_WisToGM_sub, permission, Wisp_name, message, mes_len); @@ -1098,14 +1100,14 @@ void intif_parse_Registers(int fd) char sval[254]; for (i = 0; i < max; i++) { int len = RFIFOB(fd, cursor); - safestrncpy(key, (char*)RFIFOP(fd, cursor + 1), min((int)sizeof(key), len)); + safestrncpy(key, RFIFOP(fd, cursor + 1), min((int)sizeof(key), len)); cursor += len + 1; index = RFIFOL(fd, cursor); cursor += 4; len = RFIFOB(fd, cursor); - safestrncpy(sval, (char*)RFIFOP(fd, cursor + 1), min((int)sizeof(sval), len)); + safestrncpy(sval, RFIFOP(fd, cursor + 1), min((int)sizeof(sval), len)); cursor += len + 1; script->set_reg(NULL,sd,reference_uid(script->add_str(key), index), key, (void*)sval, NULL); @@ -1121,7 +1123,7 @@ void intif_parse_Registers(int fd) int ival; int len = RFIFOB(fd, cursor); - safestrncpy(key, (char*)RFIFOP(fd, cursor + 1), min((int)sizeof(key), len)); + safestrncpy(key, RFIFOP(fd, cursor + 1), min((int)sizeof(key), len)); cursor += len + 1; index = RFIFOL(fd, cursor); @@ -1156,7 +1158,7 @@ void intif_parse_LoadGuildStorage(int fd) sd=map->id2sd( RFIFOL(fd,4) ); if( flag ){ //If flag != 0, we attach a player and open the storage if(sd==NULL){ - ShowError("intif_parse_LoadGuildStorage: user not found %d\n",RFIFOL(fd,4)); + ShowError("intif_parse_LoadGuildStorage: user not found %u\n", RFIFOL(fd,4)); return; } } @@ -1194,29 +1196,29 @@ void intif_parse_SaveGuildStorage(int fd) void intif_parse_PartyCreated(int fd) { if(battle_config.etc_log) - ShowInfo("intif: party created by account %d\n\n", RFIFOL(fd,2)); - party->created(RFIFOL(fd,2), RFIFOL(fd,6),RFIFOB(fd,10),RFIFOL(fd,11), (char *)RFIFOP(fd,15)); + ShowInfo("intif: party created by account %u\n\n", RFIFOL(fd,2)); + party->created(RFIFOL(fd,2), RFIFOL(fd,6),RFIFOB(fd,10),RFIFOL(fd,11), RFIFOP(fd,15)); } // Receive party info void intif_parse_PartyInfo(int fd) { if (RFIFOW(fd,2) == 12) { - ShowWarning("intif: party noinfo (char_id=%d party_id=%d)\n", RFIFOL(fd,4), RFIFOL(fd,8)); + ShowWarning("intif: party noinfo (char_id=%u party_id=%u)\n", RFIFOL(fd,4), RFIFOL(fd,8)); party->recv_noinfo(RFIFOL(fd,8), RFIFOL(fd,4)); return; } if (RFIFOW(fd,2) != 8+sizeof(struct party)) - ShowError("intif: party info: data size mismatch (char_id=%d party_id=%d packet_len=%d expected_len=%"PRIuS")\n", + ShowError("intif: party info: data size mismatch (char_id=%u party_id=%u packet_len=%d expected_len=%"PRIuS")\n", RFIFOL(fd,4), RFIFOL(fd,8), RFIFOW(fd,2), 8+sizeof(struct party)); - party->recv_info((struct party *)RFIFOP(fd,8), RFIFOL(fd,4)); + party->recv_info(RFIFOP(fd,8), RFIFOL(fd,4)); } // ACK adding party member void intif_parse_PartyMemberAdded(int fd) { if(battle_config.etc_log) - ShowInfo("intif: party member added Party (%d), Account(%d), Char(%d)\n",RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10)); + ShowInfo("intif: party member added Party (%u), Account(%u), Char(%u)\n", RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10)); party->member_added(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10), RFIFOB(fd, 14)); } @@ -1230,7 +1232,7 @@ void intif_parse_PartyOptionChanged(int fd) void intif_parse_PartyMemberWithdraw(int fd) { if(battle_config.etc_log) - ShowInfo("intif: party member withdraw: Party(%d), Account(%d), Char(%d)\n",RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10)); + ShowInfo("intif: party member withdraw: Party(%u), Account(%u), Char(%u)\n", RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10)); party->member_withdraw(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10)); } @@ -1247,7 +1249,7 @@ void intif_parse_PartyMove(int fd) // ACK party messages void intif_parse_PartyMessage(int fd) { - party->recv_message(RFIFOL(fd,4),RFIFOL(fd,8),(char *) RFIFOP(fd,12),RFIFOW(fd,2)-12); + party->recv_message(RFIFOL(fd,4), RFIFOL(fd,8), RFIFOP(fd,12), RFIFOW(fd,2)-12); } // ACK guild creation @@ -1258,26 +1260,26 @@ void intif_parse_GuildCreated(int fd) { // ACK guild infos void intif_parse_GuildInfo(int fd) { if (RFIFOW(fd,2) == 8) { - ShowWarning("intif: guild noinfo %d\n",RFIFOL(fd,4)); + ShowWarning("intif: guild noinfo %u\n", RFIFOL(fd,4)); guild->recv_noinfo(RFIFOL(fd,4)); return; } if (RFIFOW(fd,2)!=sizeof(struct guild)+4) - ShowError("intif: guild info: data size mismatch - Gid: %d recv size: %d Expected size: %"PRIuS"\n", - RFIFOL(fd,4),RFIFOW(fd,2),sizeof(struct guild)+4); - guild->recv_info((struct guild *)RFIFOP(fd,4)); + ShowError("intif: guild info: data size mismatch - Gid: %u recv size: %d Expected size: %"PRIuS"\n", + RFIFOL(fd,4), RFIFOW(fd,2), sizeof(struct guild)+4); + guild->recv_info(RFIFOP(fd,4)); } // ACK adding guild member void intif_parse_GuildMemberAdded(int fd) { if(battle_config.etc_log) - ShowInfo("intif: guild member added %d %d %d %d\n",RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOB(fd,14)); + ShowInfo("intif: guild member added %u %u %u %d\n", RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10), RFIFOB(fd,14)); guild->member_added(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOB(fd,14)); } // ACK member leaving guild void intif_parse_GuildMemberWithdraw(int fd) { - guild->member_withdraw(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOB(fd,14),(char *)RFIFOP(fd,55),(char *)RFIFOP(fd,15)); + guild->member_withdraw(RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10), RFIFOB(fd,14), RFIFOP(fd,55), RFIFOP(fd,15)); } // ACK guild member basic info @@ -1308,15 +1310,19 @@ void intif_parse_GuildBasicInfoChanged(int fd) { case GBI_SKILLPOINT: g->skill_point = RFIFOL(fd,10); break; case GBI_SKILLLV: { int idx, max; - struct guild_skill *gs = (struct guild_skill *)RFIFOP(fd,10); + const struct guild_skill *p_gs = RFIFOP(fd,10); + struct guild_skill *gs = NULL; - idx = gs->id - GD_SKILLBASE; + idx = p_gs->id - GD_SKILLBASE; Assert_retv(idx >= 0 && idx < MAX_GUILDSKILL); + + gs = &g->skill[idx]; + memcpy(gs, p_gs, sizeof(*gs)); + max = guild->skill_get_max(gs->id); - if( gs->lv > max ) + if (gs->lv > max) gs->lv = max; - memcpy(&(g->skill[idx]), gs, sizeof(g->skill[idx])); break; } } @@ -1340,7 +1346,7 @@ void intif_parse_GuildMemberInfoChanged(int fd) { return; idx = guild->getindex(g,account_id,char_id); - if( idx == -1 ) + if (idx == INDEX_NOT_FOUND) return; switch( type ) { @@ -1357,9 +1363,9 @@ void intif_parse_GuildMemberInfoChanged(int fd) { // ACK change of guild title void intif_parse_GuildPosition(int fd) { if (RFIFOW(fd,2)!=sizeof(struct guild_position)+12) - ShowError("intif: guild info: data size mismatch (%d) %d != %"PRIuS"\n", - RFIFOL(fd,4),RFIFOW(fd,2),sizeof(struct guild_position)+12); - guild->position_changed(RFIFOL(fd,4),RFIFOL(fd,8),(struct guild_position *)RFIFOP(fd,12)); + ShowError("intif: guild info: data size mismatch (%u) %d != %"PRIuS"\n", + RFIFOL(fd,4), RFIFOW(fd,2), sizeof(struct guild_position) + 12); + guild->position_changed(RFIFOL(fd,4), RFIFOL(fd,8), RFIFOP(fd,12)); } // ACK change of guild skill update @@ -1369,27 +1375,27 @@ void intif_parse_GuildSkillUp(int fd) { // ACK change of guild relationship void intif_parse_GuildAlliance(int fd) { - guild->allianceack(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOL(fd,14),RFIFOB(fd,18),(char *) RFIFOP(fd,19),(char *) RFIFOP(fd,43)); + guild->allianceack(RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10), RFIFOL(fd,14), RFIFOB(fd,18), RFIFOP(fd,19), RFIFOP(fd,43)); } // ACK change of guild notice void intif_parse_GuildNotice(int fd) { - guild->notice_changed(RFIFOL(fd,2),(char *) RFIFOP(fd,6),(char *) RFIFOP(fd,66)); + guild->notice_changed(RFIFOL(fd,2), RFIFOP(fd,6), RFIFOP(fd,66)); } // ACK change of guild emblem void intif_parse_GuildEmblem(int fd) { - guild->emblem_changed(RFIFOW(fd,2)-12,RFIFOL(fd,4),RFIFOL(fd,8), (char *)RFIFOP(fd,12)); + guild->emblem_changed(RFIFOW(fd,2)-12, RFIFOL(fd,4), RFIFOL(fd,8), RFIFOP(fd,12)); } // ACK guild message void intif_parse_GuildMessage(int fd) { - guild->recv_message(RFIFOL(fd,4),RFIFOL(fd,8),(char *) RFIFOP(fd,12),RFIFOW(fd,2)-12); + guild->recv_message(RFIFOL(fd,4), RFIFOL(fd,8), RFIFOP(fd,12), RFIFOW(fd,2)-12); } // Reply guild castle data request void intif_parse_GuildCastleDataLoad(int fd) { - guild->castledataloadack(RFIFOW(fd,2), (struct guild_castle *)RFIFOP(fd,4)); + guild->castledataloadack(RFIFOW(fd,2), RFIFOP(fd,4)); } // ACK change of guildmaster @@ -1440,10 +1446,10 @@ void intif_parse_ChangeNameOk(int fd) case 0: //Players [NOT SUPPORTED YET] break; case 1: //Pets - pet->change_name_ack(sd, (char*)RFIFOP(fd,12), RFIFOB(fd,11)); + pet->change_name_ack(sd, RFIFOP(fd,12), RFIFOB(fd,11)); break; case 2: //Hom - homun->change_name_ack(sd, (char*)RFIFOP(fd,12), RFIFOB(fd,11)); + homun->change_name_ack(sd, RFIFOP(fd,12), RFIFOB(fd,11)); break; } return; @@ -1459,7 +1465,7 @@ void intif_parse_CreateHomunculus(int fd) { ShowError("intif: create homun data: data size mismatch %d != %"PRIuS"\n", len, sizeof(struct s_homunculus)); return; } - homun->recv_data(RFIFOL(fd,4), (struct s_homunculus*)RFIFOP(fd,9), RFIFOB(fd,8)) ; + homun->recv_data(RFIFOL(fd,4), RFIFOP(fd,9), RFIFOB(fd,8)) ; } void intif_parse_RecvHomunculusData(int fd) { @@ -1470,13 +1476,13 @@ void intif_parse_RecvHomunculusData(int fd) { ShowError("intif: homun data: data size mismatch %d != %"PRIuS"\n", len, sizeof(struct s_homunculus)); return; } - homun->recv_data(RFIFOL(fd,4), (struct s_homunculus*)RFIFOP(fd,9), RFIFOB(fd,8)); + homun->recv_data(RFIFOL(fd,4), RFIFOP(fd,9), RFIFOB(fd,8)); } /* Really? Whats the point, shouldn't be sent when successful then [Ind] */ void intif_parse_SaveHomunculusOk(int fd) { if(RFIFOB(fd,6) != 1) - ShowError("homunculus data save failure for account %d\n", RFIFOL(fd,2)); + ShowError("homunculus data save failure for account %u\n", RFIFOL(fd,2)); } /* Really? Whats the point, shouldn't be sent when successful then [Ind] */ @@ -1527,7 +1533,7 @@ void intif_parse_QuestLog(int fd) { sd->quest_log = NULL; } } else { - struct quest *received = (struct quest *)RFIFOP(fd, 8); + const struct quest *received = RFIFOP(fd, 8); int i, k = num_received; if (sd->quest_log) { RECREATE(sd->quest_log, struct quest, num_received); @@ -1691,7 +1697,7 @@ void intif_parse_MailGetAttach(int fd) { sd = map->charid2sd( RFIFOL(fd,4) ); if (sd == NULL) { - ShowError("intif_parse_MailGetAttach: char not found %d\n",RFIFOL(fd,4)); + ShowError("intif_parse_MailGetAttach: char not found %u\n", RFIFOL(fd,4)); return; } @@ -1769,7 +1775,7 @@ void intif_parse_MailReturn(int fd) { short fail = RFIFOB(fd,10); if( sd == NULL ) { - ShowError("intif_parse_MailReturn: char not found %d\n",RFIFOL(fd,2)); + ShowError("intif_parse_MailReturn: char not found %u\n", RFIFOL(fd, 2)); return; } @@ -1837,8 +1843,8 @@ void intif_parse_MailSend(int fd) { void intif_parse_MailNew(int fd) { struct map_session_data *sd = map->charid2sd(RFIFOL(fd,2)); int mail_id = RFIFOL(fd,6); - const char* sender_name = (char*)RFIFOP(fd,10); - const char* title = (char*)RFIFOP(fd,34); + const char *sender_name = RFIFOP(fd,10); + const char *title = RFIFOP(fd,34); if( sd == NULL ) return; @@ -1876,7 +1882,7 @@ void intif_parse_AuctionResults(int fd) { struct map_session_data *sd = map->charid2sd(RFIFOL(fd,4)); short count = RFIFOW(fd,8); short pages = RFIFOW(fd,10); - uint8* data = RFIFOP(fd,12); + const uint8 *data = RFIFOP(fd,12); if( sd == NULL ) return; @@ -2063,7 +2069,7 @@ void intif_parse_MercenaryReceived(int fd) { return; } - mercenary->data_received((struct s_mercenary*)RFIFOP(fd,5), RFIFOB(fd,4)); + mercenary->data_received(RFIFOP(fd,5), RFIFOB(fd,4)); } int intif_mercenary_request(int merc_id, int char_id) @@ -2145,7 +2151,7 @@ void intif_parse_ElementalReceived(int fd) { return; } - elemental->data_received((struct s_elemental*)RFIFOP(fd,5), RFIFOB(fd,4)); + elemental->data_received(RFIFOP(fd,5), RFIFOB(fd,4)); } int intif_elemental_request(int ele_id, int char_id) @@ -2207,7 +2213,7 @@ void intif_request_accinfo( int u_fd, int aid, int group_lv, char* query ) { WFIFOL(inter_fd,2) = u_fd; WFIFOL(inter_fd,6) = aid; WFIFOL(inter_fd,10) = group_lv; - safestrncpy((char *)WFIFOP(inter_fd,14), query, NAME_LENGTH); + safestrncpy(WFIFOP(inter_fd,14), query, NAME_LENGTH); WFIFOSET(inter_fd,2 + 4 + 4 + 4 + NAME_LENGTH); @@ -2224,7 +2230,7 @@ void intif_parse_MessageToFD(int fd) { /* matching e.g. previous fd owner didn't dc during request or is still the same */ if( sd && sd->bl.id == aid ) { char msg[512]; - safestrncpy(msg, (char*)RFIFOP(fd,12), RFIFOW(fd,2) - 12); + safestrncpy(msg, RFIFOP(fd,12), RFIFOW(fd,2) - 12); clif->messagecolor_self(u_fd, COLOR_DEFAULT ,msg); } @@ -2288,9 +2294,9 @@ int intif_parse(int fd) switch(cmd){ case 0x3800: if (RFIFOL(fd,4) == 0xFF000000) //Normal announce. - clif->broadcast(NULL, (char *) RFIFOP(fd,16), packet_len-16, BC_DEFAULT, ALL_CLIENT); + clif->broadcast(NULL, RFIFOP(fd,16), packet_len-16, BC_DEFAULT, ALL_CLIENT); else //Color announce. - clif->broadcast2(NULL, (char *) RFIFOP(fd,16), packet_len-16, RFIFOL(fd,4), RFIFOW(fd,8), RFIFOW(fd,10), RFIFOW(fd,12), RFIFOW(fd,14), ALL_CLIENT); + clif->broadcast2(NULL, RFIFOP(fd,16), packet_len-16, RFIFOL(fd,4), RFIFOW(fd,8), RFIFOW(fd,10), RFIFOW(fd,12), RFIFOW(fd,14), ALL_CLIENT); break; case 0x3801: intif->pWisMessage(fd); break; case 0x3802: intif->pWisEnd(fd); break; diff --git a/src/map/intif.h b/src/map/intif.h index 0bcaae941..dccd31d80 100644 --- a/src/map/intif.h +++ b/src/map/intif.h @@ -62,13 +62,13 @@ struct intif_interface { int (*broadcast) (const char* mes, size_t len, int type); int (*broadcast2) (const char* mes, size_t len, unsigned int fontColor, short fontType, short fontSize, short fontAlign, short fontY); int (*main_message) (struct map_session_data* sd, const char* message); - int (*wis_message) (struct map_session_data *sd,char *nick,char *mes,size_t mes_len); + int (*wis_message) (struct map_session_data *sd, const char *nick, const char *mes, size_t mes_len); int (*wis_message_to_gm) (char *Wisp_name, int permission, char *mes); int (*saveregistry) (struct map_session_data *sd); int (*request_registry) (struct map_session_data *sd, int flag); int (*request_guild_storage) (int account_id, int guild_id); int (*send_guild_storage) (int account_id, struct guild_storage *gstor); - int (*create_party) (struct party_member *member,char *name,int item,int item2); + int (*create_party) (struct party_member *member, const char *name, int item, int item2); int (*request_partyinfo) (int party_id, int char_id); int (*party_addmember) (int party_id,struct party_member *member); int (*party_changeoption) (int party_id, int account_id, int exp, int item); @@ -98,7 +98,7 @@ struct intif_interface { int (*request_petdata) (int account_id, int char_id, int pet_id); int (*save_petdata) (int account_id, struct s_pet *p); int (*delete_petdata) (int pet_id); - int (*rename) (struct map_session_data *sd, int type, char *name); + int (*rename) (struct map_session_data *sd, int type, const char *name); int (*homunculus_create) (int account_id, struct s_homunculus *sh); bool (*homunculus_requestload) (int account_id, int homun_id); int (*homunculus_requestsave) (int account_id, struct s_homunculus* sh); diff --git a/src/map/irc-bot.c b/src/map/irc-bot.c index 3d8ec8b5d..b520e9e91 100644 --- a/src/map/irc-bot.c +++ b/src/map/irc-bot.c @@ -134,7 +134,7 @@ struct irc_func* irc_func_search(char* function_name) { * @see do_sockets */ int irc_parse(int fd) { - char *parse_string = NULL, *str_safe = NULL; + char *parse_string = NULL, *p = NULL, *str_safe = NULL; if (sockt->session[fd]->flag.eof) { sockt->close(fd); @@ -150,18 +150,19 @@ int irc_parse(int fd) { if( !RFIFOREST(fd) ) return 0; - parse_string = (char*)RFIFOP(fd,0); - parse_string[ RFIFOREST(fd) - 1 ] = '\0'; + parse_string = aMalloc(RFIFOREST(fd)); + safestrncpy(parse_string, RFIFOP(fd,0), RFIFOREST(fd)); + RFIFOSKIP(fd, RFIFOREST(fd)); + RFIFOFLUSH(fd); - parse_string = strtok_r(parse_string,"\r\n",&str_safe); + p = strtok_r(parse_string,"\r\n",&str_safe); - while (parse_string != NULL) { + while (p != NULL) { ircbot->parse_sub(fd,parse_string); - parse_string = strtok_r(NULL,"\r\n",&str_safe); + p = strtok_r(NULL,"\r\n",&str_safe); } + aFree(parse_string); - RFIFOSKIP(fd, RFIFOREST(fd)); - RFIFOFLUSH(fd); return 0; } @@ -244,7 +245,7 @@ void irc_send(char *str) { if (len > IRC_MESSAGE_LENGTH-3) len = IRC_MESSAGE_LENGTH-3; WFIFOHEAD(ircbot->fd, len); - snprintf((char*)WFIFOP(ircbot->fd,0),IRC_MESSAGE_LENGTH, "%s\r\n", str); + snprintf(WFIFOP(ircbot->fd,0),IRC_MESSAGE_LENGTH, "%s\r\n", str); WFIFOSET(ircbot->fd, len); } diff --git a/src/map/itemdb.c b/src/map/itemdb.c index 048efd636..ce6232965 100644 --- a/src/map/itemdb.c +++ b/src/map/itemdb.c @@ -2,7 +2,7 @@ * This file is part of Hercules. * http://herc.ws - http://github.com/HerculesWS/Hercules * - * Copyright (C) 2012-2015 Hercules Dev Team + * Copyright (C) 2012-2016 Hercules Dev Team * Copyright (C) Athena Dev Teams * * Hercules is free software: you can redistribute it and/or modify @@ -342,81 +342,202 @@ const char* itemdb_typename(int type) return "Unknown Type"; } -/*========================================== - * Converts the jobid from the format in itemdb - * to the format used by the map server. [Skotlex] - *------------------------------------------*/ -void itemdb_jobid2mapid(unsigned int *bclass, unsigned int jobmask) + /** + * Converts the JobID to the format used by map-server to check item + * restriction as per job. + * + * @param bclass Pointer to the variable containing the new format + * @param job_id Variable containing JobID + * @param enable Boolean value which (un)set the restriction. + * + * @author Dastgir + */ +void itemdb_jobid2mapid(uint64 *bclass, int job_id, bool enable) { + uint64 mask[3] = { 0 }; int i; + nullpo_retv(bclass); - bclass[0]= bclass[1]= bclass[2]= 0; + + switch(job_id) { + // Base Classes + case JOB_NOVICE: + case JOB_SUPER_NOVICE: + mask[0] = 1ULL << MAPID_NOVICE; + mask[1] = 1ULL << MAPID_NOVICE; + break; + case JOB_SWORDMAN: + case JOB_MAGE: + case JOB_ARCHER: + case JOB_ACOLYTE: + case JOB_MERCHANT: + case JOB_THIEF: + mask[0] = 1ULL << (MAPID_NOVICE+job_id); + break; + // 2-1 Classes + case JOB_KNIGHT: + mask[1] = 1ULL << MAPID_SWORDMAN; + break; + case JOB_PRIEST: + mask[1] = 1ULL << MAPID_ACOLYTE; + break; + case JOB_WIZARD: + mask[1] = 1ULL << MAPID_MAGE; + break; + case JOB_BLACKSMITH: + mask[1] = 1ULL << MAPID_MERCHANT; + break; + case JOB_HUNTER: + mask[1] = 1ULL << MAPID_ARCHER; + break; + case JOB_ASSASSIN: + mask[1] = 1ULL << MAPID_THIEF; + break; + // 2-2 Classes + case JOB_CRUSADER: + mask[2] = 1ULL << MAPID_SWORDMAN; + break; + case JOB_MONK: + mask[2] = 1ULL << MAPID_ACOLYTE; + break; + case JOB_SAGE: + mask[2] = 1ULL << MAPID_MAGE; + break; + case JOB_ALCHEMIST: + mask[2] = 1ULL << MAPID_MERCHANT; + break; + case JOB_BARD: + mask[2] = 1ULL << MAPID_ARCHER; + break; + case JOB_ROGUE: + mask[2] = 1ULL << MAPID_THIEF; + break; + // Extended Classes + case JOB_TAEKWON: + mask[0] = 1ULL << MAPID_TAEKWON; + break; + case JOB_STAR_GLADIATOR: + mask[1] = 1ULL << MAPID_TAEKWON; + break; + case JOB_SOUL_LINKER: + mask[2] = 1ULL << MAPID_TAEKWON; + break; + case JOB_GUNSLINGER: + mask[0] = 1ULL << MAPID_GUNSLINGER; + mask[1] = 1ULL << MAPID_GUNSLINGER; + break; + case JOB_NINJA: + mask[0] = 1ULL << MAPID_NINJA; + mask[1] = 1ULL << MAPID_NINJA; + break; + case JOB_KAGEROU: + case JOB_OBORO: + mask[1] = 1ULL << MAPID_NINJA; + break; + case JOB_REBELLION: + mask[1] = 1ULL << MAPID_GUNSLINGER; + break; + // Other Classes + case JOB_GANGSI: //Bongun/Munak + mask[0] = 1ULL << MAPID_GANGSI; + break; + case JOB_DEATH_KNIGHT: + mask[1] = 1ULL << MAPID_GANGSI; + break; + case JOB_DARK_COLLECTOR: + mask[2] = 1ULL << MAPID_GANGSI; + break; + } + + for (i = 0; i < ARRAYLENGTH(mask); i++) { + if (mask[i] == 0) + continue; + if (enable) + bclass[i] |= mask[i]; + else + bclass[i] &= ~mask[i]; + } +} + +/** + * Converts the JobMask to the format used by map-server to check item + * restriction as per job. + * + * @param bclass Pointer to the variable containing the new format. + * @param jobmask Variable containing JobMask. + */ +void itemdb_jobmask2mapid(uint64 *bclass, uint64 jobmask) +{ + int i; + nullpo_retv(bclass); + bclass[0] = bclass[1] = bclass[2] = 0; //Base classes - if (jobmask & 1<<JOB_NOVICE) { + if (jobmask & 1ULL<<JOB_NOVICE) { //Both Novice/Super-Novice are counted with the same ID - bclass[0] |= 1<<MAPID_NOVICE; - bclass[1] |= 1<<MAPID_NOVICE; + bclass[0] |= 1ULL<<MAPID_NOVICE; + bclass[1] |= 1ULL<<MAPID_NOVICE; } - for (i = JOB_NOVICE+1; i <= JOB_THIEF; i++) - { - if (jobmask & 1<<i) - bclass[0] |= 1<<(MAPID_NOVICE+i); + for (i = JOB_NOVICE+1; i <= JOB_THIEF; i++) { + if (jobmask & 1ULL<<i) + bclass[0] |= 1ULL<<(MAPID_NOVICE+i); } //2-1 classes - if (jobmask & 1<<JOB_KNIGHT) - bclass[1] |= 1<<MAPID_SWORDMAN; - if (jobmask & 1<<JOB_PRIEST) - bclass[1] |= 1<<MAPID_ACOLYTE; - if (jobmask & 1<<JOB_WIZARD) - bclass[1] |= 1<<MAPID_MAGE; - if (jobmask & 1<<JOB_BLACKSMITH) - bclass[1] |= 1<<MAPID_MERCHANT; - if (jobmask & 1<<JOB_HUNTER) - bclass[1] |= 1<<MAPID_ARCHER; - if (jobmask & 1<<JOB_ASSASSIN) - bclass[1] |= 1<<MAPID_THIEF; + if (jobmask & 1ULL<<JOB_KNIGHT) + bclass[1] |= 1ULL<<MAPID_SWORDMAN; + if (jobmask & 1ULL<<JOB_PRIEST) + bclass[1] |= 1ULL<<MAPID_ACOLYTE; + if (jobmask & 1ULL<<JOB_WIZARD) + bclass[1] |= 1ULL<<MAPID_MAGE; + if (jobmask & 1ULL<<JOB_BLACKSMITH) + bclass[1] |= 1ULL<<MAPID_MERCHANT; + if (jobmask & 1ULL<<JOB_HUNTER) + bclass[1] |= 1ULL<<MAPID_ARCHER; + if (jobmask & 1ULL<<JOB_ASSASSIN) + bclass[1] |= 1ULL<<MAPID_THIEF; //2-2 classes - if (jobmask & 1<<JOB_CRUSADER) - bclass[2] |= 1<<MAPID_SWORDMAN; - if (jobmask & 1<<JOB_MONK) - bclass[2] |= 1<<MAPID_ACOLYTE; - if (jobmask & 1<<JOB_SAGE) - bclass[2] |= 1<<MAPID_MAGE; - if (jobmask & 1<<JOB_ALCHEMIST) - bclass[2] |= 1<<MAPID_MERCHANT; - if (jobmask & 1<<JOB_BARD) - bclass[2] |= 1<<MAPID_ARCHER; + if (jobmask & 1ULL<<JOB_CRUSADER) + bclass[2] |= 1ULL<<MAPID_SWORDMAN; + if (jobmask & 1ULL<<JOB_MONK) + bclass[2] |= 1ULL<<MAPID_ACOLYTE; + if (jobmask & 1ULL<<JOB_SAGE) + bclass[2] |= 1ULL<<MAPID_MAGE; + if (jobmask & 1ULL<<JOB_ALCHEMIST) + bclass[2] |= 1ULL<<MAPID_MERCHANT; + if (jobmask & 1ULL<<JOB_BARD) + bclass[2] |= 1ULL<<MAPID_ARCHER; #if 0 // Bard/Dancer share the same slot now. - if (jobmask & 1<<JOB_DANCER) - bclass[2] |= 1<<MAPID_ARCHER; + if (jobmask & 1ULL<<JOB_DANCER) + bclass[2] |= 1ULL<<MAPID_ARCHER; #endif // 0 - if (jobmask & 1<<JOB_ROGUE) - bclass[2] |= 1<<MAPID_THIEF; + if (jobmask & 1ULL<<JOB_ROGUE) + bclass[2] |= 1ULL<<MAPID_THIEF; //Special classes that don't fit above. - if (jobmask & 1<<21) //Taekwon boy - bclass[0] |= 1<<MAPID_TAEKWON; - if (jobmask & 1<<22) //Star Gladiator - bclass[1] |= 1<<MAPID_TAEKWON; - if (jobmask & 1<<23) //Soul Linker - bclass[2] |= 1<<MAPID_TAEKWON; - if (jobmask & 1<<JOB_GUNSLINGER) - {//Rebellion job can equip Gunslinger equips. [Rytech] - bclass[0] |= 1<<MAPID_GUNSLINGER; - bclass[1] |= 1<<MAPID_GUNSLINGER; - } - if (jobmask & 1<<JOB_NINJA) - {bclass[0] |= 1<<MAPID_NINJA; - bclass[1] |= 1<<MAPID_NINJA;}//Kagerou/Oboro jobs can equip Ninja equips. [Rytech] - if (jobmask & 1<<26) //Bongun/Munak - bclass[0] |= 1<<MAPID_GANGSI; - if (jobmask & 1<<27) //Death Knight - bclass[1] |= 1<<MAPID_GANGSI; - if (jobmask & 1<<28) //Dark Collector - bclass[2] |= 1<<MAPID_GANGSI; - if (jobmask & 1<<29) //Kagerou / Oboro - bclass[1] |= 1<<MAPID_NINJA; - if (jobmask & 1<<30) //Rebellion - bclass[1] |= 1<<MAPID_GUNSLINGER; + if (jobmask & 1ULL<<21) //Taekwon boy + bclass[0] |= 1ULL<<MAPID_TAEKWON; + if (jobmask & 1ULL<<22) //Star Gladiator + bclass[1] |= 1ULL<<MAPID_TAEKWON; + if (jobmask & 1ULL<<23) //Soul Linker + bclass[2] |= 1ULL<<MAPID_TAEKWON; + if (jobmask & 1ULL<<JOB_GUNSLINGER) { + //Rebellion job can equip Gunslinger equips. [Rytech] + bclass[0] |= 1ULL<<MAPID_GUNSLINGER; + bclass[1] |= 1ULL<<MAPID_GUNSLINGER; + } + if (jobmask & 1ULL<<JOB_NINJA) { + //Kagerou/Oboro jobs can equip Ninja equips. [Rytech] + bclass[0] |= 1ULL<<MAPID_NINJA; + bclass[1] |= 1ULL<<MAPID_NINJA; + } + if (jobmask & 1ULL<<26) //Bongun/Munak + bclass[0] |= 1ULL<<MAPID_GANGSI; + if (jobmask & 1ULL<<27) //Death Knight + bclass[1] |= 1ULL<<MAPID_GANGSI; + if (jobmask & 1ULL<<28) //Dark Collector + bclass[2] |= 1ULL<<MAPID_GANGSI; + if (jobmask & 1ULL<<29) //Kagerou / Oboro + bclass[1] |= 1ULL<<MAPID_NINJA; + if (jobmask & 1ULL<<30) //Rebellion + bclass[1] |= 1ULL<<MAPID_GUNSLINGER; } void create_dummy_data(void) @@ -637,8 +758,8 @@ int itemdb_isidentified2(struct item_data *data) { } void itemdb_read_groups(void) { - config_t item_group_conf; - config_setting_t *itg = NULL, *it = NULL; + struct config_t item_group_conf; + struct config_setting_t *itg = NULL, *it = NULL; #ifdef RENEWAL const char *config_filename = "db/re/item_group.conf"; // FIXME hardcoded name #else @@ -648,10 +769,8 @@ void itemdb_read_groups(void) { int i = 0, count = 0, c; unsigned int *gsize = NULL; - if (libconfig->read_file(&item_group_conf, config_filename)) { - ShowError("can't read %s\n", config_filename); + if (!libconfig->load_file(&item_group_conf, config_filename)) return; - } gsize = aMalloc( libconfig->setting_length(item_group_conf.root) * sizeof(unsigned int) ); @@ -929,8 +1048,8 @@ bool itemdb_read_cached_packages(const char *config_filename) { return true; } void itemdb_read_packages(void) { - config_t item_packages_conf; - config_setting_t *itg = NULL, *it = NULL, *t = NULL; + struct config_t item_packages_conf; + struct config_setting_t *itg = NULL, *it = NULL, *t = NULL; #ifdef RENEWAL const char *config_filename = "db/re/item_packages.conf"; // FIXME hardcoded name #else @@ -946,10 +1065,8 @@ void itemdb_read_packages(void) { return; } - if (libconfig->read_file(&item_packages_conf, config_filename)) { - ShowError("can't read %s\n", config_filename); + if (!libconfig->load_file(&item_packages_conf, config_filename)) return; - } must = aMalloc( libconfig->setting_length(item_packages_conf.root) * sizeof(unsigned int) ); random = aMalloc( libconfig->setting_length(item_packages_conf.root) * sizeof(unsigned int) ); @@ -1161,8 +1278,8 @@ void itemdb_read_packages(void) { } void itemdb_read_chains(void) { - config_t item_chain_conf; - config_setting_t *itc = NULL; + struct config_t item_chain_conf; + struct config_setting_t *itc = NULL; #ifdef RENEWAL const char *config_filename = "db/re/item_chain.conf"; // FIXME hardcoded name #else @@ -1170,10 +1287,8 @@ void itemdb_read_chains(void) { #endif int i = 0, count = 0; - if (libconfig->read_file(&item_chain_conf, config_filename)) { - ShowError("can't read %s\n", config_filename); + if (!libconfig->load_file(&item_chain_conf, config_filename)) return; - } CREATE(itemdb->chains, struct item_chain, libconfig->setting_length(item_chain_conf.root)); itemdb->chain_count = (unsigned short)libconfig->setting_length(item_chain_conf.root); @@ -1186,9 +1301,9 @@ void itemdb_read_chains(void) { struct item_chain_entry *prev = NULL; const char *name = config_setting_name(itc); int c = 0; - config_setting_t *entry = NULL; + struct config_setting_t *entry = NULL; - script->set_constant2(name,i-1,0); + script->set_constant2(name, i-1, false, false); itemdb->chains[count].qty = (unsigned short)libconfig->setting_length(itc); CREATE(itemdb->chains[count].items, struct item_chain_entry, libconfig->setting_length(itc)); @@ -1254,7 +1369,8 @@ int itemdb_combo_split_atoi (char *str, int *val) { /** * <combo{:combo{:combo:{..}}}>,<{ script }> **/ -void itemdb_read_combos() { +void itemdb_read_combos(void) +{ uint32 lines = 0, count = 0; char line[1024]; char filepath[256]; @@ -1285,7 +1401,7 @@ void itemdb_read_combos() { if (!strchr(p,',')) { /* is there even a single column? */ - ShowError("itemdb_read_combos: Insufficient columns in line %d of \"%s\", skipping.\n", lines, filepath); + ShowError("itemdb_read_combos: Insufficient columns in line %u of \"%s\", skipping.\n", lines, filepath); continue; } @@ -1299,13 +1415,13 @@ void itemdb_read_combos() { p++; if (str[1][0] != '{') { - ShowError("itemdb_read_combos(#1): Invalid format (Script column) in line %d of \"%s\", skipping.\n", lines, filepath); + ShowError("itemdb_read_combos(#1): Invalid format (Script column) in line %u of \"%s\", skipping.\n", lines, filepath); continue; } /* no ending key anywhere (missing \}\) */ if ( str[1][strlen(str[1])-1] != '}' ) { - ShowError("itemdb_read_combos(#2): Invalid format (Script column) in line %d of \"%s\", skipping.\n", lines, filepath); + ShowError("itemdb_read_combos(#2): Invalid format (Script column) in line %u of \"%s\", skipping.\n", lines, filepath); continue; } else { int items[MAX_ITEMS_PER_COMBO]; @@ -1313,14 +1429,14 @@ void itemdb_read_combos() { struct item_combo *combo = NULL; if((retcount = itemdb->combo_split_atoi(str[0], items)) < 2) { - ShowError("itemdb_read_combos: line %d of \"%s\" doesn't have enough items to make for a combo (min:2), skipping.\n", lines, filepath); + ShowError("itemdb_read_combos: line %u of \"%s\" doesn't have enough items to make for a combo (min:2), skipping.\n", lines, filepath); continue; } /* validate */ for(v = 0; v < retcount; v++) { if( !itemdb->exists(items[v]) ) { - ShowError("itemdb_read_combos: line %d of \"%s\" contains unknown item ID %d, skipping.\n", lines, filepath,items[v]); + ShowError("itemdb_read_combos: line %u of \"%s\" contains unknown item ID %d, skipping.\n", lines, filepath, items[v]); break; } } @@ -1384,17 +1500,17 @@ int itemdb_gendercheck(struct item_data *id) * This function is called after preparing the item entry data, and it takes * care of inserting it and cleaning up any remainders of the previous one. * - * @param *entry Pointer to the new item_data entry. Ownership is NOT taken, - * but the content is modified to reflect the validation. - * @param n Ordinal number of the entry, to be displayed in case of - * validation errors. - * @param *source Source of the entry (table or file name), to be displayed in - * case of validation errors. + * @param entry Pointer to the new item_data entry. Ownership is NOT taken, + * but the content is modified to reflect the validation. + * @param n Ordinal number of the entry, to be displayed in case of + * validation errors. + * @param source Source of the entry (file name), to be displayed in case of + * validation errors. * @return Nameid of the validated entry, or 0 in case of failure. * - * Note: This is safe to call if the new entry is a copy of the old one (i.e. - * item_db2 inheritance), as it will make sure not to free any scripts still in - * use in the new entry. + * Note: This is safe to call if the new entry is a shallow copy of the old one + * (i.e. item_db2 inheritance), as it will make sure not to free any scripts + * still in use by the new entry. */ int itemdb_validate_entry(struct item_data *entry, int n, const char *source) { struct item_data *item; @@ -1461,7 +1577,7 @@ int itemdb_validate_entry(struct item_data *entry, int n, const char *source) { if (entry->flag.trade_restriction > ITR_ALL) { ShowWarning("itemdb_validate_entry: Invalid trade restriction flag 0x%x for item %d (%s) in '%s', defaulting to none.\n", - entry->flag.trade_restriction, entry->nameid, entry->jname, source); + (unsigned int)entry->flag.trade_restriction, entry->nameid, entry->jname, source); entry->flag.trade_restriction = ITR_NONE; } @@ -1497,6 +1613,12 @@ int itemdb_validate_entry(struct item_data *entry, int n, const char *source) { memset(&entry->stack, '\0', sizeof(entry->stack)); } + if (entry->type == IT_WEAPON && (entry->look < 0 || entry->look >= MAX_SINGLE_WEAPON_TYPE)) { + ShowWarning("itemdb_validate_entry: Invalid View for weapon items. View value %d for item %d (%s) in '%s', defaulting to 1.\n", + entry->look, entry->nameid, entry->jname, source); + entry->look = 1; + } + entry->wlv = cap_value(entry->wlv, REFINE_TYPE_ARMOR, REFINE_TYPE_MAX); if( !entry->elvmax ) @@ -1534,27 +1656,60 @@ int itemdb_validate_entry(struct item_data *entry, int n, const char *source) { return item->nameid; } -void itemdb_readdb_additional_fields(int itemid, config_setting_t *it, int n, const char *source) +void itemdb_readdb_additional_fields(int itemid, struct config_setting_t *it, int n, const char *source) { // do nothing. plugins can do own work } /** + * Processes job names and changes it into mapid format. + * + * @param id item_data entry. + * @param t Libconfig setting entry. It is expected to be valid and it won't + * be freed (it is care of the caller to do so if necessary). + */ +void itemdb_readdb_job_sub(struct item_data *id, struct config_setting_t *t) +{ + int idx = 0; + struct config_setting_t *it = NULL; + bool enable_all = false; + + id->class_base[0] = id->class_base[1] = id->class_base[2] = 0; + + if (libconfig->setting_lookup_bool_real(t, "All", &enable_all) && enable_all) { + itemdb->jobmask2mapid(id->class_base, UINT64_MAX); + } + while ((it = libconfig->setting_get_elem(t, idx++)) != NULL) { + const char *job_name = config_setting_name(it); + int job_id; + + if (strcmp(job_name, "All") == 0) + continue; + + if ((job_id = pc->check_job_name(job_name)) == -1) { + ShowWarning("itemdb_readdb_job_sub: unknown job name '%s'!\n", job_name); + } else { + itemdb->jobid2mapid(id->class_base, job_id, libconfig->setting_get_bool(it)); + } + } +} + +/** * Processes one itemdb entry from the libconfig backend, loading and inserting * it into the item database. * - * @param *it Libconfig setting entry. It is expected to be valid and it - * won't be freed (it is care of the caller to do so if - * necessary) - * @param n Ordinal number of the entry, to be displayed in case of - * validation errors. - * @param *source Source of the entry (file name), to be displayed in case of - * validation errors. + * @param it Libconfig setting entry. It is expected to be valid and it + * won't be freed (it is care of the caller to do so if + * necessary) + * @param n Ordinal number of the entry, to be displayed in case of + * validation errors. + * @param source Source of the entry (file name), to be displayed in case of + * validation errors. * @return Nameid of the validated entry, or 0 in case of failure. */ -int itemdb_readdb_libconfig_sub(config_setting_t *it, int n, const char *source) { +int itemdb_readdb_libconfig_sub(struct config_setting_t *it, int n, const char *source) { struct item_data id = { 0 }; - config_setting_t *t = NULL; + struct config_setting_t *t = NULL; const char *str = NULL; int i32 = 0; bool inherit = false; @@ -1626,7 +1781,7 @@ int itemdb_readdb_libconfig_sub(config_setting_t *it, int n, const char *source) } else { // Use old entry as default struct item_data *old_entry = itemdb->load(id.nameid); - memcpy(&id, old_entry, sizeof(struct item_data)); + memcpy(&id, old_entry, sizeof(id)); } } @@ -1680,10 +1835,17 @@ int itemdb_readdb_libconfig_sub(config_setting_t *it, int n, const char *source) if( itemdb->lookup_const(it, "Slots", &i32) && i32 >= 0 ) id.slot = i32; - if( itemdb->lookup_const(it, "Job", &i32) ) // This is an unsigned value, do not check for >= 0 - itemdb->jobid2mapid(id.class_base, (unsigned int)i32); - else if( !inherit ) - itemdb->jobid2mapid(id.class_base, UINT_MAX); + if ((t = libconfig->setting_get_member(it, "Job")) != NULL) { + if (config_setting_is_group(t)) { + itemdb->readdb_job_sub(&id, t); + } else if (itemdb->lookup_const(it, "Job", &i32)) { // This is an unsigned value, do not check for >= 0 + itemdb->jobmask2mapid(id.class_base, (uint64)i32); + } else if (!inherit) { + itemdb->jobmask2mapid(id.class_base, UINT64_MAX); + } + } else if (!inherit) { + itemdb->jobmask2mapid(id.class_base, UINT64_MAX); + } if( itemdb->lookup_const(it, "Upper", &i32) && i32 >= 0 ) id.class_upper = (unsigned int)i32; @@ -1735,7 +1897,7 @@ int itemdb_readdb_libconfig_sub(config_setting_t *it, int n, const char *source) if ( (t = libconfig->setting_get_member(it, "Trade")) ) { if (config_setting_is_group(t)) { - config_setting_t *tt = NULL; + struct config_setting_t *tt = NULL; if ((tt = libconfig->setting_get_member(t, "override"))) { id.gm_lv_trade_override = libconfig->setting_get_int(tt); @@ -1801,7 +1963,7 @@ int itemdb_readdb_libconfig_sub(config_setting_t *it, int n, const char *source) if ((t = libconfig->setting_get_member(it, "Nouse"))) { if (config_setting_is_group(t)) { - config_setting_t *nt = NULL; + struct config_setting_t *nt = NULL; if ((nt = libconfig->setting_get_member(t, "override"))) { id.item_usage.override = libconfig->setting_get_int(nt); @@ -1849,7 +2011,7 @@ int itemdb_readdb_libconfig_sub(config_setting_t *it, int n, const char *source) return itemdb->validate_entry(&id, n, source); } -bool itemdb_lookup_const(const config_setting_t *it, const char *name, int *value) +bool itemdb_lookup_const(const struct config_setting_t *it, const char *name, int *value) { nullpo_retr(false, name); nullpo_retr(false, value); @@ -1873,24 +2035,29 @@ bool itemdb_lookup_const(const config_setting_t *it, const char *name, int *valu * Reads from a libconfig-formatted itemdb file and inserts the found entries into the * item database, overwriting duplicate ones (i.e. item_db2 overriding item_db.) * - * @param *filename File name, relative to the database path. + * @param filename File name, relative to the database path. * @return The number of found entries. */ int itemdb_readdb_libconfig(const char *filename) { bool duplicate[MAX_ITEMDB]; - config_t item_db_conf; - config_setting_t *itdb, *it; + struct config_t item_db_conf; + struct config_setting_t *itdb, *it; char filepath[256]; int i = 0, count = 0; nullpo_ret(filename); + sprintf(filepath, "%s/%s", map->db_path, filename); - memset(&duplicate,0,sizeof(duplicate)); - if( libconfig->read_file(&item_db_conf, filepath) || !(itdb = libconfig->setting_get_member(item_db_conf.root, "item_db")) ) { + if (!libconfig->load_file(&item_db_conf, filepath)) + return 0; + + if ((itdb = libconfig->setting_get_member(item_db_conf.root, "item_db")) == NULL) { ShowError("can't read %s\n", filepath); return 0; } + memset(&duplicate,0,sizeof(duplicate)); + while( (it = libconfig->setting_get_elem(itdb,i++)) ) { int nameid = itemdb->readdb_libconfig_sub(it, i-1, filename); @@ -2148,7 +2315,7 @@ void itemdb_name_constants(void) { script->parser_current_file = "Item Database (Likely an invalid or conflicting AegisName)"; #endif // ENABLE_CASE_CHECK for( data = dbi_first(iter); dbi_exists(iter); data = dbi_next(iter) ) - script->set_constant2(data->name,data->nameid,0); + script->set_constant2(data->name, data->nameid, false, false); #ifdef ENABLE_CASE_CHECK script->parser_current_file = NULL; #endif // ENABLE_CASE_CHECK @@ -2176,7 +2343,7 @@ void do_init_itemdb(bool minimal) { clif->cashshop_load(); /** it failed? we disable it **/ - if( !clif->parse_roulette_db() ) + if (battle_config.feature_roulette == 1 && !clif->parse_roulette_db()) battle_config.feature_roulette = 0; } void itemdb_defaults(void) { @@ -2226,6 +2393,7 @@ void itemdb_defaults(void) { itemdb->searchname_array_sub = itemdb_searchname_array_sub; itemdb->searchrandomid = itemdb_searchrandomid; itemdb->typename = itemdb_typename; + itemdb->jobmask2mapid = itemdb_jobmask2mapid; itemdb->jobid2mapid = itemdb_jobid2mapid; itemdb->create_dummy_data = create_dummy_data; itemdb->create_item_data = create_item_data; @@ -2250,6 +2418,7 @@ void itemdb_defaults(void) { itemdb->gendercheck = itemdb_gendercheck; itemdb->validate_entry = itemdb_validate_entry; itemdb->readdb_additional_fields = itemdb_readdb_additional_fields; + itemdb->readdb_job_sub = itemdb_readdb_job_sub; itemdb->readdb_libconfig_sub = itemdb_readdb_libconfig_sub; itemdb->readdb_libconfig = itemdb_readdb_libconfig; itemdb->unique_id = itemdb_unique_id; diff --git a/src/map/itemdb.h b/src/map/itemdb.h index d751451c6..47446d617 100644 --- a/src/map/itemdb.h +++ b/src/map/itemdb.h @@ -2,7 +2,7 @@ * This file is part of Hercules. * http://herc.ws - http://github.com/HerculesWS/Hercules * - * Copyright (C) 2012-2015 Hercules Dev Team + * Copyright (C) 2012-2016 Hercules Dev Team * Copyright (C) Athena Dev Teams * * Hercules is free software: you can redistribute it and/or modify @@ -23,10 +23,10 @@ /* #include "map/map.h" */ #include "common/hercules.h" -#include "common/conf.h" #include "common/db.h" #include "common/mmo.h" // ITEM_NAME_LENGTH +struct config_setting_t; struct script_code; struct hplugin_data_store; @@ -64,6 +64,7 @@ enum item_itemid { ITEMID_BRANCH_OF_DEAD_TREE = 604, ITEMID_ANODYNE = 605, ITEMID_ALOEBERA = 606, + ITEMID_MAGNIFIER = 611, ITEMID_POISON_BOTTLE = 678, ITEMID_EMPTY_BOTTLE = 713, ITEMID_EMPERIUM = 714, @@ -136,6 +137,7 @@ enum item_itemid { ITEMID_MAGIC_CASTLE = 12308, ITEMID_BULGING_HEAD = 12309, ITEMID_THICK_MANUAL50 = 12312, + ITEMID_NOVICE_MAGNIFIER = 12325, ITEMID_ANCILLA = 12333, ITEMID_REPAIR_A = 12392, ITEMID_REPAIR_B = 12393, @@ -393,6 +395,14 @@ enum ItemNouseRestrictions { INR_ALL = 0x1 ///< Sum of all the above values }; +/** Convenience item list (entry) used in various functions */ +struct itemlist_entry { + int id; ///< Item ID or (inventory) index + int16 amount; ///< Amount +}; +/** Convenience item list used in various functions */ +VECTOR_STRUCT_DECL(itemlist, struct itemlist_entry); + struct item_combo { struct script_code *script; unsigned short nameid[MAX_ITEMS_PER_COMBO];/* nameid array */ @@ -476,7 +486,7 @@ struct item_data { int delay; //Lupus: I rearranged order of these fields due to compatibility with ITEMINFO script command // some script commands should be revised as well... - unsigned int class_base[3]; ///< Specifies if the base can wear this item (split in 3 indexes per type: 1-1, 2-1, 2-2) + uint64 class_base[3]; ///< Specifies if the base can wear this item (split in 3 indexes per type: 1-1, 2-1, 2-2) unsigned class_upper : 6; ///< Specifies if the upper-type can equip it (bitfield, 0x01: normal, 0x02: upper, 0x04: baby normal, 0x08: third normal, 0x10: third upper, 0x20: third baby) struct { unsigned short chance; @@ -606,7 +616,8 @@ struct itemdb_interface { int (*searchname_array_sub) (DBKey key, DBData data, va_list ap); int (*searchrandomid) (struct item_group *group); const char* (*typename) (int type); - void (*jobid2mapid) (unsigned int *bclass, unsigned int jobmask); + void (*jobmask2mapid) (uint64 *bclass, uint64 jobmask); + void (*jobid2mapid) (uint64 *bclass, int job_id, bool enable); void (*create_dummy_data) (void); struct item_data* (*create_item_data) (int nameid); int (*isequip) (int nameid); @@ -626,11 +637,12 @@ struct itemdb_interface { int (*isidentified) (int nameid); int (*isidentified2) (struct item_data *data); int (*combo_split_atoi) (char *str, int *val); - void (*read_combos) (); + void (*read_combos) (void); int (*gendercheck) (struct item_data *id); int (*validate_entry) (struct item_data *entry, int n, const char *source); - void (*readdb_additional_fields) (int itemid, config_setting_t *it, int n, const char *source); - int (*readdb_libconfig_sub) (config_setting_t *it, int n, const char *source); + void (*readdb_additional_fields) (int itemid, struct config_setting_t *it, int n, const char *source); + void (*readdb_job_sub) (struct item_data *id, struct config_setting_t *t); + int (*readdb_libconfig_sub) (struct config_setting_t *it, int n, const char *source); int (*readdb_libconfig) (const char *filename); uint64 (*unique_id) (struct map_session_data *sd); void (*read) (bool minimal); @@ -639,7 +651,7 @@ struct itemdb_interface { void (*clear) (bool total); struct item_combo * (*id2combo) (unsigned short id); bool (*is_item_usable) (struct item_data *item); - bool (*lookup_const) (const config_setting_t *it, const char *name, int *value); + bool (*lookup_const) (const struct config_setting_t *it, const char *name, int *value); }; #ifdef HERCULES_CORE diff --git a/src/map/log.c b/src/map/log.c index 942acb706..072f7b6fd 100644 --- a/src/map/log.c +++ b/src/map/log.c @@ -62,11 +62,21 @@ char log_picktype2char(e_log_pick_type type) { case LOG_TYPE_BUYING_STORE: return 'B'; // (B)uying Store case LOG_TYPE_LOOT: return 'L'; // (L)oot (consumed monster pick/drop) case LOG_TYPE_BANK: return 'K'; // Ban(K) Transactions + case LOG_TYPE_DIVORCE: return 'Y'; // Divorce + case LOG_TYPE_ROULETTE: return 'Z'; // Roulette + case LOG_TYPE_RENTAL: return 'W'; // Rental + case LOG_TYPE_CARD: return 'Q'; // Card + case LOG_TYPE_INV_INVALID: return 'J'; // Invalid in inventory + case LOG_TYPE_CART_INVALID: return 'H'; // Invalid in cart + case LOG_TYPE_EGG: return '@'; // Egg + case LOG_TYPE_QUEST: return '0'; // Quest + case LOG_TYPE_SKILL: return '1'; // Skill + case LOG_TYPE_REFINE: return '2'; // Refine case LOG_TYPE_OTHER: return 'X'; // Other } // should not get here, fallback - ShowDebug("log_picktype2char: Unknown pick type %d.\n", type); + ShowDebug("log_picktype2char: Unknown pick type %u.\n", type); return 'X'; } @@ -81,7 +91,7 @@ char log_chattype2char(e_log_chat_type type) { } // should not get here, fallback - ShowDebug("log_chattype2char: Unknown chat type %d.\n", type); + ShowDebug("log_chattype2char: Unknown chat type %u.\n", type); return 'O'; } diff --git a/src/map/log.h b/src/map/log.h index fbd0acc0e..69622adc6 100644 --- a/src/map/log.h +++ b/src/map/log.h @@ -57,29 +57,40 @@ typedef enum e_log_chat_type { } e_log_chat_type; typedef enum e_log_pick_type { - LOG_TYPE_NONE = 0, - LOG_TYPE_TRADE = 0x00001, - LOG_TYPE_VENDING = 0x00002, - LOG_TYPE_PICKDROP_PLAYER = 0x00004, - LOG_TYPE_PICKDROP_MONSTER = 0x00008, - LOG_TYPE_NPC = 0x00010, - LOG_TYPE_SCRIPT = 0x00020, - LOG_TYPE_STEAL = 0x00040, - LOG_TYPE_CONSUME = 0x00080, - LOG_TYPE_PRODUCE = 0x00100, - LOG_TYPE_MVP = 0x00200, - LOG_TYPE_COMMAND = 0x00400, - LOG_TYPE_STORAGE = 0x00800, - LOG_TYPE_GSTORAGE = 0x01000, - LOG_TYPE_MAIL = 0x02000, - LOG_TYPE_AUCTION = 0x04000, - LOG_TYPE_BUYING_STORE = 0x08000, - LOG_TYPE_OTHER = 0x10000, - LOG_TYPE_BANK = 0x20000, + LOG_TYPE_NONE = 0x00000000, + LOG_TYPE_TRADE = 0x00000001, + LOG_TYPE_VENDING = 0x00000002, + LOG_TYPE_PICKDROP_PLAYER = 0x00000004, + LOG_TYPE_PICKDROP_MONSTER = 0x00000008, + LOG_TYPE_NPC = 0x00000010, + LOG_TYPE_SCRIPT = 0x00000020, + LOG_TYPE_STEAL = 0x00000040, + LOG_TYPE_CONSUME = 0x00000080, + LOG_TYPE_PRODUCE = 0x00000100, + LOG_TYPE_MVP = 0x00000200, + LOG_TYPE_COMMAND = 0x00000400, + LOG_TYPE_STORAGE = 0x00000800, + LOG_TYPE_GSTORAGE = 0x00001000, + LOG_TYPE_MAIL = 0x00002000, + LOG_TYPE_AUCTION = 0x00004000, + LOG_TYPE_BUYING_STORE = 0x00008000, + LOG_TYPE_OTHER = 0x00010000, + LOG_TYPE_BANK = 0x00020000, + LOG_TYPE_DIVORCE = 0x00040000, + LOG_TYPE_ROULETTE = 0x00080000, + LOG_TYPE_RENTAL = 0x00100000, + LOG_TYPE_CARD = 0x00200000, + LOG_TYPE_INV_INVALID = 0x00400000, + LOG_TYPE_CART_INVALID = 0x00800000, + LOG_TYPE_EGG = 0x01000000, + LOG_TYPE_QUEST = 0x02000000, + LOG_TYPE_SKILL = 0x04000000, + LOG_TYPE_REFINE = 0x08000000, + // combinations LOG_TYPE_LOOT = LOG_TYPE_PICKDROP_MONSTER|LOG_TYPE_CONSUME, // all - LOG_TYPE_ALL = 0xFFFFF, + LOG_TYPE_ALL = 0xFFFFFFFF, } e_log_pick_type; /// filters for item logging diff --git a/src/map/map.c b/src/map/map.c index 1b922148b..f2e47be74 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -4982,27 +4982,27 @@ enum bl_type map_zone_bl_type(const char *entry, enum map_zone_skill_subtype *su } /* [Ind/Hercules] */ void read_map_zone_db(void) { - config_t map_zone_db; - config_setting_t *zones = NULL; + struct config_t map_zone_db; + struct config_setting_t *zones = NULL; /* TODO: #ifndef required for re/pre-re */ #ifdef RENEWAL const char *config_filename = "db/re/map_zone_db.conf"; // FIXME hardcoded name #else const char *config_filename = "db/pre-re/map_zone_db.conf"; // FIXME hardcoded name #endif - if (libconfig->read_file(&map_zone_db, config_filename)) + if (!libconfig->load_file(&map_zone_db, config_filename)) return; zones = libconfig->lookup(&map_zone_db, "zones"); if (zones != NULL) { struct map_zone_data *zone; - config_setting_t *zone_e; - config_setting_t *skills; - config_setting_t *items; - config_setting_t *mapflags; - config_setting_t *commands; - config_setting_t *caps; + struct config_setting_t *zone_e; + struct config_setting_t *skills; + struct config_setting_t *items; + struct config_setting_t *mapflags; + struct config_setting_t *commands; + struct config_setting_t *caps; const char *name; const char *zonename; int i,h,v,j; @@ -5017,7 +5017,7 @@ void read_map_zone_db(void) { zone_e = libconfig->setting_get_elem(zones, i); if (!libconfig->setting_lookup_string(zone_e, "name", &zonename)) { - ShowError("map_zone_db: missing zone name, skipping... (%s:%d)\n", + ShowError("map_zone_db: missing zone name, skipping... (%s:%u)\n", config_setting_source_file(zone_e), config_setting_source_line(zone_e)); libconfig->setting_remove_elem(zones,i);/* remove from the tree */ --zone_count; @@ -5054,7 +5054,7 @@ void read_map_zone_db(void) { disabled_skills_count = libconfig->setting_length(skills); /* validate */ for(h = 0; h < libconfig->setting_length(skills); h++) { - config_setting_t *skillinfo = libconfig->setting_get_elem(skills, h); + struct config_setting_t *skillinfo = libconfig->setting_get_elem(skills, h); name = config_setting_name(skillinfo); if( !map->zone_str2skillid(name) ) { ShowError("map_zone_db: unknown skill (%s) in disabled_skills for zone '%s', skipping skill...\n",name,zone->name); @@ -5069,7 +5069,7 @@ void read_map_zone_db(void) { /* all ok, process */ CREATE( zone->disabled_skills, struct map_zone_disabled_skill_entry *, disabled_skills_count ); for(h = 0, v = 0; h < libconfig->setting_length(skills); h++) { - config_setting_t *skillinfo = libconfig->setting_get_elem(skills, h); + struct config_setting_t *skillinfo = libconfig->setting_get_elem(skills, h); struct map_zone_disabled_skill_entry * entry; enum bl_type type; name = config_setting_name(skillinfo); @@ -5092,7 +5092,7 @@ void read_map_zone_db(void) { disabled_items_count = libconfig->setting_length(items); /* validate */ for(h = 0; h < libconfig->setting_length(items); h++) { - config_setting_t *item = libconfig->setting_get_elem(items, h); + struct config_setting_t *item = libconfig->setting_get_elem(items, h); name = config_setting_name(item); if( !map->zone_str2itemid(name) ) { ShowError("map_zone_db: unknown item (%s) in disabled_items for zone '%s', skipping item...\n",name,zone->name); @@ -5111,7 +5111,7 @@ void read_map_zone_db(void) { CREATE(zone->cant_disable_items, int, zone->cant_disable_items_count); } for(h = 0, v = 0, j = 0; h < libconfig->setting_length(items); h++) { - config_setting_t *item = libconfig->setting_get_elem(items, h); + struct config_setting_t *item = libconfig->setting_get_elem(items, h); name = config_setting_name(item); if( libconfig->setting_get_bool(item) ) { /* only add if enabled */ @@ -5143,7 +5143,7 @@ void read_map_zone_db(void) { disabled_commands_count = libconfig->setting_length(commands); /* validate */ for(h = 0; h < libconfig->setting_length(commands); h++) { - config_setting_t *command = libconfig->setting_get_elem(commands, h); + struct config_setting_t *command = libconfig->setting_get_elem(commands, h); name = config_setting_name(command); if( !atcommand->exists(name) ) { ShowError("map_zone_db: unknown command '%s' in disabled_commands for zone '%s', skipping entry...\n",name,zone->name); @@ -5158,7 +5158,7 @@ void read_map_zone_db(void) { /* all ok, process */ CREATE( zone->disabled_commands, struct map_zone_disabled_command_entry *, disabled_commands_count ); for(h = 0, v = 0; h < libconfig->setting_length(commands); h++) { - config_setting_t *command = libconfig->setting_get_elem(commands, h); + struct config_setting_t *command = libconfig->setting_get_elem(commands, h); struct map_zone_disabled_command_entry * entry; int group_lv; name = config_setting_name(command); @@ -5179,7 +5179,7 @@ void read_map_zone_db(void) { capped_skills_count = libconfig->setting_length(caps); /* validate */ for(h = 0; h < libconfig->setting_length(caps); h++) { - config_setting_t *cap = libconfig->setting_get_elem(caps, h); + struct config_setting_t *cap = libconfig->setting_get_elem(caps, h); name = config_setting_name(cap); if( !map->zone_str2skillid(name) ) { ShowError("map_zone_db: unknown skill (%s) in skill_damage_cap for zone '%s', skipping skill...\n",name,zone->name); @@ -5194,7 +5194,7 @@ void read_map_zone_db(void) { /* all ok, process */ CREATE( zone->capped_skills, struct map_zone_skill_damage_cap_entry *, capped_skills_count ); for(h = 0, v = 0; h < libconfig->setting_length(caps); h++) { - config_setting_t *cap = libconfig->setting_get_elem(caps, h); + struct config_setting_t *cap = libconfig->setting_get_elem(caps, h); struct map_zone_skill_damage_cap_entry * entry; enum bl_type type; name = config_setting_name(cap); @@ -5219,8 +5219,8 @@ void read_map_zone_db(void) { /* process inheritance, aka loop through the whole thing again :P */ for (i = 0; i < zone_count; ++i) { - config_setting_t *inherit_tree = NULL; - config_setting_t *new_entry = NULL; + struct config_setting_t *inherit_tree = NULL; + struct config_setting_t *new_entry = NULL; int inherit_count; zone_e = libconfig->setting_get_elem(zones, i); @@ -5278,7 +5278,7 @@ void read_map_zone_db(void) { for(j = 0; j < disabled_skills_count_i; j++) { int k; for(k = 0; k < disabled_skills_count; k++) { - config_setting_t *skillinfo = libconfig->setting_get_elem(skills, k); + struct config_setting_t *skillinfo = libconfig->setting_get_elem(skills, k); if( map->zone_str2skillid(config_setting_name(skillinfo)) == izone->disabled_skills[j]->nameid ) { break; } @@ -5302,7 +5302,7 @@ void read_map_zone_db(void) { for(j = 0; j < disabled_items_count_i; j++) { int k; for(k = 0; k < disabled_items_count; k++) { - config_setting_t *item = libconfig->setting_get_elem(items, k); + struct config_setting_t *item = libconfig->setting_get_elem(items, k); name = config_setting_name(item); @@ -5348,7 +5348,7 @@ void read_map_zone_db(void) { for(j = 0; j < disabled_commands_count_i; j++) { int k; for(k = 0; k < disabled_commands_count; k++) { - config_setting_t *command = libconfig->setting_get_elem(commands, k); + struct config_setting_t *command = libconfig->setting_get_elem(commands, k); if( atcommand->exists(config_setting_name(command))->func == izone->disabled_commands[j]->cmd ) { break; } @@ -5372,7 +5372,7 @@ void read_map_zone_db(void) { for(j = 0; j < capped_skills_count_i; j++) { int k; for(k = 0; k < capped_skills_count; k++) { - config_setting_t *cap = libconfig->setting_get_elem(caps, k); + struct config_setting_t *cap = libconfig->setting_get_elem(caps, k); if( map->zone_str2skillid(config_setting_name(cap)) == izone->capped_skills[j]->nameid ) { break; } @@ -5774,9 +5774,7 @@ void map_load_defaults(void) { pet_defaults(); path_defaults(); quest_defaults(); -#ifdef PCRE_SUPPORT npc_chat_defaults(); -#endif } /** * --run-once handler diff --git a/src/map/map.h b/src/map/map.h index 4c74d352c..54b0c3575 100644 --- a/src/map/map.h +++ b/src/map/map.h @@ -398,7 +398,7 @@ struct flooritem_data { struct item item_data; }; -enum status_point_types { +enum status_point_types { //we better clean up this enum and change it name [Hemagx] SP_SPEED,SP_BASEEXP,SP_JOBEXP,SP_KARMA,SP_MANNER,SP_HP,SP_MAXHP,SP_SP, // 0-7 SP_MAXSP,SP_STATUSPOINT,SP_0a,SP_BASELEVEL,SP_SKILLPOINT,SP_STR,SP_AGI,SP_VIT, // 8-15 SP_INT,SP_DEX,SP_LUK,SP_CLASS,SP_ZENY,SP_SEX,SP_NEXTBASEEXP,SP_NEXTJOBEXP, // 16-23 @@ -716,7 +716,7 @@ struct map_data { unsigned noknockback : 1; unsigned notomb : 1; unsigned nocashshop : 1; - unsigned noviewid : 22; + uint32 noviewid; ///< noviewid (bitmask - @see enum equip_pos) } flag; struct point save; struct npc_data *npc[MAX_NPC_PER_MAP]; @@ -866,6 +866,7 @@ typedef struct elemental_data TBL_ELEM; * object is passed to BL_UCAST. It's declared as static inline to let the * compiler optimize out the function call overhead. */ +static inline struct block_list *BL_UCAST_(struct block_list *bl) __attribute__((unused)); static inline struct block_list *BL_UCAST_(struct block_list *bl) { return bl; @@ -894,6 +895,7 @@ static inline struct block_list *BL_UCAST_(struct block_list *bl) * object is passed to BL_UCAST. It's declared as static inline to let the * compiler optimize out the function call overhead. */ +static inline const struct block_list *BL_UCCAST_(const struct block_list *bl) __attribute__((unused)); static inline const struct block_list *BL_UCCAST_(const struct block_list *bl) { return bl; diff --git a/src/map/mapreg_sql.c b/src/map/mapreg_sql.c index 9bf67196e..46962ac14 100644 --- a/src/map/mapreg_sql.c +++ b/src/map/mapreg_sql.c @@ -97,7 +97,7 @@ bool mapreg_setreg(int64 uid, int val) { if (name[1] != '@' && !mapreg->skip_insert) {// write new variable to database char tmp_str[(SCRIPT_VARNAME_LENGTH+1)*2+1]; SQL->EscapeStringLen(map->mysql_handle, tmp_str, name, strnlen(name, SCRIPT_VARNAME_LENGTH+1)); - if( SQL_ERROR == SQL->Query(map->mysql_handle, "INSERT INTO `%s`(`varname`,`index`,`value`) VALUES ('%s','%d','%d')", mapreg->table, tmp_str, i, val) ) + if( SQL_ERROR == SQL->Query(map->mysql_handle, "INSERT INTO `%s`(`varname`,`index`,`value`) VALUES ('%s','%u','%d')", mapreg->table, tmp_str, i, val) ) Sql_ShowDebug(map->mysql_handle); } i64db_put(mapreg->regs.vars, uid, m); @@ -111,7 +111,7 @@ bool mapreg_setreg(int64 uid, int val) { i64db_remove(mapreg->regs.vars, uid); if( name[1] != '@' ) {// Remove from database because it is unused. - if( SQL_ERROR == SQL->Query(map->mysql_handle, "DELETE FROM `%s` WHERE `varname`='%s' AND `index`='%d'", mapreg->table, name, i) ) + if( SQL_ERROR == SQL->Query(map->mysql_handle, "DELETE FROM `%s` WHERE `varname`='%s' AND `index`='%u'", mapreg->table, name, i) ) Sql_ShowDebug(map->mysql_handle); } } @@ -136,7 +136,7 @@ bool mapreg_setregstr(int64 uid, const char* str) { if( i ) script->array_update(&mapreg->regs, uid, true); if(name[1] != '@') { - if( SQL_ERROR == SQL->Query(map->mysql_handle, "DELETE FROM `%s` WHERE `varname`='%s' AND `index`='%d'", mapreg->table, name, i) ) + if (SQL_ERROR == SQL->Query(map->mysql_handle, "DELETE FROM `%s` WHERE `varname`='%s' AND `index`='%u'", mapreg->table, name, i)) Sql_ShowDebug(map->mysql_handle); } if( (m = i64db_get(mapreg->regs.vars, uid)) ) { @@ -170,7 +170,7 @@ bool mapreg_setregstr(int64 uid, const char* str) { char tmp_str2[255*2+1]; SQL->EscapeStringLen(map->mysql_handle, tmp_str, name, strnlen(name, SCRIPT_VARNAME_LENGTH+1)); SQL->EscapeStringLen(map->mysql_handle, tmp_str2, str, strnlen(str, 255)); - if( SQL_ERROR == SQL->Query(map->mysql_handle, "INSERT INTO `%s`(`varname`,`index`,`value`) VALUES ('%s','%d','%s')", mapreg->table, tmp_str, i, tmp_str2) ) + if( SQL_ERROR == SQL->Query(map->mysql_handle, "INSERT INTO `%s`(`varname`,`index`,`value`) VALUES ('%s','%u','%s')", mapreg->table, tmp_str, i, tmp_str2) ) Sql_ShowDebug(map->mysql_handle); } i64db_put(mapreg->regs.vars, uid, m); diff --git a/src/map/mercenary.c b/src/map/mercenary.c index e6c911ef6..fa337e13b 100644 --- a/src/map/mercenary.c +++ b/src/map/mercenary.c @@ -66,19 +66,23 @@ int merc_search_index(int class_) { int i; ARR_FIND(0, MAX_MERCENARY_CLASS, i, mercenary->db[i].class_ == class_); - return (i == MAX_MERCENARY_CLASS)?-1:i; + if (i == MAX_MERCENARY_CLASS) + return INDEX_NOT_FOUND; + return i; } bool merc_class(int class_) { - return (bool)(mercenary->search_index(class_) > -1); + if (mercenary->search_index(class_) != INDEX_NOT_FOUND) + return true; + return false; } struct view_data * merc_get_viewdata(int class_) { int i = mercenary->search_index(class_); - if( i < 0 ) - return 0; + if (i == INDEX_NOT_FOUND) + return NULL; return &mercenary->db[i].vd; } @@ -90,7 +94,7 @@ int merc_create(struct map_session_data *sd, int class_, unsigned int lifetime) int i; nullpo_retr(0,sd); - if( (i = mercenary->search_index(class_)) < 0 ) + if ((i = mercenary->search_index(class_)) == INDEX_NOT_FOUND) return 0; db = &mercenary->db[i]; @@ -301,7 +305,8 @@ void merc_contract_init(struct mercenary_data *md) md->regen.state.block = 0; } -int merc_data_received(struct s_mercenary *merc, bool flag) { +int merc_data_received(const struct s_mercenary *merc, bool flag) +{ struct map_session_data *sd; struct mercenary_data *md; struct s_mercenary_db *db; @@ -309,8 +314,8 @@ int merc_data_received(struct s_mercenary *merc, bool flag) { if( (sd = map->charid2sd(merc->char_id)) == NULL ) return 0; - if( !flag || i < 0 ) - { // Not created - loaded - DB info + if (!flag || i == INDEX_NOT_FOUND) { + // Not created - loaded - DB info sd->status.mer_id = 0; return 0; } diff --git a/src/map/mercenary.h b/src/map/mercenary.h index 1b3453a84..142460e2a 100644 --- a/src/map/mercenary.h +++ b/src/map/mercenary.h @@ -120,7 +120,7 @@ struct mercenary_interface { struct view_data * (*get_viewdata) (int class_); int (*create) (struct map_session_data *sd, int class_, unsigned int lifetime); - int (*data_received) (struct s_mercenary *merc, bool flag); + int (*data_received) (const struct s_mercenary *merc, bool flag); int (*save) (struct mercenary_data *md); void (*heal) (struct mercenary_data *md, int hp, int sp); diff --git a/src/map/mob.c b/src/map/mob.c index 37da81a15..8d38fead7 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -46,6 +46,7 @@ #include "map/status.h" #include "common/HPM.h" #include "common/cbasetypes.h" +#include "common/conf.h" #include "common/db.h" #include "common/ers.h" #include "common/memmgr.h" @@ -743,7 +744,7 @@ int mob_spawn_bg(const char* mapname, short x, short y, const char* mobname, int data.class_ = class_; if( (x <= 0 || y <= 0) && !map->search_freecell(NULL, m, &x, &y, -1,-1, 1) ) { - ShowWarning("mob_spawn_bg: Couldn't locate a spawn cell for guardian class %d (bg_id %d) at map %s\n",class_, bg_id, map->list[m].name); + ShowWarning("mob_spawn_bg: Couldn't locate a spawn cell for guardian class %d (bg_id %u) at map %s\n", class_, bg_id, map->list[m].name); return 0; } @@ -841,7 +842,8 @@ int mob_delayspawn(int tid, int64 tick, int id, intptr_t data) { *------------------------------------------*/ int mob_setdelayspawn(struct mob_data *md) { - unsigned int spawntime, mode; + unsigned int spawntime; + uint32 mode; struct mob_db *db; if (!md->spawn) //Doesn't has respawn data! @@ -988,7 +990,7 @@ int mob_spawn (struct mob_data *md) /*========================================== * Determines if the mob can change target. [Skotlex] *------------------------------------------*/ -int mob_can_changetarget(struct mob_data* md, struct block_list* target, int mode) +int mob_can_changetarget(const struct mob_data *md, const struct block_list *target, uint32 mode) { // if the monster was provoked ignore the above rule [celest] if(md->state.provoke_flag) @@ -1005,7 +1007,7 @@ int mob_can_changetarget(struct mob_data* md, struct block_list* target, int mod return 0; return (battle_config.mob_ai&0x4 || check_distance_bl(&md->bl, target, 3)); case MSS_RUSH: - return (mode&MD_CHANGETARGET_CHASE); + return (mode&MD_CHANGETARGET_CHASE) ? 1 : 0; case MSS_FOLLOW: case MSS_ANGRY: case MSS_IDLE: @@ -1044,17 +1046,17 @@ int mob_target(struct mob_data *md,struct block_list *bl,int dist) /*========================================== * The ?? routine of an active monster *------------------------------------------*/ -int mob_ai_sub_hard_activesearch(struct block_list *bl,va_list ap) +int mob_ai_sub_hard_activesearch(struct block_list *bl, va_list ap) { struct mob_data *md; struct block_list **target; - int mode; + uint32 mode; int dist; nullpo_ret(bl); md=va_arg(ap,struct mob_data *); target= va_arg(ap,struct block_list**); - mode= va_arg(ap,int); + mode = va_arg(ap, uint32); //If can't seek yet, not an enemy, or you can't attack it, skip. if (md->bl.id == bl->id || (*target) == bl || !status->check_skilluse(&md->bl, bl, 0, 0)) @@ -1400,7 +1402,7 @@ int mob_warpchase(struct mob_data *md, struct block_list *target) *------------------------------------------*/ bool mob_ai_sub_hard(struct mob_data *md, int64 tick) { struct block_list *tbl = NULL, *abl = NULL; - int mode; + uint32 mode; int view_range, can_move; if(md->bl.prev == NULL || md->status.hp <= 0) @@ -1541,7 +1543,7 @@ bool mob_ai_sub_hard(struct mob_data *md, int64 tick) { } if ((!tbl && mode&MD_AGGRESSIVE) || md->state.skillstate == MSS_FOLLOW) { - map->foreachinrange (mob->ai_sub_hard_activesearch, &md->bl, view_range, DEFAULT_ENEMY_TYPE(md), md, &tbl, mode); + map->foreachinrange(mob->ai_sub_hard_activesearch, &md->bl, view_range, DEFAULT_ENEMY_TYPE(md), md, &tbl, mode); } else if ((mode&MD_CHANGECHASE && (md->state.skillstate == MSS_RUSH || md->state.skillstate == MSS_FOLLOW)) || (md->sc.count && md->sc.data[SC__CHAOS])) { int search_size; search_size = view_range<md->status.rhw.range ? view_range:md->status.rhw.range; @@ -2064,7 +2066,7 @@ void mob_damage(struct mob_data *md, struct block_list *src, int damage) { if (battle_config.show_mob_info&3) clif->charnameack (0, &md->bl); - + #if PACKETVER >= 20131223 // Resend ZC_NOTIFY_MOVEENTRY to Update the HP if (battle_config.show_monster_hp_bar) @@ -2482,15 +2484,15 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) { if(mvp_sd && md->db->mexp > 0 && md->special_state.ai == AI_NONE) { int log_mvp[2] = {0}; unsigned int mexp; - double exp; + int64 exp; //mapflag: noexp check [Lorky] - if (map->list[m].flag.nobaseexp || type&2) - exp =1; - else { + if (map->list[m].flag.nobaseexp || type&2) { + exp = 1; + } else { exp = md->db->mexp; if (count > 1) - exp += exp*(battle_config.exp_bonus_attacker*(count-1))/100.; //[Gengar] + exp += apply_percentrate64(exp, battle_config.exp_bonus_attacker * (count-1), 100); //[Gengar] } mexp = (unsigned int)cap_value(exp, 1, UINT_MAX); @@ -2986,18 +2988,20 @@ int mob_summonslave(struct mob_data *md2,int *value,int amount,uint16 skill_id) /*========================================== * MOBskill lookup (get skillindex through skill_id) - * Returns -1 if not found. + * Returns INDEX_NOT_FOUND if not found. *------------------------------------------*/ int mob_skill_id2skill_idx(int class_,uint16 skill_id) { int i, max = mob->db(class_)->maxskill; struct mob_skill *ms=mob->db(class_)->skill; - if(ms==NULL) - return -1; + if (ms == NULL) + return INDEX_NOT_FOUND; - ARR_FIND( 0, max, i, ms[i].skill_id == skill_id ); - return ( i < max ) ? i : -1; + ARR_FIND(0, max, i, ms[i].skill_id == skill_id); + if (i == max) + return INDEX_NOT_FOUND; + return i; } /*========================================== @@ -3366,7 +3370,8 @@ int mob_is_clone(int class_) //If mode is not passed, a default aggressive mode is used. //If master_id is passed, clone is attached to him. //Returns: ID of newly crafted copy. -int mob_clone_spawn(struct map_session_data *sd, int16 m, int16 x, int16 y, const char *event, int master_id, int mode, int flag, unsigned int duration) { +int mob_clone_spawn(struct map_session_data *sd, int16 m, int16 x, int16 y, const char *event, int master_id, uint32 mode, int flag, unsigned int duration) +{ int class_; int i,j,h,inf, fd; struct mob_data *md; @@ -3396,7 +3401,7 @@ int mob_clone_spawn(struct map_session_data *sd, int16 m, int16 x, int16 y, cons mstatus->lhw.atk2= mstatus->dex + mstatus->lhw.atk + mstatus->lhw.atk2; //Max ATK mstatus->lhw.atk = mstatus->dex; //Min ATK } - if (mode) //User provided mode. + if (mode != MD_NONE) //User provided mode. mstatus->mode = mode; else if (flag&1) //Friendly Character, remove looting. mstatus->mode &= ~MD_LOOTER; @@ -3632,15 +3637,21 @@ int mob_makedummymobdb(int class_) //Adjusts the drop rate of item according to the criteria given. [Skotlex] unsigned int mob_drop_adjust(int baserate, int rate_adjust, unsigned short rate_min, unsigned short rate_max) { - double rate = baserate; + int64 rate = baserate; - if (battle_config.logarithmic_drops && rate_adjust > 0 && rate_adjust != 100 && baserate > 0) //Logarithmic drops equation by Ishizu-Chan - //Equation: Droprate(x,y) = x * (5 - log(x)) ^ (ln(y) / ln(5)) - //x is the normal Droprate, y is the Modificator. - rate = rate * pow((5.0 - log10(rate)), (log(rate_adjust/100.) / log(5.0))) + 0.5; - else - //Classical linear rate adjustment. - rate = rate * rate_adjust/100; + Assert_ret(baserate >= 0); + + if (rate_adjust != 100 && baserate > 0) { + if (battle_config.logarithmic_drops && rate_adjust > 0) { + // Logarithmic drops equation by Ishizu-Chan + //Equation: Droprate(x,y) = x * (5 - log(x)) ^ (ln(y) / ln(5)) + //x is the normal Droprate, y is the Modificator. + rate = (int64)(baserate * pow((5.0 - log10(baserate)), (log(rate_adjust/100.) / log(5.0))) + 0.5); + } else { + //Classical linear rate adjustment. + rate = apply_percentrate64(baserate, rate_adjust, 100); + } + } return (unsigned int)cap_value(rate,rate_min,rate_max); } @@ -3678,71 +3689,95 @@ static inline int mob_parse_dbrow_cap_value(int class_, int min, int max, int va return value; } -void mob_read_db_stats_sub(struct mob_db *entry, struct status_data *mstatus, int class_, config_setting_t *t) +/** + * Processes the stats for a mob database entry. + * + * @param[in,out] entry The destination mob_db entry, already initialized + * (mob_id is expected to be already set). + * @param[in] t The libconfig entry. + */ +void mob_read_db_stats_sub(struct mob_db *entry, struct config_setting_t *t) { int i32; if (mob->lookup_const(t, "Str", &i32) && i32 >= 0) { - mstatus->str = mob_parse_dbrow_cap_value(class_, UINT16_MIN, UINT16_MAX, i32); + entry->status.str = mob_parse_dbrow_cap_value(entry->mob_id, UINT16_MIN, UINT16_MAX, i32); } if (mob->lookup_const(t, "Agi", &i32) && i32 >= 0) { - mstatus->agi = mob_parse_dbrow_cap_value(class_, UINT16_MIN, UINT16_MAX, i32); + entry->status.agi = mob_parse_dbrow_cap_value(entry->mob_id, UINT16_MIN, UINT16_MAX, i32); } if (mob->lookup_const(t, "Vit", &i32) && i32 >= 0) { - mstatus->vit = mob_parse_dbrow_cap_value(class_, UINT16_MIN, UINT16_MAX, i32); + entry->status.vit = mob_parse_dbrow_cap_value(entry->mob_id, UINT16_MIN, UINT16_MAX, i32); } if (mob->lookup_const(t, "Int", &i32) && i32 >= 0) { - mstatus->int_ = mob_parse_dbrow_cap_value(class_, UINT16_MIN, UINT16_MAX, i32); + entry->status.int_ = mob_parse_dbrow_cap_value(entry->mob_id, UINT16_MIN, UINT16_MAX, i32); } if (mob->lookup_const(t, "Dex", &i32) && i32 >= 0) { - mstatus->dex = mob_parse_dbrow_cap_value(class_, UINT16_MIN, UINT16_MAX, i32); + entry->status.dex = mob_parse_dbrow_cap_value(entry->mob_id, UINT16_MIN, UINT16_MAX, i32); } if (mob->lookup_const(t, "Luk", &i32) && i32 >= 0) { - mstatus->luk = mob_parse_dbrow_cap_value(class_, UINT16_MIN, UINT16_MAX, i32); + entry->status.luk = mob_parse_dbrow_cap_value(entry->mob_id, UINT16_MIN, UINT16_MAX, i32); } } -int mob_read_db_mode_sub(struct mob_db *entry, struct status_data *mstatus, int class_, config_setting_t *t) +/** + * Processes the mode for a mob_db entry. + * + * @param[in] entry The destination mob_db entry, already initialized. + * @param[in] t The libconfig entry. + * + * @return The parsed mode. + */ +uint32 mob_read_db_mode_sub(struct mob_db *entry, struct config_setting_t *t) { - int mode = 0; - config_setting_t *t2; + uint32 mode = 0; + struct config_setting_t *t2; if ((t2 = libconfig->setting_get_member(t, "CanMove"))) - mode |= libconfig->setting_get_bool(t2) ? MD_CANMOVE : 0; + mode |= libconfig->setting_get_bool(t2) ? MD_CANMOVE : MD_NONE; if ((t2 = libconfig->setting_get_member(t, "Looter"))) - mode |= libconfig->setting_get_bool(t2) ? MD_LOOTER : 0; + mode |= libconfig->setting_get_bool(t2) ? MD_LOOTER : MD_NONE; if ((t2 = libconfig->setting_get_member(t, "Aggressive"))) - mode |= libconfig->setting_get_bool(t2) ? MD_AGGRESSIVE : 0; + mode |= libconfig->setting_get_bool(t2) ? MD_AGGRESSIVE : MD_NONE; if ((t2 = libconfig->setting_get_member(t, "Assist"))) - mode |= libconfig->setting_get_bool(t2) ? MD_ASSIST : 0; + mode |= libconfig->setting_get_bool(t2) ? MD_ASSIST : MD_NONE; if ((t2 = libconfig->setting_get_member(t, "CastSensorIdle"))) - mode |= libconfig->setting_get_bool(t2) ? MD_CASTSENSOR_IDLE : 0; + mode |= libconfig->setting_get_bool(t2) ? MD_CASTSENSOR_IDLE : MD_NONE; if ((t2 = libconfig->setting_get_member(t, "Boss"))) - mode |= libconfig->setting_get_bool(t2) ? MD_BOSS : 0; + mode |= libconfig->setting_get_bool(t2) ? MD_BOSS : MD_NONE; if ((t2 = libconfig->setting_get_member(t, "Plant"))) - mode |= libconfig->setting_get_bool(t2) ? MD_PLANT : 0; + mode |= libconfig->setting_get_bool(t2) ? MD_PLANT : MD_NONE; if ((t2 = libconfig->setting_get_member(t, "CanAttack"))) - mode |= libconfig->setting_get_bool(t2) ? MD_CANATTACK : 0; + mode |= libconfig->setting_get_bool(t2) ? MD_CANATTACK : MD_NONE; if ((t2 = libconfig->setting_get_member(t, "Detector"))) - mode |= libconfig->setting_get_bool(t2) ? MD_DETECTOR : 0; + mode |= libconfig->setting_get_bool(t2) ? MD_DETECTOR : MD_NONE; if ((t2 = libconfig->setting_get_member(t, "CastSensorChase"))) - mode |= libconfig->setting_get_bool(t2) ? MD_CASTSENSOR_CHASE : 0; + mode |= libconfig->setting_get_bool(t2) ? MD_CASTSENSOR_CHASE : MD_NONE; if ((t2 = libconfig->setting_get_member(t, "ChangeChase"))) - mode |= libconfig->setting_get_bool(t2) ? MD_CHANGECHASE : 0; + mode |= libconfig->setting_get_bool(t2) ? MD_CHANGECHASE : MD_NONE; if ((t2 = libconfig->setting_get_member(t, "Angry"))) - mode |= libconfig->setting_get_bool(t2) ? MD_ANGRY : 0; + mode |= libconfig->setting_get_bool(t2) ? MD_ANGRY : MD_NONE; if ((t2 = libconfig->setting_get_member(t, "ChangeTargetMelee"))) - mode |= libconfig->setting_get_bool(t2) ? MD_CHANGETARGET_MELEE : 0; + mode |= libconfig->setting_get_bool(t2) ? MD_CHANGETARGET_MELEE : MD_NONE; if ((t2 = libconfig->setting_get_member(t, "ChangeTargetChase"))) - mode |= libconfig->setting_get_bool(t2) ? MD_CHANGETARGET_CHASE : 0; + mode |= libconfig->setting_get_bool(t2) ? MD_CHANGETARGET_CHASE : MD_NONE; if ((t2 = libconfig->setting_get_member(t, "TargetWeak"))) - mode |= libconfig->setting_get_bool(t2) ? MD_TARGETWEAK : 0; + mode |= libconfig->setting_get_bool(t2) ? MD_TARGETWEAK : MD_NONE; + if ((t2 = libconfig->setting_get_member(t, "NoKnockback"))) + mode |= libconfig->setting_get_bool(t2) ? MD_NOKNOCKBACK : MD_NONE; - return mode; + return mode & MD_MASK; } -void mob_read_db_mvpdrops_sub(struct mob_db *entry, struct status_data *mstatus, int class_, config_setting_t *t) +/** + * Processes the MVP drops for a mob_db entry. + * + * @param[in,out] entry The destination mob_db entry, already initialized + * (mob_id is expected to be already set). + * @param[in] t The libconfig entry. + */ +void mob_read_db_mvpdrops_sub(struct mob_db *entry, struct config_setting_t *t) { - config_setting_t *drop; + struct config_setting_t *drop; int i = 0; int idx = 0; int i32; @@ -3752,28 +3787,26 @@ void mob_read_db_mvpdrops_sub(struct mob_db *entry, struct status_data *mstatus, int rate_adjust = battle_config.item_rate_mvp; struct item_data* id = itemdb->search_name(name); int value = 0; - if (!id) - { - ShowWarning("mob_read_db: mvp drop item %s not found in monster %d\n", name, class_); - i ++; + if (!id) { + ShowWarning("mob_read_db: mvp drop item %s not found in monster %d\n", name, entry->mob_id); + i++; continue; } if (mob->get_const(drop, &i32) && i32 >= 0) { value = i32; } - if (value <= 0) - { - ShowWarning("mob_read_db: wrong drop chance %d for mvp drop item %s in monster %d\n", value, name, class_); - i ++; + if (value <= 0) { + ShowWarning("mob_read_db: wrong drop chance %d for mvp drop item %s in monster %d\n", value, name, entry->mob_id); + i++; continue; } entry->mvpitem[idx].nameid = id->nameid; if (!entry->mvpitem[idx].nameid) { entry->mvpitem[idx].p = 0; //No item.... - i ++; + i++; continue; } - mob->item_dropratio_adjust(entry->mvpitem[idx].nameid, class_, &rate_adjust); + mob->item_dropratio_adjust(entry->mvpitem[idx].nameid, entry->mob_id, &rate_adjust); entry->mvpitem[idx].p = mob->drop_adjust(value, rate_adjust, battle_config.item_drop_mvp_min, battle_config.item_drop_mvp_max); //calculate and store Max available drop chance of the MVP item @@ -3787,13 +3820,20 @@ void mob_read_db_mvpdrops_sub(struct mob_db *entry, struct status_data *mstatus, idx++; } if (idx == MAX_MVP_DROP && libconfig->setting_get_elem(t, i)) { - ShowWarning("mob_read_db: Too many mvp drops in mob %d\n", class_); + ShowWarning("mob_read_db: Too many mvp drops in mob %d\n", entry->mob_id); } } -void mob_read_db_drops_sub(struct mob_db *entry, struct status_data *mstatus, int class_, config_setting_t *t) +/** + * Processes the drops for a mob_db entry. + * + * @param[in,out] entry The destination mob_db entry, already initialized + * (mob_id, status.mode are expected to be already set). + * @param[in] t The libconfig entry. + */ +void mob_read_db_drops_sub(struct mob_db *entry, struct config_setting_t *t) { - config_setting_t *drop; + struct config_setting_t *drop; int i = 0; int idx = 0; int i32; @@ -3805,73 +3845,72 @@ void mob_read_db_drops_sub(struct mob_db *entry, struct status_data *mstatus, in unsigned short ratemin, ratemax; struct item_data* id = itemdb->search_name(name); int value = 0; - if (!id) - { - ShowWarning("mob_read_db: drop item %s not found in monster %d\n", name, class_); - i ++; + if (!id) { + ShowWarning("mob_read_db: drop item %s not found in monster %d\n", name, entry->mob_id); + i++; continue; } if (mob->get_const(drop, &i32) && i32 >= 0) { value = i32; } - if (value <= 0) - { - ShowWarning("mob_read_db: wrong drop chance %d for drop item %s in monster %d\n", value, name, class_); - i ++; + if (value <= 0) { + ShowWarning("mob_read_db: wrong drop chance %d for drop item %s in monster %d\n", value, name, entry->mob_id); + i++; continue; } entry->dropitem[idx].nameid = id->nameid; if (!entry->dropitem[idx].nameid) { entry->dropitem[idx].p = 0; //No drop. - i ++; + i++; continue; } type = id->type; - if ((class_ >= MOBID_TREASURE_BOX1 && class_ <= MOBID_TREASURE_BOX40) || (class_ >= MOBID_TREASURE_BOX41 && class_ <= MOBID_TREASURE_BOX49)) { + if ((entry->mob_id >= MOBID_TREASURE_BOX1 && entry->mob_id <= MOBID_TREASURE_BOX40) + || (entry->mob_id >= MOBID_TREASURE_BOX41 && entry->mob_id <= MOBID_TREASURE_BOX49)) { //Treasure box drop rates [Skotlex] rate_adjust = battle_config.item_rate_treasure; ratemin = battle_config.item_drop_treasure_min; ratemax = battle_config.item_drop_treasure_max; - } - else switch (type) - { // Added support to restrict normal drops of MVP's [Reddozen] + } else { + switch (type) { // Added support to restrict normal drops of MVP's [Reddozen] case IT_HEALING: - rate_adjust = (mstatus->mode&MD_BOSS) ? battle_config.item_rate_heal_boss : battle_config.item_rate_heal; + rate_adjust = (entry->status.mode&MD_BOSS) ? battle_config.item_rate_heal_boss : battle_config.item_rate_heal; ratemin = battle_config.item_drop_heal_min; ratemax = battle_config.item_drop_heal_max; break; case IT_USABLE: case IT_CASH: - rate_adjust = (mstatus->mode&MD_BOSS) ? battle_config.item_rate_use_boss : battle_config.item_rate_use; + rate_adjust = (entry->status.mode&MD_BOSS) ? battle_config.item_rate_use_boss : battle_config.item_rate_use; ratemin = battle_config.item_drop_use_min; ratemax = battle_config.item_drop_use_max; break; case IT_WEAPON: case IT_ARMOR: case IT_PETARMOR: - rate_adjust = (mstatus->mode&MD_BOSS) ? battle_config.item_rate_equip_boss : battle_config.item_rate_equip; + rate_adjust = (entry->status.mode&MD_BOSS) ? battle_config.item_rate_equip_boss : battle_config.item_rate_equip; ratemin = battle_config.item_drop_equip_min; ratemax = battle_config.item_drop_equip_max; break; case IT_CARD: - rate_adjust = (mstatus->mode&MD_BOSS) ? battle_config.item_rate_card_boss : battle_config.item_rate_card; + rate_adjust = (entry->status.mode&MD_BOSS) ? battle_config.item_rate_card_boss : battle_config.item_rate_card; ratemin = battle_config.item_drop_card_min; ratemax = battle_config.item_drop_card_max; break; default: - rate_adjust = (mstatus->mode&MD_BOSS) ? battle_config.item_rate_common_boss : battle_config.item_rate_common; + rate_adjust = (entry->status.mode&MD_BOSS) ? battle_config.item_rate_common_boss : battle_config.item_rate_common; ratemin = battle_config.item_drop_common_min; ratemax = battle_config.item_drop_common_max; break; + } } - mob->item_dropratio_adjust(id->nameid, class_, &rate_adjust); + mob->item_dropratio_adjust(id->nameid, entry->mob_id, &rate_adjust); entry->dropitem[idx].p = mob->drop_adjust(value, rate_adjust, ratemin, ratemax); //calculate and store Max available drop chance of the item if (entry->dropitem[idx].p - && (class_ < MOBID_TREASURE_BOX1 || class_ > MOBID_TREASURE_BOX40) - && (class_ < MOBID_TREASURE_BOX41 || class_ > MOBID_TREASURE_BOX49)) { + && (entry->mob_id < MOBID_TREASURE_BOX1 || entry->mob_id > MOBID_TREASURE_BOX40) + && (entry->mob_id < MOBID_TREASURE_BOX41 || entry->mob_id > MOBID_TREASURE_BOX49)) { //Skip treasure chests. if (id->maxchance == -1 || (id->maxchance < entry->dropitem[idx].p) ) { id->maxchance = entry->dropitem[idx].p; //item has bigger drop chance or sold in shops @@ -3880,366 +3919,460 @@ void mob_read_db_drops_sub(struct mob_db *entry, struct status_data *mstatus, in if (id->mob[k].chance <= entry->dropitem[idx].p) break; } - if (k == MAX_SEARCH) - { + if (k == MAX_SEARCH) { i++; idx++; continue; } - if (id->mob[k].id != class_ && k != MAX_SEARCH - 1) + if (id->mob[k].id != entry->mob_id && k != MAX_SEARCH - 1) memmove(&id->mob[k+1], &id->mob[k], (MAX_SEARCH-k-1)*sizeof(id->mob[0])); id->mob[k].chance = entry->dropitem[idx].p; - id->mob[k].id = class_; + id->mob[k].id = entry->mob_id; } i++; idx++; } if (idx == MAX_MOB_DROP && libconfig->setting_get_elem(t, i)) { - ShowWarning("mob_read_db: Too many drops in mob %d\n", class_); + ShowWarning("mob_read_db: Too many drops in mob %d\n", entry->mob_id); } } -/*========================================== - * processes one mobdb entry - *------------------------------------------*/ -bool mob_read_db_sub(config_setting_t *mobt, int id, const char *source) +/** + * Validates a mob DB entry and inserts it into the database. + * This function is called after preparing the mob entry data, and it takes + * care of inserting it and cleaning up any remainders of the previous one (in + * case it is overwriting an existing entry). + * + * @param entry Pointer to the new mob_db entry. Ownership is NOT taken, but + * the content is modified to reflect the validation. + * @param n Ordinal number of the entry, to be displayed in case of + * validation errors. + * @param source Source of the entry (file name), to be displayed in case of + * validation errors. + * @return Mob ID of the validated entry, or 0 in case of failure. + * + * Note: This is safe to call if the new entry is a shallow copy of the old one + * (i.e. mob_db2 inheritance), as it will make sure not to free any data still + * in use by the new entry. + */ +int mob_db_validate_entry(struct mob_db *entry, int n, const char *source) { - struct mob_db *entry = NULL, tmpEntry; - config_setting_t *t = NULL; - int i32 = 0, value = 0, class_ = 0; - struct status_data *mstatus; struct mob_data data; - const char *str = NULL; - double maxhp; - double exp; - bool inherit = false; - bool range2Updated = false; - bool range3Updated = false; - bool dmotionUpdated = false; - bool maxhpUpdated = false; - bool maxspUpdated = false; - entry = &tmpEntry; - if (!libconfig->setting_lookup_int(mobt, "Id", &class_)) { - ShowWarning("mob_read_db_sub: Missing id in \"%s\", entry #%d, skipping.\n", source, class_); - return false; + if (entry->mob_id <= 1000 || entry->mob_id > MAX_MOB_DB) { + ShowError("mob_db_validate_entry: Invalid monster ID %d, must be in range %d-%d.\n", entry->mob_id, 1000, MAX_MOB_DB); + return 0; + } + if (pc->db_checkid(entry->mob_id)) { + ShowError("mob_read_db_sub: Invalid monster ID %d, reserved for player classes.\n", entry->mob_id); + return 0; + } + if (entry->mob_id >= MOB_CLONE_START && entry->mob_id < MOB_CLONE_END) { + ShowError("mob_read_db_sub: Invalid monster ID %d. Range %d-%d is reserved for player clones. Please increase MAX_MOB_DB (%d).\n", + entry->mob_id, MOB_CLONE_START, MOB_CLONE_END-1, MAX_MOB_DB); + return 0; } - if (class_ <= 1000 || class_ > MAX_MOB_DB) { - ShowError("mob_read_db_sub: Invalid monster ID %d, must be in range %d-%d.\n", class_, 1000, MAX_MOB_DB); - return false; + entry->lv = cap_value(entry->lv, 1, USHRT_MAX); + + if (entry->status.max_sp < 1) + entry->status.max_sp = 1; + //Since mobs always respawn with full life... + entry->status.hp = entry->status.max_hp; + entry->status.sp = entry->status.max_sp; + + /* + * Disabled for renewal since difference of 0 and 1 still has an impact in the formulas + * Just in case there is a mishandled division by zero please let us know. [malufett] + */ +#ifndef RENEWAL + //All status should be min 1 to prevent divisions by zero from some skills. [Skotlex] + if (entry->status.str < 1) entry->status.str = 1; + if (entry->status.agi < 1) entry->status.agi = 1; + if (entry->status.vit < 1) entry->status.vit = 1; + if (entry->status.int_< 1) entry->status.int_= 1; + if (entry->status.dex < 1) entry->status.dex = 1; + if (entry->status.luk < 1) entry->status.luk = 1; +#endif + + if (entry->range2 < 1) + entry->range2 = 1; + +#if 0 // This code was (accidentally) never enabled. It'll stay commented out until it's proven to be needed. + //Tests showed that chase range is effectively 2 cells larger than expected [Playtester] + if (entry->range3 > 0) + entry->range3 += 2; +#endif // 0 + + if (entry->range3 < entry->range2) + entry->range3 = entry->range2; + + entry->status.size = cap_value(entry->status.size, 0, 2); + + entry->status.race = cap_value(entry->status.race, 0, RC_MAX - 1); + + if (entry->status.def_ele >= ELE_MAX) { + ShowWarning("mob_read_db_sub: Invalid element type %d for monster ID %d (max=%d).\n", entry->status.def_ele, entry->mob_id, ELE_MAX-1); + entry->status.def_ele = ELE_NEUTRAL; + entry->status.ele_lv = 1; } - if (pc->db_checkid(class_)) { - ShowError("mob_read_db_sub: Invalid monster ID %d, reserved for player classes.\n", class_); - return false; + if (entry->status.ele_lv < 1 || entry->status.ele_lv > 4) { + ShowWarning("mob_read_db_sub: Invalid element level %d for monster ID %d, must be in range 1-4.\n", entry->status.ele_lv, entry->mob_id); + entry->status.ele_lv = 1; } - if (class_ >= MOB_CLONE_START && class_ < MOB_CLONE_END) { - ShowError("mob_read_db_sub: Invalid monster ID %d. Range %d-%d is reserved for player clones. Please increase MAX_MOB_DB (%d).\n", class_, MOB_CLONE_START, MOB_CLONE_END-1, MAX_MOB_DB); - return false; + // If the attack animation is longer than the delay, the client crops the attack animation! + // On aegis there is no real visible effect of having a recharge-time less than amotion anyway. + if (entry->status.adelay < entry->status.amotion) + entry->status.adelay = entry->status.amotion; + + // Fill in remaining status data by using a dummy monster. + data.bl.type = BL_MOB; + data.level = entry->lv; + memcpy(&data.status, &entry->status, sizeof(struct status_data)); + status->calc_misc(&data.bl, &entry->status, entry->lv); + + // Finally insert monster's data into the database. + if (mob->db_data[entry->mob_id] == NULL) { + mob->db_data[entry->mob_id] = (struct mob_db*)aMalloc(sizeof(struct mob_db)); + } else { + //Copy over spawn data + memcpy(&entry->spawn, mob->db_data[entry->mob_id]->spawn, sizeof(entry->spawn)); + } + memcpy(mob->db_data[entry->mob_id], entry, sizeof(struct mob_db)); + + return entry->mob_id; +} + +/** + * Processes one mobdb entry from the libconfig file, loading and inserting it + * into the mob database. + * + * @param mobt Libconfig setting entry. It is expected to be valid and it + * won't be freed (it is care of the caller to do so if + * necessary). + * @param n Ordinal number of the entry, to be displayed in case of + * validation errors. + * @param source Source of the entry (file name), to be displayed in case of + * validation errors. + * @return Mob ID of the validated entry, or 0 in case of failure. + */ +int mob_read_db_sub(struct config_setting_t *mobt, int n, const char *source) +{ + struct mob_db md = { 0 }; + struct config_setting_t *t = NULL; + const char *str = NULL; + int i32 = 0; + bool inherit = false; + bool maxhpUpdated = false; + + nullpo_ret(mobt); + /* + * // Mandatory fields + * Id: ID + * SpriteName: "SPRITE_NAME" + * Name: "Mob name" + * JName: "Mob name" + * // Optional fields + * Lv: level + * Hp: health + * Sp: mana + * Exp: basic experience + * JExp: job experience + * AttackRange: attack range + * Attack: [attack1, attack2] + * Def: defence + * Mdef: magic defence + * Stats: { + * Str: strength + * Agi: agility + * Vit: vitality + * Int: intelligence + * Dex: dexterity + * Luk: luck + * } + * ViewRange: view range + * ChaseRange: chase range + * Size: size + * Race: race + * Element: (type, level) + * Mode: { + * CanMove: true/false + * Looter: true/false + * Aggressive: true/false + * Assist: true/false + * CastSensorIdle:true/false + * Boss: true/false + * Plant: true/false + * CanAttack: true/false + * Detector: true/false + * CastSensorChase: true/false + * ChangeChase: true/false + * Angry: true/false + * ChangeTargetMelee: true/false + * ChangeTargetChase: true/false + * TargetWeak: true/false + * NoKnockback: true/false + * } + * MoveSpeed: move speed + * AttackDelay: attack delay + * AttackMotion: attack motion + * DamageMotion: damage motion + * MvpExp: mvp experience + * MvpDrops: { + * AegisName: chance + * ... + * } + * Drops: { + * AegisName: chance + * ... + * } + */ + + if (!libconfig->setting_lookup_int(mobt, "Id", &i32)) { + ShowWarning("mob_read_db_sub: Missing id in \"%s\", entry #%d, skipping.\n", source, n); + return 0; } + md.mob_id = i32; + md.vd.class_ = md.mob_id; if ((t = libconfig->setting_get_member(mobt, "Inherit")) && (inherit = libconfig->setting_get_bool(t))) { - if (!mob->db_data[class_]) { - ShowWarning("mob_read_db_sub: Trying to inherit nonexistent mob %d, default values will be used instead.\n", class_); + if (!mob->db_data[md.mob_id]) { + ShowWarning("mob_read_db_sub: Trying to inherit nonexistent mob %d, default values will be used instead.\n", md.mob_id); inherit = false; } else { // Use old entry as default - struct mob_db *old_entry = mob->db_data[class_]; - memcpy(entry, old_entry, sizeof(struct mob_db)); - inherit = true; + struct mob_db *old_entry = mob->db_data[md.mob_id]; + memcpy(&md, old_entry, sizeof(md)); } } - if (!inherit) { - memset(&tmpEntry, 0, sizeof(tmpEntry)); - } - - mstatus = &entry->status; - - entry->vd.class_ = class_; if (!libconfig->setting_lookup_string(mobt, "SpriteName", &str) || !*str ) { if (!inherit) { - ShowWarning("mob_read_db_sub: Missing SpriteName in mob %d of \"%s\", skipping.\n", class_, source); - return false; + ShowWarning("mob_read_db_sub: Missing SpriteName in mob %d of \"%s\", skipping.\n", md.mob_id, source); + return 0; } } else { - safestrncpy(entry->sprite, str, sizeof(entry->sprite)); + safestrncpy(md.sprite, str, sizeof(md.sprite)); } if (!libconfig->setting_lookup_string(mobt, "Name", &str) || !*str ) { if (!inherit) { - ShowWarning("mob_read_db_sub: Missing Name in mob %d of \"%s\", skipping.\n", class_, source); - return false; + ShowWarning("mob_read_db_sub: Missing Name in mob %d of \"%s\", skipping.\n", md.mob_id, source); + return 0; + } + } else { + safestrncpy(md.name, str, sizeof(md.name)); + } + + if (!libconfig->setting_lookup_string(mobt, "JName", &str) || !*str ) { + if (!inherit) { + safestrncpy(md.jname, md.name, sizeof(md.jname)); } } else { - safestrncpy(entry->name, str, sizeof(entry->name)); - safestrncpy(entry->jname, str, sizeof(entry->jname)); + safestrncpy(md.jname, str, sizeof(md.jname)); } if (mob->lookup_const(mobt, "Lv", &i32) && i32 >= 0) { - entry->lv = i32; - entry->lv = cap_value(entry->lv, 1, USHRT_MAX); + md.lv = i32; } else if (!inherit) { - entry->lv = 1; + md.lv = 1; } if (mob->lookup_const(mobt, "Hp", &i32) && i32 >= 0) { - mstatus->max_hp = i32; - maxhpUpdated = true; + md.status.max_hp = i32; + maxhpUpdated = true; // battle_config modifiers to max_hp are applied below } else if (!inherit) { - mstatus->max_hp = 1; - maxhpUpdated = true; + md.status.max_hp = 1; + maxhpUpdated = true; // battle_config modifiers to max_hp are applied below } if (mob->lookup_const(mobt, "Sp", &i32) && i32 >= 0) { - mstatus->max_sp = i32; - maxspUpdated = true; + md.status.max_sp = i32; } else if (!inherit) { - maxspUpdated = true; + md.status.max_sp = 1; } if (mob->lookup_const(mobt, "Exp", &i32) && i32 >= 0) { - exp = (double)(i32) * (double)battle_config.base_exp_rate / 100.; - entry->base_exp = (unsigned int)cap_value(exp, 0, UINT_MAX); + int64 exp = apply_percentrate64(i32, battle_config.base_exp_rate, 100); + md.base_exp = (unsigned int)cap_value(exp, 0, UINT_MAX); } if (mob->lookup_const(mobt, "JExp", &i32) && i32 >= 0) { - exp = (double)(i32) * (double)battle_config.job_exp_rate / 100.; - entry->job_exp = (unsigned int)cap_value(exp, 0, UINT_MAX); + int64 exp = apply_percentrate64(i32, battle_config.job_exp_rate, 100); + md.job_exp = (unsigned int)cap_value(exp, 0, UINT_MAX); } if (mob->lookup_const(mobt, "AttackRange", &i32) && i32 >= 0) { - mstatus->rhw.range = i32; + md.status.rhw.range = i32; } else { - mstatus->rhw.range = 1; + md.status.rhw.range = 1; } if ((t = libconfig->setting_get_member(mobt, "Attack"))) { if (config_setting_is_aggregate(t)) { if (libconfig->setting_length(t) >= 2) - mstatus->rhw.atk2 = libconfig->setting_get_int_elem(t, 1); + md.status.rhw.atk2 = libconfig->setting_get_int_elem(t, 1); if (libconfig->setting_length(t) >= 1) - mstatus->rhw.atk = libconfig->setting_get_int_elem(t, 0); + md.status.rhw.atk = libconfig->setting_get_int_elem(t, 0); } else if (mob->lookup_const(mobt, "Attack", &i32) && i32 >= 0) { - mstatus->rhw.atk = i32; - mstatus->rhw.atk2 = i32; + md.status.rhw.atk = i32; + md.status.rhw.atk2 = i32; } } if (mob->lookup_const(mobt, "Def", &i32) && i32 >= 0) { - mstatus->def = mob_parse_dbrow_cap_value(class_, DEFTYPE_MIN, DEFTYPE_MAX, i32); + md.status.def = mob_parse_dbrow_cap_value(md.mob_id, DEFTYPE_MIN, DEFTYPE_MAX, i32); } if (mob->lookup_const(mobt, "Mdef", &i32) && i32 >= 0) { - mstatus->mdef = mob_parse_dbrow_cap_value(class_, DEFTYPE_MIN, DEFTYPE_MAX, i32); + md.status.mdef = mob_parse_dbrow_cap_value(md.mob_id, DEFTYPE_MIN, DEFTYPE_MAX, i32); } if ((t = libconfig->setting_get_member(mobt, "Stats"))) { if (config_setting_is_group(t)) { - mob->read_db_stats_sub(entry, mstatus, class_, t); + mob->read_db_stats_sub(&md, t); } else if (mob->lookup_const(mobt, "Stats", &i32) && i32 >= 0) { - mstatus->str = mstatus->agi = mstatus->vit = mstatus->int_ = mstatus->dex = mstatus->luk = - mob_parse_dbrow_cap_value(class_, UINT16_MIN, UINT16_MAX, i32); + md.status.str = md.status.agi = md.status.vit = md.status.int_ = md.status.dex = md.status.luk = + mob_parse_dbrow_cap_value(md.mob_id, UINT16_MIN, UINT16_MAX, i32); } } - /* - * Disabled for renewal since difference of 0 and 1 still has an impact in the formulas - * Just in case there is a mishandled division by zero please let us know. [malufett] - */ -#ifndef RENEWAL - //All status should be min 1 to prevent divisions by zero from some skills. [Skotlex] - if (mstatus->str < 1) mstatus->str = 1; - if (mstatus->agi < 1) mstatus->agi = 1; - if (mstatus->vit < 1) mstatus->vit = 1; - if (mstatus->int_< 1) mstatus->int_= 1; - if (mstatus->dex < 1) mstatus->dex = 1; - if (mstatus->luk < 1) mstatus->luk = 1; -#endif - - //Tests showed that chase range is effectively 2 cells larger than expected [Playtester] - if (entry->range3 > 0) - entry->range3 += 2; - if (mob->lookup_const(mobt, "ViewRange", &i32) && i32 >= 0) { - entry->range2 = i32; - range2Updated = true; + if (battle_config.view_range_rate != 100) { + md.range2 = i32 * battle_config.view_range_rate / 100; + } else { + md.range2 = i32; + } } else if (!inherit) { - entry->range2 = 1; - range2Updated = true; + md.range2 = 1; } if (mob->lookup_const(mobt, "ChaseRange", &i32) && i32 >= 0) { - entry->range3 = i32; - range3Updated = true; - } else if (!inherit) { - entry->range3 = 1; - range3Updated = true; - } - if (range2Updated) { - if (battle_config.view_range_rate != 100) { - entry->range2 = entry->range2 * battle_config.view_range_rate / 100; - if (entry->range2 < 1) - entry->range2 = 1; - } - } - if (range3Updated) { if (battle_config.chase_range_rate != 100) { - entry->range3 = entry->range3 * battle_config.chase_range_rate / 100; - if (entry->range3 < entry->range2) - entry->range3 = entry->range2; + md.range3 = i32 * battle_config.chase_range_rate / 100; + } else { + md.range3 = i32; } + } else if (!inherit) { + md.range3 = 1; } if (mob->lookup_const(mobt, "Size", &i32) && i32 >= 0) { - mstatus->size = i32; - mstatus->size = cap_value(mstatus->size, 0, 2); + md.status.size = i32; } else if (!inherit) { - mstatus->size = 0; + md.status.size = 0; } if (mob->lookup_const(mobt, "Race", &i32) && i32 >= 0) { - mstatus->race = i32; - mstatus->race = cap_value(mstatus->race, 0, RC_MAX - 1); + md.status.race = i32; } else if (!inherit) { - mstatus->race = 0; + md.status.race = 0; } if ((t = libconfig->setting_get_member(mobt, "Element")) && config_setting_is_list(t)) { + int value = 0; if (mob->get_const(libconfig->setting_get_elem(t, 0), &i32) && mob->get_const(libconfig->setting_get_elem(t, 1), &value)) { - mstatus->def_ele = i32; - mstatus->ele_lv = value; - } - } else { - if (!inherit) { - ShowError("mob_read_db_sub: Missing element for monster ID %d.\n", class_); - return false; - } - } - - if (mstatus->def_ele >= ELE_MAX) { - if (!inherit) { - ShowError("mob_read_db_sub: Invalid element type %d for monster ID %d (max=%d).\n", mstatus->def_ele, class_, ELE_MAX-1); - return false; - } - } - if (mstatus->ele_lv < 1 || mstatus->ele_lv > 4) { - if (!inherit) { - ShowError("mob_read_db_sub: Invalid element level %d for monster ID %d, must be in range 1-4.\n", mstatus->ele_lv, class_); - return false; + md.status.def_ele = i32; + md.status.ele_lv = value; + } else if (!inherit) { + ShowWarning("mob_read_db_sub: Missing element for monster ID %d.\n", md.mob_id); + md.status.def_ele = ELE_NEUTRAL; + md.status.ele_lv = 1; } + } else if (!inherit) { + ShowWarning("mob_read_db_sub: Missing element for monster ID %d.\n", md.mob_id); + md.status.def_ele = ELE_NEUTRAL; + md.status.ele_lv = 1; } if ((t = libconfig->setting_get_member(mobt, "Mode"))) { if (config_setting_is_group(t)) { - mstatus->mode = mob->read_db_mode_sub(entry, mstatus, class_, t); + md.status.mode = mob->read_db_mode_sub(&md, t); } else if (mob->lookup_const(mobt, "Mode", &i32) && i32 >= 0) { - mstatus->mode = i32; + md.status.mode = (uint32)i32 & MD_MASK; } } - if (!battle_config.monster_active_enable) - mstatus->mode &= ~MD_AGGRESSIVE; + md.status.mode &= ~MD_AGGRESSIVE; if (mob->lookup_const(mobt, "MoveSpeed", &i32) && i32 >= 0) { - mstatus->speed = i32; + md.status.speed = i32; } - mstatus->aspd_rate = 1000; + md.status.aspd_rate = 1000; if (mob->lookup_const(mobt, "AttackDelay", &i32) && i32 >= 0) { - mstatus->adelay = cap_value(i32, battle_config.monster_max_aspd*2, 4000); + md.status.adelay = cap_value(i32, battle_config.monster_max_aspd*2, 4000); } else if (!inherit) { - mstatus->adelay = 4000; + md.status.adelay = 4000; } if (mob->lookup_const(mobt, "AttackMotion", &i32) && i32 >= 0) { - mstatus->amotion = cap_value(i32, battle_config.monster_max_aspd, 2000); + md.status.amotion = cap_value(i32, battle_config.monster_max_aspd, 2000); } else if (!inherit) { - mstatus->amotion = 2000; + md.status.amotion = 2000; } - //If the attack animation is longer than the delay, the client crops the attack animation! - //On aegis there is no real visible effect of having a recharge-time less than amotion anyway. - if (mstatus->adelay < mstatus->amotion) - mstatus->adelay = mstatus->amotion; - if (mob->lookup_const(mobt, "DamageMotion", &i32) && i32 >= 0) { - mstatus->dmotion = i32; - dmotionUpdated = true; - } else if (!inherit) { - dmotionUpdated = true; + if (battle_config.monster_damage_delay_rate != 100) + md.status.dmotion = i32 * battle_config.monster_damage_delay_rate / 100; + else + md.status.dmotion = i32; } - if (dmotionUpdated && battle_config.monster_damage_delay_rate != 100) - mstatus->dmotion = mstatus->dmotion * battle_config.monster_damage_delay_rate / 100; - - // Fill in remaining status data by using a dummy monster. - data.bl.type = BL_MOB; - data.level = entry->lv; - memcpy(&data.status, mstatus, sizeof(struct status_data)); - status->calc_misc(&data.bl, mstatus, entry->lv); - // MVP EXP Bonus: MEXP - // Some new MVP's MEXP multiple by high exp-rate cause overflow. [LuzZza] if (mob->lookup_const(mobt, "MvpExp", &i32) && i32 >= 0) { - exp = (double)i32 * (double)battle_config.mvp_exp_rate / 100.; - entry->mexp = (unsigned int)cap_value(exp, 0, UINT_MAX); - } else if (!inherit) { - exp = 0; + // Some new MVP's MEXP multiple by high exp-rate cause overflow. [LuzZza] + int64 exp = apply_percentrate64(i32, battle_config.mvp_exp_rate, 100); + md.mexp = (unsigned int)cap_value(exp, 0, UINT_MAX); } if (maxhpUpdated) { - //Now that we know if it is an mvp or not, apply battle_config modifiers [Skotlex] - maxhp = (double)mstatus->max_hp; - if (entry->mexp > 0) { //Mvp - if (battle_config.mvp_hp_rate != 100) - maxhp = maxhp * (double)battle_config.mvp_hp_rate / 100.; + // Now that we know if it is an mvp or not, apply battle_config modifiers [Skotlex] + int64 maxhp = md.status.max_hp; + if (md.mexp > 0) { //Mvp + maxhp = apply_percentrate64(maxhp, battle_config.mvp_hp_rate, 100); } else { //Normal mob - if (battle_config.monster_hp_rate != 100) - maxhp = maxhp * (double)battle_config.monster_hp_rate / 100.; + maxhp = apply_percentrate64(maxhp, battle_config.monster_hp_rate, 100); } - mstatus->max_hp = (unsigned int)cap_value(maxhp, 1, UINT_MAX); - } - if (maxspUpdated) { - if(mstatus->max_sp < 1) mstatus->max_sp = 1; + md.status.max_hp = (unsigned int)cap_value(maxhp, 1, UINT_MAX); } - //Since mobs always respawn with full life... - mstatus->hp = mstatus->max_hp; - mstatus->sp = mstatus->max_sp; - if ((t = libconfig->setting_get_member(mobt, "MvpDrops"))) { if (config_setting_is_group(t)) { - mob->read_db_mvpdrops_sub(entry, mstatus, class_, t); + mob->read_db_mvpdrops_sub(&md, t); } } if ((t = libconfig->setting_get_member(mobt, "Drops"))) { if (config_setting_is_group(t)) { - mob->read_db_drops_sub(entry, mstatus, class_, t); + mob->read_db_drops_sub(&md, t); } } - mob->read_db_additional_fields(entry, class_, mobt, id, source); - // Finally insert monster's data into the database. - if (mob->db_data[class_] == NULL) - mob->db_data[class_] = (struct mob_db*)aMalloc(sizeof(struct mob_db)); - else - //Copy over spawn data - memcpy(&entry->spawn, mob->db_data[class_]->spawn, sizeof(entry->spawn)); + mob->read_db_additional_fields(&md, mobt, n, source); - memcpy(mob->db_data[class_], entry, sizeof(struct mob_db)); - return true; + return mob->db_validate_entry(&md, n, source); } -void mob_read_db_additional_fields(struct mob_db *entry, int class_, config_setting_t *it, int n, const char *source) +/** + * Processes any (plugin-defined) additional fields for a mob_db entry. + * + * @param[in,out] entry The destination mob_db entry, already initialized + * (mob_id, status.mode are expected to be already set). + * @param[in] t The libconfig entry. + * @param[in] n Ordinal number of the entry, to be displayed in case + * of validation errors. + * @param[in] source Source of the entry (file name), to be displayed in + * case of validation errors. + */ +void mob_read_db_additional_fields(struct mob_db *entry, struct config_setting_t *t, int n, const char *source) { // do nothing. plugins can do own work } -bool mob_lookup_const(const config_setting_t *it, const char *name, int *value) +bool mob_lookup_const(const struct config_setting_t *it, const char *name, int *value) { if (libconfig->setting_lookup_int(it, name, value)) { @@ -4257,7 +4390,7 @@ bool mob_lookup_const(const config_setting_t *it, const char *name, int *value) return false; } -bool mob_get_const(const config_setting_t *it, int *value) +bool mob_get_const(const struct config_setting_t *it, int *value) { const char *str = config_setting_get_string(it); if (str && *str && script->get_constant(str, value)) @@ -4282,13 +4415,23 @@ void mob_readdb(void) { mob->name_constants(); } +/** + * Reads from a libconfig-formatted mobdb file and inserts the found entries + * into the mob database, overwriting duplicate ones (i.e. mob_db2 overriding + * mob_db.) + * + * @param filename File name, relative to the database path. + * @param ignore_missing Whether to ignore errors caused by a missing db file. + * @return the number of found entries. + */ int mob_read_libconfig(const char *filename, bool ignore_missing) { - config_t mob_db_conf; + bool duplicate[MAX_MOB_DB] = { 0 }; + struct config_t mob_db_conf; char filepath[256]; - config_setting_t *mdb; - config_setting_t *t; - int i = 0; + struct config_setting_t *mdb; + struct config_setting_t *t; + int i = 0, count = 0; nullpo_ret(filename); sprintf(filepath, "%s/%s", map->db_path, filename); @@ -4296,17 +4439,33 @@ int mob_read_libconfig(const char *filename, bool ignore_missing) if (ignore_missing && !exists(filepath)) return 0; - if (libconfig->read_file(&mob_db_conf, filepath) || !(mdb = libconfig->setting_get_member(mob_db_conf.root, "mob_db"))) { + if (!libconfig->load_file(&mob_db_conf, filepath)) + return 0; + + if ((mdb = libconfig->setting_get_member(mob_db_conf.root, "mob_db")) == NULL) { ShowError("can't read %s\n", filepath); - return -1; + return 0; } while ((t = libconfig->setting_get_elem(mdb, i++))) { - mob->read_db_sub(t, i - 1, filepath); + int mob_id = mob->read_db_sub(t, i - 1, filename); + + if (mob_id <= 0 || mob_id >= MAX_MOB_DB) + continue; + + count++; + + if (duplicate[mob_id]) { + ShowWarning("mob_read_libconfig:%s: duplicate entry of ID #%d (%s/%s)\n", + filename, mob_id, mob->db_data[mob_id]->sprite, mob->db_data[mob_id]->jname); + } else { + duplicate[mob_id] = true; + } } libconfig->destroy(&mob_db_conf); - ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", i, filepath); - return 0; + ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, filename); + + return count; } void mob_name_constants(void) { @@ -4316,7 +4475,7 @@ void mob_name_constants(void) { #endif // ENABLE_CASE_CHECK for (i = 0; i < MAX_MOB_DB; i++) { if (mob->db_data[i] && !mob->is_clone(i)) - script->set_constant2(mob->db_data[i]->sprite, i, 0); + script->set_constant2(mob->db_data[i]->sprite, i, false, false); } #ifdef ENABLE_CASE_CHECK script->parser_current_file = NULL; @@ -4529,7 +4688,7 @@ void mob_readchatdb(void) { if( j < 2 || str[2]==NULL) { - ShowError("mob_readchatdb: Insufficient number of fields for skill at %s, line %d\n", arc, lines); + ShowError("mob_readchatdb: Insufficient number of fields for skill at %s, line %u\n", arc, lines); continue; } @@ -4749,19 +4908,23 @@ bool mob_parse_row_mobskilldb(char** str, int columns, int current) ms->val[3]=(int)strtol(str[15],NULL,0); ms->val[4]=(int)strtol(str[16],NULL,0); - if(ms->skill_id == NPC_EMOTION && mob_id>0 && - ms->val[1] == mob->db(mob_id)->status.mode) - { - ms->val[1] = 0; + if (ms->skill_id == NPC_EMOTION) { + ms->val[1] &= MD_MASK; + ms->val[2] &= MD_MASK; + ms->val[3] &= MD_MASK; + } + if (ms->skill_id == NPC_EMOTION && mob_id > 0 + && (uint32)ms->val[1] == mob->db(mob_id)->status.mode) { + ms->val[1] = MD_NONE; ms->val[4] = 1; //request to return mode to normal. } - if (ms->skill_id == NPC_EMOTION_ON && mob_id>0 && ms->val[1]) { + if (ms->skill_id == NPC_EMOTION_ON && mob_id>0 && ms->val[1] != MD_NONE) { //Adds a mode to the mob. //Remove aggressive mode when the new mob type is passive. if (!(ms->val[1]&MD_AGGRESSIVE)) - ms->val[3]|=MD_AGGRESSIVE; - ms->val[2]|= ms->val[1]; //Add the new mode. - ms->val[1] = 0; //Do not "set" it. + ms->val[3] |= MD_AGGRESSIVE; + ms->val[2] |= (uint32)ms->val[1]; //Add the new mode. + ms->val[1] = MD_NONE; //Do not "set" it. } if(*str[17]) @@ -4922,7 +5085,7 @@ void mob_reload(void) { /** * Clears spawn related information for a script reload. */ -void mob_clear_spawninfo() +void mob_clear_spawninfo(void) { int i; for (i = 0; i < MAX_MOB_DB; i++) @@ -5127,6 +5290,7 @@ void mob_defaults(void) { mob->item_dropratio_adjust = item_dropratio_adjust; mob->lookup_const = mob_lookup_const; mob->get_const = mob_get_const; + mob->db_validate_entry = mob_db_validate_entry; mob->readdb = mob_readdb; mob->read_libconfig = mob_read_libconfig; mob->read_db_additional_fields = mob_read_db_additional_fields; diff --git a/src/map/mob.h b/src/map/mob.h index 5485b2a91..60bc4b869 100644 --- a/src/map/mob.h +++ b/src/map/mob.h @@ -141,6 +141,7 @@ struct spawn_info { }; struct mob_db { + int mob_id; char sprite[NAME_LENGTH],name[NAME_LENGTH],jname[NAME_LENGTH]; unsigned int base_exp,job_exp; unsigned int mexp; @@ -458,7 +459,7 @@ struct mob_interface { int (*setdelayspawn) (struct mob_data *md); int (*count_sub) (struct block_list *bl, va_list ap); int (*spawn) (struct mob_data *md); - int (*can_changetarget) (struct mob_data *md, struct block_list *target, int mode); + int (*can_changetarget) (const struct mob_data *md, const struct block_list *target, uint32 mode); int (*target) (struct mob_data *md, struct block_list *bl, int dist); int (*ai_sub_hard_activesearch) (struct block_list *bl, va_list ap); int (*ai_sub_hard_changechase) (struct block_list *bl, va_list ap); @@ -504,20 +505,21 @@ struct mob_interface { int (*skill_use) (struct mob_data *md, int64 tick, int event); int (*skill_event) (struct mob_data *md, struct block_list *src, int64 tick, int flag); int (*is_clone) (int class_); - int (*clone_spawn) (struct map_session_data *sd, int16 m, int16 x, int16 y, const char *event, int master_id, int mode, int flag, unsigned int duration); + int (*clone_spawn) (struct map_session_data *sd, int16 m, int16 x, int16 y, const char *event, int master_id, uint32 mode, int flag, unsigned int duration); int (*clone_delete) (struct mob_data *md); unsigned int (*drop_adjust) (int baserate, int rate_adjust, unsigned short rate_min, unsigned short rate_max); void (*item_dropratio_adjust) (int nameid, int mob_id, int *rate_adjust); void (*readdb) (void); - bool (*lookup_const) (const config_setting_t *it, const char *name, int *value); - bool (*get_const) (const config_setting_t *it, int *value); + bool (*lookup_const) (const struct config_setting_t *it, const char *name, int *value); + bool (*get_const) (const struct config_setting_t *it, int *value); + int (*db_validate_entry) (struct mob_db *entry, int n, const char *source); int (*read_libconfig) (const char *filename, bool ignore_missing); - void (*read_db_additional_fields) (struct mob_db *entry, int class_, config_setting_t *it, int n, const char *source); - bool (*read_db_sub) (config_setting_t *mobt, int id, const char *source); - void (*read_db_drops_sub) (struct mob_db *entry, struct status_data *mstatus, int class_, config_setting_t *t); - void (*read_db_mvpdrops_sub) (struct mob_db *entry, struct status_data *mstatus, int class_, config_setting_t *t); - int (*read_db_mode_sub) (struct mob_db *entry, struct status_data *mstatus, int class_, config_setting_t *t); - void (*read_db_stats_sub) (struct mob_db *entry, struct status_data *mstatus, int class_, config_setting_t *t); + void (*read_db_additional_fields) (struct mob_db *entry, struct config_setting_t *it, int n, const char *source); + int (*read_db_sub) (struct config_setting_t *mobt, int id, const char *source); + void (*read_db_drops_sub) (struct mob_db *entry, struct config_setting_t *t); + void (*read_db_mvpdrops_sub) (struct mob_db *entry, struct config_setting_t *t); + uint32 (*read_db_mode_sub) (struct mob_db *entry, struct config_setting_t *t); + void (*read_db_stats_sub) (struct mob_db *entry, struct config_setting_t *t); void (*name_constants) (void); bool (*readdb_mobavail) (char *str[], int columns, int current); int (*read_randommonster) (void); @@ -528,7 +530,7 @@ struct mob_interface { bool (*readdb_race2) (char *fields[], int columns, int current); bool (*readdb_itemratio) (char *str[], int columns, int current); void (*load) (bool minimal); - void (*clear_spawninfo) (); + void (*clear_spawninfo) (void); void (*destroy_mob_db) (int index); }; diff --git a/src/map/npc.c b/src/map/npc.c index 411e52c29..2b1a541d8 100644 --- a/src/map/npc.c +++ b/src/map/npc.c @@ -1386,8 +1386,9 @@ int npc_buysellsel(struct map_session_data* sd, int id, int type) { /*========================================== * Cash Shop Buy List *------------------------------------------*/ -int npc_cashshop_buylist(struct map_session_data *sd, int points, int count, unsigned short* item_list) { - int i, j, nameid, amount, new_, w, vt; +int npc_cashshop_buylist(struct map_session_data *sd, int points, struct itemlist *item_list) +{ + int i, j, new_, w, vt; struct npc_data *nd = NULL; struct npc_item_list *shop = NULL; unsigned short shop_size = 0; @@ -1395,7 +1396,7 @@ int npc_cashshop_buylist(struct map_session_data *sd, int points, int count, uns if( sd->state.trading ) return ERROR_TYPE_EXCHANGE; - if( count <= 0 ) + if (VECTOR_LENGTH(*item_list) <= 0) return ERROR_TYPE_ITEM_ID; if( points < 0 ) @@ -1421,24 +1422,23 @@ int npc_cashshop_buylist(struct map_session_data *sd, int points, int count, uns vt = 0; // Global Value // Validating Process ---------------------------------------------------- - for( i = 0; i < count; i++ ) { - nameid = item_list[i*2+1]; - amount = item_list[i*2+0]; + for (i = 0; i < VECTOR_LENGTH(*item_list); i++) { + struct itemlist_entry *entry = &VECTOR_INDEX(*item_list, i); - if( !itemdb->exists(nameid) || amount <= 0 ) + if (!itemdb->exists(entry->id) || entry->amount <= 0) return ERROR_TYPE_ITEM_ID; - ARR_FIND(0,shop_size,j,shop[j].nameid == nameid); - if( j == shop_size || shop[j].value <= 0 ) + ARR_FIND(0,shop_size,j,shop[j].nameid == entry->id); + if (j == shop_size || shop[j].value <= 0) return ERROR_TYPE_ITEM_ID; - if( !itemdb->isstackable(nameid) && amount > 1 ) { + if (!itemdb->isstackable(entry->id) && entry->amount > 1) { ShowWarning("Player %s (%d:%d) sent a hexed packet trying to buy %d of non-stackable item %d!\n", - sd->status.name, sd->status.account_id, sd->status.char_id, amount, nameid); - amount = item_list[i*2+0] = 1; + sd->status.name, sd->status.account_id, sd->status.char_id, entry->amount, entry->id); + entry->amount = 1; } - switch( pc->checkadditem(sd,nameid,amount) ) { + switch (pc->checkadditem(sd, entry->id, entry->amount)) { case ADDITEM_NEW: new_++; break; @@ -1446,8 +1446,8 @@ int npc_cashshop_buylist(struct map_session_data *sd, int points, int count, uns return ERROR_TYPE_INVENTORY_WEIGHT; } - vt += shop[j].value * amount; - w += itemdb_weight(nameid) * amount; + vt += shop[j].value * entry->amount; + w += itemdb_weight(entry->id) * entry->amount; } if( w + sd->weight > sd->max_weight ) @@ -1468,18 +1468,16 @@ int npc_cashshop_buylist(struct map_session_data *sd, int points, int count, uns pc->paycash(sd,vt,points); } // Delivery Process ---------------------------------------------------- - for( i = 0; i < count; i++ ) { + for (i = 0; i < VECTOR_LENGTH(*item_list); i++) { + struct itemlist_entry *entry = &VECTOR_INDEX(*item_list, i); struct item item_tmp; - nameid = item_list[i*2+1]; - amount = item_list[i*2+0]; - memset(&item_tmp,0,sizeof(item_tmp)); - if( !pet->create_egg(sd,nameid) ) { - item_tmp.nameid = nameid; + if (!pet->create_egg(sd, entry->id)) { + item_tmp.nameid = entry->id; item_tmp.identify = 1; - pc->additem(sd,&item_tmp,amount,LOG_TYPE_NPC); + pc->additem(sd, &item_tmp, entry->amount, LOG_TYPE_NPC); } } @@ -1487,7 +1485,7 @@ int npc_cashshop_buylist(struct map_session_data *sd, int points, int count, uns } //npc_buylist for script-controlled shops. -int npc_buylist_sub(struct map_session_data* sd, int n, unsigned short* item_list, struct npc_data* nd) +int npc_buylist_sub(struct map_session_data *sd, struct itemlist *item_list, struct npc_data *nd) { char npc_ev[EVENT_NAME_LENGTH]; int i; @@ -1499,9 +1497,12 @@ int npc_buylist_sub(struct map_session_data* sd, int n, unsigned short* item_lis script->cleararray_pc(sd, "@bought_quantity", (void*)0); // save list of bought items - for( i = 0; i < n; i++ ) { - script->setarray_pc(sd, "@bought_nameid", i, (void*)(intptr_t)item_list[i*2+1], &key_nameid); - script->setarray_pc(sd, "@bought_quantity", i, (void*)(intptr_t)item_list[i*2], &key_amount); + for (i = 0; i < VECTOR_LENGTH(*item_list); i++) { + struct itemlist_entry *entry = &VECTOR_INDEX(*item_list, i); + intptr_t nameid = entry->id; + intptr_t amount = entry->amount; + script->setarray_pc(sd, "@bought_nameid", i, (void *)nameid, &key_nameid); + script->setarray_pc(sd, "@bought_quantity", i, (void *)amount, &key_amount); } // invoke event @@ -1564,8 +1565,8 @@ void npc_market_fromsql(void) { * Saves persistent NPC Market Data into SQL **/ void npc_market_tosql(struct npc_data *nd, unsigned short index) { - if( SQL_ERROR == SQL->Query(map->mysql_handle, "REPLACE INTO `%s` VALUES ('%s','%d','%d')", - map->npc_market_data_db, nd->exname, nd->u.scr.shop->item[index].nameid, nd->u.scr.shop->item[index].qty) ) + if (SQL_ERROR == SQL->Query(map->mysql_handle, "REPLACE INTO `%s` VALUES ('%s','%d','%u')", + map->npc_market_data_db, nd->exname, nd->u.scr.shop->item[index].nameid, nd->u.scr.shop->item[index].qty)) Sql_ShowDebug(map->mysql_handle); } /** @@ -1769,9 +1770,9 @@ int npc_cashshop_buy(struct map_session_data *sd, int nameid, int amount, int po if( w + sd->weight > sd->max_weight ) return ERROR_TYPE_INVENTORY_WEIGHT; - if( (double)shop[i].value * amount > INT_MAX ) { + if ((int64)shop[i].value * amount > INT_MAX) { ShowWarning("npc_cashshop_buy: Item '%s' (%d) price overflow attempt!\n", item->name, nameid); - ShowDebug("(NPC:'%s' (%s,%d,%d), player:'%s' (%d/%d), value:%d, amount:%d)\n", + ShowDebug("(NPC:'%s' (%s,%d,%d), player:'%s' (%d/%d), value:%u, amount:%d)\n", nd->exname, map->list[nd->bl.m].name, nd->bl.x, nd->bl.y, sd->status.name, sd->status.account_id, sd->status.char_id, shop[i].value, amount); @@ -1805,14 +1806,18 @@ int npc_cashshop_buy(struct map_session_data *sd, int nameid, int amount, int po return ERROR_TYPE_NONE; } -/// Player item purchase from npc shop. -/// -/// @param item_list 'n' pairs <amount,itemid> -/// @return result code for clif->parse_NpcBuyListSend -int npc_buylist(struct map_session_data* sd, int n, unsigned short* item_list) { +/** + * Processes a player item purchase from npc shop. + * + * @param sd Buyer character. + * @param item_list List of items. + * @return result code for clif->parse_NpcBuyListSend. + */ +int npc_buylist(struct map_session_data *sd, struct itemlist *item_list) +{ struct npc_data* nd; struct npc_item_list *shop = NULL; - double z; + int64 z; int i,j,w,skill_t,new_, idx = skill->get_index(MC_DISCOUNT); unsigned short shop_size = 0; @@ -1838,30 +1843,29 @@ int npc_buylist(struct map_session_data* sd, int n, unsigned short* item_list) { w = 0; new_ = 0; // process entries in buy list, one by one - for( i = 0; i < n; ++i ) { - int nameid, amount, value; + for (i = 0; i < VECTOR_LENGTH(*item_list); ++i) { + int value; + struct itemlist_entry *entry = &VECTOR_INDEX(*item_list, i); // find this entry in the shop's sell list ARR_FIND( 0, shop_size, j, - item_list[i*2+1] == shop[j].nameid || //Normal items - item_list[i*2+1] == itemdb_viewid(shop[j].nameid) //item_avail replacement + entry->id == shop[j].nameid || //Normal items + entry->id == itemdb_viewid(shop[j].nameid) //item_avail replacement ); - - if( j == shop_size ) + if (j == shop_size) return 3; // no such item in shop - amount = item_list[i*2+0]; - nameid = item_list[i*2+1] = shop[j].nameid; //item_avail replacement + entry->id = shop[j].nameid; //item_avail replacement value = shop[j].value; - if( !itemdb->exists(nameid) ) + if (!itemdb->exists(entry->id)) return 3; // item no longer in itemdb - if( !itemdb->isstackable(nameid) && amount > 1 ) { + if (!itemdb->isstackable(entry->id) && entry->amount > 1) { //Exploit? You can't buy more than 1 of equipment types o.O ShowWarning("Player %s (%d:%d) sent a hexed packet trying to buy %d of non-stackable item %d!\n", - sd->status.name, sd->status.account_id, sd->status.char_id, amount, nameid); - amount = item_list[i*2+0] = 1; + sd->status.name, sd->status.account_id, sd->status.char_id, entry->amount, entry->id); + entry->amount = 1; } if( nd->master_nd ) { @@ -1869,7 +1873,7 @@ int npc_buylist(struct map_session_data* sd, int n, unsigned short* item_list) { continue; } - switch( pc->checkadditem(sd,nameid,amount) ) { + switch (pc->checkadditem(sd, entry->id, entry->amount)) { case ADDITEM_EXIST: break; @@ -1883,35 +1887,33 @@ int npc_buylist(struct map_session_data* sd, int n, unsigned short* item_list) { value = pc->modifybuyvalue(sd,value); - z += (double)value * amount; - w += itemdb_weight(nameid) * amount; + z += (int64)value * entry->amount; + w += itemdb_weight(entry->id) * entry->amount; } - if( nd->master_nd != NULL ) //Script-based shops. - return npc->buylist_sub(sd,n,item_list,nd->master_nd); + if (nd->master_nd != NULL) //Script-based shops. + return npc->buylist_sub(sd, item_list, nd->master_nd); - if( z > (double)sd->status.zeny ) + if (z > sd->status.zeny) return 1; // Not enough Zeny if( w + sd->weight > sd->max_weight ) return 2; // Too heavy if( pc->inventoryblank(sd) < new_ ) return 3; // Not enough space to store items - pc->payzeny(sd,(int)z,LOG_TYPE_NPC, NULL); - - for( i = 0; i < n; ++i ) { - int nameid = item_list[i*2+1]; - int amount = item_list[i*2+0]; + pc->payzeny(sd, (int)z, LOG_TYPE_NPC, NULL); - if (itemdb_type(nameid) == IT_PETEGG) { - pet->create_egg(sd, nameid); + for (i = 0; i < VECTOR_LENGTH(*item_list); ++i) { + struct itemlist_entry *entry = &VECTOR_INDEX(*item_list, i); + if (itemdb_type(entry->id) == IT_PETEGG) { + pet->create_egg(sd, entry->id); } else { struct item item_tmp; memset(&item_tmp,0,sizeof(item_tmp)); - item_tmp.nameid = nameid; + item_tmp.nameid = entry->id; item_tmp.identify = 1; - pc->additem(sd,&item_tmp,amount,LOG_TYPE_NPC); + pc->additem(sd, &item_tmp, entry->amount, LOG_TYPE_NPC); } } @@ -1921,10 +1923,10 @@ int npc_buylist(struct map_session_data* sd, int n, unsigned short* item_list) { skill_t = sd->status.skill[idx].flag - SKILL_FLAG_REPLACED_LV_0; if( skill_t > 0 ) { - z = z * (double)skill_t * (double)battle_config.shop_exp/10000.; - if( z < 1 ) + z = apply_percentrate64(z, skill_t * battle_config.shop_exp, 10000); + if (z < 1) z = 1; - pc->gainexp(sd,NULL,0,(int)z, false); + pc->gainexp(sd, NULL, 0, (int)z, false); } } @@ -1932,21 +1934,22 @@ int npc_buylist(struct map_session_data* sd, int n, unsigned short* item_list) { } /** - * parses incoming npc market purchase list + * Processes incoming npc market purchase list **/ -int npc_market_buylist(struct map_session_data* sd, unsigned short list_size, struct packet_npc_market_purchase *p) { +int npc_market_buylist(struct map_session_data *sd, struct itemlist *item_list) +{ struct npc_data* nd; struct npc_item_list *shop = NULL; - double z; + int64 z; int i,j,w,new_; unsigned short shop_size = 0; nullpo_retr(1, sd); - nullpo_retr(1, p); + nullpo_retr(1, item_list); nd = npc->checknear(sd,map->id2bl(sd->npc_shopid)); - if( nd == NULL || nd->subtype != SCRIPT || !list_size || !nd->u.scr.shop || nd->u.scr.shop->type != NST_MARKET ) + if (nd == NULL || nd->subtype != SCRIPT || VECTOR_LENGTH(*item_list) == 0 || !nd->u.scr.shop || nd->u.scr.shop->type != NST_MARKET) return 1; shop = nd->u.scr.shop->item; @@ -1957,37 +1960,37 @@ int npc_market_buylist(struct map_session_data* sd, unsigned short list_size, st new_ = 0; // process entries in buy list, one by one - for( i = 0; i < list_size; ++i ) { - int nameid, amount, value; + for (i = 0; i < VECTOR_LENGTH(*item_list); ++i) { + int value; + struct itemlist_entry *entry = &VECTOR_INDEX(*item_list, i); // find this entry in the shop's sell list ARR_FIND( 0, shop_size, j, - p->list[i].ITID == shop[j].nameid || //Normal items - p->list[i].ITID == itemdb_viewid(shop[j].nameid) //item_avail replacement + entry->id == shop[j].nameid || //Normal items + entry->id == itemdb_viewid(shop[j].nameid) //item_avail replacement ); - - if( j == shop_size ) /* TODO find official response for this */ + if (j == shop_size) /* TODO find official response for this */ return 1; // no such item in shop - if( p->list[i].qty > shop[j].qty ) + entry->id = shop[j].nameid; //item_avail replacement + + if (entry->amount > (int)shop[j].qty) return 1; - amount = p->list[i].qty; - nameid = p->list[i].ITID = shop[j].nameid; //item_avail replacement value = shop[j].value; npc_market_qty[i] = j; - if( !itemdb->exists(nameid) ) /* TODO find official response for this */ + if (!itemdb->exists(entry->id)) /* TODO find official response for this */ return 1; // item no longer in itemdb - if( !itemdb->isstackable(nameid) && amount > 1 ) { + if (!itemdb->isstackable(entry->id) && entry->amount > 1) { //Exploit? You can't buy more than 1 of equipment types o.O ShowWarning("Player %s (%d:%d) sent a hexed packet trying to buy %d of non-stackable item %d!\n", - sd->status.name, sd->status.account_id, sd->status.char_id, amount, nameid); - amount = p->list[i].qty = 1; + sd->status.name, sd->status.account_id, sd->status.char_id, entry->amount, entry->id); + entry->amount = 1; } - switch( pc->checkadditem(sd,nameid,amount) ) { + switch (pc->checkadditem(sd, entry->id, entry->amount)) { case ADDITEM_EXIST: break; case ADDITEM_NEW: @@ -1997,11 +2000,11 @@ int npc_market_buylist(struct map_session_data* sd, unsigned short list_size, st return 1; } - z += (double)value * amount; - w += itemdb_weight(nameid) * amount; + z += (int64)value * entry->amount; + w += itemdb_weight(entry->id) * entry->amount; } - if( z > (double)sd->status.zeny ) /* TODO find official response for this */ + if (z > sd->status.zeny) /* TODO find official response for this */ return 1; // Not enough Zeny if( w + sd->weight > sd->max_weight ) /* TODO find official response for this */ @@ -2012,28 +2015,27 @@ int npc_market_buylist(struct map_session_data* sd, unsigned short list_size, st pc->payzeny(sd,(int)z,LOG_TYPE_NPC, NULL); - for( i = 0; i < list_size; ++i ) { - int nameid = p->list[i].ITID; - int amount = p->list[i].qty; + for (i = 0; i < VECTOR_LENGTH(*item_list); ++i) { + struct itemlist_entry *entry = &VECTOR_INDEX(*item_list, i); j = npc_market_qty[i]; - if( p->list[i].qty > shop[j].qty ) /* wohoo someone tampered with the packet. */ + if (entry->amount > (int)shop[j].qty) /* wohoo someone tampered with the packet. */ return 1; - shop[j].qty -= amount; + shop[j].qty -= entry->amount; npc->market_tosql(nd,j); - if (itemdb_type(nameid) == IT_PETEGG) { - pet->create_egg(sd, nameid); + if (itemdb_type(entry->id) == IT_PETEGG) { + pet->create_egg(sd, entry->id); } else { struct item item_tmp; memset(&item_tmp,0,sizeof(item_tmp)); - item_tmp.nameid = nameid; + item_tmp.nameid = entry->id; item_tmp.identify = 1; - pc->additem(sd,&item_tmp,amount,LOG_TYPE_NPC); + pc->additem(sd, &item_tmp, entry->amount, LOG_TYPE_NPC); } } @@ -2041,7 +2043,7 @@ int npc_market_buylist(struct map_session_data* sd, unsigned short list_size, st } /// npc_selllist for script-controlled shops -int npc_selllist_sub(struct map_session_data* sd, int n, unsigned short* item_list, struct npc_data* nd) +int npc_selllist_sub(struct map_session_data *sd, struct itemlist *item_list, struct npc_data *nd) { char npc_ev[EVENT_NAME_LENGTH]; char card_slot[NAME_LENGTH]; @@ -2068,21 +2070,28 @@ int npc_selllist_sub(struct map_session_data* sd, int n, unsigned short* item_li } // save list of to be sold items - for (i = 0; i < n; i++) { - int idx = item_list[i*2]-2; - - script->setarray_pc(sd, "@sold_nameid", i, (void*)(intptr_t)sd->status.inventory[idx].nameid, &key_nameid); - script->setarray_pc(sd, "@sold_quantity", i, (void*)(intptr_t)item_list[i*2+1], &key_amount); + for (i = 0; i < VECTOR_LENGTH(*item_list); i++) { + struct itemlist_entry *entry = &VECTOR_INDEX(*item_list, i); + struct item *item = &sd->status.inventory[entry->id]; + intptr_t nameid = item->nameid; + intptr_t amount = entry->amount; + intptr_t refine = item->refine; + intptr_t attribute = item->attribute; + intptr_t identify = item->identify; + + script->setarray_pc(sd, "@sold_nameid", i, (void*)nameid, &key_nameid); + script->setarray_pc(sd, "@sold_quantity", i, (void*)amount, &key_amount); // process item based information into the arrays - script->setarray_pc(sd, "@sold_refine", i, (void*)(intptr_t)sd->status.inventory[idx].refine, &key_refine); - script->setarray_pc(sd, "@sold_attribute", i, (void*)(intptr_t)sd->status.inventory[idx].attribute, &key_attribute); - script->setarray_pc(sd, "@sold_identify", i, (void*)(intptr_t)sd->status.inventory[idx].identify, &key_identify); + script->setarray_pc(sd, "@sold_refine", i, (void*)refine, &key_refine); + script->setarray_pc(sd, "@sold_attribute", i, (void*)attribute, &key_attribute); + script->setarray_pc(sd, "@sold_identify", i, (void*)identify, &key_identify); for (j = 0; j < MAX_SLOTS; j++) { + intptr_t card = item->card[j]; // store each of the cards/special info from the item in the array snprintf(card_slot, sizeof(card_slot), "@sold_card%d", j + 1); - script->setarray_pc(sd, card_slot, i, (void*)(intptr_t)sd->status.inventory[idx].card[j], &key_card[j]); + script->setarray_pc(sd, card_slot, i, (void*)card, &key_card[j]); } } @@ -2097,8 +2106,9 @@ int npc_selllist_sub(struct map_session_data* sd, int n, unsigned short* item_li /// /// @param item_list 'n' pairs <index,amount> /// @return result code for clif->parse_NpcSellListSend -int npc_selllist(struct map_session_data* sd, int n, unsigned short* item_list) { - double z; +int npc_selllist(struct map_session_data *sd, struct itemlist *item_list) +{ + int64 z; int i,skill_t, skill_idx = skill->get_index(MC_OVERCHARGE); struct npc_data *nd; bool duplicates[MAX_INVENTORY] = { 0 }; @@ -2118,13 +2128,11 @@ int npc_selllist(struct map_session_data* sd, int n, unsigned short* item_list) z = 0; // verify the sell list - for (i = 0; i < n; i++) { - int nameid, amount, idx, value; - - idx = item_list[i*2]-2; - amount = item_list[i*2+1]; + for (i = 0; i < VECTOR_LENGTH(*item_list); i++) { + struct itemlist_entry *entry = &VECTOR_INDEX(*item_list, i); + int nameid, value, idx = entry->id; - if (idx >= MAX_INVENTORY || idx < 0 || amount < 0) { + if (idx >= MAX_INVENTORY || idx < 0 || entry->amount < 0) { return 1; } @@ -2136,7 +2144,7 @@ int npc_selllist(struct map_session_data* sd, int n, unsigned short* item_list) nameid = sd->status.inventory[idx].nameid; - if (!nameid || !sd->inventory_data[idx] || sd->status.inventory[idx].amount < amount) { + if (!nameid || !sd->inventory_data[idx] || sd->status.inventory[idx].amount < entry->amount) { return 1; } @@ -2147,27 +2155,25 @@ int npc_selllist(struct map_session_data* sd, int n, unsigned short* item_list) value = pc->modifysellvalue(sd, sd->inventory_data[idx]->value_sell); - z += (double)value*amount; + z += (int64)value * entry->amount; } if( nd->master_nd ) { // Script-controlled shops - return npc->selllist_sub(sd, n, item_list, nd->master_nd); + return npc->selllist_sub(sd, item_list, nd->master_nd); } // delete items - for( i = 0; i < n; i++ ) { - int amount, idx; + for (i = 0; i < VECTOR_LENGTH(*item_list); i++) { + struct itemlist_entry *entry = &VECTOR_INDEX(*item_list, i); + int idx = entry->id; - idx = item_list[i*2]-2; - amount = item_list[i*2+1]; - - if( sd->inventory_data[idx]->type == IT_PETEGG && sd->status.inventory[idx].card[0] == CARD0_PET ) { - if( pet->search_petDB_index(sd->status.inventory[idx].nameid, PET_EGG) >= 0 ) { + if (sd->inventory_data[idx]->type == IT_PETEGG && sd->status.inventory[idx].card[0] == CARD0_PET) { + if (pet->search_petDB_index(sd->status.inventory[idx].nameid, PET_EGG) >= 0) { intif->delete_petdata(MakeDWord(sd->status.inventory[idx].card[1], sd->status.inventory[idx].card[2])); } } - pc->delitem(sd, idx, amount, 0, DELITEM_SOLD, LOG_TYPE_NPC); + pc->delitem(sd, idx, entry->amount, 0, DELITEM_SOLD, LOG_TYPE_NPC); } if( z > MAX_ZENY ) @@ -2181,8 +2187,8 @@ int npc_selllist(struct map_session_data* sd, int n, unsigned short* item_list) skill_t = sd->status.skill[skill_idx].flag - SKILL_FLAG_REPLACED_LV_0; if( skill_t > 0 ) { - z = z * (double)skill_t * (double)battle_config.shop_exp/10000.; - if( z < 1 ) + z = apply_percentrate64(z, skill_t * battle_config.shop_exp, 10000); + if (z < 1) z = 1; pc->gainexp(sd, NULL, 0, (int)z, false); } @@ -2276,9 +2282,7 @@ int npc_unload(struct npc_data* nd, bool single) if (nd->chat_id) // remove npc chatroom object and kick users chat->delete_npc_chat(nd); -#ifdef PCRE_SUPPORT npc_chat->finalize(nd); // deallocate npc PCRE data structures -#endif if (single && nd->path != NULL) { npc->releasepathreference(nd->path); @@ -2503,7 +2507,7 @@ void npc_parsename(struct npc_data* nd, const char* name, const char* start, con if( p ) { // <Display name>::<Unique name> size_t len = p-name; if( len > NAME_LENGTH ) { - ShowWarning("npc_parsename: Display name of '%s' is too long (len=%u) in file '%s', line '%d'. Truncating to %u characters.\n", name, (unsigned int)len, filepath, strline(buffer,start-buffer), NAME_LENGTH); + ShowWarning("npc_parsename: Display name of '%s' is too long (len=%u) in file '%s', line '%d'. Truncating to %d characters.\n", name, (unsigned int)len, filepath, strline(buffer,start-buffer), NAME_LENGTH); safestrncpy(nd->name, name, sizeof(nd->name)); } else { memcpy(nd->name, name, len); @@ -2511,12 +2515,12 @@ void npc_parsename(struct npc_data* nd, const char* name, const char* start, con } len = strlen(p+2); if( len > NAME_LENGTH ) - ShowWarning("npc_parsename: Unique name of '%s' is too long (len=%u) in file '%s', line '%d'. Truncating to %u characters.\n", name, (unsigned int)len, filepath, strline(buffer,start-buffer), NAME_LENGTH); + ShowWarning("npc_parsename: Unique name of '%s' is too long (len=%u) in file '%s', line '%d'. Truncating to %d characters.\n", name, (unsigned int)len, filepath, strline(buffer,start-buffer), NAME_LENGTH); safestrncpy(nd->exname, p+2, sizeof(nd->exname)); } else {// <Display name> size_t len = strlen(name); if( len > NAME_LENGTH ) - ShowWarning("npc_parsename: Name '%s' is too long (len=%u) in file '%s', line '%d'. Truncating to %u characters.\n", name, (unsigned int)len, filepath, strline(buffer,start-buffer), NAME_LENGTH); + ShowWarning("npc_parsename: Name '%s' is too long (len=%u) in file '%s', line '%d'. Truncating to %d characters.\n", name, (unsigned int)len, filepath, strline(buffer,start-buffer), NAME_LENGTH); safestrncpy(nd->name, name, sizeof(nd->name)); safestrncpy(nd->exname, name, sizeof(nd->exname)); } @@ -2551,7 +2555,7 @@ void npc_parsename(struct npc_data* nd, const char* name, const char* start, con // Support for using Constants in place of NPC View IDs. int npc_parseview(const char* w4, const char* start, const char* buffer, const char* filepath) { int val = FAKE_NPC, i = 0; - char viewid[1024]; // Max size of name from const.txt, see script->read_constdb. + char viewid[1024]; // Max size of name from constants.conf, see script->read_constdb. // Extract view ID / constant while (w4[i] != '\0') { @@ -2568,7 +2572,7 @@ int npc_parseview(const char* w4, const char* start, const char* buffer, const c { // Check if constant exists and get its value. if(!script->get_constant(viewid, &val)) { - ShowWarning("npc_parseview: Invalid NPC constant '%s' specified in file '%s', line'%d'. Defaulting to INVISIBLE_CLASS. \n", viewid, filepath, strline(buffer,start-buffer)); + ShowWarning("npc_parseview: Invalid NPC constant '%s' specified in file '%s', line '%d'. Defaulting to INVISIBLE_CLASS.\n", viewid, filepath, strline(buffer,start-buffer)); val = INVISIBLE_CLASS; } } else { @@ -2764,7 +2768,7 @@ const char *npc_parse_shop(const char *w1, const char *w2, const char *w3, const } if (dir < 0 || dir > 7) { - ShowError("npc_parse_ship: Invalid NPC facing direction '%d' in file '%s', line '%d'.\n", dir, filepath, strline(buffer, start-buffer)); + ShowError("npc_parse_shop: Invalid NPC facing direction '%d' in file '%s', line '%d'.\n", dir, filepath, strline(buffer, start-buffer)); if (retval) *retval = EXIT_FAILURE; return strchr(start,'\n');//continue } @@ -4538,7 +4542,7 @@ int npc_script_event(struct map_session_data* sd, enum npce_event type) if (type == NPCE_MAX) return 0; if (!sd) { - ShowError("npc_script_event: NULL sd. Event Type %d\n", type); + ShowError("npc_script_event: NULL sd. Event Type %u\n", type); return 0; } for (i = 0; i<script_event[type].event_count; i++) diff --git a/src/map/npc.h b/src/map/npc.h index 0b2729bcf..965a34f94 100644 --- a/src/map/npc.h +++ b/src/map/npc.h @@ -27,7 +27,11 @@ #include "common/hercules.h" #include "common/db.h" +#include <pcre.h> + +/* Forward declarations */ struct hplugin_data_store; +struct itemlist; // map/itemdb.h struct view_data; enum npc_parse_options { @@ -138,7 +142,7 @@ enum actor_classes { #define MAX_NPC_CLASS 1000 // New NPC range #define MAX_NPC_CLASS2_START 10001 -#define MAX_NPC_CLASS2_END 10178 +#define MAX_NPC_CLASS2_END 10203 //Script NPC events. enum npce_event { @@ -228,12 +232,12 @@ struct npc_interface { int (*click) (struct map_session_data *sd, struct npc_data *nd); int (*scriptcont) (struct map_session_data *sd, int id, bool closing); int (*buysellsel) (struct map_session_data *sd, int id, int type); - int (*cashshop_buylist) (struct map_session_data *sd, int points, int count, unsigned short *item_list); - int (*buylist_sub) (struct map_session_data *sd, int n, unsigned short *item_list, struct npc_data *nd); + int (*cashshop_buylist) (struct map_session_data *sd, int points, struct itemlist *item_list); + int (*buylist_sub) (struct map_session_data *sd, struct itemlist *item_list, struct npc_data *nd); int (*cashshop_buy) (struct map_session_data *sd, int nameid, int amount, int points); - int (*buylist) (struct map_session_data *sd, int n, unsigned short *item_list); - int (*selllist_sub) (struct map_session_data *sd, int n, unsigned short *item_list, struct npc_data *nd); - int (*selllist) (struct map_session_data *sd, int n, unsigned short *item_list); + int (*buylist) (struct map_session_data *sd, struct itemlist *item_list); + int (*selllist_sub) (struct map_session_data *sd, struct itemlist *item_list, struct npc_data *nd); + int (*selllist) (struct map_session_data *sd, struct itemlist *item_list); int (*remove_map) (struct npc_data *nd); int (*unload_ev) (DBKey key, DBData *data, va_list ap); int (*unload_ev_label) (DBKey key, DBData *data, va_list ap); @@ -289,7 +293,7 @@ struct npc_interface { void (*trader_count_funds) (struct npc_data *nd, struct map_session_data *sd); bool (*trader_pay) (struct npc_data *nd, struct map_session_data *sd, int price, int points); void (*trader_update) (int master); - int (*market_buylist) (struct map_session_data* sd, unsigned short list_size, struct packet_npc_market_purchase *p); + int (*market_buylist) (struct map_session_data *sd, struct itemlist *item_list); bool (*trader_open) (struct map_session_data *sd, struct npc_data *nd); void (*market_fromsql) (void); void (*market_tosql) (struct npc_data *nd, unsigned short index); @@ -308,54 +312,36 @@ void npc_defaults(void); HPShared struct npc_interface *npc; -/* comes from npc_chat.c */ -#ifdef PCRE_SUPPORT -#include <pcre/include/pcre.h> -#endif // PCRE_SUPPORT - /** * Structure containing all info associated with a single pattern block */ struct pcrematch_entry { -#ifdef PCRE_SUPPORT struct pcrematch_entry* next; char* pattern; pcre* pcre_; pcre_extra* pcre_extra_; char* label; -#else // not PCRE_SUPPORT - UNAVAILABLE_STRUCT; -#endif // PCRE_SUPPORT }; /** * A set of patterns that can be activated and deactived with a single command */ struct pcrematch_set { -#ifdef PCRE_SUPPORT struct pcrematch_set* prev; struct pcrematch_set* next; struct pcrematch_entry* head; int setid; -#else // not PCRE_SUPPORT - UNAVAILABLE_STRUCT; -#endif // PCRE_SUPPORT }; /** * Entire data structure hung off a NPC */ struct npc_parse { -#ifdef PCRE_SUPPORT struct pcrematch_set* active; struct pcrematch_set* inactive; -#else // not PCRE_SUPPORT - UNAVAILABLE_STRUCT; -#endif // PCRE_SUPPORT }; struct npc_chat_interface { -#ifdef PCRE_SUPPORT int (*sub) (struct block_list* bl, va_list ap); void (*finalize) (struct npc_data* nd); void (*def_pattern) (struct npc_data* nd, int setid, const char* pattern, const char* label); @@ -365,9 +351,6 @@ struct npc_chat_interface { void (*activate_pcreset) (struct npc_data* nd, int setid); struct pcrematch_set* (*lookup_pcreset) (struct npc_data* nd, int setid); void (*finalize_pcrematch_entry) (struct pcrematch_entry* e); -#else // not PCRE_SUPPORT - UNAVAILABLE_STRUCT; -#endif // PCRE_SUPPORT }; /** @@ -376,7 +359,6 @@ struct npc_chat_interface { * should be moved into core/perhaps its own file once hpm is enhanced for login/char **/ struct pcre_interface { -#ifdef PCRE_SUPPORT pcre *(*compile) (const char *pattern, int options, const char **errptr, int *erroffset, const unsigned char *tableptr); pcre_extra *(*study) (const pcre *code, int options, const char **errptr); int (*exec) (const pcre *code, const pcre_extra *extra, PCRE_SPTR subject, int length, int startoffset, int options, int *ovector, int ovecsize); @@ -385,9 +367,6 @@ struct pcre_interface { void (*free_substring) (const char *stringptr); int (*copy_named_substring) (const pcre *code, const char *subject, int *ovector, int stringcount, const char *stringname, char *buffer, int buffersize); int (*get_substring) (const char *subject, int *ovector, int stringcount, int stringnumber, const char **stringptr); -#else // not PCRE_SUPPORT - UNAVAILABLE_STRUCT; -#endif // PCRE_SUPPORT }; /** diff --git a/src/map/npc_chat.c b/src/map/npc_chat.c index fef3ba99b..6726c65a9 100644 --- a/src/map/npc_chat.c +++ b/src/map/npc_chat.c @@ -20,8 +20,6 @@ */ #define HERCULES_CORE -#ifdef PCRE_SUPPORT - #include "npc.h" // struct npc_data #include "map/mob.h" // struct mob_data @@ -33,8 +31,7 @@ #include "common/strlib.h" #include "common/timer.h" -#include <pcre/include/pcre.h> - +#include <pcre.h> #include <stdarg.h> #include <stdio.h> #include <stdlib.h> @@ -470,5 +467,3 @@ void npc_chat_defaults(void) { libpcre->copy_named_substring = pcre_copy_named_substring; libpcre->get_substring = pcre_get_substring; } - -#endif //PCRE_SUPPORT diff --git a/src/map/packets.h b/src/map/packets.h index 9b9c7945f..0badd94f5 100644 --- a/src/map/packets.h +++ b/src/map/packets.h @@ -2910,9 +2910,15 @@ packet(0x96e,-1,clif->ackmergeitems); packet(0x08A8,26,clif->pFriendsListAdd,2); packet(0x0817,5,clif->pHomMenu,2,4); packet(0x0923,36,clif->pStoragePassword,0); - packet(0x09e8,11,clif->pDull); // CZ_OPEN_MAILBOX - packet(0x0a2e,6,clif->pDull); // TITLE - packet(0x0a02,4); // ZC_DRESSROOM_OPEN + packet(0x09E8,11,clif->pDull); // CZ_OPEN_MAILBOX + packet(0x0A2E,6,clif->pDull); // TITLE + packet(0x0A02,4); // ZC_DRESSROOM_OPEN + packet(0x0A35,4,clif->pOneClick_ItemIdentify,2); +#endif + +#if PACKETVER >= 20150805 // RagexeRE + packet(0x097f,-1); // ZC_SELECTCART + packet(0x0980,7,clif->pSelectCart); // CZ_SELECTCART #endif /* PacketKeys: http://herc.ws/board/topic/1105-hercules-wpe-free-june-14th-patch/ */ diff --git a/src/map/packets_struct.h b/src/map/packets_struct.h index 43ff0737f..e8f04c653 100644 --- a/src/map/packets_struct.h +++ b/src/map/packets_struct.h @@ -584,6 +584,7 @@ struct packet_spawn_unit { #endif #if PACKETVER >= 20150513 short body; + char name[NAME_LENGTH]; #endif } __attribute__((packed)); @@ -651,6 +652,7 @@ struct packet_unit_walking { #endif #if PACKETVER >= 20150513 short body; + char name[NAME_LENGTH]; #endif } __attribute__((packed)); @@ -716,6 +718,7 @@ struct packet_idle_unit { #endif #if PACKETVER >= 20150513 short body; + char name[NAME_LENGTH]; #endif } __attribute__((packed)); @@ -1105,7 +1108,7 @@ struct packet_npc_market_purchase { struct { unsigned short ITID; int qty; - } list[MAX_INVENTORY];/* assuming MAX_INVENTORY is max since you can't hold more than MAX_INVENTORY items thus cant buy that many at once. */ + } list[]; // Note: We assume this should be <= MAX_INVENTORY (since you can't hold more than MAX_INVENTORY items thus cant buy that many at once). } __attribute__((packed)); struct packet_npc_market_result_ack { @@ -1157,9 +1160,9 @@ struct packet_hotkey { char Rotate; #endif struct { - char isSkill; // 0: Item, 1:Skill - unsigned int ID; // Item/Skill ID - short count; // Item Quantity/Skill Level + char isSkill; // 0: Item, 1:Skill + unsigned int ID; // Item/Skill ID + short count; // Item Quantity/Skill Level } hotkey[MAX_HOTKEYS]; #else // not HOTKEY_SAVING UNAVAILABLE_STRUCT; diff --git a/src/map/party.c b/src/map/party.c index a3e59c281..77f3c2b0b 100644 --- a/src/map/party.c +++ b/src/map/party.c @@ -67,18 +67,27 @@ void party_fill_member(struct party_member* member, struct map_session_data* sd, member->online = 1; member->leader = leader; } -/// Get the member_id of a party member. -/// Return -1 if not in party. -int party_getmemberid(struct party_data* p, struct map_session_data* sd) { + +/** + * Gets the member_id of a party member. + * + * @param p Party data. + * @param sd Member data. + * @return the member_id. + * @retval INDEX_NOT_FOUND if not in party. + */ +int party_getmemberid(struct party_data *p, struct map_session_data *sd) +{ int member_id; - nullpo_retr(-1, p); - if( sd == NULL ) - return -1;// no player + nullpo_retr(INDEX_NOT_FOUND, p); + + if (sd == NULL) + return INDEX_NOT_FOUND; // no player ARR_FIND(0, MAX_PARTY, member_id, p->party.member[member_id].account_id == sd->status.account_id && p->party.member[member_id].char_id == sd->status.char_id); - if( member_id == MAX_PARTY ) - return -1;// not found + if (member_id == MAX_PARTY) + return INDEX_NOT_FOUND; // not found return member_id; } @@ -148,7 +157,7 @@ struct party_data* party_searchname(const char* str) return p; } -int party_create(struct map_session_data *sd,char *name,int item,int item2) +int party_create(struct map_session_data *sd, const char *name,int item,int item2) { struct party_member leader; char tname[NAME_LENGTH]; @@ -175,7 +184,8 @@ int party_create(struct map_session_data *sd,char *name,int item,int item2) return 0; } -void party_created(int account_id,int char_id,int fail,int party_id,char *name) { +void party_created(int account_id, int char_id, int fail, int party_id, const char *name) +{ struct map_session_data *sd; sd=map->id2sd(account_id); @@ -241,10 +251,10 @@ void party_check_state(struct party_data *p) { } } -int party_recv_info(struct party* sp, int char_id) +int party_recv_info(const struct party *sp, int char_id) { struct party_data* p; - struct party_member* member; + const struct party_member *member; struct map_session_data* sd; int removed[MAX_PARTY];// member_id in old data int removed_count = 0; @@ -325,7 +335,7 @@ int party_recv_info(struct party* sp, int char_id) if( char_id != 0 ) { // requester sd = map->charid2sd(char_id); - if( sd && sd->status.party_id == sp->party_id && party->getmemberid(p,sd) == -1 ) + if (sd != NULL && sd->status.party_id == sp->party_id && party->getmemberid(p,sd) == INDEX_NOT_FOUND) sd->status.party_id = 0;// was not in the party } return 0; @@ -510,7 +520,7 @@ int party_member_added(int party_id,int account_id,int char_id, int flag) { } /// Party member 'sd' requesting kick of member with <account_id, name>. -int party_removemember(struct map_session_data* sd, int account_id, char* name) +int party_removemember(struct map_session_data* sd, int account_id, const char *name) { struct party_data *p; int i; diff --git a/src/map/party.h b/src/map/party.h index 828916b88..b66a9770c 100644 --- a/src/map/party.h +++ b/src/map/party.h @@ -97,18 +97,18 @@ struct party_interface { int (*getmemberid) (struct party_data* p, struct map_session_data* sd); struct map_session_data* (*getavailablesd) (struct party_data *p); - int (*create) (struct map_session_data *sd,char *name, int item, int item2); - void (*created) (int account_id,int char_id,int fail,int party_id,char *name); + int (*create) (struct map_session_data *sd, const char *name, int item, int item2); + void (*created) (int account_id, int char_id, int fail, int party_id, const char *name); int (*request_info) (int party_id, int char_id); int (*invite) (struct map_session_data *sd,struct map_session_data *tsd); void (*member_joined) (struct map_session_data *sd); int (*member_added) (int party_id,int account_id,int char_id,int flag); int (*leave) (struct map_session_data *sd); - int (*removemember) (struct map_session_data *sd,int account_id,char *name); + int (*removemember) (struct map_session_data *sd, int account_id, const char *name); int (*member_withdraw) (int party_id,int account_id,int char_id); void (*reply_invite) (struct map_session_data *sd,int party_id,int flag); int (*recv_noinfo) (int party_id, int char_id); - int (*recv_info) (struct party* sp, int char_id); + int (*recv_info) (const struct party *sp, int char_id); int (*recv_movemap) (int party_id,int account_id,int char_id, unsigned short mapid,int online,int lv); int (*broken) (int party_id); int (*optionchanged) (int party_id,int account_id,int exp,int item,int flag); diff --git a/src/map/pc.c b/src/map/pc.c index 2dfd9519b..e958f32b6 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -539,7 +539,7 @@ void pc_rental_expire(struct map_session_data *sd, int i) { } clif->rental_expired(sd->fd, i, sd->status.inventory[i].nameid); - pc->delitem(sd, i, sd->status.inventory[i].amount, 0, DELITEM_NORMAL, LOG_TYPE_OTHER); + pc->delitem(sd, i, sd->status.inventory[i].amount, 0, DELITEM_NORMAL, LOG_TYPE_RENTAL); } void pc_inventory_rentals(struct map_session_data *sd) { @@ -676,6 +676,7 @@ int pc_setnewpc(struct map_session_data *sd, int account_id, int char_id, int lo //Required to prevent homunculus copuing a base speed of 0. sd->battle_status.speed = sd->base_status.speed = DEFAULT_WALK_SPEED; sd->state.warp_clean = 1; + sd->catch_target_class = -1; return 0; } @@ -998,7 +999,7 @@ int pc_isequip(struct map_session_data *sd,int n) } } //Not equipable by class. [Skotlex] - if (!(1<<(sd->class_&MAPID_BASEMASK)&item->class_base[(sd->class_&JOBL_2_1)?1:((sd->class_&JOBL_2_2)?2:0)])) + if (!(1ULL<<(sd->class_&MAPID_BASEMASK)&item->class_base[(sd->class_&JOBL_2_1)?1:((sd->class_&JOBL_2_2)?2:0)])) return 0; //Not usable by upper class. [Inkfish] while( 1 ) { @@ -1033,7 +1034,8 @@ int pc_isequip(struct map_session_data *sd,int n) * No problem with the session id * set the status that has been sent from char server *------------------------------------------*/ -bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_time, int group_id, struct mmo_charstatus *st, bool changing_mapservers) { +bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_time, int group_id, const struct mmo_charstatus *st, bool changing_mapservers) +{ int i; int64 tick = timer->gettick(); uint32 ip = sockt->session[sd->fd]->client_addr; @@ -1212,7 +1214,7 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim //display login notice ShowInfo("'"CL_WHITE"%s"CL_RESET"' logged in." " (AID/CID: '"CL_WHITE"%d/%d"CL_RESET"'," - " IP: '"CL_WHITE"%d.%d.%d.%d"CL_RESET"'," + " IP: '"CL_WHITE"%u.%u.%u.%u"CL_RESET"'," " Group '"CL_WHITE"%d"CL_RESET"').\n", sd->status.name, sd->status.account_id, sd->status.char_id, CONVIP(ip), sd->group_id); @@ -2883,6 +2885,7 @@ int pc_bonus(struct map_session_data *sd,int type,int val) { break; default: ShowWarning("pc_bonus: unknown type %d %d !\n",type,val); + Assert_report(0); break; } return 0; @@ -3675,6 +3678,7 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val) #endif default: ShowWarning("pc_bonus2: unknown type %d %d %d!\n",type,type2,val); + Assert_report(0); break; } return 0; @@ -3847,6 +3851,7 @@ int pc_bonus3(struct map_session_data *sd,int type,int type2,int type3,int val) default: ShowWarning("pc_bonus3: unknown type %d %d %d %d!\n",type,type2,type3,val); + Assert_report(0); break; } @@ -3941,6 +3946,7 @@ int pc_bonus4(struct map_session_data *sd,int type,int type2,int type3,int type4 default: ShowWarning("pc_bonus4: unknown type %d %d %d %d %d!\n",type,type2,type3,type4,val); + Assert_report(0); break; } @@ -3968,6 +3974,7 @@ int pc_bonus5(struct map_session_data *sd,int type,int type2,int type3,int type4 default: ShowWarning("pc_bonus5: unknown type %d %d %d %d %d %d!\n",type,type2,type3,type4,type5,val); + Assert_report(0); break; } @@ -4129,7 +4136,7 @@ int pc_insert_card(struct map_session_data* sd, int idx_card, int idx_equip) // remember the card id to insert nameid = sd->status.inventory[idx_card].nameid; - if( pc->delitem(sd, idx_card, 1, 1, DELITEM_NORMAL, LOG_TYPE_OTHER) == 1 ) + if( pc->delitem(sd, idx_card, 1, 1, DELITEM_NORMAL, LOG_TYPE_CARD) == 1 ) {// failed clif->insert_card(sd,idx_equip,idx_card,1); } @@ -4139,9 +4146,9 @@ int pc_insert_card(struct map_session_data* sd, int idx_card, int idx_equip) ARR_FIND( 0, sd->inventory_data[idx_equip]->slot, i, sd->status.inventory[idx_equip].card[i] == 0); if (i == sd->inventory_data[idx_equip]->slot) return 0; // no free slots - logs->pick_pc(sd, LOG_TYPE_OTHER, -1, &sd->status.inventory[idx_equip],sd->inventory_data[idx_equip]); + logs->pick_pc(sd, LOG_TYPE_CARD, -1, &sd->status.inventory[idx_equip],sd->inventory_data[idx_equip]); sd->status.inventory[idx_equip].card[i] = nameid; - logs->pick_pc(sd, LOG_TYPE_OTHER, 1, &sd->status.inventory[idx_equip],sd->inventory_data[idx_equip]); + logs->pick_pc(sd, LOG_TYPE_CARD, 1, &sd->status.inventory[idx_equip],sd->inventory_data[idx_equip]); clif->insert_card(sd,idx_equip,idx_card,0); return 1; } @@ -4156,34 +4163,39 @@ int pc_insert_card(struct map_session_data* sd, int idx_card, int idx_equip) /*========================================== * Update buying value by skills *------------------------------------------*/ -int pc_modifybuyvalue(struct map_session_data *sd,int orig_value) { - int skill_lv,val = orig_value,rate1 = 0,rate2 = 0; - if((skill_lv=pc->checkskill(sd,MC_DISCOUNT))>0) // merchant discount +int pc_modifybuyvalue(struct map_session_data *sd, int orig_value) +{ + int skill_lv, rate1 = 0, rate2 = 0; + if (orig_value <= 0) + return 0; + if ((skill_lv=pc->checkskill(sd,MC_DISCOUNT)) > 0) // merchant discount rate1 = 5+skill_lv*2-((skill_lv==10)? 1:0); - if((skill_lv=pc->checkskill(sd,RG_COMPULSION))>0) // rogue discount + if ((skill_lv=pc->checkskill(sd,RG_COMPULSION)) > 0) // rogue discount rate2 = 5+skill_lv*4; - if(rate1 < rate2) rate1 = rate2; - if(rate1) - val = (int)((double)orig_value*(double)(100-rate1)/100.); - if(val < 0) val = 0; - if(orig_value > 0 && val < 1) val = 1; - - return val; + if (rate1 < rate2) + rate1 = rate2; + if (rate1 != 0) + orig_value = apply_percentrate(orig_value, 100-rate1, 100); + if (orig_value < 1) + orig_value = 1; + return orig_value; } /*========================================== * Update selling value by skills *------------------------------------------*/ -int pc_modifysellvalue(struct map_session_data *sd,int orig_value) { - int skill_lv,val = orig_value,rate = 0; - if((skill_lv=pc->checkskill(sd,MC_OVERCHARGE))>0) //OverCharge +int pc_modifysellvalue(struct map_session_data *sd, int orig_value) +{ + int skill_lv, rate = 0; + if (orig_value <= 0) + return 0; + if ((skill_lv=pc->checkskill(sd,MC_OVERCHARGE)) > 0) //OverCharge rate = 5+skill_lv*2-((skill_lv==10)? 1:0); - if(rate) - val = (int)((double)orig_value*(double)(100+rate)/100.); - if(val < 0) val = 0; - if(orig_value > 0 && val < 1) val = 1; - - return val; + if (rate != 0) + orig_value = apply_percentrate(orig_value, 100+rate, 100); + if (orig_value < 1) + orig_value = 1; + return orig_value; } /*========================================== @@ -4837,7 +4849,7 @@ int pc_isUseitem(struct map_session_data *sd,int n) //Not equipable by class. [Skotlex] if (!( - (1<<(sd->class_&MAPID_BASEMASK)) & + (1ULL<<(sd->class_&MAPID_BASEMASK)) & (item->class_base[(sd->class_&JOBL_2_1) ? 1 : ((sd->class_&JOBL_2_2) ? 2 : 0)]) )) return 0; @@ -5259,7 +5271,7 @@ int pc_show_steal(struct block_list *bl,va_list ap) int pc_steal_item(struct map_session_data *sd,struct block_list *bl, uint16 skill_lv) { int i,itemid,flag; - double rate; + int rate; struct status_data *sd_status, *md_status; struct mob_data *md = BL_CAST(BL_MOB, bl); struct item tmp_item; @@ -5284,18 +5296,22 @@ int pc_steal_item(struct map_session_data *sd,struct block_list *bl, uint16 skil } // base skill success chance (percentual) - rate = (sd_status->dex - md_status->dex)/2 + skill_lv*6 + 4; - rate += sd->bonus.add_steal_rate; + rate = (sd_status->dex - md_status->dex)/2 + skill_lv*6 + 4 + sd->bonus.add_steal_rate; if( rate < 1 ) return 0; // Try dropping one item, in the order from first to last possible slot. // Droprate is affected by the skill success rate. - for( i = 0; i < MAX_STEAL_DROP; i++ ) - if (md->db->dropitem[i].nameid > 0 && (data = itemdb->exists(md->db->dropitem[i].nameid)) != NULL && rnd() % 10000 < md->db->dropitem[i].p * rate/100.) + for (i = 0; i < MAX_STEAL_DROP; i++) { + if (md->db->dropitem[i].nameid == 0) + continue; + if ((data = itemdb->exists(md->db->dropitem[i].nameid)) == NULL) + continue; + if (rnd() % 10000 < apply_percentrate(md->db->dropitem[i].p, rate, 100)) break; - if( i == MAX_STEAL_DROP ) + } + if (i == MAX_STEAL_DROP) return 0; itemid = md->db->dropitem[i].nameid; @@ -6612,16 +6628,16 @@ void pc_calcexp(struct map_session_data *sd, unsigned int *base_exp, unsigned in if (sd->sc.data[SC_OVERLAPEXPUP]) bonus += sd->sc.data[SC_OVERLAPEXPUP]->val1; - *base_exp = (unsigned int) cap_value(*base_exp + (double)*base_exp * bonus/100., 1, UINT_MAX); + *base_exp = (unsigned int) cap_value(*base_exp + apply_percentrate64(*base_exp, bonus, 100), 1, UINT_MAX); if (sd->sc.data[SC_CASH_PLUSONLYJOBEXP]) bonus += sd->sc.data[SC_CASH_PLUSONLYJOBEXP]->val1; - *job_exp = (unsigned int) cap_value(*job_exp + (double)*job_exp * bonus/100., 1, UINT_MAX); + *job_exp = (unsigned int) cap_value(*job_exp + apply_percentrate64(*job_exp, bonus, 100), 1, UINT_MAX); - if( sd->status.mod_exp != 100 ) { - *base_exp = (unsigned int) cap_value((double)*base_exp * sd->status.mod_exp/100., 1, UINT_MAX); - *job_exp = (unsigned int) cap_value((double)*job_exp * sd->status.mod_exp/100., 1, UINT_MAX); + if (sd->status.mod_exp != 100) { + *base_exp = (unsigned int) cap_value(apply_percentrate64(*base_exp, sd->status.mod_exp, 100), 1, UINT_MAX); + *job_exp = (unsigned int) cap_value(apply_percentrate64(*job_exp, sd->status.mod_exp, 100), 1, UINT_MAX); } } @@ -7187,7 +7203,7 @@ int pc_resetstate(struct map_session_data* sd) // New statpoint table used here - Dexity if (sd->status.base_level > MAX_LEVEL) { //pc->statp[] goes out of bounds, can't reset! - ShowError("pc_resetstate: Can't reset stats of %d:%d, the base level (%d) is greater than the max level supported (%d)\n", + ShowError("pc_resetstate: Can't reset stats of %d:%d, the base level (%u) is greater than the max level supported (%d)\n", sd->status.account_id, sd->status.char_id, sd->status.base_level, MAX_LEVEL); return 0; } @@ -7713,18 +7729,18 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) { && !map->list[sd->bl.m].flag.noexppenalty && !map_flag_gvg2(sd->bl.m) && !sd->sc.data[SC_BABY] && !sd->sc.data[SC_CASH_DEATHPENALTY] ) { - unsigned int base_penalty = 0; if (battle_config.death_penalty_base > 0) { + unsigned int base_penalty = 0; switch (battle_config.death_penalty_type) { case 1: - base_penalty = (unsigned int) ((double)pc->nextbaseexp(sd) * (double)battle_config.death_penalty_base/10000); + base_penalty = (unsigned int) apply_percentrate64(pc->nextbaseexp(sd), battle_config.death_penalty_base, 10000); break; case 2: - base_penalty = (unsigned int) ((double)sd->status.base_exp * (double)battle_config.death_penalty_base/10000); + base_penalty = (unsigned int) apply_percentrate64(sd->status.base_exp, battle_config.death_penalty_base, 10000); break; } - if(base_penalty) { + if (base_penalty != 0) { if (battle_config.pk_mode && src && src->type==BL_PC) base_penalty*=2; if( sd->status.mod_death != 100 ) @@ -7735,31 +7751,31 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) { } if(battle_config.death_penalty_job > 0) { - base_penalty = 0; + unsigned int job_penalty = 0; switch (battle_config.death_penalty_type) { case 1: - base_penalty = (unsigned int) ((double)pc->nextjobexp(sd) * (double)battle_config.death_penalty_job/10000); + job_penalty = (unsigned int) apply_percentrate64(pc->nextjobexp(sd), battle_config.death_penalty_job, 10000); break; case 2: - base_penalty = (unsigned int) ((double)sd->status.job_exp * (double)battle_config.death_penalty_job/10000); + job_penalty = (unsigned int) apply_percentrate64(sd->status.job_exp, battle_config.death_penalty_job, 10000); break; } - if(base_penalty) { + if (job_penalty != 0) { if (battle_config.pk_mode && src && src->type==BL_PC) - base_penalty*=2; + job_penalty*=2; if( sd->status.mod_death != 100 ) - base_penalty = base_penalty * sd->status.mod_death / 100; - sd->status.job_exp -= min(sd->status.job_exp, base_penalty); + job_penalty = job_penalty * sd->status.mod_death / 100; + sd->status.job_exp -= min(sd->status.job_exp, job_penalty); clif->updatestatus(sd,SP_JOBEXP); } } - if(battle_config.zeny_penalty > 0 && !map->list[sd->bl.m].flag.nozenypenalty) { - base_penalty = (unsigned int)((double)sd->status.zeny * (double)battle_config.zeny_penalty / 10000.); - if(base_penalty) - pc->payzeny(sd, base_penalty, LOG_TYPE_PICKDROP_PLAYER, NULL); + if (battle_config.zeny_penalty > 0 && !map->list[sd->bl.m].flag.nozenypenalty) { + int zeny_penalty = apply_percentrate(sd->status.zeny, battle_config.zeny_penalty, 10000); + if (zeny_penalty != 0) + pc->payzeny(sd, zeny_penalty, LOG_TYPE_PICKDROP_PLAYER, NULL); } } @@ -9556,7 +9572,7 @@ int pc_equipitem(struct map_session_data *sd,int n,int req_pos) pos = pc->equippoint(sd,n); //With a few exceptions, item should go in all specified slots. if(battle_config.battle_log) - ShowInfo("equip %d(%d) %x:%x\n",sd->status.inventory[n].nameid,n,id?id->equip:0,req_pos); + ShowInfo("equip %d(%d) %x:%x\n", sd->status.inventory[n].nameid, n, (unsigned int)(id ? id->equip : 0), (unsigned int)req_pos); if(!pc->isequip(sd,n) || !(pos&req_pos) || sd->status.inventory[n].equip != 0 || sd->status.inventory[n].attribute==1 ) { // [Valaris] // FIXME: pc->isequip: equip level failure uses 2 instead of 0 clif->equipitemack(sd,n,0,EIA_FAIL); // fail @@ -9764,7 +9780,7 @@ int pc_unequipitem(struct map_session_data *sd,int n,int flag) } if(battle_config.battle_log) - ShowInfo("unequip %d %x:%x\n",n,pc->equippoint(sd,n),sd->status.inventory[n].equip); + ShowInfo("unequip %d %x:%x\n", n, (unsigned int)(pc->equippoint(sd, n)), sd->status.inventory[n].equip); if(!sd->status.inventory[n].equip){ //Nothing to unequip clif->unequipitemack(sd,n,0,UIA_FAIL); @@ -9889,7 +9905,7 @@ int pc_checkitem(struct map_session_data *sd) if (!itemdb_available(id)) { ShowWarning("Removed invalid/disabled item id %d from inventory (amount=%d, char_id=%d).\n", id, sd->status.inventory[i].amount, sd->status.char_id); - pc->delitem(sd, i, sd->status.inventory[i].amount, 0, DELITEM_NORMAL, LOG_TYPE_OTHER); + pc->delitem(sd, i, sd->status.inventory[i].amount, 0, DELITEM_NORMAL, LOG_TYPE_INV_INVALID); continue; } @@ -9905,7 +9921,7 @@ int pc_checkitem(struct map_session_data *sd) if( !itemdb_available(id) ) { ShowWarning("Removed invalid/disabled item id %d from cart (amount=%d, char_id=%d).\n", id, sd->status.cart[i].amount, sd->status.char_id); - pc->cart_delitem(sd, i, sd->status.cart[i].amount, 0, LOG_TYPE_OTHER); + pc->cart_delitem(sd, i, sd->status.cart[i].amount, 0, LOG_TYPE_CART_INVALID); continue; } @@ -10123,9 +10139,9 @@ int pc_divorce(struct map_session_data *sd) for( i = 0; i < MAX_INVENTORY; i++ ) { if( sd->status.inventory[i].nameid == WEDDING_RING_M || sd->status.inventory[i].nameid == WEDDING_RING_F ) - pc->delitem(sd, i, 1, 0, DELITEM_NORMAL, LOG_TYPE_OTHER); + pc->delitem(sd, i, 1, 0, DELITEM_NORMAL, LOG_TYPE_DIVORCE); if( p_sd->status.inventory[i].nameid == WEDDING_RING_M || p_sd->status.inventory[i].nameid == WEDDING_RING_F ) - pc->delitem(p_sd, i, 1, 0, DELITEM_NORMAL, LOG_TYPE_OTHER); + pc->delitem(p_sd, i, 1, 0, DELITEM_NORMAL, LOG_TYPE_DIVORCE); } clif->divorced(sd, p_sd->status.name); @@ -10529,11 +10545,18 @@ void pc_del_charm(struct map_session_data *sd, int count, int type) clif->spiritcharm(sd); } -/*========================================== - * Renewal EXP/Itemdrop rate modifier base on level penalty - * 1=exp 2=itemdrop - *------------------------------------------*/ -int pc_level_penalty_mod(int diff, unsigned char race, unsigned short mode, int type) { + +/** + * Renewal EXP/Itemdrop rate modifier base on level penalty. + * + * @param diff Level difference. + * @param race Monster race. + * @param mode Monster mode. + * @param type Modifier type (1=exp 2=itemdrop) + * @return The percent rate modifier (100 = 100%) + */ +int pc_level_penalty_mod(int diff, unsigned char race, uint32 mode, int type) +{ #if defined(RENEWAL_DROP) || defined(RENEWAL_EXP) int rate = 100, i; @@ -10633,8 +10656,8 @@ int pc_split_atoui(char* str, unsigned int* val, char sep, int max) */ void pc_read_skill_tree(void) { - config_t skill_tree_conf; - config_setting_t *skt = NULL; + struct config_t skill_tree_conf; + struct config_setting_t *skt = NULL; char config_filename[128]; int i = 0; struct s_mapiterator *iter; @@ -10642,14 +10665,12 @@ void pc_read_skill_tree(void) bool loaded[CLASS_COUNT] = { false }; safesnprintf(config_filename, sizeof(config_filename), "%s/"DBPATH"skill_tree.conf", map->db_path); - if (libconfig->read_file(&skill_tree_conf, config_filename)) { - ShowError("can't read %s\n", config_filename); + if (!libconfig->load_file(&skill_tree_conf, config_filename)) return; - } // Foreach job while ((skt = libconfig->setting_get_elem(skill_tree_conf.root, i++))) { - config_setting_t *t = NULL; + struct config_setting_t *t = NULL; int job_idx; const char *job_name = config_setting_name(skt); int job_id = pc->check_job_name(job_name); @@ -10739,11 +10760,11 @@ void pc_read_skill_tree(void) } if ((t = libconfig->setting_get_member(skt, "skills")) != NULL) { int j = 0; - config_setting_t *sk = NULL; + struct config_setting_t *sk = NULL; // Foreach skill while ((sk = libconfig->setting_get_elem(t, j++)) != NULL) { int skill_id, sk_idx; - config_setting_t *rsk = NULL; + struct config_setting_t *rsk = NULL; const char *sk_name = config_setting_name(sk); struct skill_tree_entry *tree_entry = NULL; @@ -10920,7 +10941,7 @@ int pc_readdb(void) { } maxlv = atoi(split[0]); if (maxlv > MAX_LEVEL) { - ShowWarning("pc_readdb: Specified max level %u for job %d is beyond server's limit (%u).\n ", maxlv, job_id, MAX_LEVEL); + ShowWarning("pc_readdb: Specified max level %u for job %d is beyond server's limit (%d).\n ", maxlv, job_id, MAX_LEVEL); maxlv = MAX_LEVEL; } count++; @@ -11346,7 +11367,7 @@ void pc_autotrade_update(struct map_session_data *sd, enum e_pc_autotrade_update if( sd->vending[i].amount == 0 ) continue; - if (SQL_ERROR == SQL->Query(map->mysql_handle, "INSERT INTO `%s` (`char_id`,`itemkey`,`amount`,`price`) VALUES ('%d','%d','%d','%d')", + if (SQL_ERROR == SQL->Query(map->mysql_handle, "INSERT INTO `%s` (`char_id`,`itemkey`,`amount`,`price`) VALUES ('%d','%d','%d','%u')", map->autotrade_data_db, sd->status.char_id, sd->status.cart[sd->vending[i].index].id, @@ -11479,6 +11500,20 @@ bool pc_db_checkid(unsigned int class_) || (class_ >= JOB_REBELLION && class_ < JOB_MAX ); } +/** + * checks if player have any kind of magnifier in inventory + * @param sd map_session_data of Player + * @return index of magnifer, INDEX_NOT_FOUND if it is not found + */ +int pc_have_magnifier(struct map_session_data *sd) +{ + int n; + n = pc->search_inventory(sd, ITEMID_MAGNIFIER); + if (n == INDEX_NOT_FOUND) + n = pc->search_inventory(sd, ITEMID_NOVICE_MAGNIFIER); + return n; +} + void do_final_pc(void) { db_destroy(pc->itemcd_db); pc->at_db->destroy(pc->at_db,pc->autotrade_final); @@ -11846,4 +11881,6 @@ void pc_defaults(void) { pc->check_job_name = pc_check_job_name; pc->update_idle_time = pc_update_idle_time; + + pc->have_magnifier = pc_have_magnifier; } diff --git a/src/map/pc.h b/src/map/pc.h index 23b46a631..5c5ec131d 100644 --- a/src/map/pc.h +++ b/src/map/pc.h @@ -302,8 +302,8 @@ BEGIN_ZEROED_BLOCK; // this block will be globally zeroed at the beginning of st int reseff[SC_COMMON_MAX-SC_COMMON_MIN+1]; int weapon_coma_ele[ELE_MAX]; int weapon_coma_race[RC_MAX]; - int weapon_atk[16]; - int weapon_atk_rate[16]; + int weapon_atk[MAX_WEAPON_TYPE]; + int weapon_atk_rate[MAX_WEAPON_TYPE]; int arrow_addele[ELE_MAX]; int arrow_addrace[RC_MAX]; int arrow_addsize[3]; @@ -657,7 +657,7 @@ END_ZEROED_BLOCK; #define pc_stop_attack(sd) (unit->stop_attack(&(sd)->bl)) //Weapon check considering dual wielding. -#define pc_check_weapontype(sd, type) ((type)&((sd)->status.weapon < MAX_WEAPON_TYPE? \ +#define pc_check_weapontype(sd, type) ((type)&((sd)->status.weapon < MAX_SINGLE_WEAPON_TYPE? \ 1<<(sd)->status.weapon:(1<<(sd)->weapontype1)|(1<<(sd)->weapontype2)|(1<<(sd)->status.weapon))) // clientside display macros (values to the left/right of the "+") @@ -834,7 +834,7 @@ END_ZEROED_BLOCK; /* End */ int (*makesavestatus) (struct map_session_data *sd); void (*respawn) (struct map_session_data* sd, clr_type clrtype); int (*setnewpc) (struct map_session_data *sd, int account_id, int char_id, int login_id1, unsigned int client_tick, int sex, int fd); - bool (*authok) (struct map_session_data *sd, int login_id2, time_t expiration_time, int group_id, struct mmo_charstatus *st, bool changing_mapservers); + bool (*authok) (struct map_session_data *sd, int login_id2, time_t expiration_time, int group_id, const struct mmo_charstatus *st, bool changing_mapservers); void (*authfail) (struct map_session_data *sd); int (*reg_received) (struct map_session_data *sd); @@ -1028,7 +1028,7 @@ END_ZEROED_BLOCK; /* End */ void (*del_charm) (struct map_session_data *sd, int count, int type); void (*baselevelchanged) (struct map_session_data *sd); - int (*level_penalty_mod) (int diff, unsigned char race, unsigned short mode, int type); + int (*level_penalty_mod) (int diff, unsigned char race, uint32 mode, int type); int (*calc_skillpoint) (struct map_session_data* sd); int (*invincible_timer) (int tid, int64 tick, int id, intptr_t data); @@ -1088,6 +1088,8 @@ END_ZEROED_BLOCK; /* End */ int (*check_job_name) (const char *name); void (*update_idle_time) (struct map_session_data* sd, enum e_battle_config_idletime type); + + int (*have_magnifier) (struct map_session_data *sd); }; #ifdef HERCULES_CORE diff --git a/src/map/pc_groups.c b/src/map/pc_groups.c index bd46b9616..b325a8ed7 100644 --- a/src/map/pc_groups.c +++ b/src/map/pc_groups.c @@ -63,12 +63,12 @@ static inline GroupSettings* name2group(const char* group_name) * @private */ static void read_config(void) { - config_t pc_group_config; - config_setting_t *groups = NULL; + struct config_t pc_group_config; + struct config_setting_t *groups = NULL; const char *config_filename = "conf/groups.conf"; // FIXME hardcoded name int group_count = 0; - if (libconfig->read_file(&pc_group_config, config_filename)) + if (!libconfig->load_file(&pc_group_config, config_filename)) return; groups = libconfig->lookup(&pc_group_config, "groups"); @@ -83,7 +83,7 @@ static void read_config(void) { int id = 0, level = 0; const char *groupname = NULL; int log_commands = 0; - config_setting_t *group = libconfig->setting_get_elem(groups, i); + struct config_setting_t *group = libconfig->setting_get_elem(groups, i); if (!libconfig->setting_lookup_int(group, "id", &id)) { ShowConfigWarning(group, "pc_groups:read_config: \"groups\" list member #%d has undefined id, removing...", i); @@ -106,11 +106,11 @@ static void read_config(void) { if (!libconfig->setting_lookup_string(group, "name", &groupname)) { char temp[20]; - config_setting_t *name = NULL; + struct config_setting_t *name = NULL; snprintf(temp, sizeof(temp), "Group %d", id); if ((name = config_setting_add(group, "name", CONFIG_TYPE_STRING)) == NULL || !config_setting_set_string(name, temp)) { - ShowError("pc_groups:read_config: failed to set missing group name, id=%d, skipping... (%s:%d)\n", + ShowError("pc_groups:read_config: failed to set missing group name, id=%d, skipping... (%s:%u)\n", id, config_setting_source_file(group), config_setting_source_line(group)); --i; --group_count; @@ -148,7 +148,7 @@ static void read_config(void) { // Check if all commands and permissions exist iter = db_iterator(pcg->db); for (group_settings = dbi_first(iter); dbi_exists(iter); group_settings = dbi_next(iter)) { - config_setting_t *commands = group_settings->commands, *permissions = group_settings->permissions; + struct config_setting_t *commands = group_settings->commands, *permissions = group_settings->permissions; int count = 0; // Make sure there is "commands" group @@ -157,7 +157,7 @@ static void read_config(void) { count = libconfig->setting_length(commands); for (i = 0; i < count; ++i) { - config_setting_t *command = libconfig->setting_get_elem(commands, i); + struct config_setting_t *command = libconfig->setting_get_elem(commands, i); const char *name = config_setting_name(command); if (!atcommand->exists(name)) { ShowConfigWarning(command, "pc_groups:read_config: non-existent command name '%s', removing...", name); @@ -173,7 +173,7 @@ static void read_config(void) { count = libconfig->setting_length(permissions); for(i = 0; i < count; ++i) { - config_setting_t *permission = libconfig->setting_get_elem(permissions, i); + struct config_setting_t *permission = libconfig->setting_get_elem(permissions, i); const char *name = config_setting_name(permission); int j; @@ -193,7 +193,7 @@ static void read_config(void) { while (i < group_count) { iter = db_iterator(pcg->db); for (group_settings = dbi_first(iter); dbi_exists(iter); group_settings = dbi_next(iter)) { - config_setting_t *inherit = NULL, + struct config_setting_t *inherit = NULL, *commands = group_settings->commands, *permissions = group_settings->permissions; int j, inherit_count = 0, done = 0; @@ -258,11 +258,11 @@ static void read_config(void) { // Pack permissions into GroupSettings.e_permissions for faster checking iter = db_iterator(pcg->db); for (group_settings = dbi_first(iter); dbi_exists(iter); group_settings = dbi_next(iter)) { - config_setting_t *permissions = group_settings->permissions; + struct config_setting_t *permissions = group_settings->permissions; int count = libconfig->setting_length(permissions); for (i = 0; i < count; ++i) { - config_setting_t *perm = libconfig->setting_get_elem(permissions, i); + struct config_setting_t *perm = libconfig->setting_get_elem(permissions, i); const char *name = config_setting_name(perm); int val = libconfig->setting_get_bool(perm); int j; @@ -280,9 +280,9 @@ static void read_config(void) { // to atcommand->load_group() for processing. if (group_count > 0) { GroupSettings **pc_groups = NULL; - config_setting_t **commands = NULL; + struct config_setting_t **commands = NULL; CREATE(pc_groups, GroupSettings*, group_count); - CREATE(commands, config_setting_t*, group_count); + CREATE(commands, struct config_setting_t*, group_count); i = 0; iter = db_iterator(pcg->db); for (group_settings = dbi_first(iter); dbi_exists(iter); group_settings = dbi_next(iter)) { @@ -446,7 +446,7 @@ void do_init_pc_groups(void) { for(i = 0; i < len; i++) { unsigned int p; if( ( p = pc_groups_add_permission(pc_g_defaults[i].name) ) != pc_g_defaults[i].permission ) - ShowError("do_init_pc_groups: %s error : %d != %d\n",pc_g_defaults[i].name,p,pc_g_defaults[i].permission); + ShowError("do_init_pc_groups: %s error : %u != %u\n", pc_g_defaults[i].name, p, pc_g_defaults[i].permission); } /** diff --git a/src/map/pc_groups.h b/src/map/pc_groups.h index 62704fb12..3f95237b7 100644 --- a/src/map/pc_groups.h +++ b/src/map/pc_groups.h @@ -22,9 +22,11 @@ #define MAP_PC_GROUPS_H #include "common/hercules.h" -#include "common/conf.h" #include "common/db.h" +/* Forward Declarations */ +struct config_setting_t; + /// PC permissions enum e_pc_permission { PC_PERM_NONE = 0, // #0 @@ -66,11 +68,11 @@ struct GroupSettings { bool log_commands; // groups.[].log_commands int index; // internal index of the group (contiguous range starting at 0) [Ind] /// Following are used/available only during config reading - config_setting_t *commands; // groups.[].commands - config_setting_t *permissions; // groups.[].permissions - config_setting_t *inherit; // groups.[].inherit + struct config_setting_t *commands; // groups.[].commands + struct config_setting_t *permissions; // groups.[].permissions + struct config_setting_t *inherit; // groups.[].inherit bool inheritance_done; // have all inheritance rules been evaluated? - config_setting_t *root; // groups.[] + struct config_setting_t *root; // groups.[] }; typedef struct GroupSettings GroupSettings; diff --git a/src/map/pet.c b/src/map/pet.c index db8d0d1f1..e2b257e10 100644 --- a/src/map/pet.c +++ b/src/map/pet.c @@ -317,7 +317,7 @@ int pet_return_egg(struct map_session_data *sd, struct pet_data *pd) tmp_item.card[1] = GetWord(pd->pet.pet_id,0); tmp_item.card[2] = GetWord(pd->pet.pet_id,1); tmp_item.card[3] = pd->pet.rename_flag; - if((flag = pc->additem(sd,&tmp_item,1,LOG_TYPE_OTHER))) { + if((flag = pc->additem(sd,&tmp_item,1,LOG_TYPE_EGG))) { clif->additem(sd,0,0,flag); map->addflooritem(&sd->bl, &tmp_item, 1, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0); } @@ -464,7 +464,7 @@ int pet_recv_petdata(int account_id,struct s_pet *p,int flag) { return 1; } if (!pet->birth_process(sd,p)) //Pet hatched. Delete egg. - pc->delitem(sd, i, 1, 0, DELITEM_NORMAL, LOG_TYPE_OTHER); + pc->delitem(sd, i, 1, 0, DELITEM_NORMAL, LOG_TYPE_EGG); } else { pet->data_init(sd,p); if(sd->pd && sd->bl.prev != NULL) { @@ -646,7 +646,7 @@ int pet_menu(struct map_session_data *sd,int menunum) return 0; } -int pet_change_name(struct map_session_data *sd,char *name) +int pet_change_name(struct map_session_data *sd, const char *name) { int i; struct pet_data *pd; @@ -664,19 +664,23 @@ int pet_change_name(struct map_session_data *sd,char *name) return intif_rename_pet(sd, name); } -int pet_change_name_ack(struct map_session_data *sd, char* name, int flag) +int pet_change_name_ack(struct map_session_data *sd, const char *name, int flag) { struct pet_data *pd = sd->pd; + char *newname = NULL; if (!pd) return 0; - normalize_name(name," ");//bugreport:3032 + newname = aStrndup(name, NAME_LENGTH-1); + normalize_name(newname, " ");//bugreport:3032 // FIXME[Haru]: This should be normalized by the inter-server (so that it's const here) - if ( !flag || !strlen(name) ) { + if (flag == 0 || strlen(newname) == 0) { clif->message(sd->fd, msg_sd(sd,280)); // You cannot use this name for your pet. clif->send_petstatus(sd); //Send status so client knows oet name change got rejected. + aFree(newname); return 0; } - memcpy(pd->pet.name, name, NAME_LENGTH); + safestrncpy(pd->pet.name, newname, NAME_LENGTH); + aFree(newname); clif->charnameack (0,&pd->bl); pd->pet.rename_flag = 1; clif->send_petdata(NULL, sd->pd, 3, sd->pd->vd.head_bottom); @@ -699,7 +703,7 @@ int pet_equipitem(struct map_session_data *sd,int index) { return 1; } - pc->delitem(sd, index, 1, 0, DELITEM_NORMAL, LOG_TYPE_OTHER); + pc->delitem(sd, index, 1, 0, DELITEM_NORMAL, LOG_TYPE_CONSUME); pd->pet.equip = nameid; status->set_viewdata(&pd->bl, pd->pet.class_); //Updates view_data. clif->send_petdata(NULL, sd->pd, 3, sd->pd->vd.head_bottom); @@ -730,7 +734,7 @@ int pet_unequipitem(struct map_session_data *sd, struct pet_data *pd) { memset(&tmp_item,0,sizeof(tmp_item)); tmp_item.nameid = nameid; tmp_item.identify = 1; - if((flag = pc->additem(sd,&tmp_item,1,LOG_TYPE_OTHER))) { + if((flag = pc->additem(sd,&tmp_item,1,LOG_TYPE_CONSUME))) { clif->additem(sd,0,0,flag); map->addflooritem(&sd->bl, &tmp_item, 1, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0); } @@ -1178,7 +1182,7 @@ int pet_skill_support_timer(int tid, int64 tick, int id, intptr_t data) { /** * Loads (or reloads) the pet database. */ -int read_petdb() +int read_petdb(void) { const char *filename[] = { DBPATH"pet_db.txt", diff --git a/src/map/pet.h b/src/map/pet.h index 2442a381f..79cbeddae 100644 --- a/src/map/pet.h +++ b/src/map/pet.h @@ -154,8 +154,8 @@ struct pet_interface { int (*food) (struct map_session_data *sd, struct pet_data *pd); int (*ai_sub_hard_lootsearch) (struct block_list *bl, va_list ap); int (*menu) (struct map_session_data *sd, int menunum); - int (*change_name) (struct map_session_data *sd, char *name); - int (*change_name_ack) (struct map_session_data *sd, char *name, int flag); + int (*change_name) (struct map_session_data *sd, const char *name); + int (*change_name_ack) (struct map_session_data *sd, const char *name, int flag); int (*equipitem) (struct map_session_data *sd, int index); int (*randomwalk) (struct pet_data *pd, int64 tick); int (*ai_sub_hard) (struct pet_data *pd, struct map_session_data *sd, int64 tick); @@ -166,7 +166,7 @@ struct pet_interface { int (*skill_bonus_timer) (int tid, int64 tick, int id, intptr_t data); int (*recovery_timer) (int tid, int64 tick, int id, intptr_t data); int (*skill_support_timer) (int tid, int64 tick, int id, intptr_t data); - int (*read_db) (); + int (*read_db) (void); }; #ifdef HERCULES_CORE diff --git a/src/map/quest.c b/src/map/quest.c index 0dbea56f8..79328ae9d 100644 --- a/src/map/quest.c +++ b/src/map/quest.c @@ -316,7 +316,7 @@ void quest_update_objective(struct map_session_data *sd, int mob_id) item.nameid = dropitem->nameid; item.identify = itemdb->isidentified2(data); item.amount = 1; - if((temp = pc->additem(sd, &item, 1, LOG_TYPE_OTHER)) != 0) { // TODO: We might want a new log type here? + if((temp = pc->additem(sd, &item, 1, LOG_TYPE_QUEST)) != 0) { // TODO: We might want a new log type here? // Failed to obtain the item clif->additem(sd, 0, 0, temp); } @@ -409,7 +409,7 @@ int quest_check(struct map_session_data *sd, int quest_id, enum quest_check_type } return 0; default: - ShowError("quest_check_quest: Unknown parameter %d",type); + ShowError("quest_check_quest: Unknown parameter %u", type); break; } @@ -425,10 +425,10 @@ int quest_check(struct map_session_data *sd, int quest_id, enum quest_check_type * @return The parsed quest entry. * @retval NULL in case of errors. */ -struct quest_db *quest_read_db_sub(config_setting_t *cs, int n, const char *source) +struct quest_db *quest_read_db_sub(struct config_setting_t *cs, int n, const char *source) { struct quest_db *entry = NULL; - config_setting_t *t = NULL; + struct config_setting_t *t = NULL; int i32 = 0, quest_id; const char *str = NULL; /* @@ -477,7 +477,7 @@ struct quest_db *quest_read_db_sub(config_setting_t *cs, int n, const char *sour for (i = 0; i < len && entry->objectives_count < MAX_QUEST_OBJECTIVES; i++) { // Note: We ensure that objectives_count < MAX_QUEST_OBJECTIVES because // quest_log (as well as the client) expect this maximum size. - config_setting_t *tt = libconfig->setting_get_elem(t, i); + struct config_setting_t *tt = libconfig->setting_get_elem(t, i); int mob_id = 0, count = 0; if (!tt) break; @@ -496,7 +496,7 @@ struct quest_db *quest_read_db_sub(config_setting_t *cs, int n, const char *sour if ((t=libconfig->setting_get_member(cs, "Drops")) && config_setting_is_list(t)) { int i, len = libconfig->setting_length(t); for (i = 0; i < len; i++) { - config_setting_t *tt = libconfig->setting_get_elem(t, i); + struct config_setting_t *tt = libconfig->setting_get_elem(t, i); int mob_id = 0, nameid = 0, rate = 0; if (!tt) break; @@ -527,13 +527,16 @@ struct quest_db *quest_read_db_sub(config_setting_t *cs, int n, const char *sour int quest_read_db(void) { char filepath[256]; - config_t quest_db_conf; - config_setting_t *qdb = NULL, *q = NULL; + struct config_t quest_db_conf; + struct config_setting_t *qdb = NULL, *q = NULL; int i = 0, count = 0; const char *filename = "quest_db.conf"; sprintf(filepath, "%s/%s", map->db_path, filename); - if (libconfig->read_file(&quest_db_conf, filepath) || !(qdb = libconfig->setting_get_member(quest_db_conf.root, "quest_db"))) { + if (!libconfig->load_file(&quest_db_conf, filepath)) + return -1; + + if ((qdb = libconfig->setting_get_member(quest_db_conf.root, "quest_db")) == NULL) { ShowError("can't read %s\n", filepath); return -1; } diff --git a/src/map/quest.h b/src/map/quest.h index 8e2cb4e23..e0768ef40 100644 --- a/src/map/quest.h +++ b/src/map/quest.h @@ -22,10 +22,11 @@ #define MAP_QUEST_H #include "common/hercules.h" -#include "common/conf.h" #include "common/mmo.h" // enum quest_state +/* Forward Declarations */ struct block_list; +struct config_setting_t; struct map_session_data; #define MAX_QUEST_DB (60355+1) // Highest quest ID + 1 @@ -77,7 +78,7 @@ struct quest_interface { int (*check) (struct map_session_data *sd, int quest_id, enum quest_check_type type); void (*clear) (void); int (*read_db) (void); - struct quest_db *(*read_db_sub) (config_setting_t *cs, int n, const char *source); + struct quest_db *(*read_db_sub) (struct config_setting_t *cs, int n, const char *source); }; #ifdef HERCULES_CORE diff --git a/src/map/script.c b/src/map/script.c index befb85304..fd653523d 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -55,6 +55,7 @@ #include "map/storage.h" #include "map/unit.h" #include "common/cbasetypes.h" +#include "common/conf.h" #include "common/memmgr.h" #include "common/md5calc.h" #include "common/mmo.h" // NEW_CARTS @@ -159,10 +160,8 @@ const char* script_op2name(int op) { RETURN_OP_NAME(C_SUB_POST); RETURN_OP_NAME(C_ADD_PRE); RETURN_OP_NAME(C_SUB_PRE); -#ifdef PCRE_SUPPORT RETURN_OP_NAME(C_RE_EQ); RETURN_OP_NAME(C_RE_NE); -#endif // PCRE_SUPPORT default: ShowDebug("script_op2name: unexpected op=%d\n", op); @@ -236,9 +235,9 @@ void script_reportsrc(struct script_state *st) { break; default: if( bl->m >= 0 ) - ShowDebug("Source (Non-NPC type %d): name %s at %s (%d,%d)\n", bl->type, status->get_name(bl), map->list[bl->m].name, bl->x, bl->y); + ShowDebug("Source (Non-NPC type %u): name %s at %s (%d,%d)\n", bl->type, clif->get_bl_name(bl), map->list[bl->m].name, bl->x, bl->y); else - ShowDebug("Source (Non-NPC type %d): name %s (invisible/not on a map)\n", bl->type, status->get_name(bl)); + ShowDebug("Source (Non-NPC type %u): name %s (invisible/not on a map)\n", bl->type, clif->get_bl_name(bl)); break; } } @@ -266,7 +265,7 @@ void script_reportdata(struct script_data* data) case C_NAME:// reference if( reference_tovariable(data) ) {// variable const char* name = reference_getname(data); - ShowDebug("Data: variable name='%s' index=%d\n", name, reference_getindex(data)); + ShowDebug("Data: variable name='%s' index=%u\n", name, reference_getindex(data)); } else if( reference_toconstant(data) ) {// constant ShowDebug("Data: constant name='%s' value=%d\n", reference_getname(data), reference_getconstant(data)); } else if( reference_toparam(data) ) {// param @@ -1379,6 +1378,10 @@ const char* parse_simpleexpr(const char *p) return pv; } + if (script->str_data[l].type == C_INT && script->str_data[l].deprecated) { + disp_warning_message("This constant is deprecated and it will be removed in a future version. Please see the script documentation and constants.conf for an alternative.\n", p); + } + p=script->skip_word(p); if( *p == '[' ) { // array(name[i] => getelementofarray(name,i) ) @@ -1442,10 +1445,8 @@ const char* script_parse_subexpr(const char* p,int limit) || (op=C_XOR, opl=4, len=1,*p=='^') // ^ || (op=C_EQ, opl=6, len=2,*p=='=' && p[1]=='=') // == || (op=C_NE, opl=6, len=2,*p=='!' && p[1]=='=') // != -#ifdef PCRE_SUPPORT || (op=C_RE_EQ, opl=6, len=2,*p=='~' && p[1]=='=') // ~= || (op=C_RE_NE, opl=6, len=2,*p=='~' && p[1]=='!') // ~! -#endif // PCRE_SUPPORT || (op=C_R_SHIFT,opl=8, len=2,*p=='>' && p[1]=='>') // >> || (op=C_GE, opl=7, len=2,*p=='>' && p[1]=='=') // >= || (op=C_GT, opl=7, len=1,*p=='>') // > @@ -1565,32 +1566,32 @@ const char* parse_curly_close(const char* p) char label[256]; int l; // Remove temporary variables - sprintf(label,"__setr $@__SW%x_VAL,0;",script->syntax.curly[pos].index); + sprintf(label, "__setr $@__SW%x_VAL,0;", (unsigned int)script->syntax.curly[pos].index); script->syntax.curly[script->syntax.curly_count++].type = TYPE_NULL; script->parse_line(label); script->syntax.curly_count--; // Go to the end pointer unconditionally - sprintf(label,"goto __SW%x_FIN;",script->syntax.curly[pos].index); + sprintf(label,"goto __SW%x_FIN;", (unsigned int)script->syntax.curly[pos].index); script->syntax.curly[script->syntax.curly_count++].type = TYPE_NULL; script->parse_line(label); script->syntax.curly_count--; // You are here labeled - sprintf(label,"__SW%x_%x",script->syntax.curly[pos].index,script->syntax.curly[pos].count); + sprintf(label,"__SW%x_%x", (unsigned int)script->syntax.curly[pos].index, (unsigned int)script->syntax.curly[pos].count); l=script->add_str(label); script->set_label(l,script->pos, p); if(script->syntax.curly[pos].flag) { //Exists default - sprintf(label,"goto __SW%x_DEF;",script->syntax.curly[pos].index); + sprintf(label,"goto __SW%x_DEF;", (unsigned int)script->syntax.curly[pos].index); script->syntax.curly[script->syntax.curly_count++].type = TYPE_NULL; script->parse_line(label); script->syntax.curly_count--; } // Label end - sprintf(label,"__SW%x_FIN",script->syntax.curly[pos].index); + sprintf(label,"__SW%x_FIN", (unsigned int)script->syntax.curly[pos].index); l=script->add_str(label); script->set_label(l,script->pos, p); linkdb_final(&script->syntax.curly[pos].case_label); // free the list of case label @@ -1620,16 +1621,16 @@ const char* parse_syntax(const char* p) int pos = script->syntax.curly_count - 1; while(pos >= 0) { if(script->syntax.curly[pos].type == TYPE_DO) { - sprintf(label,"goto __DO%x_FIN;",script->syntax.curly[pos].index); + sprintf(label, "goto __DO%x_FIN;", (unsigned int)script->syntax.curly[pos].index); break; } else if(script->syntax.curly[pos].type == TYPE_FOR) { - sprintf(label,"goto __FR%x_FIN;",script->syntax.curly[pos].index); + sprintf(label, "goto __FR%x_FIN;", (unsigned int)script->syntax.curly[pos].index); break; } else if(script->syntax.curly[pos].type == TYPE_WHILE) { - sprintf(label,"goto __WL%x_FIN;",script->syntax.curly[pos].index); + sprintf(label, "goto __WL%x_FIN;", (unsigned int)script->syntax.curly[pos].index); break; } else if(script->syntax.curly[pos].type == TYPE_SWITCH) { - sprintf(label,"goto __SW%x_FIN;",script->syntax.curly[pos].index); + sprintf(label, "goto __SW%x_FIN;", (unsigned int)script->syntax.curly[pos].index); break; } pos--; @@ -1663,13 +1664,13 @@ const char* parse_syntax(const char* p) char *np; if(script->syntax.curly[pos].count != 1) { //Jump for FALLTHRU - sprintf(label,"goto __SW%x_%xJ;",script->syntax.curly[pos].index,script->syntax.curly[pos].count); + sprintf(label,"goto __SW%x_%xJ;", (unsigned int)script->syntax.curly[pos].index, (unsigned int)script->syntax.curly[pos].count); script->syntax.curly[script->syntax.curly_count++].type = TYPE_NULL; script->parse_line(label); script->syntax.curly_count--; // You are here labeled - sprintf(label,"__SW%x_%x",script->syntax.curly[pos].index,script->syntax.curly[pos].count); + sprintf(label,"__SW%x_%x", (unsigned int)script->syntax.curly[pos].index, (unsigned int)script->syntax.curly[pos].count); l=script->add_str(label); script->set_label(l,script->pos, p); } @@ -1701,7 +1702,7 @@ const char* parse_syntax(const char* p) if(*p != ':') disp_error_message("parse_syntax: expect ':'",p); sprintf(label,"if(%d != $@__SW%x_VAL) goto __SW%x_%x;", - v,script->syntax.curly[pos].index,script->syntax.curly[pos].index,script->syntax.curly[pos].count+1); + v, (unsigned int)script->syntax.curly[pos].index, (unsigned int)script->syntax.curly[pos].index, (unsigned int)script->syntax.curly[pos].count+1); script->syntax.curly[script->syntax.curly_count++].type = TYPE_NULL; // Bad I do not parse twice p2 = script->parse_line(label); @@ -1709,7 +1710,7 @@ const char* parse_syntax(const char* p) script->syntax.curly_count--; if(script->syntax.curly[pos].count != 1) { // Label after the completion of FALLTHRU - sprintf(label,"__SW%x_%xJ",script->syntax.curly[pos].index,script->syntax.curly[pos].count); + sprintf(label, "__SW%x_%xJ", (unsigned int)script->syntax.curly[pos].index, (unsigned int)script->syntax.curly[pos].count); l=script->add_str(label); script->set_label(l,script->pos,p); } @@ -1718,7 +1719,7 @@ const char* parse_syntax(const char* p) disp_error_message("parse_syntax: dup 'case'",p); linkdb_insert(&script->syntax.curly[pos].case_label, (void*)h64BPTRSIZE(v), (void*)1); - sprintf(label,"__setr $@__SW%x_VAL,0;",script->syntax.curly[pos].index); + sprintf(label, "__setr $@__SW%x_VAL,0;", (unsigned int)script->syntax.curly[pos].index); script->syntax.curly[script->syntax.curly_count++].type = TYPE_NULL; script->parse_line(label); @@ -1732,14 +1733,14 @@ const char* parse_syntax(const char* p) int pos = script->syntax.curly_count - 1; while(pos >= 0) { if(script->syntax.curly[pos].type == TYPE_DO) { - sprintf(label,"goto __DO%x_NXT;",script->syntax.curly[pos].index); + sprintf(label, "goto __DO%x_NXT;", (unsigned int)script->syntax.curly[pos].index); script->syntax.curly[pos].flag = 1; //Flag put the link for continue break; } else if(script->syntax.curly[pos].type == TYPE_FOR) { - sprintf(label,"goto __FR%x_NXT;",script->syntax.curly[pos].index); + sprintf(label, "goto __FR%x_NXT;", (unsigned int)script->syntax.curly[pos].index); break; } else if(script->syntax.curly[pos].type == TYPE_WHILE) { - sprintf(label,"goto __WL%x_NXT;",script->syntax.curly[pos].index); + sprintf(label, "goto __WL%x_NXT;", (unsigned int)script->syntax.curly[pos].index); break; } pos--; @@ -1776,18 +1777,18 @@ const char* parse_syntax(const char* p) if(*p != ':') { disp_error_message("parse_syntax: need ':'",p); } - sprintf(label,"__SW%x_%x",script->syntax.curly[pos].index,script->syntax.curly[pos].count); + sprintf(label, "__SW%x_%x", (unsigned int)script->syntax.curly[pos].index, (unsigned int)script->syntax.curly[pos].count); l=script->add_str(label); script->set_label(l,script->pos,p); // Skip to the next link w/o condition - sprintf(label,"goto __SW%x_%x;",script->syntax.curly[pos].index,script->syntax.curly[pos].count+1); + sprintf(label, "goto __SW%x_%x;", (unsigned int)script->syntax.curly[pos].index, (unsigned int)script->syntax.curly[pos].count + 1); script->syntax.curly[script->syntax.curly_count++].type = TYPE_NULL; script->parse_line(label); script->syntax.curly_count--; // The default label - sprintf(label,"__SW%x_DEF",script->syntax.curly[pos].index); + sprintf(label, "__SW%x_DEF", (unsigned int)script->syntax.curly[pos].index); l=script->add_str(label); script->set_label(l,script->pos,p); @@ -1805,7 +1806,7 @@ const char* parse_syntax(const char* p) script->syntax.curly[script->syntax.curly_count].index = script->syntax.index++; script->syntax.curly[script->syntax.curly_count].flag = 0; // Label of the (do) form here - sprintf(label,"__DO%x_BGN",script->syntax.curly[script->syntax.curly_count].index); + sprintf(label, "__DO%x_BGN", (unsigned int)script->syntax.curly[script->syntax.curly_count].index); l=script->add_str(label); script->set_label(l,script->pos,p); script->syntax.curly_count++; @@ -1836,7 +1837,7 @@ const char* parse_syntax(const char* p) script->syntax.curly_count--; // Form the start of label decision - sprintf(label,"__FR%x_J",script->syntax.curly[pos].index); + sprintf(label, "__FR%x_J", (unsigned int)script->syntax.curly[pos].index); l=script->add_str(label); script->set_label(l,script->pos,p); @@ -1846,7 +1847,7 @@ const char* parse_syntax(const char* p) ; } else { // Skip to the end point if the condition is false - sprintf(label,"__FR%x_FIN",script->syntax.curly[pos].index); + sprintf(label, "__FR%x_FIN", (unsigned int)script->syntax.curly[pos].index); script->addl(script->add_str("__jump_zero")); script->addc(C_ARG); p=script->parse_expr(p); @@ -1859,13 +1860,13 @@ const char* parse_syntax(const char* p) p++; // Skip to the beginning of the loop - sprintf(label,"goto __FR%x_BGN;",script->syntax.curly[pos].index); + sprintf(label, "goto __FR%x_BGN;", (unsigned int)script->syntax.curly[pos].index); script->syntax.curly[script->syntax.curly_count++].type = TYPE_NULL; script->parse_line(label); script->syntax.curly_count--; // Labels to form the next loop - sprintf(label,"__FR%x_NXT",script->syntax.curly[pos].index); + sprintf(label, "__FR%x_NXT", (unsigned int)script->syntax.curly[pos].index); l=script->add_str(label); script->set_label(l,script->pos,p); @@ -1878,13 +1879,13 @@ const char* parse_syntax(const char* p) script->parse_syntax_for_flag = 0; // Skip to the determination process conditions - sprintf(label,"goto __FR%x_J;",script->syntax.curly[pos].index); + sprintf(label, "goto __FR%x_J;", (unsigned int)script->syntax.curly[pos].index); script->syntax.curly[script->syntax.curly_count++].type = TYPE_NULL; script->parse_line(label); script->syntax.curly_count--; // Loop start labeling - sprintf(label,"__FR%x_BGN",script->syntax.curly[pos].index); + sprintf(label, "__FR%x_BGN", (unsigned int)script->syntax.curly[pos].index); l=script->add_str(label); script->set_label(l,script->pos,p); return p; @@ -1925,7 +1926,7 @@ const char* parse_syntax(const char* p) ++script->syntax.curly_count; // Jump over the function code - sprintf(label, "goto __FN%x_FIN;", script->syntax.curly[script->syntax.curly_count-1].index); + sprintf(label, "goto __FN%x_FIN;", (unsigned int)script->syntax.curly[script->syntax.curly_count-1].index); script->syntax.curly[script->syntax.curly_count].type = TYPE_NULL; ++script->syntax.curly_count; script->parse_line(label); @@ -1964,7 +1965,7 @@ const char* parse_syntax(const char* p) script->syntax.curly[script->syntax.curly_count].count = 1; script->syntax.curly[script->syntax.curly_count].index = script->syntax.index++; script->syntax.curly[script->syntax.curly_count].flag = 0; - sprintf(label,"__IF%x_%x",script->syntax.curly[script->syntax.curly_count].index,script->syntax.curly[script->syntax.curly_count].count); + sprintf(label, "__IF%x_%x", (unsigned int)script->syntax.curly[script->syntax.curly_count].index, (unsigned int)script->syntax.curly[script->syntax.curly_count].count); script->syntax.curly_count++; script->addl(script->add_str("__jump_zero")); script->addc(C_ARG); @@ -1988,7 +1989,7 @@ const char* parse_syntax(const char* p) script->syntax.curly[script->syntax.curly_count].count = 1; script->syntax.curly[script->syntax.curly_count].index = script->syntax.index++; script->syntax.curly[script->syntax.curly_count].flag = 0; - sprintf(label,"$@__SW%x_VAL",script->syntax.curly[script->syntax.curly_count].index); + sprintf(label, "$@__SW%x_VAL", (unsigned int)script->syntax.curly[script->syntax.curly_count].index); script->syntax.curly_count++; script->addl(script->add_str("__setr")); script->addc(C_ARG); @@ -2016,12 +2017,12 @@ const char* parse_syntax(const char* p) script->syntax.curly[script->syntax.curly_count].index = script->syntax.index++; script->syntax.curly[script->syntax.curly_count].flag = 0; // Form the start of label decision - sprintf(label,"__WL%x_NXT",script->syntax.curly[script->syntax.curly_count].index); + sprintf(label, "__WL%x_NXT", (unsigned int)script->syntax.curly[script->syntax.curly_count].index); l=script->add_str(label); script->set_label(l,script->pos,p); // Skip to the end point if the condition is false - sprintf(label,"__WL%x_FIN",script->syntax.curly[script->syntax.curly_count].index); + sprintf(label, "__WL%x_FIN", (unsigned int)script->syntax.curly[script->syntax.curly_count].index); script->syntax.curly_count++; script->addl(script->add_str("__jump_zero")); script->addc(C_ARG); @@ -2067,13 +2068,13 @@ const char* parse_syntax_close_sub(const char* p,int* flag) script->parse_nextline(false, p); // Skip to the last location if - sprintf(label,"goto __IF%x_FIN;",script->syntax.curly[pos].index); + sprintf(label, "goto __IF%x_FIN;", (unsigned int)script->syntax.curly[pos].index); script->syntax.curly[script->syntax.curly_count++].type = TYPE_NULL; script->parse_line(label); script->syntax.curly_count--; // Put the label of the location - sprintf(label,"__IF%x_%x",script->syntax.curly[pos].index,script->syntax.curly[pos].count); + sprintf(label, "__IF%x_%x", (unsigned int)script->syntax.curly[pos].index, (unsigned int)script->syntax.curly[pos].count); l=script->add_str(label); script->set_label(l,script->pos,p); @@ -2090,7 +2091,7 @@ const char* parse_syntax_close_sub(const char* p,int* flag) if(*p != '(') { disp_error_message("need '('",p); } - sprintf(label,"__IF%x_%x",script->syntax.curly[pos].index,script->syntax.curly[pos].count); + sprintf(label, "__IF%x_%x", (unsigned int)script->syntax.curly[pos].index, (unsigned int)script->syntax.curly[pos].count); script->addl(script->add_str("__jump_zero")); script->addc(C_ARG); p=script->parse_expr(p); @@ -2111,7 +2112,7 @@ const char* parse_syntax_close_sub(const char* p,int* flag) // Close if script->syntax.curly_count--; // Put the label of the final location - sprintf(label,"__IF%x_FIN",script->syntax.curly[pos].index); + sprintf(label, "__IF%x_FIN", (unsigned int)script->syntax.curly[pos].index); l=script->add_str(label); script->set_label(l,script->pos,p); if(script->syntax.curly[pos].flag == 1) { @@ -2124,7 +2125,7 @@ const char* parse_syntax_close_sub(const char* p,int* flag) if(script->syntax.curly[pos].flag) { // (Come here continue) to form the label here - sprintf(label,"__DO%x_NXT",script->syntax.curly[pos].index); + sprintf(label, "__DO%x_NXT", (unsigned int)script->syntax.curly[pos].index); l=script->add_str(label); script->set_label(l,script->pos,p); } @@ -2144,7 +2145,7 @@ const char* parse_syntax_close_sub(const char* p,int* flag) // do-block end is a new line script->parse_nextline(false, p); - sprintf(label,"__DO%x_FIN",script->syntax.curly[pos].index); + sprintf(label, "__DO%x_FIN", (unsigned int)script->syntax.curly[pos].index); script->addl(script->add_str("__jump_zero")); script->addc(C_ARG); p=script->parse_expr(p); @@ -2153,13 +2154,13 @@ const char* parse_syntax_close_sub(const char* p,int* flag) script->addc(C_FUNC); // Skip to the starting point - sprintf(label,"goto __DO%x_BGN;",script->syntax.curly[pos].index); + sprintf(label, "goto __DO%x_BGN;", (unsigned int)script->syntax.curly[pos].index); script->syntax.curly[script->syntax.curly_count++].type = TYPE_NULL; script->parse_line(label); script->syntax.curly_count--; // Form label of the end point conditions - sprintf(label,"__DO%x_FIN",script->syntax.curly[pos].index); + sprintf(label, "__DO%x_FIN", (unsigned int)script->syntax.curly[pos].index); l=script->add_str(label); script->set_label(l,script->pos,p); p = script->skip_space(p); @@ -2175,13 +2176,13 @@ const char* parse_syntax_close_sub(const char* p,int* flag) script->parse_nextline(false, p); // Skip to the next loop - sprintf(label,"goto __FR%x_NXT;",script->syntax.curly[pos].index); + sprintf(label, "goto __FR%x_NXT;", (unsigned int)script->syntax.curly[pos].index); script->syntax.curly[script->syntax.curly_count++].type = TYPE_NULL; script->parse_line(label); script->syntax.curly_count--; // End for labeling - sprintf(label,"__FR%x_FIN",script->syntax.curly[pos].index); + sprintf(label, "__FR%x_FIN", (unsigned int)script->syntax.curly[pos].index); l=script->add_str(label); script->set_label(l,script->pos,p); script->syntax.curly_count--; @@ -2191,13 +2192,13 @@ const char* parse_syntax_close_sub(const char* p,int* flag) script->parse_nextline(false, p); // Skip to the decision while - sprintf(label,"goto __WL%x_NXT;",script->syntax.curly[pos].index); + sprintf(label, "goto __WL%x_NXT;", (unsigned int)script->syntax.curly[pos].index); script->syntax.curly[script->syntax.curly_count++].type = TYPE_NULL; script->parse_line(label); script->syntax.curly_count--; // End while labeling - sprintf(label,"__WL%x_FIN",script->syntax.curly[pos].index); + sprintf(label, "__WL%x_FIN", (unsigned int)script->syntax.curly[pos].index); l=script->add_str(label); script->set_label(l,script->pos,p); script->syntax.curly_count--; @@ -2210,7 +2211,7 @@ const char* parse_syntax_close_sub(const char* p,int* flag) script->syntax.curly_count--; // Put the label of the location - sprintf(label,"__FN%x_FIN",script->syntax.curly[pos].index); + sprintf(label, "__FN%x_FIN", (unsigned int)script->syntax.curly[pos].index); l=script->add_str(label); script->set_label(l,script->pos,p); script->syntax.curly_count--; @@ -2231,25 +2232,31 @@ bool script_get_constant(const char* name, int* value) return false; } value[0] = script->str_data[n].val; + if (script->str_data[n].deprecated) { + ShowWarning("The constant '%s' is deprecated and it will be removed in a future version. Please see the script documentation and constants.conf for an alternative.\n", name); + } return true; } /// Creates new constant or parameter with given value. -void script_set_constant(const char* name, int value, bool isparameter) { +void script_set_constant(const char *name, int value, bool is_parameter, bool is_deprecated) +{ int n = script->add_str(name); if( script->str_data[n].type == C_NOP ) {// new - script->str_data[n].type = isparameter ? C_PARAM : C_INT; + script->str_data[n].type = is_parameter ? C_PARAM : C_INT; script->str_data[n].val = value; + script->str_data[n].deprecated = is_deprecated ? 1 : 0; } else if( script->str_data[n].type == C_PARAM || script->str_data[n].type == C_INT ) {// existing parameter or constant ShowError("script_set_constant: Attempted to overwrite existing %s '%s' (old value=%d, new value=%d).\n", ( script->str_data[n].type == C_PARAM ) ? "parameter" : "constant", name, script->str_data[n].val, value); } else {// existing name - ShowError("script_set_constant: Invalid name for %s '%s' (already defined as %s).\n", isparameter ? "parameter" : "constant", name, script->op2name(script->str_data[n].type)); + ShowError("script_set_constant: Invalid name for %s '%s' (already defined as %s).\n", is_parameter ? "parameter" : "constant", name, script->op2name(script->str_data[n].type)); } } /* adds data to a existent constant in the database, inserted normally via parse */ -void script_set_constant2(const char *name, int value, bool isparameter) { +void script_set_constant2(const char *name, int value, bool is_parameter, bool is_deprecated) +{ int n = script->add_str(name); if( script->str_data[n].type == C_PARAM ) { @@ -2273,38 +2280,138 @@ void script_set_constant2(const char *name, int value, bool isparameter) { script->str_data[n].label = -1; } - script->str_data[n].type = isparameter ? C_PARAM : C_INT; + script->str_data[n].type = is_parameter ? C_PARAM : C_INT; script->str_data[n].val = value; - + script->str_data[n].deprecated = is_deprecated ? 1 : 0; } -/*========================================== - * Reading constant databases - * const.txt - *------------------------------------------*/ -void read_constdb(void) { - FILE *fp; - char line[1024],name[1024],val[1024]; - int type; - sprintf(line, "%s/const.txt", map->db_path); - fp=fopen(line, "r"); - if(fp==NULL) { - ShowError("can't read %s\n", line); - return ; +/** + * Loads the constants database from constants.conf + */ +void read_constdb(void) +{ + struct config_t constants_conf; + char filepath[256]; + struct config_setting_t *cdb; + struct config_setting_t *t; + int i = 0; + + sprintf(filepath, "%s/constants.conf", map->db_path); + + if (!libconfig->load_file(&constants_conf, filepath)) + return; + + if ((cdb = libconfig->setting_get_member(constants_conf.root, "constants_db")) == NULL) { + ShowError("can't read %s\n", filepath); + return; } - while (fgets(line, sizeof(line), fp)) { - if (line[0] == '/' && line[1] == '/') + + while ((t = libconfig->setting_get_elem(cdb, i++))) { + bool is_parameter = false; + bool is_deprecated = false; + int value = 0; + const char *name = config_setting_name(t); + const char *p = name; + + while (*p != '\0') { + if (!ISALNUM(*p) && *p != '_') + break; + p++; + } + if (*p != '\0') { + ShowWarning("read_constdb: Invalid constant name %s. Skipping.\n", name); + continue; + } + if (strcmp(name, "comment__") == 0) { + const char *comment = libconfig->setting_get_string(t); + if (comment == NULL) + continue; + if (*comment == '\0') + comment = NULL; + script->constdb_comment(comment); continue; - type = 0; - if (sscanf(line, "%1023[A-Za-z0-9_],%1023[-0-9xXA-Fa-f],%d", name, val, &type) >=2 - || sscanf(line, "%1023[A-Za-z0-9_] %1023[-0-9xXA-Fa-f] %d", name, val, &type) >=2 - ) { - script->set_constant(name, (int)strtol(val, NULL, 0), (bool)type); } + if (config_setting_is_aggregate(t)) { + int i32; + if (!libconfig->setting_lookup_int(t, "Value", &i32)) { + ShowWarning("read_constdb: Invalid entry for %s. Skipping.\n", name); + continue; + } + value = i32; + if (libconfig->setting_lookup_bool(t, "Parameter", &i32)) { + if (i32 != 0) + is_parameter = true; + } + if (libconfig->setting_lookup_bool(t, "Deprecated", &i32)) { + if (i32 != 0) + is_deprecated = true; + } + } else { + value = libconfig->setting_get_int(t); + } + if (is_parameter) + ShowWarning("read_constdb: Defining parameters in the constants configuration is deprecated and will no longer be possible in a future version. Parameters should be defined in source. (parameter = '%s')\n", name); + script->set_constant(name, value, is_parameter, is_deprecated); } - fclose(fp); + script->constdb_comment(NULL); + libconfig->destroy(&constants_conf); } +/** + * Sets the current constdb comment. + * + * This function does nothing (used by plugins only) + * + * @param comment The comment to set (NULL to unset) + */ +void script_constdb_comment(const char *comment) +{ + (void)comment; +} + +void script_load_parameters(void) +{ + int i = 0; + struct { + char *name; + enum status_point_types type; + } parameters[] = { + {"BaseExp", SP_BASEEXP}, + {"JobExp", SP_JOBEXP}, + {"Karma", SP_KARMA}, + {"Manner", SP_MANNER}, + {"Hp", SP_HP}, + {"MaxHp", SP_MAXHP}, + {"Sp", SP_SP}, + {"MaxSp", SP_MAXSP}, + {"StatusPoint", SP_STATUSPOINT}, + {"BaseLevel", SP_BASELEVEL}, + {"SkillPoint", SP_SKILLPOINT}, + {"Class", SP_CLASS}, + {"Zeny", SP_ZENY}, + {"Sex", SP_SEX}, + {"NextBaseExp", SP_NEXTBASEEXP}, + {"NextJobExp", SP_NEXTJOBEXP}, + {"Weight", SP_WEIGHT}, + {"MaxWeight", SP_MAXWEIGHT}, + {"JobLevel", SP_JOBLEVEL}, + {"Upper", SP_UPPER}, + {"BaseJob", SP_BASEJOB}, + {"BaseClass", SP_BASECLASS}, + {"killerrid", SP_KILLERRID}, + {"killedrid", SP_KILLEDRID}, + {"SlotChange", SP_SLOTCHANGE}, + {"CharRename", SP_CHARRENAME}, + {"ModExp", SP_MOD_EXP}, + {"ModDrop", SP_MOD_DROP}, + {"ModDeath", SP_MOD_DEATH}, + }; + + script->constdb_comment("Parameters"); + for (i=0; i < ARRAYLENGTH(parameters); ++i) + script->set_constant(parameters[i].name, parameters[i].type, true, false); + script->constdb_comment(NULL); +} // Standard UNIX tab size is 8 #define TAB_SIZE 8 #define update_tabstop(tabstop,chars) \ @@ -3553,7 +3660,7 @@ void script_free_state(struct script_state* st) { struct map_session_data *sd = st->rid ? map->id2sd(st->rid) : NULL; if(st->bk_st) {// backup was not restored - ShowDebug("script_free_state: Previous script state lost (rid=%d, oid=%d, state=%d, bk_npcid=%d).\n", st->bk_st->rid, st->bk_st->oid, st->bk_st->state, st->bk_npcid); + ShowDebug("script_free_state: Previous script state lost (rid=%d, oid=%d, state=%u, bk_npcid=%d).\n", st->bk_st->rid, st->bk_st->oid, st->bk_st->state, st->bk_npcid); } if(sd && sd->st == st) { //Current script is aborted. @@ -3699,7 +3806,6 @@ void op_2str(struct script_state* st, int op, const char* s1, const char* s2) case C_GE: a = (strcmp(s1,s2) >= 0); break; case C_LT: a = (strcmp(s1,s2) < 0); break; case C_LE: a = (strcmp(s1,s2) <= 0); break; -#ifdef PCRE_SUPPORT case C_RE_EQ: case C_RE_NE: { @@ -3764,7 +3870,6 @@ void op_2str(struct script_state* st, int op, const char* s1, const char* s2) libpcre->free(extra_regex); } break; -#endif // PCRE_SUPPORT case C_ADD: { char* buf = (char *)aMalloc((strlen(s1)+strlen(s2)+1)*sizeof(char)); @@ -3789,7 +3894,7 @@ void op_2str(struct script_state* st, int op, const char* s1, const char* s2) void op_2num(struct script_state* st, int op, int i1, int i2) { int ret; - double ret_double; + int64 ret64; switch( op ) { case C_AND: ret = i1 & i2; break; @@ -3821,25 +3926,21 @@ void op_2num(struct script_state* st, int op, int i1, int i2) ret = i1 % i2; break; default: - switch( op ) - {// operators that can overflow/underflow - case C_ADD: ret = i1 + i2; ret_double = (double)i1 + (double)i2; break; - case C_SUB: ret = i1 - i2; ret_double = (double)i1 - (double)i2; break; - case C_MUL: ret = i1 * i2; ret_double = (double)i1 * (double)i2; break; + switch (op) { // operators that can overflow/underflow + case C_ADD: ret = i1 + i2; ret64 = (int64)i1 + i2; break; + case C_SUB: ret = i1 - i2; ret64 = (int64)i1 - i2; break; + case C_MUL: ret = i1 * i2; ret64 = (int64)i1 * i2; break; default: ShowError("script:op_2num: unexpected number operator %s i1=%d i2=%d\n", script->op2name(op), i1, i2); script->reportsrc(st); script_pushnil(st); return; } - if( ret_double < (double)INT_MIN ) - { + if (ret64 < INT_MIN) { ShowWarning("script:op_2num: underflow detected op=%s i1=%d i2=%d\n", script->op2name(op), i1, i2); script->reportsrc(st); ret = INT_MIN; - } - else if( ret_double > (double)INT_MAX ) - { + } else if (ret64 > INT_MAX) { ShowWarning("script:op_2num: overflow detected op=%s i1=%d i2=%d\n", script->op2name(op), i1, i2); script->reportsrc(st); ret = INT_MAX; @@ -4206,7 +4307,7 @@ void script_detach_state(struct script_state* st, bool dequeue_event) { npc->event_dequeue(sd); } } else if(st->bk_st) { // rid was set to 0, before detaching the script state - ShowError("script_detach_state: Found previous script state without attached player (rid=%d, oid=%d, state=%d, bk_npcid=%d)\n", st->bk_st->rid, st->bk_st->oid, st->bk_st->state, st->bk_npcid); + ShowError("script_detach_state: Found previous script state without attached player (rid=%d, oid=%d, state=%u, bk_npcid=%d)\n", st->bk_st->rid, st->bk_st->oid, st->bk_st->state, st->bk_npcid); script->reportsrc(st->bk_st); script->free_state(st->bk_st); @@ -4226,7 +4327,7 @@ void script_attach_state(struct script_state* st) { { if(st->bk_st) {// there is already a backup - ShowDebug("script_free_state: Previous script state lost (rid=%d, oid=%d, state=%d, bk_npcid=%d).\n", st->bk_st->rid, st->bk_st->oid, st->bk_st->state, st->bk_npcid); + ShowDebug("script_free_state: Previous script state lost (rid=%d, oid=%d, state=%u, bk_npcid=%d).\n", st->bk_st->rid, st->bk_st->oid, st->bk_st->state, st->bk_npcid); } st->bk_st = sd->st; st->bk_npcid = sd->npc_id; @@ -4361,10 +4462,8 @@ void run_script_main(struct script_state *st) { case C_LOR: case C_R_SHIFT: case C_L_SHIFT: -#ifdef PCRE_SUPPORT case C_RE_EQ: case C_RE_NE: -#endif // PCRE_SUPPORT script->op_2(st, c); break; @@ -4377,7 +4476,7 @@ void run_script_main(struct script_state *st) { break; default: - ShowError("unknown command : %d @ %d\n",c,st->pos); + ShowError("unknown command : %u @ %d\n", c, st->pos); st->state=END; break; } @@ -4750,9 +4849,9 @@ uint8 script_add_language(const char *name) { * Goes thru db/translations.conf file **/ void script_load_translations(void) { - config_t translations_conf; + struct config_t translations_conf; const char *config_filename = "db/translations.conf"; // FIXME hardcoded name - config_setting_t *translations = NULL; + struct config_setting_t *translations = NULL; int i, size; uint32 total = 0; uint8 lang_id = 0, k; @@ -4772,12 +4871,10 @@ void script_load_translations(void) { script->add_language("English");/* 0 is default, which is whatever is in the npc files hardcoded (in our case, English) */ - if (libconfig->read_file(&translations_conf, config_filename)) { - ShowError("load_translations: can't read '%s'\n", config_filename); + if (!libconfig->load_file(&translations_conf, config_filename)) return; - } - if( !(translations = libconfig->lookup(&translations_conf, "translations")) ) { + if ((translations = libconfig->lookup(&translations_conf, "translations")) == NULL) { ShowError("load_translations: invalid format on '%s'\n",config_filename); return; } @@ -4951,7 +5048,7 @@ void script_load_translation(const char *file, uint8 lang_id, uint32 *total) { RECREATE(st->buf, char, st->len + inner_len); WBUFB(st->buf, st->len) = lang_id; - safestrncpy((char*)WBUFP(st->buf, st->len + 1), msgstr.ptr, msgstr_len + 1); + safestrncpy(WBUFP(st->buf, st->len + 1), msgstr.ptr, msgstr_len + 1); st->translations++; st->len += inner_len; @@ -5089,6 +5186,7 @@ void do_init_script(bool minimal) { script->parse_builtin(); script->read_constdb(); + script->load_parameters(); script->hardcoded_constants(); if (minimal) @@ -6599,7 +6697,7 @@ BUILDIN(getarraysize) return true; } int script_array_index_cmp(const void *a, const void *b) { - return ( *(unsigned int*)a - *(unsigned int*)b ); + return ( *(const unsigned int*)a - *(const unsigned int*)b ); } /// Deletes count or all the elements in an array, from the starting index. @@ -6950,7 +7048,7 @@ BUILDIN(checkweight) // item id id = itemdb->exists(script_getnum(st, i)); } else { - ShowError("buildin_checkweight: invalid type for argument '%d'.\n", i); + ShowError("buildin_checkweight: invalid type for argument '%u'.\n", i); script_pushint(st,0); return false; } @@ -7253,7 +7351,7 @@ BUILDIN(getitem2) int get_count, i; memset(&item_tmp,0,sizeof(item_tmp)); if (item_data == NULL) - return -1; + return false; if(item_data->type==IT_WEAPON || item_data->type==IT_ARMOR) { ref = cap_value(ref, 0, MAX_REFINE); } @@ -9648,20 +9746,18 @@ BUILDIN(makepet) BUILDIN(getexp) { int base=0,job=0; - double bonus; struct map_session_data *sd = script->rid2sd(st); if (sd == NULL) return true; - base=script_getnum(st,2); - job =script_getnum(st,3); - if(base<0 || job<0) + base = script_getnum(st,2); + job = script_getnum(st,3); + if (base < 0 || job < 0) return true; // bonus for npc-given exp - bonus = battle_config.quest_exp_rate / 100.; - base = (int) cap_value(base * bonus, 0, INT_MAX); - job = (int) cap_value(job * bonus, 0, INT_MAX); + base = cap_value(apply_percentrate(base, battle_config.quest_exp_rate, 100), 0, INT_MAX); + job = cap_value(apply_percentrate(job, battle_config.quest_exp_rate, 100), 0, INT_MAX); pc->gainexp(sd, &sd->bl, base, job, true); @@ -9743,7 +9839,7 @@ BUILDIN(monster) size = script_getnum(st, 9); if (size > 3) { - ShowWarning("buildin_monster: Attempted to spawn non-existing size %d for monster class %d\n", size, class_); + ShowWarning("buildin_monster: Attempted to spawn non-existing size %u for monster class %d\n", size, class_); return false; } } @@ -9752,7 +9848,7 @@ BUILDIN(monster) { ai = script_getnum(st, 10); if (ai > AI_FLORA) { - ShowWarning("buildin_monster: Attempted to spawn non-existing ai %d for monster class %d\n", ai, class_); + ShowWarning("buildin_monster: Attempted to spawn non-existing ai %u for monster class %d\n", ai, class_); return false; } } @@ -9848,7 +9944,7 @@ BUILDIN(areamonster) { if (script_hasdata(st, 11)) { size = script_getnum(st, 11); if (size > 3) { - ShowWarning("buildin_monster: Attempted to spawn non-existing size %d for monster class %d\n", size, class_); + ShowWarning("buildin_monster: Attempted to spawn non-existing size %u for monster class %d\n", size, class_); return false; } } @@ -9856,7 +9952,7 @@ BUILDIN(areamonster) { if (script_hasdata(st, 12)) { ai = script_getnum(st, 12); if (ai > AI_FLORA) { - ShowWarning("buildin_monster: Attempted to spawn non-existing ai %d for monster class %d\n", ai, class_); + ShowWarning("buildin_monster: Attempted to spawn non-existing ai %u for monster class %d\n", ai, class_); return false; } } @@ -10001,7 +10097,8 @@ BUILDIN(killmonsterall) { *------------------------------------------*/ BUILDIN(clone) { struct map_session_data *sd, *msd = NULL; - int char_id,master_id=0,x,y, mode = 0, flag = 0, m; + int char_id, master_id = 0, x, y, flag = 0, m; + uint32 mode = 0; unsigned int duration = 0; const char *mapname, *event; @@ -10014,8 +10111,8 @@ BUILDIN(clone) { if( script_hasdata(st,7) ) master_id=script_getnum(st,7); - if( script_hasdata(st,8) ) - mode=script_getnum(st,8); + if (script_hasdata(st,8)) + mode = script_getnum(st,8); if( script_hasdata(st,9) ) flag=script_getnum(st,9); @@ -10957,7 +11054,7 @@ BUILDIN(getstatus) case 4: script_pushint(st, sd->sc.data[id]->val4); break; case 5: { - struct TimerData* td = (struct TimerData*)timer->get(sd->sc.data[id]->timer); + const struct TimerData* td = (const struct TimerData*)timer->get(sd->sc.data[id]->timer); if( td ) { // return the amount of time remaining @@ -11684,7 +11781,7 @@ BUILDIN(getmapflag) case MF_RESET: script_pushint(st,map->list[m].flag.reset); break; case MF_NOTOMB: script_pushint(st,map->list[m].flag.notomb); break; case MF_NOCASHSHOP: script_pushint(st,map->list[m].flag.nocashshop); break; - case MF_NOVIEWID: script_pushint(st,map->list[m].flag.noviewid); break; + case MF_NOVIEWID: script_pushint(st,map->list[m].flag.noviewid); break; } } @@ -11808,7 +11905,7 @@ BUILDIN(setmapflag) { case MF_RESET: map->list[m].flag.reset = 1; break; case MF_NOTOMB: map->list[m].flag.notomb = 1; break; case MF_NOCASHSHOP: map->list[m].flag.nocashshop = 1; break; - case MF_NOVIEWID: map->list[m].flag.noviewid = (val <= 0) ? 0 : val; break; + case MF_NOVIEWID: map->list[m].flag.noviewid = (val <= 0) ? EQP_NONE : val; break; } } @@ -11895,7 +11992,7 @@ BUILDIN(removemapflag) { case MF_RESET: map->list[m].flag.reset = 0; break; case MF_NOTOMB: map->list[m].flag.notomb = 0; break; case MF_NOCASHSHOP: map->list[m].flag.nocashshop = 0; break; - case MF_NOVIEWID: map->list[m].flag.noviewid = 0; break; + case MF_NOVIEWID: map->list[m].flag.noviewid = EQP_NONE; break; } } @@ -12055,7 +12152,7 @@ BUILDIN(emotion) { clif->emotion(&sd->bl,type); } else if( script_hasdata(st,4) ) { struct npc_data *nd = npc->name2id(script_getstr(st,4)); - if (nd == NULL) + if (nd != NULL) clif->emotion(&nd->bl,type); } else { clif->emotion(map->id2bl(st->oid),type); @@ -12169,7 +12266,7 @@ BUILDIN(flagemblem) if( nd == NULL ) { ShowError("script:flagemblem: npc %d not found\n", st->oid); } else if( nd->subtype != SCRIPT ) { - ShowError("script:flagemblem: unexpected subtype %d for npc %d '%s'\n", nd->subtype, st->oid, nd->exname); + ShowError("script:flagemblem: unexpected subtype %u for npc %d '%s'\n", nd->subtype, st->oid, nd->exname); } else { bool changed = ( nd->u.scr.guild_id != g_id )?true:false; nd->u.scr.guild_id = g_id; @@ -13534,25 +13631,27 @@ BUILDIN(npcskilleffect) { * Special effects [Valaris] *------------------------------------------*/ BUILDIN(specialeffect) { - struct block_list *bl=map->id2bl(st->oid); + struct block_list *bl = NULL; int type = script_getnum(st,2); enum send_target target = script_hasdata(st,3) ? (send_target)script_getnum(st,3) : AREA; - if(bl==NULL) - return true; - if (script_hasdata(st,4)) { struct npc_data *nd = npc->name2id(script_getstr(st,4)); if (nd != NULL) - clif->specialeffect(&nd->bl, type, target); + bl = &nd->bl; } else { - if (target == SELF) { - struct map_session_data *sd = script->rid2sd(st); - if (sd != NULL) - clif->specialeffect_single(bl,type,sd->fd); - } else { - clif->specialeffect(bl, type, target); - } + bl = map->id2bl(st->oid); + } + + if (bl == NULL) + return true; + + if (target == SELF) { + struct map_session_data *sd = script->rid2sd(st); + if (sd != NULL) + clif->specialeffect_single(bl, type, sd->fd); + } else { + clif->specialeffect(bl, type, target); } return true; @@ -13862,7 +13961,7 @@ BUILDIN(movenpc) y = script_getnum(st,4); if ((nd = npc->name2id(npc_name)) == NULL) - return -1; + return false; if (script_hasdata(st,5)) nd->dir = script_getnum(st,5) % 8; @@ -15886,7 +15985,7 @@ int buildin_query_sql_sub(struct script_state* st, Sql* handle) } } if( i == max_rows && max_rows < SQL->NumRows(handle) ) { - ShowWarning("script:query_sql: Only %d/%u rows have been stored.\n", max_rows, (unsigned int)SQL->NumRows(handle)); + ShowWarning("script:query_sql: Only %u/%u rows have been stored.\n", max_rows, (unsigned int)SQL->NumRows(handle)); script->reportsrc(st); } @@ -16294,7 +16393,7 @@ BUILDIN(getmonsterinfo) script_pushconststr(st,"null"); else script_pushint(st,-1); - return -1; + return false; } monster = mob->db(mob_id); switch ( script_getnum(st,3) ) { @@ -16676,7 +16775,7 @@ BUILDIN(unitattack) { BL_UCAST(BL_PET, unit_bl)->target_id = target_bl->id; break; default: - ShowError("script:unitattack: unsupported source unit type %d\n", unit_bl->type); + ShowError("script:unitattack: unsupported source unit type %u\n", unit_bl->type); script_pushint(st, 0); return false; } @@ -16720,7 +16819,7 @@ BUILDIN(unittalk) { if( bl != NULL ) { struct StringBuf sbuf; StrBuf->Init(&sbuf); - StrBuf->Printf(&sbuf, "%s : %s", status->get_name(bl), message); + StrBuf->Printf(&sbuf, "%s : %s", clif->get_bl_name(bl), message); clif->disp_overhead(bl, StrBuf->Value(&sbuf)); StrBuf->Destroy(&sbuf); } @@ -17034,7 +17133,7 @@ BUILDIN(checkcell) { cell_chk type = (cell_chk)script_getnum(st,5); if ( m == -1 ) { - ShowWarning("checkcell: Attempted to run on unexsitent map '%s', type %d, x/y %d,%d\n",script_getstr(st,2),type,x,y); + ShowWarning("checkcell: Attempted to run on unexsitent map '%s', type %u, x/y %d,%d\n", script_getstr(st,2), type, x, y); return true; } @@ -17060,7 +17159,7 @@ BUILDIN(setcell) { int x,y; if ( m == -1 ) { - ShowWarning("setcell: Attempted to run on unexistent map '%s', type %d, x1/y1 - %d,%d | x2/y2 - %d,%d\n",script_getstr(st, 2),type,x1,y1,x2,y2); + ShowWarning("setcell: Attempted to run on unexistent map '%s', type %u, x1/y1 - %d,%d | x2/y2 - %d,%d\n", script_getstr(st, 2), type, x1, y1, x2, y2); return true; } @@ -18450,7 +18549,7 @@ BUILDIN(setcashmount) if (sd->sc.data[SC_ALL_RIDING]) status_change_end(&sd->bl, SC_ALL_RIDING, INVALID_TIMER); else - sc_start(NULL,&sd->bl, SC_ALL_RIDING, 100, 0, -1); + sc_start(NULL, &sd->bl, SC_ALL_RIDING, 100, 25, INFINITE_DURATION); script_pushint(st,1);//in both cases, return 1. } return true; @@ -19590,7 +19689,7 @@ BUILDIN(countbound) } script_pushint(st,j); - return 0; + return true; } /*========================================== @@ -19646,7 +19745,7 @@ BUILDIN(checkbound) /* returns 0 when successful, 1 otherwise */ BUILDIN(bg_match_over) { bool canceled = script_hasdata(st,3) ? true : false; - struct bg_arena *arena = bg->name2arena((char*)script_getstr(st, 2)); + struct bg_arena *arena = bg->name2arena((const char*)script_getstr(st, 2)); if( arena ) { bg->match_over(arena,canceled); @@ -20067,7 +20166,6 @@ BUILDIN(_) { } // declarations that were supposed to be exported from npc_chat.c -#ifdef PCRE_SUPPORT BUILDIN(defpattern); BUILDIN(activatepset); BUILDIN(deactivatepset); @@ -20080,7 +20178,6 @@ BUILDIN(pcre_match) { script->op_2str(st, C_RE_EQ, input, regex); return true; } -#endif /** * Adds a built-in script function. @@ -20497,13 +20594,11 @@ void script_parse_builtin(void) { BUILDIN_DEF(getrefine,""), // returns the refined number of the current item, or an item with index specified [celest] BUILDIN_DEF(night,""), // sets the server to night time BUILDIN_DEF(day,""), // sets the server to day time -#ifdef PCRE_SUPPORT BUILDIN_DEF(defpattern,"iss"), // Define pattern to listen for [MouseJstr] BUILDIN_DEF(activatepset,"i"), // Activate a pattern set [MouseJstr] BUILDIN_DEF(deactivatepset,"i"), // Deactive a pattern set [MouseJstr] BUILDIN_DEF(deletepset,"i"), // Delete a pattern set [MouseJstr] BUILDIN_DEF(pcre_match,"ss"), -#endif BUILDIN_DEF(dispbottom,"s?"), //added from jA [Lupus] BUILDIN_DEF(getusersname,""), BUILDIN_DEF(recovery,""), @@ -20778,119 +20873,164 @@ void script_label_add(int key, int pos) { /** * Sets source-end constants for scripts to play with **/ -void script_hardcoded_constants(void) { - /* server defines */ - script->set_constant("PACKETVER",PACKETVER,false); - script->set_constant("MAX_LEVEL",MAX_LEVEL,false); - script->set_constant("MAX_STORAGE",MAX_STORAGE,false); - script->set_constant("MAX_GUILD_STORAGE",MAX_GUILD_STORAGE,false); - script->set_constant("MAX_CART",MAX_INVENTORY,false); - script->set_constant("MAX_INVENTORY",MAX_INVENTORY,false); - script->set_constant("MAX_ZENY",MAX_ZENY,false); - script->set_constant("MAX_BG_MEMBERS",MAX_BG_MEMBERS,false); - script->set_constant("MAX_CHAT_USERS",MAX_CHAT_USERS,false); - script->set_constant("MAX_REFINE",MAX_REFINE,false); - - /* status options */ - script->set_constant("Option_Nothing",OPTION_NOTHING,false); - script->set_constant("Option_Sight",OPTION_SIGHT,false); - script->set_constant("Option_Hide",OPTION_HIDE,false); - script->set_constant("Option_Cloak",OPTION_CLOAK,false); - script->set_constant("Option_Falcon",OPTION_FALCON,false); - script->set_constant("Option_Riding",OPTION_RIDING,false); - script->set_constant("Option_Invisible",OPTION_INVISIBLE,false); - script->set_constant("Option_Orcish",OPTION_ORCISH,false); - script->set_constant("Option_Wedding",OPTION_WEDDING,false); - script->set_constant("Option_Chasewalk",OPTION_CHASEWALK,false); - script->set_constant("Option_Flying",OPTION_FLYING,false); - script->set_constant("Option_Xmas",OPTION_XMAS,false); - script->set_constant("Option_Transform",OPTION_TRANSFORM,false); - script->set_constant("Option_Summer",OPTION_SUMMER,false); - script->set_constant("Option_Dragon1",OPTION_DRAGON1,false); - script->set_constant("Option_Wug",OPTION_WUG,false); - script->set_constant("Option_Wugrider",OPTION_WUGRIDER,false); - script->set_constant("Option_Madogear",OPTION_MADOGEAR,false); - script->set_constant("Option_Dragon2",OPTION_DRAGON2,false); - script->set_constant("Option_Dragon3",OPTION_DRAGON3,false); - script->set_constant("Option_Dragon4",OPTION_DRAGON4,false); - script->set_constant("Option_Dragon5",OPTION_DRAGON5,false); - script->set_constant("Option_Hanbok",OPTION_HANBOK,false); - script->set_constant("Option_Oktoberfest",OPTION_OKTOBERFEST,false); - - /* status option compounds */ - script->set_constant("Option_Dragon",OPTION_DRAGON,false); - script->set_constant("Option_Costume",OPTION_COSTUME,false); - - /* send_target */ - script->set_constant("ALL_CLIENT",ALL_CLIENT,false); - script->set_constant("ALL_SAMEMAP",ALL_SAMEMAP,false); - script->set_constant("AREA",AREA,false); - script->set_constant("AREA_WOS",AREA_WOS,false); - script->set_constant("AREA_WOC",AREA_WOC,false); - script->set_constant("AREA_WOSC",AREA_WOSC,false); - script->set_constant("AREA_CHAT_WOC",AREA_CHAT_WOC,false); - script->set_constant("CHAT",CHAT,false); - script->set_constant("CHAT_WOS",CHAT_WOS,false); - script->set_constant("PARTY",PARTY,false); - script->set_constant("PARTY_WOS",PARTY_WOS,false); - script->set_constant("PARTY_SAMEMAP",PARTY_SAMEMAP,false); - script->set_constant("PARTY_SAMEMAP_WOS",PARTY_SAMEMAP_WOS,false); - script->set_constant("PARTY_AREA",PARTY_AREA,false); - script->set_constant("PARTY_AREA_WOS",PARTY_AREA_WOS,false); - script->set_constant("GUILD",GUILD,false); - script->set_constant("GUILD_WOS",GUILD_WOS,false); - script->set_constant("GUILD_SAMEMAP",GUILD_SAMEMAP,false); - script->set_constant("GUILD_SAMEMAP_WOS",GUILD_SAMEMAP_WOS,false); - script->set_constant("GUILD_AREA",GUILD_AREA,false); - script->set_constant("GUILD_AREA_WOS",GUILD_AREA_WOS,false); - script->set_constant("GUILD_NOBG",GUILD_NOBG,false); - script->set_constant("DUEL",DUEL,false); - script->set_constant("DUEL_WOS",DUEL_WOS,false); - script->set_constant("SELF",SELF,false); - script->set_constant("BG",BG,false); - script->set_constant("BG_WOS",BG_WOS,false); - script->set_constant("BG_SAMEMAP",BG_SAMEMAP,false); - script->set_constant("BG_SAMEMAP_WOS",BG_SAMEMAP_WOS,false); - script->set_constant("BG_AREA",BG_AREA,false); - script->set_constant("BG_AREA_WOS",BG_AREA_WOS,false); - script->set_constant("BG_QUEUE",BG_QUEUE,false); - - /* Renewal */ +void script_hardcoded_constants(void) +{ + script->constdb_comment("Boolean"); + script->set_constant("true", 1, false, false); + script->set_constant("false", 0, false, false); + + script->constdb_comment("Server defines"); + script->set_constant("PACKETVER",PACKETVER,false, false); + script->set_constant("MAX_LEVEL",MAX_LEVEL,false, false); + script->set_constant("MAX_STORAGE",MAX_STORAGE,false, false); + script->set_constant("MAX_GUILD_STORAGE",MAX_GUILD_STORAGE,false, false); + script->set_constant("MAX_CART",MAX_INVENTORY,false, false); + script->set_constant("MAX_INVENTORY",MAX_INVENTORY,false, false); + script->set_constant("MAX_ZENY",MAX_ZENY,false, false); + script->set_constant("MAX_BG_MEMBERS",MAX_BG_MEMBERS,false, false); + script->set_constant("MAX_CHAT_USERS",MAX_CHAT_USERS,false, false); + script->set_constant("MAX_REFINE",MAX_REFINE,false, false); + + script->constdb_comment("status options"); + script->set_constant("Option_Nothing",OPTION_NOTHING,false, false); + script->set_constant("Option_Sight",OPTION_SIGHT,false, false); + script->set_constant("Option_Hide",OPTION_HIDE,false, false); + script->set_constant("Option_Cloak",OPTION_CLOAK,false, false); + script->set_constant("Option_Falcon",OPTION_FALCON,false, false); + script->set_constant("Option_Riding",OPTION_RIDING,false, false); + script->set_constant("Option_Invisible",OPTION_INVISIBLE,false, false); + script->set_constant("Option_Orcish",OPTION_ORCISH,false, false); + script->set_constant("Option_Wedding",OPTION_WEDDING,false, false); + script->set_constant("Option_Chasewalk",OPTION_CHASEWALK,false, false); + script->set_constant("Option_Flying",OPTION_FLYING,false, false); + script->set_constant("Option_Xmas",OPTION_XMAS,false, false); + script->set_constant("Option_Transform",OPTION_TRANSFORM,false, false); + script->set_constant("Option_Summer",OPTION_SUMMER,false, false); + script->set_constant("Option_Dragon1",OPTION_DRAGON1,false, false); + script->set_constant("Option_Wug",OPTION_WUG,false, false); + script->set_constant("Option_Wugrider",OPTION_WUGRIDER,false, false); + script->set_constant("Option_Madogear",OPTION_MADOGEAR,false, false); + script->set_constant("Option_Dragon2",OPTION_DRAGON2,false, false); + script->set_constant("Option_Dragon3",OPTION_DRAGON3,false, false); + script->set_constant("Option_Dragon4",OPTION_DRAGON4,false, false); + script->set_constant("Option_Dragon5",OPTION_DRAGON5,false, false); + script->set_constant("Option_Hanbok",OPTION_HANBOK,false, false); + script->set_constant("Option_Oktoberfest",OPTION_OKTOBERFEST,false, false); + + script->constdb_comment("status option compounds"); + script->set_constant("Option_Dragon",OPTION_DRAGON,false, false); + script->set_constant("Option_Costume",OPTION_COSTUME,false, false); + + script->constdb_comment("send_target"); + script->set_constant("ALL_CLIENT",ALL_CLIENT,false, false); + script->set_constant("ALL_SAMEMAP",ALL_SAMEMAP,false, false); + script->set_constant("AREA",AREA,false, false); + script->set_constant("AREA_WOS",AREA_WOS,false, false); + script->set_constant("AREA_WOC",AREA_WOC,false, false); + script->set_constant("AREA_WOSC",AREA_WOSC,false, false); + script->set_constant("AREA_CHAT_WOC",AREA_CHAT_WOC,false, false); + script->set_constant("CHAT",CHAT,false, false); + script->set_constant("CHAT_WOS",CHAT_WOS,false, false); + script->set_constant("PARTY",PARTY,false, false); + script->set_constant("PARTY_WOS",PARTY_WOS,false, false); + script->set_constant("PARTY_SAMEMAP",PARTY_SAMEMAP,false, false); + script->set_constant("PARTY_SAMEMAP_WOS",PARTY_SAMEMAP_WOS,false, false); + script->set_constant("PARTY_AREA",PARTY_AREA,false, false); + script->set_constant("PARTY_AREA_WOS",PARTY_AREA_WOS,false, false); + script->set_constant("GUILD",GUILD,false, false); + script->set_constant("GUILD_WOS",GUILD_WOS,false, false); + script->set_constant("GUILD_SAMEMAP",GUILD_SAMEMAP,false, false); + script->set_constant("GUILD_SAMEMAP_WOS",GUILD_SAMEMAP_WOS,false, false); + script->set_constant("GUILD_AREA",GUILD_AREA,false, false); + script->set_constant("GUILD_AREA_WOS",GUILD_AREA_WOS,false, false); + script->set_constant("GUILD_NOBG",GUILD_NOBG,false, false); + script->set_constant("DUEL",DUEL,false, false); + script->set_constant("DUEL_WOS",DUEL_WOS,false, false); + script->set_constant("SELF",SELF,false, false); + script->set_constant("BG",BG,false, false); + script->set_constant("BG_WOS",BG_WOS,false, false); + script->set_constant("BG_SAMEMAP",BG_SAMEMAP,false, false); + script->set_constant("BG_SAMEMAP_WOS",BG_SAMEMAP_WOS,false, false); + script->set_constant("BG_AREA",BG_AREA,false, false); + script->set_constant("BG_AREA_WOS",BG_AREA_WOS,false, false); + script->set_constant("BG_QUEUE",BG_QUEUE,false, false); + + script->constdb_comment("LOOK_ constants, use in setlook/changelook script commands"); + script->set_constant("LOOK_BASE", LOOK_BASE, false, false); + script->set_constant("LOOK_HAIR", LOOK_HAIR, false, false); + script->set_constant("LOOK_WEAPON", LOOK_WEAPON, false, false); + script->set_constant("LOOK_HEAD_BOTTOM", LOOK_HEAD_BOTTOM, false, false); + script->set_constant("LOOK_HEAD_TOP", LOOK_HEAD_TOP, false, false); + script->set_constant("LOOK_HEAD_MID", LOOK_HEAD_MID, false, false); + script->set_constant("LOOK_HAIR_COLOR", LOOK_HAIR_COLOR, false, false); + script->set_constant("LOOK_CLOTHES_COLOR", LOOK_CLOTHES_COLOR, false, false); + script->set_constant("LOOK_SHIELD", LOOK_SHIELD, false, false); + script->set_constant("LOOK_SHOES", LOOK_SHOES, false, false); + script->set_constant("LOOK_BODY", LOOK_BODY, false, false); + script->set_constant("LOOK_FLOOR", LOOK_FLOOR, false, false); + script->set_constant("LOOK_ROBE", LOOK_ROBE, false, false); + script->set_constant("LOOK_BODY2", LOOK_BODY2, false, false); + + script->constdb_comment("Equip Position in Bits, use with *getiteminfo type 5, or @inventorylist_equip"); + script->set_constant("EQP_HEAD_LOW", EQP_HEAD_LOW, false, false); + script->set_constant("EQP_HEAD_MID", EQP_HEAD_MID, false, false); + script->set_constant("EQP_HEAD_TOP", EQP_HEAD_TOP, false, false); + script->set_constant("EQP_HAND_R", EQP_HAND_R, false, false); + script->set_constant("EQP_HAND_L", EQP_HAND_L, false, false); + script->set_constant("EQP_ARMOR", EQP_ARMOR, false, false); + script->set_constant("EQP_SHOES", EQP_SHOES, false, false); + script->set_constant("EQP_GARMENT", EQP_GARMENT, false, false); + script->set_constant("EQP_ACC_L", EQP_ACC_L, false, false); + script->set_constant("EQP_ACC_R", EQP_ACC_R, false, false); + script->set_constant("EQP_COSTUME_HEAD_TOP", EQP_COSTUME_HEAD_TOP, false, false); + script->set_constant("EQP_COSTUME_HEAD_MID", EQP_COSTUME_HEAD_MID, false, false); + script->set_constant("EQP_COSTUME_HEAD_LOW", EQP_COSTUME_HEAD_LOW, false, false); + script->set_constant("EQP_COSTUME_GARMENT", EQP_COSTUME_GARMENT, false, false); + script->set_constant("EQP_AMMO", EQP_AMMO, false, false); + script->set_constant("EQP_SHADOW_ARMOR", EQP_SHADOW_ARMOR, false, false); + script->set_constant("EQP_SHADOW_WEAPON", EQP_SHADOW_WEAPON, false, false); + script->set_constant("EQP_SHADOW_SHIELD", EQP_SHADOW_SHIELD, false, false); + script->set_constant("EQP_SHADOW_SHOES", EQP_SHADOW_SHOES, false, false); + script->set_constant("EQP_SHADOW_ACC_R", EQP_SHADOW_ACC_R, false, false); + script->set_constant("EQP_SHADOW_ACC_L", EQP_SHADOW_ACC_L, false, false); + + script->constdb_comment("Renewal"); #ifdef RENEWAL - script->set_constant("RENEWAL", 1, false); + script->set_constant("RENEWAL", 1, false, false); #else - script->set_constant("RENEWAL", 0, false); + script->set_constant("RENEWAL", 0, false, false); #endif #ifdef RENEWAL_CAST - script->set_constant("RENEWAL_CAST", 1, false); + script->set_constant("RENEWAL_CAST", 1, false, false); #else - script->set_constant("RENEWAL_CAST", 0, false); + script->set_constant("RENEWAL_CAST", 0, false, false); #endif #ifdef RENEWAL_DROP - script->set_constant("RENEWAL_DROP", 1, false); + script->set_constant("RENEWAL_DROP", 1, false, false); #else - script->set_constant("RENEWAL_DROP", 0, false); + script->set_constant("RENEWAL_DROP", 0, false, false); #endif #ifdef RENEWAL_EXP - script->set_constant("RENEWAL_EXP", 1, false); + script->set_constant("RENEWAL_EXP", 1, false, false); #else - script->set_constant("RENEWAL_EXP", 0, false); + script->set_constant("RENEWAL_EXP", 0, false, false); #endif #ifdef RENEWAL_LVDMG - script->set_constant("RENEWAL_LVDMG", 1, false); + script->set_constant("RENEWAL_LVDMG", 1, false, false); #else - script->set_constant("RENEWAL_LVDMG", 0, false); + script->set_constant("RENEWAL_LVDMG", 0, false, false); #endif #ifdef RENEWAL_EDP - script->set_constant("RENEWAL_EDP", 1, false); + script->set_constant("RENEWAL_EDP", 1, false, false); #else - script->set_constant("RENEWAL_EDP", 0, false); + script->set_constant("RENEWAL_EDP", 0, false, false); #endif #ifdef RENEWAL_ASPD - script->set_constant("RENEWAL_ASPD", 1, false); + script->set_constant("RENEWAL_ASPD", 1, false, false); #else - script->set_constant("RENEWAL_ASPD", 0, false); + script->set_constant("RENEWAL_ASPD", 0, false, false); #endif + script->constdb_comment(NULL); } /** @@ -21068,6 +21208,8 @@ void script_defaults(void) { script->parse_expr = parse_expr; script->parse_line = parse_line; script->read_constdb = read_constdb; + script->constdb_comment = script_constdb_comment; + script->load_parameters = script_load_parameters; script->print_line = script_print_line; script->errorwarning_sub = script_errorwarning_sub; script->set_reg = set_reg; diff --git a/src/map/script.h b/src/map/script.h index 5f71662c6..fffe1fb1c 100644 --- a/src/map/script.h +++ b/src/map/script.h @@ -233,10 +233,8 @@ typedef enum c_op { C_SUB_POST, // a-- C_ADD_PRE, // ++a C_SUB_PRE, // --a -#ifdef PCRE_SUPPORT C_RE_EQ, // ~= C_RE_NE, // ~! -#endif // PCRE_SUPPORT } c_op; /// Script queue options @@ -666,8 +664,8 @@ struct script_interface { struct script_data* (*push_str) (struct script_stack* stack, enum c_op type, char* str); struct script_data* (*push_copy) (struct script_stack* stack, int pos); void (*pop_stack) (struct script_state* st, int start, int end); - void (*set_constant) (const char* name, int value, bool isparameter); - void (*set_constant2) (const char *name, int value, bool isparameter); + void (*set_constant) (const char *name, int value, bool is_parameter, bool is_deprecated); + void (*set_constant2) (const char *name, int value, bool is_parameter, bool is_deprecated); bool (*get_constant) (const char* name, int* value); void (*label_add)(int key, int pos); void (*run) (struct script_code *rootscript, int pos, int rid, int oid); @@ -726,6 +724,8 @@ struct script_interface { const char* (*parse_expr) (const char *p); const char* (*parse_line) (const char *p); void (*read_constdb) (void); + void (*constdb_comment) (const char *comment); + void (*load_parameters) (void); const char* (*print_line) (StringBuf *buf, const char *p, const char *mark, int line); void (*errorwarning_sub) (StringBuf *buf, const char *src, const char *file, int start_line, const char *error_msg, const char *error_pos); int (*set_reg) (struct script_state *st, struct map_session_data *sd, int64 num, const char *name, const void *value, struct reg_db *ref); diff --git a/src/map/skill.c b/src/map/skill.c index b3c264e43..13418fece 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -2089,7 +2089,7 @@ int skill_blown(struct block_list* src, struct block_list* target, int count, in case BL_MOB: { const struct mob_data *md = BL_UCCAST(BL_MOB, target); - if (md->class_ == MOBID_EMPELIUM) + if (md->status.mode&MD_NOKNOCKBACK) return 0; if (src != target && is_boss(target)) // Bosses can't be knocked-back return 0; @@ -2833,7 +2833,7 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr if ( ssc->data[SC_POISONINGWEAPON]->val1 == 9 )// Oblivion Curse gives a 2nd success chance after the 1st one passes which is reducible. [Rytech] rate = 100 - tstatus->int_ * 4 / 5; sc_start(src, bl,ssc->data[SC_POISONINGWEAPON]->val2,rate,ssc->data[SC_POISONINGWEAPON]->val1,skill->get_time2(GC_POISONINGWEAPON,1) - (tstatus->vit + tstatus->luk) / 2 * 1000); - status_change_end(src,SC_POISONINGWEAPON,-1); + status_change_end(src, SC_POISONINGWEAPON, INVALID_TIMER); clif->skill_nodamage(src,bl,skill_id,skill_lv,1); } } @@ -4374,7 +4374,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1 clif->slide(src, x, y); clif->fixpos(src); // the official server send these two packets. skill->attack(BF_WEAPON, src, src, bl, skill_id, skill_lv, tick, flag); - if ( rnd() % 100 < 4 * skill_lv && skill_id == GC_DARKILLUSION ) + if (rnd() % 100 < 4 * skill_lv && skill_id == GC_DARKILLUSION) skill->castend_damage_id(src, bl, GC_CROSSIMPACT, skill_lv, tick, flag); } } @@ -5123,7 +5123,7 @@ int skill_castend_id(int tid, int64 tick, int id, intptr_t data) { unit->set_walkdelay(src, tick, battle_config.default_walk_delay+skill->get_walkdelay(ud->skill_id, ud->skill_lv), 1); if(battle_config.skill_log && battle_config.skill_log&src->type) - ShowInfo("Type %d, ID %d skill castend id [id =%d, lv=%d, target ID %d]\n", + ShowInfo("Type %u, ID %d skill castend id [id =%d, lv=%d, target ID %d]\n", src->type, src->id, ud->skill_id, ud->skill_lv, target->id); map->freeblock_lock(); @@ -5401,12 +5401,12 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin type = status->skill2sc(skill_id); tsc = status->get_sc(bl); - tsce = (tsc && type != -1)?tsc->data[type]:NULL; + tsce = (tsc != NULL && type != SC_NONE) ? tsc->data[type] : NULL; - if (src!=bl && type > -1 && - (element = skill->get_ele(skill_id, skill_lv)) > ELE_NEUTRAL && - skill->get_inf(skill_id) != INF_SUPPORT_SKILL && - battle->attr_fix(NULL, NULL, 100, element, tstatus->def_ele, tstatus->ele_lv) <= 0) + if (src != bl && type > SC_NONE + && (element = skill->get_ele(skill_id, skill_lv)) > ELE_NEUTRAL + && skill->get_inf(skill_id) != INF_SUPPORT_SKILL + && battle->attr_fix(NULL, NULL, 100, element, tstatus->def_ele, tstatus->ele_lv) <= 0) return 1; //Skills that cause an status should be blocked if the target element blocks its element. map->freeblock_lock(); @@ -6047,7 +6047,14 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin break; case MC_CHANGECART: - clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); + break; + + case MC_CARTDECORATE: + if (sd) { + clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); + clif->selectcart(sd); + } break; case TK_MISSION: @@ -7290,7 +7297,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin case NPC_REBIRTH: if( md && md->state.rebirth ) break; // only works once - sc_start(src,bl,type,100,skill_lv,-1); + sc_start(src, bl, type, 100, skill_lv, INFINITE_DURATION); break; case NPC_DARKBLESSING: @@ -7498,7 +7505,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin memset(&item_tmp,0,sizeof(item_tmp)); item_tmp.nameid = skill->dbs->db[su->group->skill_id].itemid[i]; item_tmp.identify = 1; - if (item_tmp.nameid && (success=pc->additem(sd,&item_tmp,skill->dbs->db[su->group->skill_id].amount[i],LOG_TYPE_OTHER)) != 0) { + if (item_tmp.nameid && (success=pc->additem(sd,&item_tmp,skill->dbs->db[su->group->skill_id].amount[i],LOG_TYPE_SKILL)) != 0) { clif->additem(sd,0,0,success); map->addflooritem(&sd->bl, &item_tmp, skill->dbs->db[su->group->skill_id].amount[i], sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0); } @@ -7510,7 +7517,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin memset(&item_tmp,0,sizeof(item_tmp)); item_tmp.nameid = su->group->item_id?su->group->item_id:ITEMID_TRAP; item_tmp.identify = 1; - if (item_tmp.nameid && (flag=pc->additem(sd,&item_tmp,1,LOG_TYPE_OTHER)) != 0) { + if (item_tmp.nameid && (flag=pc->additem(sd,&item_tmp,1,LOG_TYPE_SKILL)) != 0) { clif->additem(sd,0,0,flag); map->addflooritem(&sd->bl, &item_tmp, 1, sd->bl.m, sd->bl.x, sd->bl.y, 0, 0, 0, 0); } @@ -8511,9 +8518,8 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin for(i = 0; i < SC_MAX; i++) { if ( !tsc->data[i] ) continue; - if( SC_COMMON_MAX > i ) - if ( status->get_sc_type(i)&SC_NO_CLEARANCE ) - continue; + if (status->get_sc_type(i)&SC_NO_CLEARANCE) + continue; switch (i) { case SC_ASSUMPTIO: if( bl->type == BL_MOB ) @@ -8641,7 +8647,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin break; } - sc_start(src, bl, SC_STOP, 100, skill_lv, INVALID_TIMER); //Can't move while selecting a spellbook. + sc_start(src, bl, SC_STOP, 100, skill_lv, INFINITE_DURATION); //Can't move while selecting a spellbook. clif->spellbook_list(sd); clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); } @@ -8770,7 +8776,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin if( sd ) { int idx1 = skill->get_index(sd->reproduceskill_id), idx2 = skill->get_index(sd->cloneskill_id); if( sd->status.skill[idx1].id || sd->status.skill[idx2].id ) { - sc_start(src,src,SC_STOP,100,skill_lv,-1);// The skill_lv is stored in val1 used in skill_select_menu to determine the used skill lvl [Xazax] + sc_start(src, src, SC_STOP, 100, skill_lv, INFINITE_DURATION); // The skill_lv is stored in val1 used in skill_select_menu to determine the used skill lvl [Xazax] clif->autoshadowspell_list(sd); clif->skill_nodamage(src,bl,skill_id,1,1); } @@ -8887,7 +8893,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin splashrange = 3; switch( opt ) { case 1: - sc_start(src,bl,SC_SHIELDSPELL_DEF,100,opt,INVALID_TIMER); //Splash AoE ATK + sc_start(src, bl, SC_SHIELDSPELL_DEF, 100, opt, INFINITE_DURATION); // Splash AoE ATK clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL); map->foreachinrange(skill->area_sub,src,splashrange,BL_CHAR,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_damage_id); status_change_end(bl,SC_SHIELDSPELL_DEF,INVALID_TIMER); @@ -8914,7 +8920,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin splashrange = 3; switch( opt ) { case 1: - sc_start(src,bl,SC_SHIELDSPELL_MDEF,100,opt,INVALID_TIMER); //Splash AoE MATK + sc_start(src, bl, SC_SHIELDSPELL_MDEF, 100, opt, INFINITE_DURATION); // Splash AoE MATK clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL); map->foreachinrange(skill->area_sub,src,splashrange,BL_CHAR,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_damage_id); status_change_end(bl,SC_SHIELDSPELL_MDEF,INVALID_TIMER); @@ -8951,7 +8957,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin sc_start(src,bl,SC_SCRESIST,100,rate,shield->refine * 30000)); break; case 3: - sc_start(src,bl,SC_SHIELDSPELL_REF,100,opt,INVALID_TIMER); //HP Recovery + sc_start(src, bl, SC_SHIELDSPELL_REF, 100, opt, INFINITE_DURATION); // HP Recovery val = sstatus->max_hp * ((status->get_lv(src) / 10) + (shield->refine + 1)) / 100; status->heal(bl, val, 0, 2); status_change_end(bl,SC_SHIELDSPELL_REF,INVALID_TIMER); @@ -9424,7 +9430,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin case SO_EL_CONTROL: if( sd ) { - int mode = EL_MODE_PASSIVE; // Standard mode. + uint32 mode = EL_MODE_PASSIVE; // Standard mode. if( !sd->ed ) break; @@ -9436,7 +9442,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin case 2: mode = EL_MODE_ASSIST; break; case 3: mode = EL_MODE_AGGRESSIVE; break; } - if( !elemental->change_mode(sd->ed,mode) ) { + if (!elemental->change_mode(sd->ed, mode)) { clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); break; } @@ -9661,7 +9667,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin if(sd) { struct mob_data *summon_md; - summon_md = mob->once_spawn_sub(src, src->m, src->x, src->y, status->get_name(src), MOBID_KO_KAGE, "", SZ_SMALL, AI_NONE); + summon_md = mob->once_spawn_sub(src, src->m, src->x, src->y, clif->get_bl_name(src), MOBID_KO_KAGE, "", SZ_SMALL, AI_NONE); if( summon_md ) { summon_md->master_id = src->id; summon_md->special_state.ai = AI_ZANZOU; @@ -9841,7 +9847,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin break; for (i = 0; i < summons[skill_lv-1].quantity; i++) { - struct mob_data *summon_md = mob->once_spawn_sub(src, src->m, src->x, src->y, status->get_name(src), + struct mob_data *summon_md = mob->once_spawn_sub(src, src->m, src->x, src->y, clif->get_bl_name(src), summons[skill_lv-1].mob_id, "", SZ_SMALL, AI_ATTACK); if (summon_md != NULL) { summon_md->master_id = src->id; @@ -10016,7 +10022,7 @@ int skill_castend_pos(int tid, int64 tick, int id, intptr_t data) } if(battle_config.skill_log && battle_config.skill_log&src->type) - ShowInfo("Type %d, ID %d skill castend pos [id =%d, lv=%d, (%d,%d)]\n", + ShowInfo("Type %u, ID %d skill castend pos [id =%d, lv=%d, (%d,%d)]\n", src->type, src->id, ud->skill_id, ud->skill_lv, ud->skillx, ud->skilly); if (ud->walktimer != INVALID_TIMER) @@ -10260,7 +10266,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui sc = status->get_sc(src); type = status->skill2sc(skill_id); - sce = (sc && type != -1)?sc->data[type]:NULL; + sce = (sc != NULL && type != SC_NONE) ? sc->data[type] : NULL; switch (skill_id) { //Skill effect. case WZ_METEOR: @@ -10582,7 +10588,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui } // Correct info, don't change any of this! [Celest] - md = mob->once_spawn_sub(src, src->m, x, y, status->get_name(src), class_, "", SZ_SMALL, AI_NONE); + md = mob->once_spawn_sub(src, src->m, x, y, clif->get_bl_name(src), class_, "", SZ_SMALL, AI_NONE); if (md) { md->master_id = src->id; md->special_state.ai = (skill_id == AM_SPHEREMINE) ? AI_SPHERE : AI_FLORA; @@ -10827,7 +10833,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui case NC_SILVERSNIPER: { - struct mob_data *md = mob->once_spawn_sub(src, src->m, x, y, status->get_name(src), MOBID_SILVERSNIPER, "", SZ_SMALL, AI_NONE); + struct mob_data *md = mob->once_spawn_sub(src, src->m, x, y, clif->get_bl_name(src), MOBID_SILVERSNIPER, "", SZ_SMALL, AI_NONE); if (md) { md->master_id = src->id; md->special_state.ai = AI_FLORA; @@ -11663,7 +11669,7 @@ int skill_unit_onplace(struct skill_unit *src, struct block_list *bl, int64 tick return 0; type = status->skill2sc(sg->skill_id); - sce = (sc && type != -1)?sc->data[type]:NULL; + sce = (sc != NULL && type != SC_NONE) ? sc->data[type] : NULL; skill_id = sg->skill_id; //In case the group is deleted, we need to return the correct skill id, still. switch (sg->unit_id) { case UNT_SPIDERWEB: @@ -11770,6 +11776,10 @@ int skill_unit_onplace(struct skill_unit *src, struct block_list *bl, int64 tick sc_start4(ss,bl,type,100,sg->skill_lv,sg->val1,sg->val2,0,sg->limit); break; case UNT_APPLEIDUN: + // If Aegis, apple of idun doesn't update its effect + if (!battle_config.song_timer_reset && sc && sce) + return 0; + // Let it fall through case UNT_WHISTLE: case UNT_ASSASSINCROSS: case UNT_POEMBRAGI: @@ -11777,19 +11787,34 @@ int skill_unit_onplace(struct skill_unit *src, struct block_list *bl, int64 tick case UNT_DONTFORGETME: case UNT_FORTUNEKISS: case UNT_SERVICEFORYOU: + // Don't buff themselves without link! if (sg->src_id==bl->id && !(sc && sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_BARDDANCER)) return 0; if (!sc) return 0; if (!sce) sc_start4(ss,bl,type,100,sg->skill_lv,sg->val1,sg->val2,0,sg->limit); + // From here songs are already active else if (battle_config.song_timer_reset && sce->val4 == 1) { - //Readjust timers since the effect will not last long. + // eA style: + // Readjust timers since the effect will not last long. sce->val4 = 0; timer->delete(sce->timer, status->change_timer); sce->timer = timer->add(tick+sg->limit, status->change_timer, bl->id, type); + } else if (!battle_config.song_timer_reset) { + // Aegis style: + // Songs won't renew unless finished + const struct TimerData *td = timer->get(sce->timer); + if (DIFF_TICK32(td->tick, timer->gettick()) < sg->interval) { + // Update with new values as the current one will vanish soon + timer->delete(sce->timer, status->change_timer); + sce->timer = timer->add(tick+sg->limit, status->change_timer, bl->id, type); + sce->val1 = sg->skill_lv; // Why are we storing skill_lv as val1? + sce->val2 = sg->val1; + sce->val3 = sg->val2; + sce->val4 = 0; + } } - break; case UNT_FOGWALL: @@ -11924,7 +11949,7 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6 case UNT_MANHOLE: return 0; default: - ShowError("skill_unit_onplace_timer: interval error (unit id %x)\n", sg->unit_id); + ShowError("skill_unit_onplace_timer: interval error (unit id %x)\n", (unsigned int)sg->unit_id); return 0; } } @@ -12194,18 +12219,25 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6 if (md && md->class_ == MOBID_EMPELIUM) break; #endif - if ((sg->src_id == bl->id && !(tsc && tsc->data[SC_SOULLINK] && tsc->data[SC_SOULLINK]->val2 == SL_BARDDANCER)) - || (!(battle_config.song_timer_reset) && tsc && tsc->data[type] && tsc->data[type]->val4 == 1)) + // Don't buff themselves! + if ((sg->src_id == bl->id && !(tsc && tsc->data[SC_SOULLINK] && tsc->data[SC_SOULLINK]->val2 == SL_BARDDANCER))) break; - heal = skill->calc_heal(ss,bl,sg->skill_id, sg->skill_lv, true); - if( tsc && tsc->data[SC_AKAITSUKI] && heal ) - heal = ~heal + 1; - clif->skill_nodamage(&src->bl, bl, AL_HEAL, heal, 1); - status->heal(bl, heal, 0, 0); - - if (!battle_config.song_timer_reset) + // Aegis style + // Check if the remaining time is enough to survive the next update + if (!battle_config.song_timer_reset + && !(tsc && tsc->data[type] && tsc->data[type]->val4 == 1)) { + // Apple of Idun is not active. Start it now sc_start4(ss, bl, type, 100, sg->skill_lv, sg->val1, sg->val2, 0, sg->limit); + } + + if (tstatus->hp < tstatus->max_hp) { + heal = skill->calc_heal(ss,bl,sg->skill_id, sg->skill_lv, true); + if( tsc && tsc->data[SC_AKAITSUKI] && heal ) + heal = ~heal + 1; + clif->skill_nodamage(&src->bl, bl, AL_HEAL, heal, 1); + status->heal(bl, heal, 0, 0); + } } break; case UNT_POEMBRAGI: @@ -12215,12 +12247,30 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6 case UNT_DONTFORGETME: case UNT_FORTUNEKISS: case UNT_SERVICEFORYOU: - if (battle_config.song_timer_reset - || (!(battle_config.song_timer_reset) && tsc && tsc->data[type] && tsc->data[type]->val4 == 1) - || (sg->src_id == bl->id && !(tsc && tsc->data[SC_SOULLINK] && tsc->data[SC_SOULLINK]->val2 == SL_BARDDANCER)) - ) + // eA style: doesn't need this + if (battle_config.song_timer_reset) + break; + // Don't let buff themselves! + if (sg->src_id == bl->id && !(tsc && tsc->data[SC_SOULLINK] && tsc->data[SC_SOULLINK]->val2 == SL_BARDDANCER)) break; + // Aegis style + // Check if song has enough time to survive the next check + if (!(battle_config.song_timer_reset) && tsc && tsc->data[type] && tsc->data[type]->val4 == 1) { + const struct TimerData *td = timer->get(tsc->data[type]->timer); + if (DIFF_TICK32(td->tick, timer->gettick()) < sg->interval) { + // Update with new values as the current one will vanish + timer->delete(tsc->data[type]->timer, status->change_timer); + tsc->data[type]->timer = timer->add(tick+sg->limit, status->change_timer, bl->id, type); + tsc->data[type]->val1 = sg->skill_lv; + tsc->data[type]->val2 = sg->val1; + tsc->data[type]->val3 = sg->val2; + tsc->data[type]->val4 = 0; + } + break; // Had enough time or not, it now has. Exit + } + + // Song was not active. Start it now sc_start4(ss, bl, type, 100, sg->skill_lv, sg->val1, sg->val2, 0, sg->limit); break; case UNT_TATAMIGAESHI: @@ -12617,7 +12667,7 @@ int skill_unit_onout(struct skill_unit *src, struct block_list *bl, int64 tick) nullpo_ret(sg=src->group); sc = status->get_sc(bl); type = status->skill2sc(sg->skill_id); - sce = (sc && type != -1)?sc->data[type]:NULL; + sce = (sc != NULL && type != SC_NONE) ? sc->data[type] : NULL; if( bl->prev == NULL || (status->isdead(bl) && sg->unit_id != UNT_ANKLESNARE && sg->unit_id != UNT_SPIDERWEB && sg->unit_id != UNT_THORNS_TRAP) @@ -12681,7 +12731,7 @@ int skill_unit_onleft(uint16 skill_id, struct block_list *bl, int64 tick) { sc = NULL; type = status->skill2sc(skill_id); - sce = (sc && type != -1)?sc->data[type]:NULL; + sce = (sc != NULL && type != SC_NONE) ? sc->data[type] : NULL; switch (skill_id) { case WZ_QUAGMIRE: @@ -12742,8 +12792,9 @@ int skill_unit_onleft(uint16 skill_id, struct block_list *bl, int64 tick) { case DC_DONTFORGETME: case DC_FORTUNEKISS: case DC_SERVICEFORYOU: - if ((battle_config.song_timer_reset && sce) // athena style - || (!battle_config.song_timer_reset && sce && sce->val4 != 1) + + if ((battle_config.song_timer_reset && sce) // eAthena style: update everytime + || (!battle_config.song_timer_reset && sce && sce->val4 != 1) // Aegis style: update only when it was not a reduced effect ) { timer->delete(sce->timer, status->change_timer); //NOTE: It'd be nice if we could get the skill_lv for a more accurate extra time, but alas... @@ -14836,7 +14887,7 @@ int skill_vfcastfix(struct block_list *bl, double time, uint16 skill_id, uint16 } if (sc->data[SC_MYSTICSCROLL]) VARCAST_REDUCTION(sc->data[SC_MYSTICSCROLL]->val1); - + // Fixed cast reduction bonuses if( sc->data[SC__LAZINESS] ) fixcast_r = max(fixcast_r, sc->data[SC__LAZINESS]->val2); @@ -15262,12 +15313,12 @@ void skill_weaponrefine (struct map_session_data *sd, int idx) else per += 5 * ((signed int)sd->status.job_level - 50); - pc->delitem(sd, i, 1, 0, DELITEM_NORMAL, LOG_TYPE_OTHER); // FIXME: is this the correct reason flag? + pc->delitem(sd, i, 1, 0, DELITEM_NORMAL, LOG_TYPE_REFINE); // FIXME: is this the correct reason flag? if (per > rnd() % 1000) { int ep = 0; - logs->pick_pc(sd, LOG_TYPE_OTHER, -1, item, ditem); + logs->pick_pc(sd, LOG_TYPE_REFINE, -1, item, ditem); item->refine++; - logs->pick_pc(sd, LOG_TYPE_OTHER, 1, item, ditem); + logs->pick_pc(sd, LOG_TYPE_REFINE, 1, item, ditem); if(item->equip) { ep = item->equip; pc->unequipitem(sd, idx, PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE); @@ -15300,7 +15351,7 @@ void skill_weaponrefine (struct map_session_data *sd, int idx) if(item->equip) pc->unequipitem(sd, idx, PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE); clif->refine(sd->fd,1,idx,item->refine); - pc->delitem(sd, idx, 1, 0, DELITEM_NORMAL, LOG_TYPE_OTHER); + pc->delitem(sd, idx, 1, 0, DELITEM_NORMAL, LOG_TYPE_REFINE); clif->misceffect(&sd->bl,2); clif->emotion(&sd->bl, E_OMG); } @@ -16467,7 +16518,7 @@ struct skill_unit_group_tickset *skill_unitgrouptickset_search(struct block_list } if (j == -1) { - ShowWarning ("skill_unitgrouptickset_search: tickset is full. ( failed for skill '%s' on unit %d )\n",skill->get_name(group->skill_id),bl->type); + ShowWarning ("skill_unitgrouptickset_search: tickset is full. ( failed for skill '%s' on unit %u )\n", skill->get_name(group->skill_id), bl->type); j = id % MAX_SKILLUNITGROUPTICKSET; } @@ -17673,7 +17724,7 @@ int skill_poisoningweapon( struct map_session_data *sd, int nameid) { return 0; } - status_change_end(&sd->bl, SC_POISONINGWEAPON, -1);//Status must be forced to end so that a new poison will be applied if a player decides to change poisons. [Rytech] + status_change_end(&sd->bl, SC_POISONINGWEAPON, INVALID_TIMER); // Status must be forced to end so that a new poison will be applied if a player decides to change poisons. [Rytech] chance = 2 + 2 * sd->menuskill_val; // 2 + 2 * skill_lv sc_start4(&sd->bl, &sd->bl, SC_POISONINGWEAPON, 100, pc->checkskill(sd, GC_RESEARCHNEWPOISON), //in Aegis it store the level of GC_RESEARCHNEWPOISON in val1 type, chance, 0, skill->get_time(GC_POISONINGWEAPON, sd->menuskill_val)); @@ -17793,13 +17844,13 @@ int skill_spellbook (struct map_session_data *sd, int nameid) { for(i = SC_SPELLBOOK7; i >= SC_SPELLBOOK1; i--){ // This is how official saves spellbook. [malufett] if( !sc->data[i] ){ sc->data[SC_READING_SB]->val2 += point; // increase points - sc_start4(&sd->bl,&sd->bl, (sc_type)i, 100, skill_id, pc->checkskill(sd,skill_id), point, 0, INVALID_TIMER); + sc_start4(&sd->bl, &sd->bl, (sc_type)i, 100, skill_id, pc->checkskill(sd, skill_id), point, 0, INFINITE_DURATION); break; } } - }else{ - sc_start2(&sd->bl,&sd->bl, SC_READING_SB, 100, 0, point, INVALID_TIMER); - sc_start4(&sd->bl,&sd->bl, SC_SPELLBOOK7, 100, skill_id, pc->checkskill(sd,skill_id), point, 0, INVALID_TIMER); + } else { + sc_start2(&sd->bl, &sd->bl, SC_READING_SB, 100, 0, point, INFINITE_DURATION); + sc_start4(&sd->bl, &sd->bl, SC_SPELLBOOK7, 100, skill_id, pc->checkskill(sd, skill_id), point, 0, INFINITE_DURATION); } return 1; @@ -17827,27 +17878,31 @@ int skill_select_menu(struct map_session_data *sd,uint16 skill_id) { sc_start4(&sd->bl,&sd->bl,SC__AUTOSHADOWSPELL,100,id,lv,prob,0,skill->get_time(SC_AUTOSHADOWSPELL,aslvl)); return 0; } -int skill_elementalanalysis(struct map_session_data* sd, int n, uint16 skill_lv, unsigned short* item_list) { + +int skill_elementalanalysis(struct map_session_data *sd, uint16 skill_lv, const struct itemlist *item_list) +{ int i; nullpo_ret(sd); nullpo_ret(item_list); - if( n <= 0 ) + if (VECTOR_LENGTH(*item_list) <= 0) return 1; - for (i = 0; i < n; i++) { - int nameid, add_amount, del_amount, idx, product; + for (i = 0; i < VECTOR_LENGTH(*item_list); i++) { struct item tmp_item; - - idx = item_list[i*2+0]-2; - del_amount = item_list[i*2+1]; + const struct itemlist_entry *entry = &VECTOR_INDEX(*item_list, i); + int nameid, add_amount, product; + int del_amount = entry->amount; + int idx = entry->id; if( skill_lv == 2 ) del_amount -= (del_amount % 10); add_amount = (skill_lv == 1) ? del_amount * (5 + rnd()%5) : del_amount / 10 ; - if( (nameid = sd->status.inventory[idx].nameid) <= 0 || del_amount > sd->status.inventory[idx].amount ) { + if (idx < 0 || idx >= MAX_INVENTORY + || (nameid = sd->status.inventory[idx].nameid) <= 0 + || del_amount < 0 || del_amount > sd->status.inventory[idx].amount) { clif->skill_fail(sd,SO_EL_ANALYSIS,USESKILL_FAIL_LEVEL,0); return 1; } @@ -17897,7 +17952,8 @@ int skill_elementalanalysis(struct map_session_data* sd, int n, uint16 skill_lv, return 0; } -int skill_changematerial(struct map_session_data *sd, int n, unsigned short *item_list) { +int skill_changematerial(struct map_session_data *sd, const struct itemlist *item_list) +{ int i, j, k, c, p = 0, nameid, amount; nullpo_ret(sd); @@ -17912,11 +17968,13 @@ int skill_changematerial(struct map_session_data *sd, int n, unsigned short *ite // Verification of overlap between the objects required and the list submitted. for( j = 0; j < MAX_PRODUCE_RESOURCE; j++ ) { if( skill->dbs->produce_db[i].mat_id[j] > 0 ) { - for( k = 0; k < n; k++ ) { - int idx = item_list[k*2+0]-2; + for (k = 0; k < VECTOR_LENGTH(*item_list); k++) { + const struct itemlist_entry *entry = &VECTOR_INDEX(*item_list, k); + int idx = entry->id; + Assert_ret(idx >= 0 && idx < MAX_INVENTORY); + amount = entry->amount; nameid = sd->status.inventory[idx].nameid; - amount = item_list[k*2+1]; - if( nameid > 0 && sd->status.inventory[idx].identify == 0 ){ + if (nameid > 0 && sd->status.inventory[idx].identify == 0) { clif->msgtable_skill(sd, GN_CHANGEMATERIAL, MSG_SKILL_ITEM_NEED_IDENTIFY); return 0; } @@ -17929,7 +17987,7 @@ int skill_changematerial(struct map_session_data *sd, int n, unsigned short *ite break; // No more items required } p++; - } while(n == j && c == n); + } while (c == j && VECTOR_LENGTH(*item_list) == c); p--; if ( p > 0 ) { skill->produce_mix(sd,GN_CHANGEMATERIAL,skill->dbs->produce_db[i].nameid,0,0,0,p); @@ -18076,7 +18134,7 @@ int skill_blockpc_start_(struct map_session_data *sd, uint16 skill_id, int tick) return 0; else { int cursor; - /** somehow, the timer vanished. (bugreport:8367) **/ + /* somehow, the timer vanished. (bugreport:8367) */ ers_free(skill->cd_entry_ers, cd->entry[i]); cd->entry[i] = NULL; @@ -18788,7 +18846,7 @@ bool skill_parse_row_skilldb(char* split[], int columns, int current) { safestrncpy(skill->dbs->db[idx].name, trim(split[15]), sizeof(skill->dbs->db[idx].name)); safestrncpy(skill->dbs->db[idx].desc, trim(split[16]), sizeof(skill->dbs->db[idx].desc)); strdb_iput(skill->name2id_db, skill->dbs->db[idx].name, skill_id); - script->set_constant2(skill->dbs->db[idx].name,(int)skill_id,0); + script->set_constant2(skill->dbs->db[idx].name, (int)skill_id, false, false); return true; } diff --git a/src/map/skill.h b/src/map/skill.h index 96bef090a..fb2acfb62 100644 --- a/src/map/skill.h +++ b/src/map/skill.h @@ -32,6 +32,7 @@ **/ struct Damage; struct homun_data; +struct itemlist; // map/itemdb.h struct map_session_data; struct mercenary_data; struct unit_data; @@ -2060,8 +2061,8 @@ struct skill_interface { int (*magicdecoy) (struct map_session_data *sd, int nameid); int (*poisoningweapon) ( struct map_session_data *sd, int nameid); int (*select_menu) (struct map_session_data *sd,uint16 skill_id); - int (*elementalanalysis) (struct map_session_data *sd, int n, uint16 skill_lv, unsigned short *item_list); - int (*changematerial) (struct map_session_data *sd, int n, unsigned short *item_list); + int (*elementalanalysis) (struct map_session_data *sd, uint16 skill_lv, const struct itemlist *item_list); + int (*changematerial) (struct map_session_data *sd, const struct itemlist *item_list); int (*get_elemental_type) (uint16 skill_id, uint16 skill_lv); void (*cooldown_save) (struct map_session_data * sd); int (*get_new_group_id) (void); diff --git a/src/map/status.c b/src/map/status.c index 538ebc5e3..a8771c0a5 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -862,38 +862,38 @@ void initChangeTables(void) { status->dbs->IconChangeTable[SC_M_LIFEPOTION] = SI_M_LIFEPOTION; status->dbs->IconChangeTable[SC_G_LIFEPOTION] = SI_G_LIFEPOTION; status->dbs->IconChangeTable[SC_MYSTICPOWDER] = SI_MYSTICPOWDER; - + // Eden Crystal Synthesis status->dbs->IconChangeTable[SC_QUEST_BUFF1] = SI_QUEST_BUFF1; status->dbs->IconChangeTable[SC_QUEST_BUFF2] = SI_QUEST_BUFF2; status->dbs->IconChangeTable[SC_QUEST_BUFF3] = SI_QUEST_BUFF3; - + // Geffen Magic Tournament status->dbs->IconChangeTable[SC_GEFFEN_MAGIC1] = SI_GEFFEN_MAGIC1; status->dbs->IconChangeTable[SC_GEFFEN_MAGIC2] = SI_GEFFEN_MAGIC2; status->dbs->IconChangeTable[SC_GEFFEN_MAGIC3] = SI_GEFFEN_MAGIC3; status->dbs->IconChangeTable[SC_FENRIR_CARD] = SI_FENRIR_CARD; - + // MVP Scrolls status->dbs->IconChangeTable[SC_MVPCARD_TAOGUNKA] = SI_MVPCARD_TAOGUNKA; status->dbs->IconChangeTable[SC_MVPCARD_MISTRESS] = SI_MVPCARD_MISTRESS; status->dbs->IconChangeTable[SC_MVPCARD_ORCHERO] = SI_MVPCARD_ORCHERO; status->dbs->IconChangeTable[SC_MVPCARD_ORCLORD] = SI_MVPCARD_ORCLORD; - + // Mercenary Bonus Effects status->dbs->IconChangeTable[SC_MER_FLEE] = SI_MER_FLEE; status->dbs->IconChangeTable[SC_MER_ATK] = SI_MER_ATK; status->dbs->IconChangeTable[SC_MER_HP] = SI_MER_HP; status->dbs->IconChangeTable[SC_MER_SP] = SI_MER_SP; status->dbs->IconChangeTable[SC_MER_HIT] = SI_MER_HIT; - + // Warlock Spheres status->dbs->IconChangeTable[SC_SUMMON1] = SI_SPHERE_1; status->dbs->IconChangeTable[SC_SUMMON2] = SI_SPHERE_2; status->dbs->IconChangeTable[SC_SUMMON3] = SI_SPHERE_3; status->dbs->IconChangeTable[SC_SUMMON4] = SI_SPHERE_4; status->dbs->IconChangeTable[SC_SUMMON5] = SI_SPHERE_5; - + // Warlock Preserved spells status->dbs->IconChangeTable[SC_SPELLBOOK1] = SI_SPELLBOOK1; status->dbs->IconChangeTable[SC_SPELLBOOK2] = SI_SPELLBOOK2; @@ -977,7 +977,7 @@ void initChangeTables(void) { status->dbs->IconChangeTable[SC_REBOUND] = SI_REBOUND; status->dbs->IconChangeTable[SC_ALL_RIDING] = SI_ALL_RIDING; status->dbs->IconChangeTable[SC_MONSTER_TRANSFORM] = SI_MONSTER_TRANSFORM; - + // Costumes status->dbs->IconChangeTable[SC_MOONSTAR] = SI_MOONSTAR; status->dbs->IconChangeTable[SC_SUPER_STAR] = SI_SUPER_STAR; @@ -993,7 +993,7 @@ void initChangeTables(void) { status->dbs->IconChangeTable[SC_TIME_ACCESSORY] = SI_TIME_ACCESSORY; status->dbs->IconChangeTable[SC_MAGICAL_FEATHER] = SI_MAGICAL_FEATHER; status->dbs->IconChangeTable[SC_BLOSSOM_FLUTTERING] = SI_BLOSSOM_FLUTTERING; - + // Other SC which are not necessarily associated to skills. status->dbs->ChangeFlagTable[SC_ATTHASTE_POTION1] |= SCB_ASPD; status->dbs->ChangeFlagTable[SC_ATTHASTE_POTION2] |= SCB_ASPD; @@ -1061,7 +1061,7 @@ void initChangeTables(void) { status->dbs->ChangeFlagTable[SC_PHI_DEMON] |= SCB_ALL; status->dbs->ChangeFlagTable[SC_MAGIC_CANDY] |= SCB_MATK | SCB_ALL; status->dbs->ChangeFlagTable[SC_MYSTICPOWDER] |= SCB_FLEE | SCB_LUK; - + // Cash Items status->dbs->ChangeFlagTable[SC_FOOD_STR_CASH] |= SCB_STR; status->dbs->ChangeFlagTable[SC_FOOD_AGI_CASH] |= SCB_AGI; @@ -1069,14 +1069,14 @@ void initChangeTables(void) { status->dbs->ChangeFlagTable[SC_FOOD_DEX_CASH] |= SCB_DEX; status->dbs->ChangeFlagTable[SC_FOOD_INT_CASH] |= SCB_INT; status->dbs->ChangeFlagTable[SC_FOOD_LUK_CASH] |= SCB_LUK; - + // Mercenary Bonus Effects status->dbs->ChangeFlagTable[SC_MER_FLEE] |= SCB_FLEE; status->dbs->ChangeFlagTable[SC_MER_ATK] |= SCB_WATK; status->dbs->ChangeFlagTable[SC_MER_HP] |= SCB_MAXHP; status->dbs->ChangeFlagTable[SC_MER_SP] |= SCB_MAXSP; status->dbs->ChangeFlagTable[SC_MER_HIT] |= SCB_HIT; - + // Guillotine Cross Poison Effects status->dbs->ChangeFlagTable[SC_PARALYSE] |= SCB_FLEE | SCB_SPEED | SCB_ASPD; status->dbs->ChangeFlagTable[SC_VENOMBLEED] |= SCB_MAXHP; @@ -1084,11 +1084,11 @@ void initChangeTables(void) { status->dbs->ChangeFlagTable[SC_DEATHHURT] |= SCB_REGEN; status->dbs->ChangeFlagTable[SC_PYREXIA] |= SCB_HIT | SCB_FLEE; status->dbs->ChangeFlagTable[SC_OBLIVIONCURSE] |= SCB_REGEN; - + // Royal Guard status status->dbs->ChangeFlagTable[SC_SHIELDSPELL_DEF] |= SCB_WATK; status->dbs->ChangeFlagTable[SC_SHIELDSPELL_REF] |= SCB_DEF; - + // Mechanic status status->dbs->ChangeFlagTable[SC_STEALTHFIELD_MASTER] |= SCB_SPEED; @@ -1116,7 +1116,7 @@ void initChangeTables(void) { status->dbs->ChangeFlagTable[SC_STOMACHACHE] |= SCB_STR | SCB_AGI | SCB_VIT | SCB_INT | SCB_DEX | SCB_LUK | SCB_SPEED; status->dbs->ChangeFlagTable[SC_PROMOTE_HEALTH_RESERCH] |= SCB_MAXHP | SCB_ALL; status->dbs->ChangeFlagTable[SC_ENERGY_DRINK_RESERCH] |= SCB_MAXSP | SCB_ALL; - + // Geffen Scrolls status->dbs->ChangeFlagTable[SC_SKELSCROLL] |= SCB_ALL; status->dbs->ChangeFlagTable[SC_DISTRUCTIONSCROLL] |= SCB_ALL; @@ -1135,24 +1135,24 @@ void initChangeTables(void) { status->dbs->ChangeFlagTable[SC_MTF_HITFLEE] |= SCB_HIT | SCB_FLEE; status->dbs->ChangeFlagTable[SC_MTF_MHP] |= SCB_MAXHP; status->dbs->ChangeFlagTable[SC_MTF_MSP] |= SCB_MAXSP; - + // Eden Crystal Synthesis status->dbs->ChangeFlagTable[SC_QUEST_BUFF1] |= SCB_BATK | SCB_MATK; status->dbs->ChangeFlagTable[SC_QUEST_BUFF2] |= SCB_BATK | SCB_MATK; status->dbs->ChangeFlagTable[SC_QUEST_BUFF3] |= SCB_BATK | SCB_MATK; - + // Geffen Magic Tournament status->dbs->ChangeFlagTable[SC_GEFFEN_MAGIC1] |= SCB_ALL; status->dbs->ChangeFlagTable[SC_GEFFEN_MAGIC2] |= SCB_ALL; status->dbs->ChangeFlagTable[SC_GEFFEN_MAGIC3] |= SCB_ALL; status->dbs->ChangeFlagTable[SC_FENRIR_CARD] |= SCB_MATK | SCB_ALL; - + // MVP Scrolls status->dbs->ChangeFlagTable[SC_MVPCARD_TAOGUNKA] |= SCB_MAXHP | SCB_DEF | SCB_MDEF; status->dbs->ChangeFlagTable[SC_MVPCARD_MISTRESS] |= SCB_ALL; status->dbs->ChangeFlagTable[SC_MVPCARD_ORCHERO] |= SCB_ALL; status->dbs->ChangeFlagTable[SC_MVPCARD_ORCLORD] |= SCB_ALL; - + // Costumes status->dbs->ChangeFlagTable[SC_MOONSTAR] |= SCB_NONE; status->dbs->ChangeFlagTable[SC_SUPER_STAR] |= SCB_NONE; @@ -1192,7 +1192,7 @@ void initChangeTables(void) { status->dbs->DisplayType[SC_BLOOD_SUCKER] = true; status->dbs->DisplayType[SC__SHADOWFORM] = true; status->dbs->DisplayType[SC_MONSTER_TRANSFORM] = true; - + // Costumes status->dbs->DisplayType[SC_MOONSTAR] = true; status->dbs->DisplayType[SC_SUPER_STAR] = true; @@ -2095,7 +2095,7 @@ int status_calc_mob_(struct mob_data* md, enum e_status_calc_opt opt) { mstatus->max_hp = 3000 + 3000 * ud->skill_lv + status_get_max_sp(battle->get_master(mbl)); } else { //AM_CANNIBALIZE mstatus->max_hp = 1500 + 200*ud->skill_lv + 10*status->get_lv(mbl); - mstatus->mode|= MD_CANATTACK|MD_AGGRESSIVE; + mstatus->mode |= MD_CANATTACK|MD_AGGRESSIVE; } mstatus->hp = mstatus->max_hp; if( ud->skill_id == NC_SILVERSNIPER ) @@ -2200,9 +2200,9 @@ int status_calc_pet_(struct pet_data *pd, enum e_status_calc_opt opt) pd->status.mode = MD_CANMOVE; // pets discard all modes, except walking pd->status.speed = pd->petDB->speed; - if(battle_config.pet_attack_support || battle_config.pet_damage_support) - {// attack support requires the pet to be able to attack - pd->status.mode|= MD_CANATTACK; + if(battle_config.pet_attack_support || battle_config.pet_damage_support) { + // attack support requires the pet to be able to attack + pd->status.mode |= MD_CANATTACK; } } @@ -2255,7 +2255,8 @@ int status_calc_pet_(struct pet_data *pd, enum e_status_calc_opt opt) return 1; } -unsigned int status_get_base_maxsp(struct map_session_data* sd, struct status_data *st) { +unsigned int status_get_base_maxsp(const struct map_session_data *sd, const struct status_data *st) +{ uint64 val = pc->class2idx(sd->status.class_); val = status->dbs->SP_table[val][sd->status.base_level]; @@ -2272,7 +2273,8 @@ unsigned int status_get_base_maxsp(struct map_session_data* sd, struct status_da return (unsigned int)cap_value(val, 0, UINT_MAX); } -unsigned int status_get_base_maxhp(struct map_session_data *sd, struct status_data *st) { +unsigned int status_get_base_maxhp(const struct map_session_data *sd, const struct status_data *st) +{ uint64 val = pc->class2idx(sd->status.class_); val = status->dbs->HP_table[val][sd->status.base_level]; @@ -2500,7 +2502,7 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) { } else if(sd->inventory_data[index]->type == IT_ARMOR) { int r = sd->status.inventory[index].refine; - + if ( (!battle_config.costume_refine_def && itemdb_is_costumeequip(sd->inventory_data[index]->equip)) || (!battle_config.shadow_refine_def && itemdb_is_shadowequip(sd->inventory_data[index]->equip)) ) @@ -2718,7 +2720,7 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) { // Base batk value is set on status->calc_misc // weapon-type bonus (FIXME: Why is the weapon_atk bonus applied to base attack?) - if (sd->status.weapon < MAX_WEAPON_TYPE && sd->weapon_atk[sd->status.weapon]) + if (sd->status.weapon < MAX_SINGLE_WEAPON_TYPE && sd->weapon_atk[sd->status.weapon]) bstatus->batk += sd->weapon_atk[sd->status.weapon]; // Absolute modifiers from passive skills #ifndef RENEWAL @@ -3110,7 +3112,7 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) { sd->magic_addele[ELE_WIND] += 25; if (sc->data[SC_EARTH_INSIGNIA] && sc->data[SC_EARTH_INSIGNIA]->val1 == 3) sd->magic_addele[ELE_EARTH] += 25; - + // Geffen Scrolls if (sc->data[SC_SKELSCROLL]) { #ifdef RENEWAL @@ -3136,11 +3138,11 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) { } if (sc->data[SC_IMMUNITYSCROLL]) sd->subele[ELE_NEUTRAL] += sc->data[SC_IMMUNITYSCROLL]->val1; - + // Geffen Magic Tournament if (sc->data[SC_GEFFEN_MAGIC1]) { sd->right_weapon.addrace[RC_DEMIHUMAN] += sc->data[SC_GEFFEN_MAGIC1]->val1; - sd->left_weapon.addrace[RC_DEMIHUMAN] += sc->data[SC_GEFFEN_MAGIC1]->val1; + sd->left_weapon.addrace[RC_DEMIHUMAN] += sc->data[SC_GEFFEN_MAGIC1]->val1; } if (sc->data[SC_GEFFEN_MAGIC2]) sd->magic_addrace[RC_DEMIHUMAN] += sc->data[SC_GEFFEN_MAGIC2]->val1; @@ -3212,7 +3214,7 @@ int status_calc_elemental_(struct elemental_data *ed, enum e_status_calc_opt opt if ( opt&SCO_FIRST ) { memcpy(estatus, &ed->db->status, sizeof(struct status_data)); - if ( !ele->mode ) + if (ele->mode == MD_NONE) estatus->mode = EL_MODE_PASSIVE; else estatus->mode = ele->mode; @@ -3533,9 +3535,12 @@ void status_calc_regen_rate(struct block_list *bl, struct regen_data *regen, str } if (sc->data[SC_MAGNIFICAT]) { +#ifndef RENEWAL // HP Regen applies only in Pre-renewal regen->rate.hp += 1; +#endif regen->rate.sp += 1; } + if (sc->data[SC_GDSKILL_REGENERATION]) { const struct status_change_entry *sce = sc->data[SC_GDSKILL_REGENERATION]; if (!sce->val4) { @@ -4194,15 +4199,19 @@ int status_base_amotion_pc(struct map_session_data *sd, struct status_data *st) float temp; int skill_lv, val = 0; amotion = status->dbs->aspd_base[pc->class2idx(sd->status.class_)][sd->weapontype1]; - if ( sd->status.weapon > MAX_WEAPON_TYPE ) + if ( sd->status.weapon > MAX_SINGLE_WEAPON_TYPE) amotion += status->dbs->aspd_base[pc->class2idx(sd->status.class_)][sd->weapontype2] / 4; if ( sd->status.shield ) - amotion += status->dbs->aspd_base[pc->class2idx(sd->status.class_)][MAX_WEAPON_TYPE]; + amotion += status->dbs->aspd_base[pc->class2idx(sd->status.class_)][MAX_SINGLE_WEAPON_TYPE]; switch ( sd->status.weapon ) { - case W_BOW: case W_MUSICAL: - case W_WHIP: case W_REVOLVER: - case W_RIFLE: case W_GATLING: - case W_SHOTGUN: case W_GRENADE: + case W_BOW: + case W_MUSICAL: + case W_WHIP: + case W_REVOLVER: + case W_RIFLE: + case W_GATLING: + case W_SHOTGUN: + case W_GRENADE: temp = st->dex * st->dex / 7.0f + st->agi * st->agi * 0.5f; break; default: @@ -4216,7 +4225,7 @@ int status_base_amotion_pc(struct map_session_data *sd, struct status_data *st) amotion = ((int)(temp + ((float)(status->calc_aspd(&sd->bl, &sd->sc, 1) + val) * st->agi / 200)) - min(amotion, 200)); #else // base weapon delay - amotion = (sd->status.weapon < MAX_WEAPON_TYPE) + amotion = (sd->status.weapon < MAX_SINGLE_WEAPON_TYPE) ? (status->dbs->aspd_base[pc->class2idx(sd->status.class_)][sd->status.weapon]) // single weapon : (status->dbs->aspd_base[pc->class2idx(sd->status.class_)][sd->weapontype1] + status->dbs->aspd_base[pc->class2idx(sd->status.class_)][sd->weapontype2]) * 7 / 10; // dual-wield @@ -4280,12 +4289,14 @@ unsigned short status_base_atk(const struct block_list *bl, const struct status_ str = (int)(dstr + (float)dex / 5 + (float)st->luk / 3 + (float)BL_UCCAST(BL_PC, bl)->status.base_level / 4); else if (bl->type == BL_MOB) str = dstr + BL_UCCAST(BL_MOB, bl)->level; - //else if (bl->type == BL_MER) // FIXME: What should go here? - // str = dstr + BL_UCCAST(BL_MER, bl)->level; -#else +#if 0 + else if (bl->type == BL_MER) // FIXME: What should go here? + str = dstr + BL_UCCAST(BL_MER, bl)->level; +#endif // 0 +#else // ! RENEWAL if (bl->type == BL_PC) str += dex / 5 + st->luk / 5; -#endif +#endif // RENEWAL return cap_value(str, 0, USHRT_MAX); } @@ -4822,7 +4833,7 @@ unsigned short status_calc_batk(struct block_list *bl, struct status_change *sc, batk += 100 * sc->data[SC_SATURDAY_NIGHT_FEVER]->val1; if (sc->data[SC_BATTLESCROLL]) batk += batk * sc->data[SC_BATTLESCROLL]->val1 / 100; - + // Eden Crystal Synthesis if (sc->data[SC_QUEST_BUFF1]) batk += sc->data[SC_QUEST_BUFF1]->val1; @@ -5007,7 +5018,7 @@ unsigned short status_calc_matk(struct block_list *bl, struct status_change *sc, matk += sc->data[SC_MTF_MATK]->val1; if (sc->data[SC_MYSTICSCROLL]) matk += matk * sc->data[SC_MYSTICSCROLL]->val1 / 100; - + // Eden Crystal Synthesis if (sc->data[SC_QUEST_BUFF1]) matk += sc->data[SC_QUEST_BUFF1]->val1; @@ -5015,7 +5026,7 @@ unsigned short status_calc_matk(struct block_list *bl, struct status_change *sc, matk += sc->data[SC_QUEST_BUFF2]->val1; if (sc->data[SC_QUEST_BUFF3]) matk += sc->data[SC_QUEST_BUFF3]->val1; - + // Geffen Magic Tournament if (sc->data[SC_FENRIR_CARD]) matk += sc->data[SC_FENRIR_CARD]->val1; @@ -5124,7 +5135,7 @@ signed short status_calc_hit(struct block_list *bl, struct status_change *sc, in hit += sc->data[SC_ACARAJE]->val1; if (sc->data[SC_BUCHEDENOEL]) hit += sc->data[SC_BUCHEDENOEL]->val3; - + return (short)cap_value(hit, 1, SHRT_MAX); } @@ -5545,8 +5556,10 @@ unsigned short status_calc_speed(struct block_list *bl, struct status_change *sc if(sc->data[SC_FUSION]) { val = 25; } else if (sd) { - if (pc_isridingpeco(sd) || pc_isridingdragon(sd) || sd->sc.data[SC_ALL_RIDING]) + if (pc_isridingpeco(sd) || pc_isridingdragon(sd)) val = 25;//Same bonus + else if (sd->sc.data[SC_ALL_RIDING]) + val = sd->sc.data[SC_ALL_RIDING]->val1; else if (pc_isridingwug(sd)) val = 15 + 5 * pc->checkskill(sd, RA_WUGRIDER); else if (pc_ismadogear(sd)) { @@ -5625,10 +5638,8 @@ unsigned short status_calc_speed(struct block_list *bl, struct status_change *sc val = max( val, sc->data[SC_MELON_BOMB]->val1 ); if (sc->data[SC_STOMACHACHE]) val = max(val, sc->data[SC_STOMACHACHE]->val2); - - if( sc->data[SC_MARSHOFABYSS] ) // It stacks to other statuses so always put this at the end. - val = max( 50, val + 10 * sc->data[SC_MARSHOFABYSS]->val1 ); - + if (sc->data[SC_MARSHOFABYSS]) // It stacks to other statuses so always put this at the end. + val = max(50, val + 10 * sc->data[SC_MARSHOFABYSS]->val1); if (sc->data[SC_MOVHASTE_POTION]) { // Doesn't affect the movement speed by Quagmire, Decrease Agi, Slow Grace [Frost] if (sc->data[SC_DEC_AGI] || sc->data[SC_QUAGMIRE] || sc->data[SC_DONTFORGETME]) return 0; @@ -6217,22 +6228,36 @@ unsigned char status_calc_attack_element(struct block_list *bl, struct status_ch return (unsigned char)cap_value(element,0,UCHAR_MAX); } -unsigned short status_calc_mode(struct block_list *bl, struct status_change *sc, int mode) +/** + * Calculates the new mode, based on status changes. + * + * @param bl The current unit. + * @param sc The current status change list. + * @param mode The starting mode. + * @return The calculated mode. + */ +uint32 status_calc_mode(const struct block_list *bl, const struct status_change *sc, uint32 mode) { - if(!sc || !sc->count) - return mode; - if(sc->data[SC_MODECHANGE]) { - if (sc->data[SC_MODECHANGE]->val2) + if (sc == NULL || sc->count == 0) + return mode & MD_MASK; + if (sc->data[SC_MODECHANGE] != NULL) { + if (sc->data[SC_MODECHANGE]->val2 != 0) mode = sc->data[SC_MODECHANGE]->val2; //Set mode if (sc->data[SC_MODECHANGE]->val3) - mode|= sc->data[SC_MODECHANGE]->val3; //Add mode + mode |= sc->data[SC_MODECHANGE]->val3; //Add mode if (sc->data[SC_MODECHANGE]->val4) - mode&=~sc->data[SC_MODECHANGE]->val4; //Del mode + mode &= ~sc->data[SC_MODECHANGE]->val4; //Del mode } - return cap_value(mode,0,USHRT_MAX); + return mode & MD_MASK; } -const char *status_get_name(struct block_list *bl) +/** + * Returns the name of the given bl. + * + * @param bl The requested bl. + * @return The bl's name or NULL if not available. + */ +const char *status_get_name(const struct block_list *bl) { nullpo_ret(bl); switch (bl->type) { @@ -6248,7 +6273,7 @@ const char *status_get_name(struct block_list *bl) case BL_HOM: return BL_UCCAST(BL_HOM, bl)->homunculus.name; case BL_NPC: return BL_UCCAST(BL_NPC, bl)->name; } - return "Unknown"; + return NULL; } /*========================================== @@ -6257,7 +6282,7 @@ const char *status_get_name(struct block_list *bl) * 0 = fail * class_id = success *------------------------------------------*/ -int status_get_class(struct block_list *bl) +int status_get_class(const struct block_list *bl) { nullpo_ret(bl); switch (bl->type) { @@ -6277,7 +6302,7 @@ int status_get_class(struct block_list *bl) * 1 = fail * level = success *------------------------------------------*/ -int status_get_lv(struct block_list *bl) +int status_get_lv(const struct block_list *bl) { nullpo_ret(bl); switch (bl->type) { @@ -6367,7 +6392,8 @@ unsigned short status_get_speed(struct block_list *bl) return status->get_status_data(bl)->speed; } -int status_get_party_id(struct block_list *bl) { +int status_get_party_id(const struct block_list *bl) +{ nullpo_ret(bl); switch (bl->type) { case BL_PC: @@ -6422,7 +6448,7 @@ int status_get_party_id(struct block_list *bl) { return 0; } -int status_get_guild_id(struct block_list *bl) +int status_get_guild_id(const struct block_list *bl) { nullpo_ret(bl); switch (bl->type) { @@ -6488,7 +6514,8 @@ int status_get_guild_id(struct block_list *bl) return 0; } -int status_get_emblem_id(struct block_list *bl) { +int status_get_emblem_id(const struct block_list *bl) +{ nullpo_ret(bl); switch (bl->type) { case BL_PC: @@ -6549,7 +6576,7 @@ int status_get_emblem_id(struct block_list *bl) { return 0; } -int status_get_mexp(struct block_list *bl) +int status_get_mexp(const struct block_list *bl) { nullpo_ret(bl); if (bl->type == BL_MOB) @@ -6559,7 +6586,7 @@ int status_get_mexp(struct block_list *bl) return 0; } -int status_get_race2(struct block_list *bl) +int status_get_race2(const struct block_list *bl) { nullpo_ret(bl); if (bl->type == BL_MOB) @@ -7427,20 +7454,24 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t break; case SC_MODECHANGE: { - int mode; - struct status_data *bst = status->get_base_status(bl); - if (!bst) return 0; - if (sc->data[type]) { - //Pile up with previous values. - if(!val2) val2 = sc->data[type]->val2; + uint32 mode = MD_NONE; + const struct status_data *bst = status->get_base_status(bl); + if (bst == NULL) + return 0; + if (sc->data[type] != NULL) { + // Pile up with previous values. + if (val2 == 0) + val2 = sc->data[type]->val2; val3 |= sc->data[type]->val3; val4 |= sc->data[type]->val4; } - mode = val2 ? val2 : bst->mode; //Base mode - if (val4) mode&=~val4; //Del mode - if (val3) mode|= val3; //Add mode + mode = val2 != 0 ? val2 : bst->mode; // Base mode + if (val4 != 0) + mode &= ~val4; //Del mode + if (val3 != 0) + mode |= val3; //Add mode if (mode == bst->mode) { //No change. - if (sc->data[type]) //Abort previous status + if (sc->data[type] != NULL) //Abort previous status return status_change_end(bl, type, INVALID_TIMER); return 0; } @@ -8042,23 +8073,23 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t } } //val4 signals infinite endure (if val4 == 2 it is infinite endure from Berserk) - if( val4 ) - tick = -1; + if (val4) + tick = INFINITE_DURATION; break; case SC_AUTOBERSERK: if (st->hp < st->max_hp>>2 && (!sc->data[SC_PROVOKE] || sc->data[SC_PROVOKE]->val2==0)) sc_start4(src,bl,SC_PROVOKE,100,10,1,0,0,60000); - tick = -1; + tick = INFINITE_DURATION; break; case SC_CRUCIS: val2 = 10 + 4*val1; //Def reduction - tick = -1; + tick = INFINITE_DURATION; clif->emotion(bl,E_SWT); break; case SC_MAXIMIZEPOWER: tick_time = val2 = tick>0?tick:60000; - tick = -1; // duration sent to the client should be infinite + tick = INFINITE_DURATION; // duration sent to the client should be infinite break; case SC_EDP: // [Celest] //Chance to Poison enemies. @@ -8099,7 +8130,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t break; case SC_SACRIFICE: val2 = 5; //Lasts 5 hits - tick = -1; + tick = INFINITE_DURATION; break; case SC_ENCHANTPOISON: val2= 250+50*val1; //Poisoning Chance (2.5+0.5%) in 1/10000 rate @@ -8352,7 +8383,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t if (!sd) //Monsters should be able to walk with no penalties. [Skotlex] val1 = 10; tick_time = val2 = tick>0?tick:60000; //SP consumption rate. - tick = -1; // duration sent to the client should be infinite + tick = INFINITE_DURATION; // duration sent to the client should be infinite val3 = 0; // unused, previously walk speed adjustment //val4&1 signals the presence of a wall. //val4&2 makes cloak not end on normal attacks [Skotlex] @@ -8383,7 +8414,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t case SC_TURNKICK_READY: case SC_DODGE_READY: case SC_PUSH_CART: - tick = -1; + tick = INFINITE_DURATION; break; case SC_AUTOGUARD: @@ -8437,7 +8468,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t val2 = 12; //SP cost val4 = 10000; //Decrease at 10secs intervals. val3 = tick/val4; - tick = -1; // duration sent to the client should be infinite + tick = INFINITE_DURATION; // duration sent to the client should be infinite tick_time = val4; // [GodLesZ] tick time break; case SC_PARRYING: @@ -8533,12 +8564,12 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t case SC_SWORDREJECT: val2 = 15*val1; //Reflect chance val3 = 3; //Reflections - tick = -1; + tick = INFINITE_DURATION; break; case SC_MEMORIZE: val2 = 5; //Memorized casts. - tick = -1; + tick = INFINITE_DURATION; break; case SC_GRAVITATION: @@ -8651,7 +8682,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t val3 = (int)(currenttick&0x00000000ffffffffLL); val4 = (int)((currenttick&0xffffffff00000000LL)>>32); } - tick = -1; + tick = INFINITE_DURATION; break; case SC_KAAHI: val2 = 200*val1; //HP heal @@ -8666,7 +8697,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t break; case SC_TRICKDEAD: if (vd) vd->dead_sit = 1; - tick = -1; + tick = INFINITE_DURATION; break; case SC_CONCENTRATION: val2 = 2 + val1; @@ -8986,8 +9017,8 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t tick_time = 3000; // [GodLesZ] tick time break; case SC_CLOAKINGEXCEED: - val2 = ( val1 + 1 ) / 2; // Hits - val3 = 90 + val1 * 10; // Walk speed + val2 = (val1 + 1) / 2; // Hits + val3 = (val1 - 1) * 10; // Walk speed if (bl->type == BL_PC) val4 |= battle_config.pc_cloak_check_type&7; else @@ -9059,7 +9090,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t val3 = (int)(currenttick&0x00000000ffffffffLL); val4 = (int)((currenttick&0xffffffff00000000LL)>>32); } - tick = -1; + tick = INFINITE_DURATION; break; case SC__REPRODUCE: val4 = tick / 1000; @@ -9256,7 +9287,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t case SC_FORCEOFVANGUARD: val2 = 8 + 12 * val1; // Chance val3 = 5 + 2 * val1; // Max rage counters - tick = -1; //endless duration in the client + tick = INFINITE_DURATION; //endless duration in the client break; case SC_EXEEDBREAK: if( sd ){ @@ -9522,7 +9553,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t break; case SC_NEUTRALBARRIER: tick_time = tick; - tick = -1; + tick = INFINITE_DURATION; break; case SC_GOLDENE_FERSE: val2 = 10 + 10*val1; //max hp bonus @@ -9554,7 +9585,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t sc_start(src, bl, SC_ENDURE, 100, val1, tick); //start endure for same duration break; case SC_STYLE_CHANGE: //[Lighta] need real info - tick = -1; + tick = INFINITE_DURATION; if(val2 == MH_MD_FIGHTING) val2 = MH_MD_GRAPPLING; else val2 = MH_MD_FIGHTING; break; @@ -9590,7 +9621,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t val1 = MOBID_PORING; break; case SC_ALL_RIDING: - tick = -1; + tick = INFINITE_DURATION; break; case SC_FLASHCOMBO: /** @@ -10593,7 +10624,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const // need to do it here. if( sd ) { map->quit(sd); - // Because map->quit calls status_change_end with tid -1 + // Because map->quit calls status_change_end with tid INVALID_TIMER // from here it's not neccesary to continue return 1; } @@ -10623,7 +10654,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const case SC_WHITEIMPRISON: { struct block_list* src = map->id2bl(sce->val2); - if( tid == -1 || !src) + if (tid == INVALID_TIMER || src == NULL) break; // Terminated by Damage status_fix_damage(src,bl,400*sce->val1,clif->damage(bl,bl,0,0,400*sce->val1,0,BDT_NORMAL,0)); } @@ -10633,7 +10664,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const struct unit_data *ud = unit->bl2ud(bl); if (ud) { ud->state.running = 0; - if (ud->walktimer != -1) + if (ud->walktimer != INVALID_TIMER) unit->stop_walking(bl, STOPWALKING_FLAG_FIXPOS); } } @@ -11015,7 +11046,7 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) { st = status->get_status_data(bl); if (!sc || (sce = sc->data[type]) == NULL) { - ShowDebug("status_change_timer: Null pointer id: %d data: %"PRIdPTR" bl-type: %d\n", id, data, bl->type); + ShowDebug("status_change_timer: Null pointer id: %d data: %"PRIdPTR" bl-type: %u\n", id, data, bl->type); return 0; } @@ -12298,8 +12329,9 @@ int status_change_spread( struct block_list *src, struct block_list *bl ) { if (td == NULL || td->func != status->change_timer || DIFF_TICK(td->tick,tick) < 0) continue; data.tick = DIFF_TICK32(td->tick,tick); - } else - data.tick = INVALID_TIMER; + } else { + data.tick = INFINITE_DURATION; + } break; // Special cases case SC_POISON: @@ -12557,9 +12589,9 @@ int status_get_sc_type(sc_type type) { return status->dbs->sc_conf[type]; } -void status_read_job_db_sub(int idx, const char *name, config_setting_t *jdb) +void status_read_job_db_sub(int idx, const char *name, struct config_setting_t *jdb) { - config_setting_t *temp = NULL; + struct config_setting_t *temp = NULL; int i32 = 0; struct { @@ -12591,7 +12623,7 @@ void status_read_job_db_sub(int idx, const char *name, config_setting_t *jdb) { "FuumaShuriken", W_HUUMA }, { "TwoHandRod", W_2HSTAFF }, #ifdef RENEWAL_ASPD - { "Shield", MAX_WEAPON_TYPE } + { "Shield", MAX_SINGLE_WEAPON_TYPE } #endif }; @@ -12699,7 +12731,7 @@ void status_read_job_db_sub(int idx, const char *name, config_setting_t *jdb) if ((temp = libconfig->setting_get_member(jdb, "BaseASPD"))) { int widx = 0; - config_setting_t *wpn = NULL; + struct config_setting_t *wpn = NULL; while ((wpn = libconfig->setting_get_elem(temp, widx++))) { int w, wlen = ARRAYLENGTH(wnames); const char *wname = config_setting_name(wpn); @@ -12715,7 +12747,7 @@ void status_read_job_db_sub(int idx, const char *name, config_setting_t *jdb) if ((temp = libconfig->setting_get_member(jdb, "HPTable"))) { int level = 0, avg_increment, base; - config_setting_t *hp = NULL; + struct config_setting_t *hp = NULL; while (level <= MAX_LEVEL && (hp = libconfig->setting_get_elem(temp, level)) != NULL) { i32 = libconfig->setting_get_int(hp); status->dbs->HP_table[idx][++level] = min(i32, battle_config.max_hp); @@ -12735,7 +12767,7 @@ void status_read_job_db_sub(int idx, const char *name, config_setting_t *jdb) if ((temp = libconfig->setting_get_member(jdb, "SPTable"))) { int level = 0, avg_increment, base; - config_setting_t *sp = NULL; + struct config_setting_t *sp = NULL; while (level <= MAX_LEVEL && (sp = libconfig->setting_get_elem(temp, level)) != NULL) { i32 = libconfig->setting_get_int(sp); status->dbs->SP_table[idx][++level] = min(i32, battle_config.max_sp); @@ -12763,18 +12795,17 @@ void status_read_job_db_sub(int idx, const char *name, config_setting_t *jdb) *------------------------------------------*/ void status_read_job_db(void) { /* [malufett/Hercules] */ int i = 0; - config_t job_db_conf; - config_setting_t *jdb = NULL; + struct config_t job_db_conf; + struct config_setting_t *jdb = NULL; #ifdef RENEWAL_ASPD const char *config_filename = "db/re/job_db.conf"; #else const char *config_filename = "db/pre-re/job_db.conf"; #endif - if ( libconfig->read_file(&job_db_conf, config_filename) ) { - ShowError("can't read %s\n", config_filename); + if (!libconfig->load_file(&job_db_conf, config_filename)) return; - } + while ( (jdb = libconfig->setting_get_elem(job_db_conf.root, i++)) ) { int class_, idx; const char *name = config_setting_name(jdb); @@ -12815,7 +12846,7 @@ bool status_readdb_sizefix(char* fields[], int columns, int current) { unsigned int i; - for(i = 0; i < MAX_WEAPON_TYPE; i++) + for(i = 0; i < MAX_SINGLE_WEAPON_TYPE; i++) { status->dbs->atkmods[current][i] = atoi(fields[i]); } @@ -12825,24 +12856,24 @@ bool status_readdb_sizefix(char* fields[], int columns, int current) /** * Processes a refine_db.conf entry. * - * @param *r Libconfig setting entry. It is expected to be valid and it - * won't be freed (it is care of the caller to do so if - * necessary) - * @param n Ordinal number of the entry, to be displayed in case of - * validation errors. - * @param *source Source of the entry (file name), to be displayed in case of - * validation errors. + * @param r Libconfig setting entry. It is expected to be valid and it + * won't be freed (it is care of the caller to do so if + * necessary) + * @param n Ordinal number of the entry, to be displayed in case of + * validation errors. + * @param source Source of the entry (file name), to be displayed in case of + * validation errors. * @return # of the validated entry, or 0 in case of failure. */ -int status_readdb_refine_libconfig_sub(config_setting_t *r, const char *name, const char *source) +int status_readdb_refine_libconfig_sub(struct config_setting_t *r, const char *name, const char *source) { - config_setting_t *rate = NULL; + struct config_setting_t *rate = NULL; int type = REFINE_TYPE_ARMOR, bonus_per_level = 0, rnd_bonus_v = 0, rnd_bonus_lv = 0; char lv[4]; nullpo_ret(r); nullpo_ret(name); nullpo_ret(source); - + if (strncmp(name, "Armors", 6) == 0) { type = REFINE_TYPE_ARMOR; } else if (strncmp(name, "WeaponLevel", 11) != 0 || !strspn(&name[strlen(name)-1], "0123456789") || (type = atoi(strncpy(lv, name+11, 2))) == REFINE_TYPE_ARMOR) { @@ -12867,7 +12898,7 @@ int status_readdb_refine_libconfig_sub(config_setting_t *r, const char *name, co } if ((rate=libconfig->setting_get_member(r, "Rates")) != NULL && config_setting_is_group(rate)) { - config_setting_t *t = NULL; + struct config_setting_t *t = NULL; bool duplicate[MAX_REFINE]; int bonus[MAX_REFINE], rnd_bonus[MAX_REFINE], chance[MAX_REFINE]; int i; @@ -12927,18 +12958,17 @@ int status_readdb_refine_libconfig_sub(config_setting_t *r, const char *name, co */ int status_readdb_refine_libconfig(const char *filename) { bool duplicate[REFINE_TYPE_MAX]; - config_t refine_db_conf; - config_setting_t *r; + struct config_t refine_db_conf; + struct config_setting_t *r; char filepath[256]; int i = 0, count = 0,type = 0; - + sprintf(filepath, "%s/%s", map->db_path, filename); - memset(&duplicate,0,sizeof(duplicate)); - if( libconfig->read_file(&refine_db_conf, filepath) ) { - ShowError("can't read %s\n", filepath); + if (!libconfig->load_file(&refine_db_conf, filepath)) return 0; - } - + + memset(&duplicate,0,sizeof(duplicate)); + while((r = libconfig->setting_get_elem(refine_db_conf.root,i++))) { char *name = config_setting_name(r); if((type=status->readdb_refine_libconfig_sub(r, name, filename))) { @@ -12950,7 +12980,7 @@ int status_readdb_refine_libconfig(const char *filename) { } libconfig->destroy(&refine_db_conf); ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, filename); - + return count; } @@ -12989,16 +13019,16 @@ int status_readdb(void) memset(status->dbs->job_bonus,0,sizeof(status->dbs->job_bonus)); // Job-specific stats bonus } for ( i = 0; i < CLASS_COUNT; i++ ) { - for ( j = 0; j < MAX_WEAPON_TYPE; j++ ) + for ( j = 0; j < MAX_SINGLE_WEAPON_TYPE; j++ ) status->dbs->aspd_base[i][j] = 2000; #ifdef RENEWAL_ASPD - status->dbs->aspd_base[i][MAX_WEAPON_TYPE] = 0; + status->dbs->aspd_base[i][MAX_SINGLE_WEAPON_TYPE] = 0; #endif } // size_fix.txt for(i = 0; i < ARRAYLENGTH(status->dbs->atkmods); i++) - for(j = 0; j < MAX_WEAPON_TYPE; j++) + for(j = 0; j < MAX_SINGLE_WEAPON_TYPE; j++) status->dbs->atkmods[i][j] = 100; // refine_db.txt @@ -13013,7 +13043,7 @@ int status_readdb(void) // read databases // sv->readdb(map->db_path, "job_db2.txt", ',', 1, 1+MAX_LEVEL, -1, status->readdb_job2); - sv->readdb(map->db_path, DBPATH"size_fix.txt", ',', MAX_WEAPON_TYPE, MAX_WEAPON_TYPE, ARRAYLENGTH(status->dbs->atkmods), status->readdb_sizefix); + sv->readdb(map->db_path, DBPATH"size_fix.txt", ',', MAX_SINGLE_WEAPON_TYPE, MAX_SINGLE_WEAPON_TYPE, ARRAYLENGTH(status->dbs->atkmods), status->readdb_sizefix); status->readdb_refine_libconfig(DBPATH"refine_db.conf"); sv->readdb(map->db_path, "sc_config.txt", ',', 2, 2, SC_MAX, status->readdb_scconfig); status->read_job_db(); diff --git a/src/map/status.h b/src/map/status.h index 51ca1e78b..2b932b149 100644 --- a/src/map/status.h +++ b/src/map/status.h @@ -21,11 +21,11 @@ #ifndef MAP_STATUS_H #define MAP_STATUS_H -#include "common/conf.h" #include "common/hercules.h" #include "common/mmo.h" // NEW_CARTS struct block_list; +struct config_setting_t; struct elemental_data; struct homun_data; struct mercenary_data; @@ -758,13 +758,13 @@ typedef enum sc_type { SC_MTF_MSP, SC_MTF_PUMPKIN, SC_MTF_HITFLEE, - + SC_LJOSALFAR, SC_MERMAID_LONGING, - + SC_ACARAJE, // 590 SC_TARGET_ASPD, - + // Geffen Scrolls SC_SKELSCROLL, SC_DISTRUCTIONSCROLL, @@ -775,25 +775,25 @@ typedef enum sc_type { SC_ARMORSCROLL, SC_FREYJASCROLL, SC_SOULSCROLL, // 600 - + // Eden Crystal Synthesis SC_QUEST_BUFF1, SC_QUEST_BUFF2, SC_QUEST_BUFF3, - + // Geffen Magic Tournament SC_GEFFEN_MAGIC1, SC_GEFFEN_MAGIC2, SC_GEFFEN_MAGIC3, SC_FENRIR_CARD, - + SC_ATKER_ASPD, SC_ATKER_MOVESPEED, SC_FOOD_CRITICALSUCCESSVALUE, // 610 SC_CUP_OF_BOZA, SC_OVERLAPEXPUP, SC_MORA_BUFF, - + // MVP Scrolls SC_MVPCARD_TAOGUNKA, SC_MVPCARD_MISTRESS, @@ -1789,9 +1789,13 @@ enum si_type { //SI_DORAM_BUF_01 = 935, //SI_DORAM_BUF_02 = 936, //SI_SPRITEMABLE = 937, + //SI_EP16_2_BUFF_SS = 963, + //SI_EP16_2_BUFF_SC = 964, + //SI_EP16_2_BUFF_AC = 965, SI_MAX, }; + // JOINTBEAT stackable ailments enum e_joint_break { @@ -1804,26 +1808,33 @@ enum e_joint_break BREAK_FLAGS = BREAK_ANKLE | BREAK_WRIST | BREAK_KNEE | BREAK_SHOULDER | BREAK_WAIST | BREAK_NECK, }; - -//Mode definitions to clear up code reading. [Skotlex] +/** + * Mob mode definitions. [Skotlex] + * + * @see doc/mob_db_mode_list.txt for a description of each mode. + */ enum e_mode { - MD_CANMOVE = 0x0001, - MD_LOOTER = 0x0002, - MD_AGGRESSIVE = 0x0004, - MD_ASSIST = 0x0008, - MD_CASTSENSOR_IDLE = 0x0010, - MD_BOSS = 0x0020, - MD_PLANT = 0x0040, - MD_CANATTACK = 0x0080, - MD_DETECTOR = 0x0100, - MD_CASTSENSOR_CHASE = 0x0200, - MD_CHANGECHASE = 0x0400, - MD_ANGRY = 0x0800, - MD_CHANGETARGET_MELEE = 0x1000, - MD_CHANGETARGET_CHASE = 0x2000, - MD_TARGETWEAK = 0x4000, - MD_MASK = 0xFFFF, + MD_NONE = 0x00000000, + MD_CANMOVE = 0x00000001, + MD_LOOTER = 0x00000002, + MD_AGGRESSIVE = 0x00000004, + MD_ASSIST = 0x00000008, + MD_CASTSENSOR_IDLE = 0x00000010, + MD_BOSS = 0x00000020, + MD_PLANT = 0x00000040, + MD_CANATTACK = 0x00000080, + MD_DETECTOR = 0x00000100, + MD_CASTSENSOR_CHASE = 0x00000200, + MD_CHANGECHASE = 0x00000400, + MD_ANGRY = 0x00000800, + MD_CHANGETARGET_MELEE = 0x00001000, + MD_CHANGETARGET_CHASE = 0x00002000, + MD_TARGETWEAK = 0x00004000, + MD_NOKNOCKBACK = 0x00008000, + //MD_RANDOMTARGET = 0x00010000, // Not implemented + // Note: This should be kept within INT_MAX, since it's often cast to int. + MD_MASK = 0x7FFFFFFF, }; //Status change option definitions (options are what makes status changes visible to chars @@ -1975,8 +1986,8 @@ struct status_data { batk, matk_min, matk_max, speed, - amotion, adelay, dmotion, - mode; + amotion, adelay, dmotion; + uint32 mode; short hit, flee, cri, flee2, def2, mdef2, @@ -2151,7 +2162,7 @@ BEGIN_ZEROED_BLOCK; /* Everything within this block will be memset to 0 when sta int max_weight_base[CLASS_COUNT]; int HP_table[CLASS_COUNT][MAX_LEVEL + 1]; int SP_table[CLASS_COUNT][MAX_LEVEL + 1]; - int aspd_base[CLASS_COUNT][MAX_WEAPON_TYPE+1]; // +1 for RENEWAL_ASPD + int aspd_base[CLASS_COUNT][MAX_SINGLE_WEAPON_TYPE+1]; // +1 for RENEWAL_ASPD sc_type Skill2SCTable[MAX_SKILL]; // skill -> status int IconChangeTable[SC_MAX]; // status -> "icon" (icon is a bit of a misnomer, since there exist values with no icon associated) unsigned int ChangeFlagTable[SC_MAX]; // status -> flags @@ -2161,7 +2172,7 @@ BEGIN_ZEROED_BLOCK; /* Everything within this block will be memset to 0 when sta /* */ struct s_refine_info refine_info[REFINE_TYPE_MAX]; /* */ - int atkmods[3][MAX_WEAPON_TYPE];//ATK weapon modification for size (size_fix.txt) + int atkmods[3][MAX_SINGLE_WEAPON_TYPE];//ATK weapon modification for size (size_fix.txt) char job_bonus[CLASS_COUNT][MAX_LEVEL]; sc_conf_type sc_conf[SC_MAX]; END_ZEROED_BLOCK; /* End */ @@ -2208,17 +2219,17 @@ struct status_interface { struct regen_data * (*get_regen_data) (struct block_list *bl); struct status_data * (*get_status_data) (struct block_list *bl); struct status_data * (*get_base_status) (struct block_list *bl); - const char * (*get_name) (struct block_list *bl); - int (*get_class) (struct block_list *bl); - int (*get_lv) (struct block_list *bl); + const char *(*get_name) (const struct block_list *bl); + int (*get_class) (const struct block_list *bl); + int (*get_lv) (const struct block_list *bl); defType (*get_def) (struct block_list *bl); unsigned short (*get_speed) (struct block_list *bl); unsigned char (*calc_attack_element) (struct block_list *bl, struct status_change *sc, int element); - int (*get_party_id) (struct block_list *bl); - int (*get_guild_id) (struct block_list *bl); - int (*get_emblem_id) (struct block_list *bl); - int (*get_mexp) (struct block_list *bl); - int (*get_race2) (struct block_list *bl); + int (*get_party_id) (const struct block_list *bl); + int (*get_guild_id) (const struct block_list *bl); + int (*get_emblem_id) (const struct block_list *bl); + int (*get_mexp) (const struct block_list *bl); + int (*get_race2) (const struct block_list *bl); struct view_data * (*get_viewdata) (struct block_list *bl); void (*set_viewdata) (struct block_list *bl, int class_); void (*change_init) (struct block_list *bl); @@ -2264,8 +2275,8 @@ struct status_interface { void (*initDummyData) (void); int (*base_amotion_pc) (struct map_session_data *sd, struct status_data *st); unsigned short (*base_atk) (const struct block_list *bl, const struct status_data *st); - unsigned int (*get_base_maxhp) (struct map_session_data *sd, struct status_data *st); - unsigned int (*get_base_maxsp) (struct map_session_data *sd, struct status_data *st); + unsigned int (*get_base_maxhp) (const struct map_session_data *sd, const struct status_data *st); + unsigned int (*get_base_maxsp) (const struct map_session_data *sd, const struct status_data *st); int (*calc_npc_) (struct npc_data *nd, enum e_status_calc_opt opt); unsigned short (*calc_str) (struct block_list *bl, struct status_change *sc, int str); unsigned short (*calc_agi) (struct block_list *bl, struct status_change *sc, int agi); @@ -2288,7 +2299,7 @@ struct status_interface { unsigned int (*calc_maxsp) (struct block_list *bl, struct status_change *sc, unsigned int maxsp); unsigned char (*calc_element) (struct block_list *bl, struct status_change *sc, int element); unsigned char (*calc_element_lv) (struct block_list *bl, struct status_change *sc, int lv); - unsigned short (*calc_mode) (struct block_list *bl, struct status_change *sc, int mode); + uint32 (*calc_mode) (const struct block_list *bl, const struct status_change *sc, uint32 mode); unsigned short (*calc_ematk) (struct block_list *bl, struct status_change *sc, int matk); void (*calc_bl_main) (struct block_list *bl, int flag); void (*display_add) (struct map_session_data *sd, enum sc_type type, int dval1, int dval2, int dval3); @@ -2298,10 +2309,10 @@ struct status_interface { bool (*readdb_job2) (char *fields[], int columns, int current); bool (*readdb_sizefix) (char *fields[], int columns, int current); int (*readdb_refine_libconfig) (const char *filename); - int (*readdb_refine_libconfig_sub) (config_setting_t *r, const char *name, const char *source); + int (*readdb_refine_libconfig_sub) (struct config_setting_t *r, const char *name, const char *source); bool (*readdb_scconfig) (char *fields[], int columns, int current); void (*read_job_db) (void); - void (*read_job_db_sub) (int idx, const char *name, config_setting_t *jdb); + void (*read_job_db_sub) (int idx, const char *name, struct config_setting_t *jdb); }; #ifdef HERCULES_CORE diff --git a/src/map/storage.c b/src/map/storage.c index f938a41ad..ceac85916 100644 --- a/src/map/storage.c +++ b/src/map/storage.c @@ -52,8 +52,8 @@ struct guild_storage_interface *gstorage; *------------------------------------------*/ int storage_comp_item(const void *i1_, const void *i2_) { - struct item *i1 = (struct item *)i1_; - struct item *i2 = (struct item *)i2_; + const struct item *i1 = (const struct item *)i1_; + const struct item *i2 = (const struct item *)i2_; if (i1->nameid == i2->nameid) return 0; diff --git a/src/map/unit.c b/src/map/unit.c index 03334f7f3..9a698b77e 100644 --- a/src/map/unit.c +++ b/src/map/unit.c @@ -121,7 +121,7 @@ int unit_walktoxy_sub(struct block_list *bl) #ifdef OFFICIAL_WALKPATH if( !path->search_long(NULL, bl, bl->m, bl->x, bl->y, ud->to_x, ud->to_y, CELL_CHKNOPASS) // Check if there is an obstacle between - && wpd.path_len > 14 // Official number of walkable cells is 14 if and only if there is an obstacle between. [malufett] + && wpd.path_len > 14 // Official number of walkable cells is 14 if and only if there is an obstacle between. [malufett] && (bl->type != BL_NPC) ) // If type is a NPC, please disregard. return 0; #endif @@ -937,7 +937,7 @@ int unit_warp(struct block_list *bl,short m,short x,short y,clr_type type) if (x<0 || y<0) { //Random map position. if (!map->search_freecell(NULL, m, &x, &y, -1, -1, 1)) { - ShowWarning("unit_warp failed. Unit Id:%d/Type:%d, target position map %d (%s) at [%d,%d]\n", bl->id, bl->type, m, map->list[m].name, x, y); + ShowWarning("unit_warp failed. Unit Id:%d/Type:%u, target position map %d (%s) at [%d,%d]\n", bl->id, bl->type, m, map->list[m].name, x, y); return 2; } @@ -947,7 +947,7 @@ int unit_warp(struct block_list *bl,short m,short x,short y,clr_type type) if (!map->search_freecell(NULL, m, &x, &y, 4, 4, 1)) { //Can't find a nearby cell - ShowWarning("unit_warp failed. Unit Id:%d/Type:%d, target position map %d (%s) at [%d,%d]\n", bl->id, bl->type, m, map->list[m].name, x, y); + ShowWarning("unit_warp failed. Unit Id:%d/Type:%u, target position map %d (%s) at [%d,%d]\n", bl->id, bl->type, m, map->list[m].name, x, y); return 2; } } @@ -1976,6 +1976,7 @@ bool unit_can_reach_pos(struct block_list *bl,int x,int y, int easy) bool unit_can_reach_bl(struct block_list *bl,struct block_list *tbl, int range, int easy, short *x, short *y) { short dx,dy; + struct walkpath_data wpd; nullpo_retr(false, bl); nullpo_retr(false, tbl); @@ -2005,7 +2006,20 @@ bool unit_can_reach_bl(struct block_list *bl,struct block_list *tbl, int range, if (x) *x = tbl->x-dx; if (y) *y = tbl->y-dy; - return path->search(NULL,bl,bl->m,bl->x,bl->y,tbl->x-dx,tbl->y-dy,easy,CELL_CHKNOREACH); + + if (!path->search(&wpd,bl,bl->m,bl->x,bl->y,tbl->x-dx,tbl->y-dy,easy,CELL_CHKNOREACH)) + return false; + +#ifdef OFFICIAL_WALKPATH + if( !path->search_long(NULL, bl, bl->m, bl->x, bl->y, tbl->x-dx, tbl->y-dy, CELL_CHKNOPASS) // Check if there is an obstacle between + && wpd.path_len > 14 // Official number of walkable cells is 14 if and only if there is an obstacle between. [malufett] + && (bl->type != BL_NPC) ) // If type is a NPC, please disregard. + return false; +#endif + + return true; + + } /*========================================== * Calculates position of Pet/Mercenary/Homunculus/Elemental diff --git a/src/map/vending.c b/src/map/vending.c index 810e6b07a..2346932ba 100644 --- a/src/map/vending.c +++ b/src/map/vending.c @@ -89,7 +89,7 @@ void vending_vendinglistreq(struct map_session_data* sd, unsigned int id) { *------------------------------------------*/ void vending_purchasereq(struct map_session_data* sd, int aid, unsigned int uid, const uint8* data, int count) { int i, j, cursor, w, new_ = 0, blank, vend_list[MAX_VENDING]; - double z; + int64 z; struct s_vending vend[MAX_VENDING]; // against duplicate packets struct map_session_data* vsd = map->id2sd(aid); @@ -116,11 +116,11 @@ void vending_purchasereq(struct map_session_data* sd, int aid, unsigned int uid, memcpy(&vend, &vsd->vending, sizeof(vsd->vending)); // copy vending list // some checks - z = 0.; // zeny counter + z = 0; // zeny counter w = 0; // weight counter for( i = 0; i < count; i++ ) { - short amount = *(uint16*)(data + 4*i + 0); - short idx = *(uint16*)(data + 4*i + 2); + short amount = *(const uint16*)(data + 4*i + 0); + short idx = *(const uint16*)(data + 4*i + 2); idx -= 2; if( amount <= 0 ) @@ -136,12 +136,12 @@ void vending_purchasereq(struct map_session_data* sd, int aid, unsigned int uid, else vend_list[i] = j; - z += ((double)vsd->vending[j].value * (double)amount); - if( z > (double)sd->status.zeny || z < 0. || z > (double)MAX_ZENY ) { + z += (int64)vsd->vending[j].value * amount; + if (z > sd->status.zeny || z < 0 || z > MAX_ZENY) { clif->buyvending(sd, idx, amount, 1); // you don't have enough zeny return; } - if( z + (double)vsd->status.zeny > (double)MAX_ZENY && !battle_config.vending_over_max ) { + if (z > MAX_ZENY - vsd->status.zeny && !battle_config.vending_over_max) { clif->buyvending(sd, idx, vsd->vending[j].amount, 4); // too much zeny = overflow return; @@ -181,12 +181,12 @@ void vending_purchasereq(struct map_session_data* sd, int aid, unsigned int uid, pc->payzeny(sd, (int)z, LOG_TYPE_VENDING, vsd); if( battle_config.vending_tax ) - z -= z * (battle_config.vending_tax/10000.); + z -= apply_percentrate64(z, battle_config.vending_tax, 10000); pc->getzeny(vsd, (int)z, LOG_TYPE_VENDING, sd); for( i = 0; i < count; i++ ) { - short amount = *(uint16*)(data + 4*i + 0); - short idx = *(uint16*)(data + 4*i + 2); + short amount = *(const uint16*)(data + 4*i + 0); + short idx = *(const uint16*)(data + 4*i + 2); idx -= 2; // vending item @@ -266,9 +266,9 @@ void vending_openvending(struct map_session_data* sd, const char* message, const // filter out invalid items i = 0; for( j = 0; j < count; j++ ) { - short index = *(uint16*)(data + 8*j + 0); - short amount = *(uint16*)(data + 8*j + 2); - unsigned int value = *(uint32*)(data + 8*j + 4); + short index = *(const uint16*)(data + 8*j + 0); + short amount = *(const uint16*)(data + 8*j + 2); + unsigned int value = *(const uint32*)(data + 8*j + 4); index -= 2; // offset adjustment (client says that the first cart position is 2) |