summaryrefslogtreecommitdiff
path: root/src/map
diff options
context:
space:
mode:
Diffstat (limited to 'src/map')
-rw-r--r--src/map/Makefile.in21
-rw-r--r--src/map/atcommand.c115
-rw-r--r--src/map/atcommand.h6
-rw-r--r--src/map/battle.c5
-rw-r--r--src/map/battleground.c13
-rw-r--r--src/map/battleground.h8
-rw-r--r--src/map/channel.c82
-rw-r--r--src/map/channel.h8
-rw-r--r--src/map/chat.c18
-rw-r--r--src/map/chat.h5
-rw-r--r--src/map/chrif.c13
-rw-r--r--src/map/chrif.h8
-rw-r--r--src/map/clif.c845
-rw-r--r--src/map/clif.h21
-rw-r--r--src/map/duel.c16
-rw-r--r--src/map/guild.c50
-rw-r--r--src/map/guild.h26
-rw-r--r--src/map/homunculus.c2
-rw-r--r--src/map/instance.c9
-rw-r--r--src/map/intif.c50
-rw-r--r--src/map/intif.h8
-rw-r--r--src/map/irc-bot.c211
-rw-r--r--src/map/irc-bot.h133
-rw-r--r--src/map/itemdb.c19
-rw-r--r--src/map/itemdb.h10
-rw-r--r--src/map/log.c43
-rw-r--r--src/map/log.h55
-rw-r--r--src/map/map.c196
-rw-r--r--src/map/map.h39
-rw-r--r--src/map/mapreg.h2
-rw-r--r--src/map/mapreg_sql.c19
-rw-r--r--src/map/mercenary.c17
-rw-r--r--src/map/mob.c197
-rw-r--r--src/map/npc.c298
-rw-r--r--src/map/npc.h28
-rw-r--r--src/map/packets_struct.h895
-rw-r--r--src/map/party.c29
-rw-r--r--src/map/party.h8
-rw-r--r--src/map/path.c8
-rw-r--r--src/map/pc.c157
-rw-r--r--src/map/pc.h26
-rw-r--r--src/map/pc_groups.c4
-rw-r--r--src/map/pc_groups.h6
-rw-r--r--src/map/pet.c8
-rw-r--r--src/map/quest.c2
-rw-r--r--src/map/script.c567
-rw-r--r--src/map/script.h56
-rw-r--r--src/map/skill.c40
-rw-r--r--src/map/skill.h14
-rw-r--r--src/map/status.c98
-rw-r--r--src/map/status.h27
-rw-r--r--src/map/storage.c8
-rw-r--r--src/map/storage.h6
-rw-r--r--src/map/unit.c19
-rw-r--r--src/map/unit.h1
-rw-r--r--src/map/vending.c8
-rw-r--r--src/map/vending.h5
57 files changed, 2670 insertions, 1918 deletions
diff --git a/src/map/Makefile.in b/src/map/Makefile.in
index b5a3d4461..3c6a3f806 100644
--- a/src/map/Makefile.in
+++ b/src/map/Makefile.in
@@ -1,7 +1,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,7 +23,7 @@ CONFIG_D = ../config
CONFIG_H = $(wildcard $(CONFIG_D)/*.h) $(wildcard $(CONFIG_D)/*/*.h)
COMMON_D = ../common
-COMMON_H = $(wildcard $(COMMON_D)/*.h)
+COMMON_H = $(filter-out %.p.h, $(wildcard $(COMMON_D)/*.h)) ../plugins/HPMHooking.h
SYSINFO_INC = $(COMMON_D)/sysinfo.inc
COMMON_INCLUDE = -I..
@@ -53,6 +53,7 @@ MAP_H = atcommand.h battle.h battleground.h buyingstore.h channel.h chat.h \
mercenary.h mob.h npc.h packets.h packets_struct.h party.h path.h \
pc.h pc_groups.h pet.h quest.h script.h searchstore.h skill.h \
status.h storage.h trade.h unit.h vending.h
+MAP_PH =
HAVE_MYSQL=@HAVE_MYSQL@
ifeq ($(HAVE_MYSQL),yes)
@@ -95,7 +96,7 @@ help:
Makefile: Makefile.in
@$(MAKE) -C ../.. src/map/Makefile
-$(SYSINFO_INC): $(MAP_C) $(MAP_H) $(COMMON_H) $(CONFIG_H) $(MT19937AR_H) $(LIBCONFIG_H)
+$(SYSINFO_INC): $(MAP_C) $(MAP_PH) $(MAP_H) $(COMMON_H) $(CONFIG_H) $(MT19937AR_H) $(LIBCONFIG_H)
@echo " MAKE $@"
@$(MAKE) -C ../.. sysinfo
@@ -118,12 +119,6 @@ map-server: ../../map-server@EXEEXT@
@$(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@ @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) @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $<
-
# missing object files
$(COMMON_D)/obj_all/common.a:
@echo " MAKE $@"
@@ -140,3 +135,11 @@ $(MT19937AR_OBJ):
$(LIBCONFIG_OBJ):
@echo " MAKE $@"
@$(MAKE) -C $(LIBCONFIG_D)
+
+.SECONDEXPANSION:
+
+# map object files
+
+obj_sql/%.o: %.c $$(filter %.p.h, $(MAP_PH)) $(MAP_H) $(COMMON_H) $(CONFIG_H) $(MT19937AR_H) $(LIBCONFIG_H) | obj_sql
+ @echo " CC $<"
+ @$(CC) @CFLAGS@ @DEFS@ $(COMMON_INCLUDE) $(THIRDPARTY_INCLUDE) @MYSQL_CFLAGS@ @CPPFLAGS@ -c $(OUTPUT_OPTION) $<
diff --git a/src/map/atcommand.c b/src/map/atcommand.c
index f28c24dcb..841cf855d 100644
--- a/src/map/atcommand.c
+++ b/src/map/atcommand.c
@@ -547,7 +547,7 @@ ACMD(jumpto) {
return false;
}
- if((pl_sd=map->nick2sd((const char *)message)) == NULL && (pl_sd=map->charid2sd(atoi(message))) == NULL) {
+ if ((pl_sd=map->nick2sd(message)) == NULL && (pl_sd=map->charid2sd(atoi(message))) == NULL) {
clif->message(fd, msg_fd(fd,3)); // Character not found.
return false;
}
@@ -1091,9 +1091,9 @@ ACMD(kami)
sscanf(message, "%199[^\n]", atcmd_output);
if (stristr(info->command, "l") != NULL)
- clif->broadcast(&sd->bl, atcmd_output, strlen(atcmd_output) + 1, BC_DEFAULT, ALL_SAMEMAP);
+ clif->broadcast(&sd->bl, atcmd_output, (int)strlen(atcmd_output) + 1, BC_DEFAULT, ALL_SAMEMAP);
else
- intif->broadcast(atcmd_output, strlen(atcmd_output) + 1, (*(info->command + 4) == 'b' || *(info->command + 4) == 'B') ? BC_BLUE : BC_YELLOW);
+ intif->broadcast(atcmd_output, (int)strlen(atcmd_output) + 1, (*(info->command + 4) == 'b' || *(info->command + 4) == 'B') ? BC_BLUE : BC_YELLOW);
} else {
if(!*message || (sscanf(message, "%10u %199[^\n]", &color, atcmd_output) < 2)) {
clif->message(fd, msg_fd(fd,981)); // Please enter color and message (usage: @kamic <color> <message>).
@@ -1104,7 +1104,7 @@ ACMD(kami)
clif->message(fd, msg_fd(fd,982)); // Invalid color.
return false;
}
- intif->broadcast2(atcmd_output, strlen(atcmd_output) + 1, color, 0x190, 12, 0, 0);
+ intif->broadcast2(atcmd_output, (int)strlen(atcmd_output) + 1, color, 0x190, 12, 0, 0);
}
return true;
}
@@ -1511,7 +1511,7 @@ ACMD(help) {
clif->message(fd, atcmd_output);
{ // Display aliases
- DBIterator* iter;
+ struct DBIterator *iter;
AtCommandInfo *command_info;
AliasInfo *alias_info = NULL;
StringBuf buf;
@@ -2747,7 +2747,7 @@ ACMD(recall) {
return false;
}
- if((pl_sd=map->nick2sd((const char *)message)) == NULL && (pl_sd=map->charid2sd(atoi(message))) == NULL) {
+ if ((pl_sd=map->nick2sd(message)) == NULL && (pl_sd=map->charid2sd(atoi(message))) == NULL) {
clif->message(fd, msg_fd(fd,3)); // Character not found.
return false;
}
@@ -3072,7 +3072,7 @@ ACMD(kick)
return false;
}
- if((pl_sd=map->nick2sd((const char *)message)) == NULL && (pl_sd=map->charid2sd(atoi(message))) == NULL) {
+ if ((pl_sd=map->nick2sd(message)) == NULL && (pl_sd=map->charid2sd(atoi(message))) == NULL) {
clif->message(fd, msg_fd(fd,3)); // Character not found.
return false;
}
@@ -3643,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
@@ -3791,7 +3793,7 @@ ACMD(mapinfo)
if( pl_sd->mapindex == m_index ) {
if( pl_sd->state.vending )
vend_num++;
- else if ((cd = map->id2cd(pl_sd->chatID)) != NULL && cd->usersd[0] == pl_sd)
+ else if ((cd = map->id2cd(pl_sd->chat_id)) != NULL && cd->usersd[0] == pl_sd)
chat_num++;
}
}
@@ -3970,7 +3972,7 @@ ACMD(mapinfo)
clif->message(fd, msg_fd(fd,1113)); // ----- Chats in Map -----
iter = mapit_getallusers();
for (pl_sd = BL_UCCAST(BL_PC, mapit->first(iter)); mapit->exists(iter); pl_sd = BL_UCCAST(BL_PC, mapit->next(iter))) {
- if ((cd = map->id2cd(pl_sd->chatID)) != NULL && pl_sd->mapindex == m_index && cd->usersd[0] == pl_sd) {
+ if ((cd = map->id2cd(pl_sd->chat_id)) != NULL && pl_sd->mapindex == m_index && cd->usersd[0] == pl_sd) {
safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,1114), // Chat: %s | Player: %s | Location: %d %d
cd->title, pl_sd->status.name, cd->bl.x, cd->bl.y);
clif->message(fd, atcmd_output);
@@ -4909,7 +4911,7 @@ ACMD(broadcast)
}
safesnprintf(atcmd_output, sizeof(atcmd_output), "%s: %s", sd->status.name, message);
- intif->broadcast(atcmd_output, strlen(atcmd_output) + 1, BC_DEFAULT);
+ intif->broadcast(atcmd_output, (int)strlen(atcmd_output) + 1, BC_DEFAULT);
return true;
}
@@ -4928,7 +4930,7 @@ ACMD(localbroadcast)
safesnprintf(atcmd_output, sizeof(atcmd_output), "%s: %s", sd->status.name, message);
- clif->broadcast(&sd->bl, atcmd_output, strlen(atcmd_output) + 1, BC_DEFAULT, ALL_SAMEMAP);
+ clif->broadcast(&sd->bl, atcmd_output, (int)strlen(atcmd_output) + 1, BC_DEFAULT, ALL_SAMEMAP);
return true;
}
@@ -5123,8 +5125,7 @@ ACMD(follow) {
return true;
}
- if ((pl_sd = map->nick2sd((const char *)message)) == NULL)
- {
+ if ((pl_sd = map->nick2sd(message)) == NULL) {
clif->message(fd, msg_fd(fd,3)); // Character not found.
return false;
}
@@ -5262,7 +5263,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);
@@ -5277,12 +5278,13 @@ ACMD(clearcart)
*------------------------------------------*/
#define MAX_SKILLID_PARTIAL_RESULTS 5
#define MAX_SKILLID_PARTIAL_RESULTS_LEN 74 /* "skill " (6) + "%d:" (up to 5) + "%s" (up to 30) + " (%s)" (up to 33) */
-ACMD(skillid) {
+ACMD(skillid)
+{
int i, found = 0;
size_t skillen;
- DBIterator* iter;
- DBKey key;
- DBData *data;
+ struct DBIterator *iter;
+ union DBKey key;
+ struct DBData *data;
char partials[MAX_SKILLID_PARTIAL_RESULTS][MAX_SKILLID_PARTIAL_RESULTS_LEN];
if (!*message) {
@@ -5601,7 +5603,7 @@ ACMD(changegm) {
return false;
}
- if ((pl_sd=map->nick2sd((const char *) message)) == NULL || pl_sd->status.guild_id != sd->status.guild_id) {
+ if ((pl_sd=map->nick2sd(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;
}
@@ -5621,7 +5623,7 @@ ACMD(changeleader) {
return false;
}
- if (party->changeleader(sd, map->nick2sd((const char *) message)))
+ if (party->changeleader(sd, map->nick2sd(message)))
return true;
return false;
}
@@ -6380,7 +6382,7 @@ ACMD(trade) {
return false;
}
- if ( (pl_sd = map->nick2sd((const char *)message)) == NULL ) {
+ if ((pl_sd = map->nick2sd(message)) == NULL) {
clif->message(fd, msg_fd(fd,3)); // Character not found.
return false;
}
@@ -6423,8 +6425,7 @@ ACMD(unmute) {
return false;
}
- if ((pl_sd = map->nick2sd((const char *)message)) == NULL)
- {
+ if ((pl_sd = map->nick2sd(message)) == NULL) {
clif->message(fd, msg_fd(fd,3)); // Character not found.
return false;
}
@@ -6778,7 +6779,7 @@ ACMD(showmobs)
clif->message(fd, atcmd_output);
it = mapit_geteachmob();
- for (md = BL_UCCAST(BL_MOB, mapit->first(it)); mapit->next(it); md = BL_UCCAST(BL_MOB, mapit->next(it))) {
+ for (md = BL_UCCAST(BL_MOB, mapit->first(it)); mapit->exists(it); md = BL_UCCAST(BL_MOB, mapit->next(it))) {
if( md->bl.m != sd->bl.m )
continue;
if( mob_id != -1 && md->class_ != mob_id )
@@ -7665,9 +7666,10 @@ ACMD(showdelay)
* @reject - reject invitation
* @leave - leave duel
*------------------------------------------*/
-ACMD(invite) {
+ACMD(invite)
+{
unsigned int did = sd->duel_group;
- struct map_session_data *target_sd = map->nick2sd((const char *)message);
+ struct map_session_data *target_sd = map->nick2sd(message);
if (did == 0)
{
@@ -7739,8 +7741,7 @@ ACMD(duel) {
}
duel->create(sd, maxpl);
} else {
- struct map_session_data *target_sd;
- target_sd = map->nick2sd((const char *)message);
+ struct map_session_data *target_sd = map->nick2sd(message);
if (target_sd != NULL) {
unsigned int newduel;
if ((newduel = duel->create(sd, 2)) != -1) {
@@ -7835,7 +7836,7 @@ ACMD(cash)
// If this option is set, the message is already sent by pc function
if( !battle_config.cashshop_show_points ){
sprintf(output, msg_fd(fd,505), ret, sd->cashPoints);
- clif_disp_onlyself(sd, output, strlen(output));
+ clif_disp_onlyself(sd, output);
clif->message(fd, output);
}
} else
@@ -7843,7 +7844,7 @@ ACMD(cash)
} else {
if( (ret=pc->paycash(sd, -value, 0)) >= 0){
sprintf(output, msg_fd(fd,410), ret, sd->cashPoints);
- clif_disp_onlyself(sd, output, strlen(output));
+ clif_disp_onlyself(sd, output);
clif->message(fd, output);
} else
clif->message(fd, msg_fd(fd,41)); // Unable to decrease the number/value.
@@ -7854,7 +7855,7 @@ ACMD(cash)
// If this option is set, the message is already sent by pc function
if( !battle_config.cashshop_show_points ){
sprintf(output, msg_fd(fd,506), ret, sd->kafraPoints);
- clif_disp_onlyself(sd, output, strlen(output));
+ clif_disp_onlyself(sd, output);
clif->message(fd, output);
}
} else
@@ -7862,7 +7863,7 @@ ACMD(cash)
} else {
if( (ret=pc->paycash(sd, -value, -value)) >= 0){
sprintf(output, msg_fd(fd,411), ret, sd->kafraPoints);
- clif_disp_onlyself(sd, output, strlen(output));
+ clif_disp_onlyself(sd, output);
clif->message(fd, output);
} else
clif->message(fd, msg_fd(fd,41)); // Unable to decrease the number/value.
@@ -7882,7 +7883,7 @@ ACMD(clone) {
return false;
}
- if ((pl_sd=map->nick2sd((const char *)message)) == NULL && (pl_sd=map->charid2sd(atoi(message))) == NULL) {
+ if ((pl_sd=map->nick2sd(message)) == NULL && (pl_sd=map->charid2sd(atoi(message))) == NULL) {
clif->message(fd, msg_fd(fd,3)); // Character not found.
return false;
}
@@ -7957,7 +7958,7 @@ ACMD(request)
safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,278), message); // (@request): %s
intif->wis_message_to_gm(sd->status.name, PC_PERM_RECEIVE_REQUESTS, atcmd_output);
- clif_disp_onlyself(sd, atcmd_output, strlen(atcmd_output));
+ clif_disp_onlyself(sd, atcmd_output);
clif->message(sd->fd,msg_fd(fd,279)); // @request sent.
return true;
}
@@ -8352,7 +8353,7 @@ void atcommand_commands_sub(struct map_session_data* sd, const int fd, AtCommand
char line_buff[CHATBOX_SIZE];
char* cur = line_buff;
AtCommandInfo* cmd;
- DBIterator *iter = db_iterator(atcommand->db);
+ struct DBIterator *iter = db_iterator(atcommand->db);
int count = 0;
memset(line_buff,' ',CHATBOX_SIZE);
@@ -8498,30 +8499,34 @@ ACMD(set)
CREATE(data, struct script_data,1);
- if( is_str ) {// string variable
- switch( reg[0] ) {
+ if (is_str) {
+ // string variable
+ const char *str = NULL;
+ switch (reg[0]) {
case '@':
- data->u.str = pc->readregstr(sd, script->add_str(reg));
+ str = pc->readregstr(sd, script->add_str(reg));
break;
case '$':
- data->u.str = mapreg->readregstr(script->add_str(reg));
+ str = mapreg->readregstr(script->add_str(reg));
break;
case '#':
- if( reg[1] == '#' )
- data->u.str = pc_readaccountreg2str(sd, script->add_str(reg));// global
+ if (reg[1] == '#')
+ str = pc_readaccountreg2str(sd, script->add_str(reg));// global
else
- data->u.str = pc_readaccountregstr(sd, script->add_str(reg));// local
+ str = pc_readaccountregstr(sd, script->add_str(reg));// local
break;
default:
- data->u.str = pc_readglobalreg_str(sd, script->add_str(reg));
+ str = pc_readglobalreg_str(sd, script->add_str(reg));
break;
}
- if( data->u.str == NULL || data->u.str[0] == '\0' ) {// empty string
+ if (str == NULL || str[0] == '\0') {
+ // empty string
data->type = C_CONSTSTR;
data->u.str = "";
- } else {// duplicate string
+ } else {
+ // duplicate string
data->type = C_STR;
- data->u.str = aStrdup(data->u.str);
+ data->u.mutstr = aStrdup(str);
}
} else {// integer variable
data->type = C_INT;
@@ -8549,7 +8554,7 @@ ACMD(set)
safesnprintf(atcmd_output, sizeof(atcmd_output),msg_fd(fd,1373),reg,data->u.num); // %s value is now :%d
break;
case C_STR:
- safesnprintf(atcmd_output, sizeof(atcmd_output),msg_fd(fd,1374),reg,data->u.str); // %s value is now :%s
+ safesnprintf(atcmd_output, sizeof(atcmd_output),msg_fd(fd,1374),reg,data->u.mutstr); // %s value is now :%s
break;
case C_CONSTSTR:
safesnprintf(atcmd_output, sizeof(atcmd_output),msg_fd(fd,1375),reg); // %s is empty
@@ -8822,7 +8827,7 @@ ACMD(channel) {
clif->messagecolor_self(fd, channel->config->colors[k], atcmd_output);
}
} else {
- DBIterator *iter = db_iterator(channel->db);
+ struct DBIterator *iter = db_iterator(channel->db);
bool show_all = pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN) ? true : false;
clif->message(fd, msg_fd(fd,1410)); // -- Public Channels
if (channel->config->local) {
@@ -9052,9 +9057,9 @@ ACMD(channel) {
clif->message(fd, atcmd_output);
} else if (strcmpi(subcmd,"banlist") == 0) {
// sub1 = channel name; sub2 = unused; sub3 = unused
- DBIterator *iter = NULL;
- DBKey key;
- DBData *data;
+ struct DBIterator *iter = NULL;
+ union DBKey key;
+ struct DBData *data;
bool isA = pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN)?true:false;
if (sub1[0] != '#') {
clif->message(fd, msg_fd(fd,1405));// Channel name must start with a '#'
@@ -9729,8 +9734,7 @@ const char* atcommand_checkalias(const char *aliasname) {
/// AtCommand suggestion
void atcommand_get_suggestions(struct map_session_data* sd, const char *name, bool is_atcmd_cmd) {
- DBIterator* atcommand_iter;
- DBIterator* alias_iter;
+ struct DBIterator *atcommand_iter, *alias_iter;
AtCommandInfo* command_info = NULL;
AliasInfo* alias_info = NULL;
AtCommandType type = is_atcmd_cmd ? COMMAND_ATCOMMAND : COMMAND_CHARCOMMAND;
@@ -10116,7 +10120,7 @@ static inline int atcommand_command_type2idx(AtCommandType type)
*/
void atcommand_db_load_groups(GroupSettings **groups, struct config_setting_t **commands_, size_t sz)
{
- DBIterator *iter = db_iterator(atcommand->db);
+ struct DBIterator *iter = db_iterator(atcommand->db);
AtCommandInfo *atcmd;
nullpo_retv(groups);
@@ -10218,7 +10222,8 @@ bool atcommand_hp_add(char *name, AtCommandFunc func) {
/**
* @see DBApply
*/
-int atcommand_db_clear_sub(DBKey key, DBData *data, va_list args) {
+int atcommand_db_clear_sub(union DBKey key, struct DBData *data, va_list args)
+{
AtCommandInfo *cmd = DB->data2ptr(data);
aFree(cmd->at_groups);
aFree(cmd->char_groups);
diff --git a/src/map/atcommand.h b/src/map/atcommand.h
index a4f9afce7..0e7895825 100644
--- a/src/map/atcommand.h
+++ b/src/map/atcommand.h
@@ -94,8 +94,8 @@ struct atcommand_interface {
struct atcmd_binding_data** binding;
int binding_count;
/* other vars */
- DBMap* db; //name -> AtCommandInfo
- DBMap* alias_db; //alias -> AtCommandInfo
+ struct DBMap *db; //name -> AtCommandInfo
+ struct DBMap *alias_db; //alias -> AtCommandInfo
/**
* msg_table[lang_id][msg_id]
* Server messages (0-499 reserved for GM commands, 500-999 reserved for others)
@@ -135,7 +135,7 @@ struct atcommand_interface {
/* */
void (*commands_sub) (struct map_session_data* sd, const int fd, AtCommandType type);
void (*cmd_db_clear) (void);
- int (*cmd_db_clear_sub) (DBKey key, DBData *data, va_list args);
+ int (*cmd_db_clear_sub) (union DBKey key, struct DBData *data, va_list args);
void (*doload) (void);
void (*base_commands) (void);
bool (*add) (char *name, AtCommandFunc func, bool replace);
diff --git a/src/map/battle.c b/src/map/battle.c
index a7a6f4719..09b99aa05 100644
--- a/src/map/battle.c
+++ b/src/map/battle.c
@@ -3512,8 +3512,6 @@ int battle_blewcount_bonus(struct map_session_data *sd, uint16 skill_id) {
struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list *target,uint16 skill_id,uint16 skill_lv,int mflag) {
int nk;
short s_ele = 0;
- unsigned int skillratio = 100; //Skill dmg modifiers.
-
struct map_session_data *sd = NULL;
struct status_change *sc;
struct Damage ad;
@@ -3666,6 +3664,7 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
ad.damage = status->get_lv(src) * 10 + sstatus->int_;
break;
default: {
+ unsigned int skillratio = 100; //Skill dmg modifiers.
MATK_ADD( status->get_matk(src, 2) );
#ifdef RENEWAL
ad.damage = battle->calc_cardfix(BF_MAGIC, src, target, nk, s_ele, 0, ad.damage, 0, ad.flag);
@@ -4276,7 +4275,6 @@ void battle_calc_misc_attack_unknown(struct block_list *src, struct block_list *
// FIXME: wflag is undocumented
struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list *target,uint16 skill_id,uint16 skill_lv,int wflag)
{
- unsigned int skillratio = 100; //Skill dmg modifiers.
short temp=0;
short s_ele, s_ele_;
int i, nk;
@@ -4775,6 +4773,7 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
} //End hit/miss calculation
if (flag.hit && !flag.infdef) { //No need to do the math for plants
+ unsigned int skillratio = 100; //Skill dmg modifiers.
//Hitting attack
//Assuming that 99% of the cases we will not need to check for the flag.rh... we don't.
diff --git a/src/map/battleground.c b/src/map/battleground.c
index 311690ec3..5231ce3d2 100644
--- a/src/map/battleground.c
+++ b/src/map/battleground.c
@@ -171,7 +171,7 @@ int bg_team_leave(struct map_session_data *sd, enum bg_team_leave_type flag) {
sprintf(output, "Server : %s has been afk-kicked from the battlefield...", sd->status.name);
break;
}
- clif->bg_message(bgd, 0, "Server", output, strlen(output) + 1);
+ clif->bg_message(bgd, 0, "Server", output);
}
if( bgd->logout_event[0] && flag )
@@ -265,21 +265,23 @@ int bg_team_get_id(struct block_list *bl) {
return 0;
}
-bool bg_send_message(struct map_session_data *sd, const char *mes, int len) {
+bool bg_send_message(struct map_session_data *sd, const char *mes)
+{
struct battleground_data *bgd;
nullpo_ret(sd);
nullpo_ret(mes);
if( sd->bg_id == 0 || (bgd = bg->team_search(sd->bg_id)) == NULL )
return false; // Couldn't send message
- clif->bg_message(bgd, sd->bl.id, sd->status.name, mes, len);
+ clif->bg_message(bgd, sd->bl.id, sd->status.name, mes);
return true;
}
/**
* @see DBApply
*/
-int bg_send_xy_timer_sub(DBKey key, DBData *data, va_list ap) {
+int bg_send_xy_timer_sub(union DBKey key, struct DBData *data, va_list ap)
+{
struct battleground_data *bgd = DB->data2ptr(data);
struct map_session_data *sd;
int i;
@@ -925,7 +927,8 @@ void do_init_battleground(bool minimal) {
/**
* @see DBApply
*/
-int bg_team_db_final(DBKey key, DBData *data, va_list ap) {
+int bg_team_db_final(union DBKey key, struct DBData *data, va_list ap)
+{
struct battleground_data* bgd = DB->data2ptr(data);
HPM->data_store_destroy(&bgd->hdata);
diff --git a/src/map/battleground.h b/src/map/battleground.h
index bb77db125..4c3d4878f 100644
--- a/src/map/battleground.h
+++ b/src/map/battleground.h
@@ -102,7 +102,7 @@ struct battleground_interface {
struct bg_arena **arena;
unsigned char arenas;
/* */
- DBMap *team_db; // int bg_id -> struct battleground_data*
+ struct DBMap *team_db; // int bg_id -> struct battleground_data*
unsigned int team_counter; // Next bg_id
/* */
void (*init) (bool minimal);
@@ -130,11 +130,11 @@ struct battleground_interface {
bool (*member_respawn) (struct map_session_data *sd);
int (*create) (unsigned short map_index, short rx, short ry, const char *ev, const char *dev);
int (*team_get_id) (struct block_list *bl);
- bool (*send_message) (struct map_session_data *sd, const char *mes, int len);
- int (*send_xy_timer_sub) (DBKey key, DBData *data, va_list ap);
+ bool (*send_message) (struct map_session_data *sd, const char *mes);
+ int (*send_xy_timer_sub) (union DBKey key, struct DBData *data, va_list ap);
int (*send_xy_timer) (int tid, int64 tick, int id, intptr_t data);
int (*afk_timer) (int tid, int64 tick, int id, intptr_t data);
- int (*team_db_final) (DBKey key, DBData *data, va_list ap);
+ int (*team_db_final) (union DBKey key, struct DBData *data, va_list ap);
/* */
enum bg_queue_types (*str2teamtype) (const char *str);
/* */
diff --git a/src/map/channel.c b/src/map/channel.c
index 28ef854da..ee8242b23 100644
--- a/src/map/channel.c
+++ b/src/map/channel.c
@@ -127,9 +127,8 @@ void channel_delete(struct channel_data *chan)
nullpo_retv(chan);
if (db_size(chan->users) && !channel->config->closing) {
- DBIterator *iter;
struct map_session_data *sd;
- iter = db_iterator(chan->users);
+ struct DBIterator *iter = db_iterator(chan->users);
for (sd = dbi_first(iter); dbi_exists(iter); sd = dbi_next(iter)) {
channel->leave_sub(chan, sd);
}
@@ -610,7 +609,10 @@ void read_channels_config(void)
local_autojoin = 0, ally_autojoin = 0,
allow_user_channel_creation = 0,
irc_enabled = 0,
- irc_autojoin = 0;
+ irc_autojoin = 0,
+ irc_flood_protection_rate = 0,
+ irc_flood_protection_burst = 0,
+ irc_flood_protection_enabled = 0;
if( !libconfig->setting_lookup_string(settings, "map_local_channel_name", &local_name) )
local_name = "map";
@@ -641,58 +643,52 @@ void read_channels_config(void)
const char *irc_server, *irc_channel,
*irc_nick, *irc_nick_pw;
int irc_use_ghost = 0;
- if( libconfig->setting_lookup_string(settings, "irc_channel_network", &irc_server) ) {
- if( !strstr(irc_server,":") ) {
+ if (!libconfig->setting_lookup_string(settings, "irc_channel_network", &irc_server)) {
+ channel->config->irc = false;
+ ShowWarning("channels.conf : irc channel enabled but irc_channel_network wasn't found, disabling irc channel...\n");
+ } else {
+ char *server = aStrdup(irc_server);
+ char *port = strchr(server, ':');
+ if (port == NULL) {
channel->config->irc = false;
- ShowWarning("channels.conf : network port wasn't found in 'irc_channel_network', disabling irc channel...\n");
+ ShowWarning("channels.conf: network port wasn't found in 'irc_channel_network', disabling irc channel...\n");
+ } else if ((size_t)(port-server) > sizeof channel->config->irc_server - 1) {
+ channel->config->irc = false;
+ ShowWarning("channels.conf: server name is too long in 'irc_channel_network', disabling irc channel...\n");
} else {
- unsigned char d = 0, dlen = strlen(irc_server);
- char server[40];
- if (dlen > 39)
- dlen = 39;
- memset(server, '\0', sizeof(server));
-
- for(d = 0; d < dlen; d++) {
- if(irc_server[d] == ':') {
- memcpy(server, irc_server, d);
- safestrncpy(channel->config->irc_server, server, 40);
- memcpy(server, &irc_server[d+1], dlen - d - 1);
- channel->config->irc_server_port = atoi(server);
- break;
- }
- }
+ *port = '\0';
+ port++;
+ safestrncpy(channel->config->irc_server, server, sizeof channel->config->irc_server);
+ channel->config->irc_server_port = atoi(port);
}
- } else {
- channel->config->irc = false;
- ShowWarning("channels.conf : irc channel enabled but irc_channel_network wasn't found, disabling irc channel...\n");
+ aFree(server);
}
- if( libconfig->setting_lookup_string(settings, "irc_channel_channel", &irc_channel) )
+ if (libconfig->setting_lookup_string(settings, "irc_channel_channel", &irc_channel)) {
safestrncpy(channel->config->irc_channel, irc_channel, 50);
- else {
+ } else {
channel->config->irc = false;
ShowWarning("channels.conf : irc channel enabled but irc_channel_channel wasn't found, disabling irc channel...\n");
}
- if( libconfig->setting_lookup_string(settings, "irc_channel_nick", &irc_nick) ) {
- if( strcmpi(irc_nick,"Hercules_chSysBot") == 0 ) {
+ if (libconfig->setting_lookup_string(settings, "irc_channel_nick", &irc_nick)) {
+ if (strcmpi(irc_nick,"Hercules_chSysBot") == 0) {
sprintf(channel->config->irc_nick, "Hercules_chSysBot%d",rnd()%777);
- } else
+ } else {
safestrncpy(channel->config->irc_nick, irc_nick, 40);
+ }
} else {
channel->config->irc = false;
ShowWarning("channels.conf : irc channel enabled but irc_channel_nick wasn't found, disabling irc channel...\n");
}
- if( libconfig->setting_lookup_string(settings, "irc_channel_nick_pw", &irc_nick_pw) ) {
+ if (libconfig->setting_lookup_string(settings, "irc_channel_nick_pw", &irc_nick_pw)) {
safestrncpy(channel->config->irc_nick_pw, irc_nick_pw, 30);
config_setting_lookup_bool(settings, "irc_channel_use_ghost", &irc_use_ghost);
channel->config->irc_use_ghost = irc_use_ghost;
}
-
}
libconfig->setting_lookup_bool(settings, "map_local_channel_autojoin", &local_autojoin);
libconfig->setting_lookup_bool(settings, "ally_channel_autojoin", &ally_autojoin);
libconfig->setting_lookup_bool(settings, "irc_channel_autojoin", &irc_autojoin);
-
if (local_autojoin)
channel->config->local_autojoin = true;
if (ally_autojoin)
@@ -700,6 +696,26 @@ void read_channels_config(void)
if (irc_autojoin)
channel->config->irc_autojoin = true;
+ libconfig->setting_lookup_bool(settings, "irc_flood_protection_enabled", &irc_flood_protection_enabled);
+
+ if (irc_flood_protection_enabled) {
+ ircbot->flood_protection_enabled = true;
+
+ libconfig->setting_lookup_int(settings, "irc_flood_protection_rate", &irc_flood_protection_rate);
+ libconfig->setting_lookup_int(settings, "irc_flood_protection_burst", &irc_flood_protection_burst);
+
+ if (irc_flood_protection_rate > 0)
+ ircbot->flood_protection_rate = irc_flood_protection_rate;
+ else
+ ircbot->flood_protection_rate = 1000;
+ if (irc_flood_protection_burst > 0)
+ ircbot->flood_protection_burst = irc_flood_protection_burst;
+ else
+ ircbot->flood_protection_burst = 3;
+ } else {
+ ircbot->flood_protection_enabled = false;
+ }
+
libconfig->setting_lookup_bool(settings, "allow_user_channel_creation", &allow_user_channel_creation);
if( allow_user_channel_creation )
@@ -814,7 +830,7 @@ int do_init_channel(bool minimal)
void do_final_channel(void)
{
- DBIterator *iter = db_iterator(channel->db);
+ struct DBIterator *iter = db_iterator(channel->db);
struct channel_data *chan;
unsigned char i;
diff --git a/src/map/channel.h b/src/map/channel.h
index ac1c8f0cb..e8696fd90 100644
--- a/src/map/channel.h
+++ b/src/map/channel.h
@@ -21,12 +21,12 @@
#define MAP_CHANNEL_H
#include "common/hercules.h"
-#include "common/db.h"
#include "common/mmo.h"
/**
* Declarations
**/
+struct DBMap; // common/db.h
struct map_session_data;
struct guild;
@@ -83,8 +83,8 @@ struct channel_data {
char name[HCS_NAME_LENGTH];
char password[HCS_NAME_LENGTH];
unsigned char color;
- DBMap *users;
- DBMap *banned;
+ struct DBMap *users;
+ struct DBMap *banned;
unsigned int options;
unsigned int owner;
enum channel_types type;
@@ -94,7 +94,7 @@ struct channel_data {
struct channel_interface {
/* vars */
- DBMap *db;
+ struct DBMap *db;
struct Channel_Config *config;
int (*init) (bool minimal);
diff --git a/src/map/chat.c b/src/map/chat.c
index d60b9bece..df48e1f2c 100644
--- a/src/map/chat.c
+++ b/src/map/chat.c
@@ -97,7 +97,7 @@ bool chat_createpcchat(struct map_session_data* sd, const char* title, const cha
nullpo_ret(title);
nullpo_ret(pass);
- if( sd->chatID )
+ if (sd->chat_id != 0)
return false; //Prevent people abusing the chat system by creating multiple chats, as pointed out by End of Exam. [Skotlex]
if( sd->state.vending || sd->state.buyingstore )
@@ -142,8 +142,10 @@ bool chat_joinchat(struct map_session_data* sd, int chatid, const char* pass) {
nullpo_ret(pass);
cd = map->id2cd(chatid);
- if( cd == NULL || cd->bl.type != BL_CHAT || cd->bl.m != sd->bl.m || sd->state.vending || sd->state.buyingstore || sd->chatID || ((cd->owner->type == BL_NPC) ? cd->users+1 : cd->users) >= cd->limit )
- {
+ if (cd == NULL || cd->bl.type != BL_CHAT || cd->bl.m != sd->bl.m
+ || sd->state.vending || sd->state.buyingstore || sd->chat_id != 0
+ || ((cd->owner->type == BL_NPC) ? cd->users+1 : cd->users) >= cd->limit
+ ) {
clif->joinchatfail(sd,0); // room full
return false;
}
@@ -204,8 +206,8 @@ int chat_leavechat(struct map_session_data* sd, bool kicked) {
nullpo_retr(0, sd);
- cd = map->id2cd(sd->chatID);
- if( cd == NULL ) {
+ cd = map->id2cd(sd->chat_id);
+ if (cd == NULL) {
pc_setchatid(sd, 0);
return 0;
}
@@ -279,7 +281,7 @@ bool chat_changechatowner(struct map_session_data* sd, const char* nextownername
nullpo_ret(sd);
nullpo_ret(nextownername);
- cd = map->id2cd(sd->chatID);
+ cd = map->id2cd(sd->chat_id);
if (cd == NULL || &sd->bl != cd->owner)
return false;
@@ -324,7 +326,7 @@ bool chat_changechatstatus(struct map_session_data* sd, const char* title, const
nullpo_ret(title);
nullpo_ret(pass);
- cd = map->id2cd(sd->chatID);
+ cd = map->id2cd(sd->chat_id);
if (cd == NULL || &sd->bl != cd->owner)
return false;
@@ -352,7 +354,7 @@ bool chat_kickchat(struct map_session_data* sd, const char* kickusername) {
nullpo_ret(sd);
nullpo_ret(kickusername);
- cd = map->id2cd(sd->chatID);
+ cd = map->id2cd(sd->chat_id);
if (cd == NULL || &sd->bl != cd->owner)
return false;
diff --git a/src/map/chat.h b/src/map/chat.h
index 603d8441f..59d61a46e 100644
--- a/src/map/chat.h
+++ b/src/map/chat.h
@@ -23,8 +23,9 @@
#include "map/map.h" // struct block_list, CHATROOM_TITLE_SIZE
#include "common/hercules.h"
-#include "common/db.h"
+/* Forward Declarations */
+struct DBMap; // common/db.h
struct chat_data;
struct map_session_data;
struct npc_data;
@@ -46,7 +47,7 @@ struct chat_data {
struct block_list* owner;
char npc_event[EVENT_NAME_LENGTH];
/* isn't this a waste? there is a enormous overhead, wouldn't something like skill_blockpc_start be better here? [Ind] */
- DBMap* kick_list; ///< DBMap of users who were kicked from this chat
+ struct DBMap *kick_list; ///< DBMap of users who were kicked from this chat
};
/*=====================================
diff --git a/src/map/chrif.c b/src/map/chrif.c
index 578942897..52af1137e 100644
--- a/src/map/chrif.c
+++ b/src/map/chrif.c
@@ -471,7 +471,8 @@ void chrif_connectack(int fd) {
/**
* @see DBApply
*/
-int chrif_reconnect(DBKey key, DBData *data, va_list ap) {
+int chrif_reconnect(union DBKey key, struct DBData *data, va_list ap)
+{
struct auth_node *node = DB->data2ptr(data);
nullpo_ret(node);
@@ -681,7 +682,8 @@ void chrif_authfail(int fd) {/* HELLO WORLD. ip in RFIFOL 15 is not being used (
* This can still happen (client times out while waiting for char to confirm auth data)
* @see DBApply
*/
-int auth_db_cleanup_sub(DBKey key, DBData *data, va_list ap) {
+int auth_db_cleanup_sub(union DBKey key, struct DBData *data, va_list ap)
+{
struct auth_node *node = DB->data2ptr(data);
nullpo_retr(1, node);
@@ -933,14 +935,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;
@@ -1617,7 +1619,8 @@ void chrif_del_scdata_single(int account_id, int char_id, short type)
/**
* @see DBApply
*/
-int auth_db_final(DBKey key, DBData *data, va_list ap) {
+int auth_db_final(union DBKey key, struct DBData *data, va_list ap)
+{
struct auth_node *node = DB->data2ptr(data);
nullpo_ret(node);
diff --git a/src/map/chrif.h b/src/map/chrif.h
index 6a5ec36b6..4a1e1da47 100644
--- a/src/map/chrif.h
+++ b/src/map/chrif.h
@@ -72,7 +72,7 @@ struct chrif_interface {
/* */
struct eri *auth_db_ers; //For re-utilizing player login structures.
- DBMap* auth_db; // int id -> struct auth_node*
+ struct DBMap *auth_db; // int id -> struct auth_node*
/* */
int packet_len_table[CHRIF_PACKET_LEN_TABLE_SIZE];
int fd;
@@ -133,10 +133,10 @@ struct chrif_interface {
int (*check_connect_char_server) (int tid, int64 tick, int id, intptr_t data);
bool (*auth_logout) (struct map_session_data *sd, enum sd_state state);
void (*save_ack) (int fd);
- int (*reconnect) (DBKey key, DBData *data, va_list ap);
- int (*auth_db_cleanup_sub) (DBKey key, DBData *data, va_list ap);
+ int (*reconnect) (union DBKey key, struct DBData *data, va_list ap);
+ int (*auth_db_cleanup_sub) (union DBKey key, struct DBData *data, va_list ap);
bool (*char_ask_name_answer) (int acc, const char* player_name, uint16 type, uint16 answer);
- int (*auth_db_final) (DBKey key, DBData *data, va_list ap);
+ int (*auth_db_final) (union DBKey key, struct DBData *data, va_list ap);
int (*send_usercount_tochar) (int tid, int64 tick, int id, intptr_t data);
int (*auth_db_cleanup) (int tid, int64 tick, int id, intptr_t data);
diff --git a/src/map/clif.c b/src/map/clif.c
index 07b0b323b..259bc7253 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -319,17 +319,17 @@ int clif_send_sub(struct block_list *bl, va_list ap) {
return 0;
break;
case AREA_WOC:
- if (sd->chatID || bl == src_bl)
+ if (sd->chat_id != 0 || bl == src_bl)
return 0;
break;
case AREA_WOSC: {
if (src_bl->type == BL_PC) {
const struct map_session_data *ssd = BL_UCCAST(BL_PC, src_bl);
- if (ssd != NULL && sd->chatID != 0 && (sd->chatID == ssd->chatID))
+ if (ssd != NULL && sd->chat_id != 0 && (sd->chat_id == ssd->chat_id))
return 0;
} else if (src_bl->type == BL_NPC) {
const struct npc_data *nd = BL_UCCAST(BL_NPC, src_bl);
- if (nd != NULL && sd->chatID != 0 && (sd->chatID == nd->chat_id))
+ if (nd != NULL && sd->chat_id != 0 && (sd->chat_id == nd->chat_id))
return 0;
}
}
@@ -435,7 +435,7 @@ bool clif_send(const void* buf, int len, struct block_list* bl, enum send_target
{
const struct chat_data *cd = NULL;
if (sd != NULL) {
- cd = map->id2cd(sd->chatID);
+ cd = map->id2cd(sd->chat_id);
} else {
cd = BL_CCAST(BL_CHAT, bl);
}
@@ -1049,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);
@@ -1189,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);
@@ -1280,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);
@@ -1954,20 +1957,23 @@ void clif_selllist(struct map_session_data *sd)
/// - set npcid of dialog window (0 by default)
/// - if set to clear on next mes, clear contents
/// - append this text
-void clif_scriptmes(struct map_session_data *sd, int npcid, const char *mes) {
- int fd = sd->fd;
- size_t slen;
+void clif_scriptmes(struct map_session_data *sd, int npcid, const char *mes)
+{
+ int fd, slen;
nullpo_retv(sd);
nullpo_retv(mes);
- slen = strlen(mes) + 9;
+
+ fd = sd->fd;
+ slen = (int)strlen(mes) + 9;
+ Assert_retv(slen <= INT16_MAX);
sd->state.dialog = 1;
WFIFOHEAD(fd, slen);
- WFIFOW(fd,0)=0xb4;
- WFIFOW(fd,2)=slen;
- WFIFOL(fd,4)=npcid;
+ WFIFOW(fd,0) = 0xb4;
+ WFIFOW(fd,2) = slen;
+ WFIFOL(fd,4) = npcid;
memcpy(WFIFOP(fd,8), mes, slen-8);
WFIFOSET(fd,WFIFOW(fd,2));
}
@@ -2069,24 +2075,27 @@ void clif_sendfakenpc(struct map_session_data *sd, int npcid) {
/// WARNING: the 'cancel' button closes other windows besides the dialog window and the menu window.
/// Which suggests their have intertwined behavior. (probably the mouse targeting)
/// TODO investigate behavior of other windows [FlavioJS]
-void clif_scriptmenu(struct map_session_data* sd, int npcid, const char* mes) {
- int fd;
- size_t slen;
+void clif_scriptmenu(struct map_session_data *sd, int npcid, const char *mes)
+{
+ int fd, slen;
struct block_list *bl = NULL;
nullpo_retv(sd);
nullpo_retv(mes);
+
fd = sd->fd;
- slen = strlen(mes) + 9;
+ slen = (int)strlen(mes) + 9;
+ Assert_retv(slen <= INT16_MAX);
+
if (!sd->state.using_fake_npc && (npcid == npc->fake_nd->bl.id || ((bl = map->id2bl(npcid)) != NULL && (bl->m!=sd->bl.m ||
bl->x<sd->bl.x-AREA_SIZE-1 || bl->x>sd->bl.x+AREA_SIZE+1 ||
bl->y<sd->bl.y-AREA_SIZE-1 || bl->y>sd->bl.y+AREA_SIZE+1))))
clif->sendfakenpc(sd, npcid);
WFIFOHEAD(fd, slen);
- WFIFOW(fd,0)=0xb7;
- WFIFOW(fd,2)=slen;
- WFIFOL(fd,4)=npcid;
+ WFIFOW(fd,0) = 0xb7;
+ WFIFOW(fd,2) = slen;
+ WFIFOL(fd,4) = npcid;
memcpy(WFIFOP(fd,8), mes, slen-8);
WFIFOSET(fd,WFIFOW(fd,2));
}
@@ -3607,26 +3616,29 @@ void clif_createchat(struct map_session_data* sd, int flag)
/// 1 = public
/// 2 = arena (npc waiting room)
/// 3 = PK zone (non-clickable)
-void clif_dispchat(struct chat_data* cd, int fd)
+void clif_dispchat(struct chat_data *cd, int fd)
{
unsigned char buf[128];
uint8 type;
+ int len;
- if( cd == NULL || cd->owner == NULL )
+ if (cd == NULL || cd->owner == NULL)
return;
type = (cd->owner->type == BL_PC ) ? (cd->pub) ? 1 : 0
: (cd->owner->type == BL_NPC) ? (cd->limit) ? 2 : 3
: 1;
+ len = (int)strlen(cd->title);
+ Assert_retv(len <= INT16_MAX - 17);
WBUFW(buf, 0) = 0xd7;
- WBUFW(buf, 2) = 17 + strlen(cd->title);
+ WBUFW(buf, 2) = 17 + len;
WBUFL(buf, 4) = cd->owner->id;
WBUFL(buf, 8) = cd->bl.id;
WBUFW(buf,12) = cd->limit;
WBUFW(buf,14) = (cd->owner->type == BL_NPC) ? cd->users+1 : cd->users;
WBUFB(buf,16) = type;
- memcpy(WBUFP(buf,17), cd->title, strlen(cd->title)); // not zero-terminated
+ memcpy(WBUFP(buf,17), cd->title, len); // not zero-terminated
if( fd ) {
WFIFOHEAD(fd,WBUFW(buf,2));
@@ -3644,10 +3656,11 @@ void clif_dispchat(struct chat_data* cd, int fd)
/// 1 = public
/// 2 = arena (npc waiting room)
/// 3 = PK zone (non-clickable)
-void clif_changechatstatus(struct chat_data* cd)
+void clif_changechatstatus(struct chat_data *cd)
{
unsigned char buf[128];
uint8 type;
+ int len;
if( cd == NULL || cd->usersd[0] == NULL )
return;
@@ -3655,15 +3668,17 @@ void clif_changechatstatus(struct chat_data* cd)
type = (cd->owner->type == BL_PC ) ? (cd->pub) ? 1 : 0
: (cd->owner->type == BL_NPC) ? (cd->limit) ? 2 : 3
: 1;
+ len = (int)strlen(cd->title);
+ Assert_retv(len <= INT16_MAX - 17);
WBUFW(buf, 0) = 0xdf;
- WBUFW(buf, 2) = 17 + strlen(cd->title);
+ WBUFW(buf, 2) = 17 + len;
WBUFL(buf, 4) = cd->owner->id;
WBUFL(buf, 8) = cd->bl.id;
WBUFW(buf,12) = cd->limit;
WBUFW(buf,14) = (cd->owner->type == BL_NPC) ? cd->users+1 : cd->users;
WBUFB(buf,16) = type;
- memcpy(WBUFP(buf,17), cd->title, strlen(cd->title)); // not zero-terminated
+ memcpy(WBUFP(buf,17), cd->title, len); // not zero-terminated
clif->send(buf,WBUFW(buf,2),cd->owner,CHAT);
}
@@ -4112,8 +4127,8 @@ void clif_getareachar_pc(struct map_session_data* sd,struct map_session_data* ds
nullpo_retv(sd);
nullpo_retv(dstsd);
- if( dstsd->chatID ) {
- struct chat_data *cd = map->id2cd(dstsd->chatID);
+ if (dstsd->chat_id != 0) {
+ struct chat_data *cd = map->id2cd(dstsd->chat_id);
if (cd != NULL && cd->usersd[0] == dstsd)
clif->dispchat(cd,sd->fd);
} else if( dstsd->state.vending )
@@ -4615,9 +4630,9 @@ int clif_outsight(struct block_list *bl,va_list ap)
case BL_PC:
if (sd->vd.class_ != INVISIBLE_CLASS)
clif->clearunit_single(bl->id,CLR_OUTSIGHT,tsd->fd);
- if (sd->chatID) {
- struct chat_data *cd = map->id2cd(sd->chatID);
- if(cd->usersd[0]==sd)
+ if (sd->chat_id != 0) {
+ struct chat_data *cd = map->id2cd(sd->chat_id);
+ if (cd != NULL && cd->usersd[0] == sd)
clif->dispchat(cd,tsd->fd);
}
if( sd->state.vending )
@@ -5475,23 +5490,24 @@ void clif_status_change(struct block_list *bl,int type,int flag,int tick,int val
/// Send message (modified by [Yor]) (ZC_NOTIFY_PLAYERCHAT).
/// 008e <packet len>.W <message>.?B
-void clif_displaymessage(const int fd, const char* mes) {
+void clif_displaymessage(const int fd, const char *mes)
+{
nullpo_retv(mes);
- if( map->cpsd_active && fd == 0 ) {
+ if (map->cpsd_active && fd == 0) {
ShowInfo("HCP: %s\n",mes);
- } else if ( fd > 0 ) {
+ } else if (fd > 0) {
#if PACKETVER == 20141022
/** for some reason game client crashes depending on message pattern (only for this packet) **/
/** so we redirect to ZC_NPC_CHAT **/
clif->messagecolor_self(fd, COLOR_DEFAULT, mes);
#else
- size_t len;
+ int len = (int)strnlen(mes, 255);
- if ( ( len = strnlen(mes, 255) ) > 0 ) { // don't send a void message (it's not displaying on the client chat). @help can send void line.
+ if (len > 0) { // don't send a void message (it's not displaying on the client chat). @help can send void line.
WFIFOHEAD(fd, 5 + len);
WFIFOW(fd,0) = 0x8e;
- WFIFOW(fd,2) = 5 + len; // 4 + len + NULL terminate
+ WFIFOW(fd,2) = 5 + len; // 4 + len + NUL terminate
safestrncpy(WFIFOP(fd,4), mes, len + 1);
WFIFOSET(fd, 5 + len);
}
@@ -5513,7 +5529,7 @@ void clif_displaymessage2(const int fd, const char* mes) {
line = strtok(message, "\n");
while(line != NULL) {
// Limit message to 255+1 characters (otherwise it causes a buffer overflow in the client)
- size_t len = strnlen(line, 255);
+ int len = (int)strnlen(line, 255);
if (len > 0) { // don't send a void message (it's not displaying on the client chat). @help can send void line.
if( map->cpsd_active && fd == 0 ) {
@@ -5567,7 +5583,7 @@ void clif_displaymessage_sprintf(const int fd, const char *mes, ...) {
}
/// Send broadcast message in yellow or blue without font formatting (ZC_BROADCAST).
/// 009a <packet len>.W <message>.?B
-void clif_broadcast(struct block_list *bl, const char *mes, size_t len, int type, enum send_target target)
+void clif_broadcast(struct block_list *bl, const char *mes, int len, int type, enum send_target target)
{
int lp = (type&BC_COLOR_MASK) ? 4 : 0;
unsigned char *buf = NULL;
@@ -5591,38 +5607,38 @@ void clif_broadcast(struct block_list *bl, const char *mes, size_t len, int type
* Displays a message on a 'bl' to all it's nearby clients
* Used by npc_globalmessage
*------------------------------------------*/
-void clif_GlobalMessage(struct block_list* bl, const char* message) {
+void clif_GlobalMessage(struct block_list *bl, const char *message)
+{
char buf[256];
- size_t len;
+ int len;
nullpo_retv(bl);
- if(!message)
+ if (message == NULL)
return;
- len = strlen(message)+1;
+ len = (int)strlen(message)+1;
- if (len > sizeof(buf)-8) {
- ShowWarning("clif_GlobalMessage: Truncating too long message '%s' (len=%"PRIuS").\n", message, len);
- len = sizeof(buf)-8;
+ if (len > (int)sizeof(buf)-8) {
+ ShowWarning("clif_GlobalMessage: Truncating too long message '%s' (len=%d).\n", message, len);
+ len = (int)sizeof(buf)-8;
}
- WBUFW(buf,0)=0x8d;
- WBUFW(buf,2)=len+8;
- WBUFL(buf,4)=bl->id;
+ WBUFW(buf,0) = 0x8d;
+ WBUFW(buf,2) = len+8;
+ WBUFL(buf,4) = bl->id;
safestrncpy(WBUFP(buf,8),message,len);
- clif->send((unsigned char *) buf,WBUFW(buf,2),bl,ALL_CLIENT);
-
+ clif->send(buf,WBUFW(buf,2),bl,ALL_CLIENT);
}
/// Send broadcast message with font formatting (ZC_BROADCAST2).
/// 01c3 <packet len>.W <fontColor>.L <fontType>.W <fontSize>.W <fontAlign>.W <fontY>.W <message>.?B
-void clif_broadcast2(struct block_list* bl, const char* mes, size_t len, unsigned int fontColor, short fontType, short fontSize, short fontAlign, short fontY, enum send_target target)
+void clif_broadcast2(struct block_list *bl, const char *mes, int len, unsigned int fontColor, short fontType, short fontSize, short fontAlign, short fontY, enum send_target target)
{
unsigned char *buf;
nullpo_retv(mes);
- buf = (unsigned char*)aMalloc((16 + len)*sizeof(unsigned char));
+ buf = aMalloc((16 + len)*sizeof(unsigned char));
WBUFW(buf,0) = 0x1c3;
WBUFW(buf,2) = len + 16;
WBUFL(buf,4) = fontColor;
@@ -5790,7 +5806,7 @@ void clif_upgrademessage(int fd, int result, int item_id)
/// Whisper is transmitted to the destination player (ZC_WHISPER).
/// 0097 <packet len>.W <nick>.24B <message>.?B
/// 0097 <packet len>.W <nick>.24B <isAdmin>.L <message>.?B (PACKETVER >= 20091104)
-void clif_wis_message(int fd, const char *nick, const char *mes, size_t mes_len)
+void clif_wis_message(int fd, const char *nick, const char *mes, int mes_len)
{
#if PACKETVER >= 20091104
struct map_session_data *ssd = NULL;
@@ -5799,21 +5815,21 @@ void clif_wis_message(int fd, const char *nick, const char *mes, size_t mes_len)
nullpo_retv(mes);
#if PACKETVER < 20091104
- WFIFOHEAD(fd, mes_len + NAME_LENGTH + 4);
+ WFIFOHEAD(fd, mes_len + NAME_LENGTH + 5);
WFIFOW(fd,0) = 0x97;
- WFIFOW(fd,2) = mes_len + NAME_LENGTH + 4;
+ WFIFOW(fd,2) = mes_len + NAME_LENGTH + 5;
safestrncpy(WFIFOP(fd,4), nick, NAME_LENGTH);
- safestrncpy(WFIFOP(fd,28), mes, mes_len);
+ safestrncpy(WFIFOP(fd,28), mes, mes_len + 1);
WFIFOSET(fd,WFIFOW(fd,2));
#else
ssd = map->nick2sd(nick);
- WFIFOHEAD(fd, mes_len + NAME_LENGTH + 8);
+ WFIFOHEAD(fd, mes_len + NAME_LENGTH + 9);
WFIFOW(fd,0) = 0x97;
- WFIFOW(fd,2) = mes_len + NAME_LENGTH + 8;
+ WFIFOW(fd,2) = mes_len + NAME_LENGTH + 9;
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(WFIFOP(fd,32), mes, mes_len);
+ safestrncpy(WFIFOP(fd,32), mes, mes_len + 1);
WFIFOSET(fd,WFIFOW(fd,2));
#endif
}
@@ -6599,7 +6615,7 @@ void clif_party_withdraw(struct party_data* p, struct map_session_data* sd, int
/// Party chat message (ZC_NOTIFY_CHAT_PARTY).
/// 0109 <packet len>.W <account id>.L <message>.?B
-void clif_party_message(struct party_data* p, int account_id, const char* mes, int len)
+void clif_party_message(struct party_data *p, int account_id, const char *mes, int len)
{
struct map_session_data *sd;
int i;
@@ -6607,22 +6623,24 @@ void clif_party_message(struct party_data* p, int account_id, const char* mes, i
nullpo_retv(p);
nullpo_retv(mes);
- for(i=0; i < MAX_PARTY && !p->data[i].sd;i++);
- if(i < MAX_PARTY){
+ ARR_FIND(0, MAX_PARTY, i, p->data[i].sd != NULL);
+
+ if (i < MAX_PARTY) {
unsigned char buf[1024];
+ int maxlen = (int)sizeof(buf) - 9;
- if (len > sizeof(buf)-8) {
- ShowWarning("clif_party_message: Truncated message '%s' (len=%d, max=%"PRIuS", party_id=%d).\n",
- mes, len, sizeof(buf)-8, p->party.party_id);
- len = sizeof(buf)-8;
+ if (len > maxlen) {
+ ShowWarning("clif_party_message: Truncated message '%s' (len=%d, max=%d, party_id=%d).\n",
+ mes, len, maxlen, p->party.party_id);
+ len = maxlen;
}
sd = p->data[i].sd;
- WBUFW(buf,0)=0x109;
- WBUFW(buf,2)=len+8;
- WBUFL(buf,4)=account_id;
- safestrncpy(WBUFP(buf,8), mes, len);
- clif->send(buf,len+8,&sd->bl,PARTY);
+ WBUFW(buf,0) = 0x109;
+ WBUFW(buf,2) = len+9;
+ WBUFL(buf,4) = account_id;
+ safestrncpy(WBUFP(buf,8), mes, len+1);
+ clif->send(buf, len+9, &sd->bl, PARTY);
}
}
@@ -7934,19 +7952,21 @@ void clif_marriage_proposal(int fd, struct map_session_data *sd, struct map_sess
/*==========================================
* Displays a message using the guild-chat colors to the specified targets. [Skotlex]
*------------------------------------------*/
-void clif_disp_message(struct block_list* src, const char* mes, size_t len, enum send_target target)
+void clif_disp_message(struct block_list *src, const char *mes, enum send_target target)
{
unsigned char buf[256];
+ int len;
+
+ nullpo_retv(mes);
+ nullpo_retv(src);
+ len = (int)strlen(mes);
if (len == 0)
return;
- nullpo_retv(src);
- nullpo_retv(mes);
-
- if (len > sizeof(buf)-5) {
- ShowWarning("clif_disp_message: Truncated message '%s' (len=%"PRIuS", max=%"PRIuS", aid=%d).\n", mes, len, sizeof(buf)-5, src->id);
- len = sizeof(buf)-5;
+ if (len > (int)sizeof(buf)-5) {
+ ShowWarning("clif_disp_message: Truncated message '%s' (len=%d, max=%"PRIuS", aid=%d).\n", mes, len, sizeof(buf)-5, src->id);
+ len = (int)sizeof(buf)-5;
}
WBUFW(buf, 0) = 0x17f;
@@ -8200,10 +8220,11 @@ void clif_specialeffect_value(struct block_list* bl, int effect_id, int num, sen
*/
void clif_messagecolor_self(int fd, uint32 color, const char *msg)
{
- size_t msg_len;
+ int msg_len;
nullpo_retv(msg);
- msg_len = strlen(msg) + 1;
+ msg_len = (int)strlen(msg) + 1;
+ Assert_retv(msg_len <= INT16_MAX - 12);
WFIFOHEAD(fd,msg_len + 12);
WFIFOW(fd,0) = 0x2C1;
@@ -8223,17 +8244,19 @@ void clif_messagecolor_self(int fd, uint32 color, const char *msg)
* @param color Message color (RGB format: 0xRRGGBB)
* @param msg Message text
*/
-void clif_messagecolor(struct block_list* bl, uint32 color, const char *msg)
+void clif_messagecolor(struct block_list *bl, uint32 color, const char *msg)
{
- size_t msg_len = strlen(msg) + 1;
+ int msg_len;
uint8 buf[256];
nullpo_retv(bl);
nullpo_retv(msg);
- if (msg_len > sizeof(buf)-12) {
- ShowWarning("clif_messagecolor: Truncating too long message '%s' (len=%"PRIuS").\n", msg, msg_len);
- msg_len = sizeof(buf)-12;
+ msg_len = (int)strlen(msg) + 1;
+
+ if (msg_len > (int)sizeof(buf)-12) {
+ ShowWarning("clif_messagecolor: Truncating too long message '%s' (len=%d).\n", msg, msg_len);
+ msg_len = (int)sizeof(buf)-12;
}
WBUFW(buf,0) = 0x2C1;
@@ -8313,7 +8336,7 @@ void clif_refresh(struct map_session_data *sd)
clif->elemental_info(sd);
map->foreachinrange(clif->getareachar,&sd->bl,AREA_SIZE,BL_ALL,sd);
clif->weather_check(sd);
- if( sd->chatID )
+ if (sd->chat_id != 0)
chat->leave(sd, false);
if( sd->state.vending )
clif->openvending(sd, sd->bl.id, sd->vending);
@@ -8553,34 +8576,33 @@ void clif_slide(struct block_list *bl, int x, int y)
/// Public chat message (ZC_NOTIFY_CHAT). lordalfa/Skotlex - used by @me as well
/// 008d <packet len>.W <id>.L <message>.?B
-void clif_disp_overhead(struct block_list *bl, const char* mes)
+void clif_disp_overhead(struct block_list *bl, const char *mes)
{
unsigned char buf[256]; //This should be more than sufficient, the theoretical max is CHAT_SIZE + 8 (pads and extra inserted crap)
- size_t len_mes;
+ int mes_len;
nullpo_retv(bl);
nullpo_retv(mes);
- len_mes = strlen(mes)+1; //Account for \0
+ mes_len = (int)strlen(mes)+1; //Account for \0
- if (len_mes > sizeof(buf)-8) {
- ShowError("clif_disp_overhead: Message too long (length %"PRIuS")\n", len_mes);
- len_mes = sizeof(buf)-8; //Trunk it to avoid problems.
+ if (mes_len > (int)sizeof(buf)-8) {
+ ShowError("clif_disp_overhead: Message too long (length %d)\n", mes_len);
+ mes_len = sizeof(buf)-8; //Trunk it to avoid problems.
}
// send message to others
WBUFW(buf,0) = 0x8d;
- WBUFW(buf,2) = len_mes + 8; // len of message + 8 (command+len+id)
+ WBUFW(buf,2) = mes_len + 8; // len of message + 8 (command+len+id)
WBUFL(buf,4) = bl->id;
- safestrncpy(WBUFP(buf,8), mes, len_mes);
+ safestrncpy(WBUFP(buf,8), mes, mes_len);
clif->send(buf, WBUFW(buf,2), bl, AREA_CHAT_WOC);
// send back message to the speaker
- if( bl->type == BL_PC ) {
+ if (bl->type == BL_PC) {
WBUFW(buf,0) = 0x8e;
- WBUFW(buf, 2) = len_mes + 4;
- safestrncpy(WBUFP(buf,4), mes, len_mes);
+ WBUFW(buf, 2) = mes_len + 4;
+ safestrncpy(WBUFP(buf,4), mes, mes_len);
clif->send(buf, WBUFW(buf,2), bl, SELF);
}
-
}
/*==========================
@@ -8864,120 +8886,153 @@ void clif_msgtable_skill(struct map_session_data* sd, uint16 skill_id, int msg_i
WFIFOSET(fd, packet_len(0x7e6));
}
-/// Validates one global/guild/party/whisper message packet and tries to recognize its components.
-/// 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, const char **name_, size_t *namelen_, const char **message_, size_t *messagelen_)
+/**
+ * Validates and processes a global/guild/party message packet.
+ *
+ * @param[in] sd The source character.
+ * @param[in] packet The packet data.
+ * @param[out] out_buf The output buffer (must be a valid buffer), that will
+ * be filled with "Name : Message".
+ * @param[in] out_buflen The size of out_buf (including the NUL terminator).
+ * @return a pointer to the "Message" part of out_buf.
+ * @retval NULL if the validation failed, the messages was a command or the
+ * character can't send chat messages. out_buf shan't be used.
+ */
+const char *clif_process_chat_message(struct map_session_data *sd, const struct packet_chat_message *packet, char *out_buf, int out_buflen)
{
- const char *text, *name, *message;
- unsigned int packetlen, textlen;
- size_t namelen, messagelen;
- int fd = sd->fd;
+ const char *srcname = NULL, *srcmessage = NULL, *message = NULL;
+ int textlen = 0, namelen = 0, messagelen = 0;
- nullpo_retr(false, sd);
- nullpo_retr(false, name_);
- nullpo_retr(false, namelen_);
- nullpo_retr(false, message_);
- nullpo_retr(false, messagelen_);
-
- *name_ = NULL;
- *namelen_ = 0;
- *message_ = NULL;
- *messagelen_ = 0;
-
- packetlen = RFIFOW(fd,2);
- // basic structure checks
- if (packetlen < 4 + 1) {
+ nullpo_ret(sd);
+ nullpo_ret(packet);
+ nullpo_ret(out_buf);
+
+ if (packet->packet_len < 4 + 1) {
// 4-byte header and at least an empty string is expected
- ShowWarning("clif_process_message: Received malformed packet from player '%s' (no message data)!\n", sd->status.name);
- return false;
+ ShowWarning("clif_process_chat_message: Received malformed packet from player '%s' (no message data)!\n", sd->status.name);
+ return NULL;
}
- text = RFIFOP(fd,4);
- textlen = packetlen - 4;
+#if PACKETVER >= 20151001
+ // Packet doesn't include a NUL terminator
+ textlen = packet->packet_len - 4;
+#else // PACKETVER < 20151001
+ // Packet includes a NUL terminator
+ textlen = packet->packet_len - 4 - 1;
+#endif // PACKETVER > 20151001
- // process <name> part of the packet
- if( format == 0 )
- {// name and message are separated by ' : '
- // validate name
- name = text;
- namelen = strnlen(sd->status.name, NAME_LENGTH-1); // name length (w/o zero byte)
+ // name and message are separated by ' : '
+ srcname = packet->message;
+ namelen = (int)strnlen(sd->status.name, NAME_LENGTH-1); // name length (w/o zero byte)
- if( strncmp(name, sd->status.name, namelen) || // the text must start with the speaker's name
- name[namelen] != ' ' || name[namelen+1] != ':' || name[namelen+2] != ' ' ) // followed by ' : '
- {
- //Hacked message, or infamous "client desynchronize" issue where they pick one char while loading another.
- ShowWarning("clif_process_message: Player '%s' sent a message using an incorrect name! Forcing a relog...\n", sd->status.name);
- sockt->eof(fd); // Just kick them out to correct it.
- return false;
- }
+ if (strncmp(srcname, sd->status.name, namelen) != 0 // the text must start with the speaker's name
+ || srcname[namelen] != ' ' || srcname[namelen+1] != ':' || srcname[namelen+2] != ' ' // followed by ' : '
+ ) {
+ //Hacked message, or infamous "client desynchronize" issue where they pick one char while loading another.
+ ShowWarning("clif_process_chat_message: Player '%s' sent a message using an incorrect name! Forcing a relog...\n", sd->status.name);
+ sockt->eof(sd->fd); // Just kick them out to correct it.
+ return NULL;
+ }
+
+ srcmessage = packet->message + namelen + 3; // <name> " : " <message>
+ messagelen = textlen - namelen - 3;
- message = name + namelen + 3;
- messagelen = textlen - namelen - 3; // this should be the message length (w/ zero byte included)
+ if (messagelen >= CHAT_SIZE_MAX || textlen >= out_buflen) {
+ // messages mustn't be too long
+ // Normally you can only enter CHATBOX_SIZE-1 letters into the chat box, but Frost Joke / Dazzler's text can be longer.
+ // Also, the physical size of strings that use multibyte encoding can go multiple times over the chatbox capacity.
+ // Neither the official client nor server place any restriction on the length of the data in the packet,
+ // but we'll only allow reasonably long strings here. This also makes sure that they fit into the `chatlog` table.
+ ShowWarning("clif_process_chat_message: Player '%s' sent a message too long ('%.*s')!\n", sd->status.name, CHATBOX_SIZE-1, srcmessage);
+ return NULL;
}
- else
- {// name has fixed width
- if( textlen < NAME_LENGTH + 1 )
- {
- ShowWarning("clif_process_message: Received malformed packet from player '%s' (packet length is incorrect)!\n", sd->status.name);
- return false;
- }
- // validate name
- name = text;
- namelen = strnlen(name, NAME_LENGTH-1); // name length (w/o zero byte)
+ safestrncpy(out_buf, packet->message, textlen+1); // [!] packet->message is not necessarily NUL terminated
+ message = out_buf + namelen + 3;
- if (name[namelen] != '\0') {
- // only restriction is that the name must be zero-terminated
- ShowWarning("clif_process_message: Player '%s' sent an unterminated name!\n", sd->status.name);
- return false;
- }
+ if (!pc->process_chat_message(sd, message))
+ return NULL;
+ return message;
+}
- message = name + NAME_LENGTH;
- messagelen = textlen - NAME_LENGTH; // this should be the message length (w/ zero byte included)
- }
+/**
+ * Validates and processes a whisper message packet.
+ *
+ * @param[in] sd The source character.
+ * @param[in] packet The packet data.
+ * @param[out] out_name The parsed target name buffer (must be a valid
+ * buffer of size NAME_LENGTH).
+ * @param[out] out_message The output message buffer (must be a valid buffer).
+ * @param[in] out_messagelen The size of out_message.
+ * @retval true if the validation succeeded and the message is a chat message.
+ * @retval false if the validation failed, the messages was a command or the
+ * character can't send chat messages. out_name and out_message
+ * shan't be used.
+ */
+bool clif_process_whisper_message(struct map_session_data *sd, const struct packet_whisper_message *packet, char *out_name, char *out_message, int out_messagelen)
+{
+ int namelen = 0, messagelen = 0;
+
+ nullpo_retr(false, sd);
+ nullpo_retr(false, packet);
+ nullpo_retr(false, out_name);
+ nullpo_retr(false, out_message);
- if (messagelen != strnlen(message, messagelen)+1) {
- // the declared length must match real length
- ShowWarning("clif_process_message: Received malformed packet from player '%s' (length is incorrect)!\n", sd->status.name);
+ if (packet->packet_len < NAME_LENGTH + 4 + 1) {
+ // 4-byte header and at least an empty string is expected
+ ShowWarning("clif_process_whisper_message: Received malformed packet from player '%s' (packet length is incorrect)!\n", sd->status.name);
return false;
}
- // verify <message> part of the packet
- if (message[messagelen-1] != '\0') {
- // message must be zero-terminated
- ShowWarning("clif_process_message: Player '%s' sent an unterminated message string!\n", sd->status.name);
+
+ // validate name
+ namelen = (int)strnlen(packet->name, NAME_LENGTH-1); // name length (w/o zero byte)
+
+ if (packet->name[namelen] != '\0') {
+ // only restriction is that the name must be zero-terminated
+ ShowWarning("clif_process_whisper_message: Player '%s' sent an unterminated name!\n", sd->status.name);
return false;
}
- if (messagelen > CHAT_SIZE_MAX-1) {
+
+#if PACKETVER >= 20151001
+ // Packet doesn't include a NUL terminator
+ messagelen = packet->packet_len - NAME_LENGTH - 4;
+#else // PACKETVER < 20151001
+ // Packet includes a NUL terminator
+ messagelen = packet->packet_len - NAME_LENGTH - 4 - 1;
+#endif // PACKETVER > 20151001
+
+ if (messagelen >= CHAT_SIZE_MAX || messagelen >= out_messagelen) {
// messages mustn't be too long
// Normally you can only enter CHATBOX_SIZE-1 letters into the chat box, but Frost Joke / Dazzler's text can be longer.
// Also, the physical size of strings that use multibyte encoding can go multiple times over the chatbox capacity.
// Neither the official client nor server place any restriction on the length of the data in the packet,
// but we'll only allow reasonably long strings here. This also makes sure that they fit into the `chatlog` table.
- ShowWarning("clif_process_message: Player '%s' sent a message too long ('%.*s')!\n", sd->status.name, CHAT_SIZE_MAX-1, message);
+ ShowWarning("clif_process_whisper_message: Player '%s' sent a message too long ('%.*s')!\n", sd->status.name, CHAT_SIZE_MAX-1, packet->message);
return false;
}
- *name_ = name;
- *namelen_ = namelen;
- *message_ = message;
- *messagelen_ = messagelen;
+ safestrncpy(out_name, packet->name, namelen+1); // [!] packet->name is not NUL terminated
+ safestrncpy(out_message, packet->message, messagelen+1); // [!] packet->message is not necessarily NUL terminated
+
+ if (!pc->process_chat_message(sd, out_message))
+ return false;
+
return true;
}
void clif_channel_msg(struct channel_data *chan, struct map_session_data *sd, char *msg)
{
- DBIterator *iter;
+ struct DBIterator *iter;
struct map_session_data *user;
- unsigned short msg_len;
+ int msg_len;
uint32 color;
nullpo_retv(chan);
nullpo_retv(sd);
nullpo_retv(msg);
iter = db_iterator(chan->users);
- msg_len = strlen(msg) + 1;
+ msg_len = (int)strlen(msg) + 1;
+ Assert_retv(msg_len <= INT16_MAX - 12);
color = channel->config->colors[chan->color];
WFIFOHEAD(sd->fd,msg_len + 12);
@@ -9002,16 +9057,17 @@ void clif_channel_msg(struct channel_data *chan, struct map_session_data *sd, ch
void clif_channel_msg2(struct channel_data *chan, char *msg)
{
- DBIterator *iter;
+ struct DBIterator *iter;
struct map_session_data *user;
unsigned char buf[210];
- unsigned short msg_len;
+ int msg_len;
uint32 color;
nullpo_retv(chan);
nullpo_retv(msg);
iter = db_iterator(chan->users);
- msg_len = strlen(msg) + 1;
+ msg_len = (int)strlen(msg) + 1;
+ Assert_retv(msg_len <= INT16_MAX - 12);
color = channel->config->colors[chan->color];
WBUFW(buf,0) = 0x2C1;
@@ -9377,7 +9433,7 @@ void clif_parse_LoadEndAck(int fd, struct map_session_data *sd) {
if( map->list[sd->bl.m].flag.allowks && !map_flag_ks(sd->bl.m) ) {
char output[128];
sprintf(output, "[ Kill Steal Protection Disabled. KS is allowed in this map ]");
- clif->broadcast(&sd->bl, output, strlen(output) + 1, BC_BLUE, SELF);
+ clif->broadcast(&sd->bl, output, (int)strlen(output) + 1, BC_BLUE, SELF);
}
map->iwall_get(sd); // Updates Walls Info on this Map to Client
@@ -9709,144 +9765,108 @@ int clif_undisguise_timer(int tid, int64 tick, int id, intptr_t data) {
return 0;
}
-void clif_parse_GlobalMessage(int fd, struct map_session_data* sd) __attribute__((nonnull (2)));
-/// Validates and processes global messages
-/// 008c <packet len>.W <text>.?B (<name> : <message>) 00 (CZ_REQUEST_CHAT)
-/// There are various variants of this packet.
-void clif_parse_GlobalMessage(int fd, struct map_session_data* sd)
+/**
+ * Validates and processed global messages.
+ *
+ * There are various variants of this packet.
+ *
+ * @code
+ * 008c <packet len>.W <text>.?B (<name> : <message>) 00 (CZ_REQUEST_CHAT)
+ * @endcode
+ *
+ * @param fd The incoming file descriptor.
+ * @param sd The related character.
+ */
+void clif_parse_GlobalMessage(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+void clif_parse_GlobalMessage(int fd, struct map_session_data *sd)
{
- const char *text = RFIFOP(fd,4);
- size_t textlen = RFIFOW(fd,2) - 4;
-
- const char *name = NULL, *message = NULL;
- char *fakename = NULL;
- size_t namelen, messagelen;
+ const struct packet_chat_message *packet = NULL;
+ char full_message[CHAT_SIZE_MAX + NAME_LENGTH + 3 + 1];
+ const char *message = NULL;
+ bool is_fakename = false;
+ int outlen = 0;
- bool is_fake;
-
- // validate packet and retrieve name and message
- if( !clif->process_message(sd, 0, &name, &namelen, &message, &messagelen) )
+ packet = RP2PTR(fd);
+ message = clif->process_chat_message(sd, packet, full_message, sizeof full_message);
+ if (message == NULL)
return;
- if( atcommand->exec(fd, sd, message, true) )
- return;
+ pc->check_supernovice_call(sd, message);
- if( !pc->can_talk(sd) )
+ if (sd->gcbind != NULL) {
+ channel->send(sd->gcbind, sd, message);
return;
-
- if( battle_config.min_chat_delay ) { //[Skotlex]
- if (DIFF_TICK(sd->cantalk_tick, timer->gettick()) > 0)
- return;
- sd->cantalk_tick = timer->gettick() + battle_config.min_chat_delay;
}
- if( (sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE ) {
- unsigned int next = pc->nextbaseexp(sd);
- if( next == 0 ) next = pc->thisbaseexp(sd);
- if( next ) { // 0%, 10%, 20%, ...
- int percent = (int)( ( (float)sd->status.base_exp/(float)next )*1000. );
- if( (battle_config.snovice_call_type || percent) && ( percent%100 ) == 0 ) {// 10.0%, 20.0%, ..., 90.0%
- switch (sd->state.snovice_call_flag) {
- case 0:
- if( strstr(message, msg_txt(1479)) ) // "Dear angel, can you hear my voice?"
- sd->state.snovice_call_flag = 1;
- break;
- case 1: {
- char buf[256];
- snprintf(buf, 256, msg_txt(1480), sd->status.name);
- if( strstr(message, buf) ) // "I am %s Super Novice~"
- sd->state.snovice_call_flag = 2;
- }
- break;
- case 2:
- if( strstr(message, msg_txt(1481)) ) // "Help me out~ Please~ T_T"
- sd->state.snovice_call_flag = 3;
- break;
- case 3:
- sc_start(NULL,&sd->bl, status->skill2sc(MO_EXPLOSIONSPIRITS), 100, 17, skill->get_time(MO_EXPLOSIONSPIRITS, 5)); //Lv17-> +50 critical (noted by Poki) [Skotlex]
- clif->skill_nodamage(&sd->bl, &sd->bl, MO_EXPLOSIONSPIRITS, 5, 1); // prayer always shows successful Lv5 cast and disregards noskill restrictions
- sd->state.snovice_call_flag = 0;
- break;
- }
- }
- }
+ if (sd->fakename[0] != '\0') {
+ is_fakename = true;
+ outlen = (int)strlen(sd->fakename) + (int)strlen(message) + 3 + 1;
+ } else {
+ outlen = (int)strlen(full_message) + 1;
}
- pc->update_idle_time(sd, BCIDLE_CHAT);
-
- if( sd->gcbind ) {
- channel->send(sd->gcbind,sd,message);
- return;
- } else if ( sd->fontcolor && !sd->chatID ) {
- char mout[200];
- unsigned char mylen = 1;
+ if (sd->fontcolor != 0 && sd->chat_id == 0) {
uint32 color = 0;
- if( sd->disguise == -1 ) {
+ if (sd->disguise == -1) {
sd->fontcolor_tid = timer->add(timer->gettick()+5000, clif->undisguise_timer, sd->bl.id, 0);
pc->disguise(sd,sd->status.class_);
- if( pc_isdead(sd) )
+ if (pc_isdead(sd))
clif->clearunit_single(-sd->bl.id, CLR_DEAD, sd->fd);
- if( unit->is_walking(&sd->bl) )
+ if (unit->is_walking(&sd->bl))
clif->move(&sd->ud);
- } else if ( sd->disguise == sd->status.class_ && sd->fontcolor_tid != INVALID_TIMER ) {
+ } else if (sd->disguise == sd->status.class_ && sd->fontcolor_tid != INVALID_TIMER) {
const struct TimerData *td;
- if( (td = timer->get(sd->fontcolor_tid)) ) {
+ if ((td = timer->get(sd->fontcolor_tid)) != NULL)
timer->settick(sd->fontcolor_tid, td->tick+5000);
- }
}
- mylen += snprintf(mout, 200, "%s : %s",sd->fakename[0]?sd->fakename:sd->status.name,message);
-
color = channel->config->colors[sd->fontcolor - 1];
- WFIFOHEAD(fd,mylen + 12);
+ WFIFOHEAD(fd, outlen + 12);
WFIFOW(fd,0) = 0x2C1;
- WFIFOW(fd,2) = mylen + 12;
+ WFIFOW(fd,2) = outlen + 12;
WFIFOL(fd,4) = sd->bl.id;
WFIFOL(fd,8) = RGB2BGR(color);
- safestrncpy(WFIFOP(fd,12), mout, mylen);
+ if (is_fakename)
+ safesnprintf(WFIFOP(fd, 12), outlen, "%s : %s", sd->fakename, message);
+ else
+ safestrncpy(WFIFOP(fd, 12), full_message, outlen);
clif->send(WFIFOP(fd,0), WFIFOW(fd,2), &sd->bl, AREA_WOS);
WFIFOL(fd,4) = -sd->bl.id;
- WFIFOSET(fd, mylen + 12);
+ WFIFOSET(fd, outlen + 12);
return;
}
- /**
- * Fake Name Design by FatalEror (bug report #9)
- **/
- if( ( is_fake = ( sd->fakename[0] ) ) ) {
- fakename = (char*) aMalloc(strlen(sd->fakename)+messagelen+3);
- strcpy(fakename, sd->fakename);
- strcat(fakename, " : ");
- strcat(fakename, message);
- textlen = strlen(fakename) + 1;
+ {
+ // send message to others
+ void *buf = aMalloc(8 + outlen);
+ WBUFW(buf, 0) = 0x8d;
+ WBUFW(buf, 2) = 8 + outlen;
+ WBUFL(buf, 4) = sd->bl.id;
+ if (is_fakename)
+ safesnprintf(WBUFP(buf, 8), outlen, "%s : %s", sd->fakename, message);
+ else
+ safestrncpy(WBUFP(buf, 8), full_message, outlen);
+ //FIXME: chat has range of 9 only
+ clif->send(buf, WBUFW(buf, 2), &sd->bl, sd->chat_id != 0 ? CHAT_WOS : AREA_CHAT_WOC);
+ aFree(buf);
}
- // send message to others (using the send buffer for temp. storage)
- WFIFOHEAD(fd, 8 + textlen);
- WFIFOW(fd,0) = 0x8d;
- WFIFOW(fd,2) = 8 + textlen;
- WFIFOL(fd,4) = sd->bl.id;
- 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);
// send back message to the speaker
- if( is_fake ) {
- WFIFOW(fd,0) = 0x8e;
- WFIFOW(fd,2) = textlen + 4;
- safestrncpy(WFIFOP(fd,4), fakename, textlen);
- aFree(fakename);
- } else {
- memcpy(WFIFOP(fd,0), RFIFOP(fd,0), RFIFOW(fd,2));
- WFIFOW(fd,0) = 0x8e;
- }
+ WFIFOHEAD(fd, 4 + outlen);
+ WFIFOW(fd, 0) = 0x8e;
+ WFIFOW(fd, 2) = 4 + outlen;
+ if (is_fakename)
+ safesnprintf(WFIFOP(fd, 4), outlen, "%s : %s", sd->fakename, message);
+ else
+ safestrncpy(WFIFOP(fd, 4), full_message, outlen);
WFIFOSET(fd, WFIFOW(fd,2));
// 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);
// trigger listening npcs
- map->foreachinrange(npc_chat->sub, &sd->bl, AREA_SIZE, BL_NPC, text, textlen, &sd->bl);
+ map->foreachinrange(npc_chat->sub, &sd->bl, AREA_SIZE, BL_NPC, full_message, strlen(full_message), &sd->bl);
}
void clif_parse_MapMove(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
@@ -10119,37 +10139,28 @@ void clif_parse_Restart(int fd, struct map_session_data *sd) {
}
}
-void clif_parse_WisMessage(int fd, struct map_session_data* sd) __attribute__((nonnull (2)));
-/// Validates and processes whispered messages (CZ_WHISPER).
-/// 0096 <packet len>.W <nick>.24B <message>.?B
+/**
+ * Validates and processes whispered messages (CZ_WHISPER).
+ *
+ * @code
+ * 0096 <packet len>.W <nick>.24B <message>.?B
+ * @endcode
+ *
+ * @param fd The incoming file descriptor.
+ * @param sd The related character.
+ */
+void clif_parse_WisMessage(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
void clif_parse_WisMessage(int fd, struct map_session_data* sd)
{
struct map_session_data* dstsd;
int i;
- const char *target, *message;
- size_t namelen, messagelen;
-
- // validate packet and retrieve name and message
- if( !clif->process_message(sd, 1, &target, &namelen, &message, &messagelen) )
- return;
-
- if ( atcommand->exec(fd, sd, message, true) )
- return;
+ char target[NAME_LENGTH], message[CHAT_SIZE_MAX + 1];
+ const struct packet_whisper_message *packet = RP2PTR(fd);
- // Statuses that prevent the player from whispering
- if( !pc->can_talk(sd) )
+ if (!clif->process_whisper_message(sd, packet, target, message, sizeof message))
return;
- if (battle_config.min_chat_delay) { //[Skotlex]
- if (DIFF_TICK(sd->cantalk_tick, timer->gettick()) > 0) {
- return;
- }
- sd->cantalk_tick = timer->gettick() + battle_config.min_chat_delay;
- }
-
- pc->update_idle_time(sd, BCIDLE_CHAT);
-
// Chat logging type 'W' / Whisper
logs->chat(LOG_CHAT_WHISPER, 0, sd->status.char_id, sd->status.account_id, mapindex_id2name(sd->mapindex), sd->bl.x, sd->bl.y, target, message);
@@ -10219,7 +10230,7 @@ void clif_parse_WisMessage(int fd, struct map_session_data* sd)
// if there are 'Test' player on an other map-server and 'test' player on this map-server,
// and if we ask for 'Test', we must not contact 'test' player
// so, we send information to inter-server, which is the only one which decide (and copy correct name).
- intif->wis_message(sd, target, message, messagelen);
+ intif->wis_message(sd, target, message, (int)strlen(message));
return;
}
@@ -10233,10 +10244,10 @@ void clif_parse_WisMessage(int fd, struct map_session_data* sd)
}
// if player is autotrading
- if( dstsd->state.autotrade ) {
+ if (dstsd->state.autotrade) {
char output[256];
sprintf(output, "%s is in autotrade mode and cannot receive whispered messages.", dstsd->status.name);
- clif->wis_message(fd, map->wisp_server_name, output, strlen(output) + 1);
+ clif->wis_message(fd, map->wisp_server_name, output, (int)strlen(output));
return;
}
@@ -10253,7 +10264,7 @@ void clif_parse_WisMessage(int fd, struct map_session_data* sd)
clif->wis_end(fd, 0); // 0: success to send wisper
// Normal message
- clif->wis_message(dstsd->fd, sd->status.name, message, messagelen);
+ clif->wis_message(dstsd->fd, sd->status.name, message, (int)strlen(message));
}
void clif_parse_Broadcast(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
@@ -10370,7 +10381,7 @@ void clif_parse_UseItem(int fd, struct map_session_data *sd)
return;
}
- if ( (!sd->npc_id && pc_istrading(sd)) || sd->chatID )
+ if ((!sd->npc_id && pc_istrading(sd)) || sd->chat_id != 0)
return;
//Whether the item is used or not is irrelevant, the char ain't idle. [Skotlex]
@@ -10730,10 +10741,10 @@ void clif_noask_sub(struct map_session_data *src, struct map_session_data *targe
nullpo_retv(src);
// Your request has been rejected by autoreject option.
msg = msg_sd(src,392);
- clif_disp_onlyself(src, msg, strlen(msg));
+ clif_disp_onlyself(src, msg);
//Notice that a request was rejected.
snprintf(output, 256, msg_sd(target,393+type), src->status.name, 256);
- clif_disp_onlyself(target, output, strlen(output));
+ clif_disp_onlyself(target, output);
}
void clif_parse_TradeRequest(int fd,struct map_session_data *sd) __attribute__((nonnull (2)));
@@ -10744,7 +10755,7 @@ void clif_parse_TradeRequest(int fd,struct map_session_data *sd) {
t_sd = map->id2sd(RFIFOL(fd,2));
- if(!sd->chatID && pc_cant_act(sd))
+ if (sd->chat_id == 0 && pc_cant_act(sd))
return; //You can trade while in a chatroom.
// @noask [LuzZza]
@@ -11521,7 +11532,7 @@ void clif_parse_OneClick_ItemIdentify(int fd, struct map_session_data *sd)
return;
if ((n = pc->have_magnifier(sd) ) != INDEX_NOT_FOUND &&
- pc->delitem(sd, n, 1, 0, DELITEM_NORMAL, LOG_TYPE_OTHER) == 0)
+ pc->delitem(sd, n, 1, 0, DELITEM_NORMAL, LOG_TYPE_CONSUME) == 0)
skill->identify(sd, idx);
}
@@ -11949,36 +11960,26 @@ void clif_parse_PartyChangeOption(int fd, struct map_session_data *sd)
#endif
}
-void clif_parse_PartyMessage(int fd, struct map_session_data* sd) __attribute__((nonnull (2)));
-/// Validates and processes party messages (CZ_REQUEST_CHAT_PARTY).
-/// 0108 <packet len>.W <text>.?B (<name> : <message>) 00
-void clif_parse_PartyMessage(int fd, struct map_session_data* sd)
+/**
+ * Validates and processes party messages (CZ_REQUEST_CHAT_PARTY).
+ *
+ * @code
+ * 0108 <packet len>.W <text>.?B (<name> : <message>) 00
+ * @endcode
+ *
+ * @param fd The incoming file descriptor.
+ * @param sd The related character.
+ */
+void clif_parse_PartyMessage(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+void clif_parse_PartyMessage(int fd, struct map_session_data *sd)
{
- const char *text = RFIFOP(fd,4);
- int textlen = RFIFOW(fd,2) - 4;
-
- const char *name, *message;
- size_t namelen, messagelen;
+ const struct packet_chat_message *packet = RP2PTR(fd);
+ char message[CHAT_SIZE_MAX + NAME_LENGTH + 3 + 1];
- // validate packet and retrieve name and message
- if( !clif->process_message(sd, 0, &name, &namelen, &message, &messagelen) )
+ if (clif->process_chat_message(sd, packet, message, sizeof message) == NULL)
return;
- if( atcommand->exec(fd, sd, message, true) )
- return;
-
- if( !pc->can_talk(sd) )
- return;
-
- if (battle_config.min_chat_delay) {
- if (DIFF_TICK(sd->cantalk_tick, timer->gettick()) > 0)
- return;
- sd->cantalk_tick = timer->gettick() + battle_config.min_chat_delay;
- }
-
- pc->update_idle_time(sd, BCIDLE_CHAT);
-
- party->send_message(sd, text, textlen);
+ party->send_message(sd, message);
}
void clif_parse_PartyChangeLeader(int fd, struct map_session_data* sd) __attribute__((nonnull (2)));
@@ -12820,7 +12821,7 @@ bool clif_validate_emblem(const uint8 *emblem, unsigned long emblem_len) {
//uint8 b;
//uint8 g;
//uint8 r;
- unsigned int rgb:24;
+ uint32 rgb:24;
} __attribute__((packed));
#if !defined(sun) && (!defined(__NETBSD__) || __NetBSD_Version__ >= 600000000) // NetBSD 5 and Solaris don't like pragma pack but accept the packed attribute
#pragma pack(pop)
@@ -13057,39 +13058,29 @@ void clif_parse_GuildExpulsion(int fd,struct map_session_data *sd) {
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)));
-/// Validates and processes guild messages (CZ_GUILD_CHAT).
-/// 017e <packet len>.W <text>.?B (<name> : <message>) 00
-void clif_parse_GuildMessage(int fd, struct map_session_data* sd)
+/**
+ * Validates and processes guild messages (CZ_GUILD_CHAT).
+ *
+ * @code
+ * 017e <packet len>.W <text>.?B (<name> : <message>) 00
+ * @endcode
+ *
+ * @param fd The incoming file descriptor.
+ * @param sd The related character.
+ */
+void clif_parse_GuildMessage(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+void clif_parse_GuildMessage(int fd, struct map_session_data *sd)
{
- const char *text = RFIFOP(fd,4);
- int textlen = RFIFOW(fd,2) - 4;
+ const struct packet_chat_message *packet = RP2PTR(fd);
+ char message[CHAT_SIZE_MAX + NAME_LENGTH + 3 + 1];
- const char *name, *message;
- size_t namelen, messagelen;
-
- // validate packet and retrieve name and message
- if( !clif->process_message(sd, 0, &name, &namelen, &message, &messagelen) )
- return;
-
- if( atcommand->exec(fd, sd, message, true) )
+ if (clif->process_chat_message(sd, packet, message, sizeof message) == NULL)
return;
- if( !pc->can_talk(sd) )
- return;
-
- if (battle_config.min_chat_delay) {
- if (DIFF_TICK(sd->cantalk_tick, timer->gettick()) > 0)
- return;
- sd->cantalk_tick = timer->gettick() + battle_config.min_chat_delay;
- }
-
- pc->update_idle_time(sd, BCIDLE_CHAT);
-
- if( sd->bg_id )
- bg->send_message(sd, text, textlen);
+ if (sd->bg_id)
+ bg->send_message(sd, message);
else
- guild->send_message(sd, text, textlen);
+ guild->send_message(sd, message);
}
void clif_parse_GuildRequestAlliance(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
@@ -13284,7 +13275,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;
@@ -13299,7 +13290,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'
}
@@ -14671,7 +14662,7 @@ void clif_Mail_refreshinbox(struct map_session_data *sd)
if( md->full ) {// TODO: is this official?
char output[100];
sprintf(output, "Inbox is full (Max %d). Delete some mails.", MAIL_MAX_INBOX);
- clif_disp_onlyself(sd, output, strlen(output));
+ clif_disp_onlyself(sd, output);
}
}
@@ -14709,11 +14700,16 @@ void clif_Mail_read(struct map_session_data *sd, int mail_id)
struct mail_message *msg = &sd->mail.inbox.msg[i];
struct item *item = &msg->item;
struct item_data *data;
- size_t msg_len = strlen(msg->body), len;
+ int msg_len = (int)strlen(msg->body), len;
- if( msg_len == 0 ) {
+ if (msg_len == 0) {
strcpy(msg->body, "(no message)");
- msg_len = strlen(msg->body);
+ msg_len = (int)strlen(msg->body);
+ }
+
+ if (msg_len > UINT8_MAX) {
+ Assert_report(msg_len > UINT8_MAX);
+ msg_len = UINT8_MAX;
}
len = 101 + msg_len;
@@ -14741,7 +14737,7 @@ void clif_Mail_read(struct map_session_data *sd, int mail_id)
} else // no item, set all to zero
memset(WFIFOP(fd,80), 0x00, 19);
- WFIFOB(fd,99) = (unsigned char)msg_len;
+ WFIFOB(fd,99) = (uint8)msg_len;
safestrncpy(WFIFOP(fd,100), msg->body, msg_len + 1);
WFIFOSET(fd,len);
@@ -14775,7 +14771,6 @@ void clif_parse_Mail_getattach(int fd, struct map_session_data *sd)
{
int mail_id = RFIFOL(fd,2);
int i;
- bool fail = false;
if( !chrif->isconnected() )
return;
@@ -14799,6 +14794,7 @@ void clif_parse_Mail_getattach(int fd, struct map_session_data *sd)
if( sd->mail.inbox.msg[i].item.nameid > 0 ) {
struct item_data *data;
unsigned int weight;
+ bool fail = false;
if ((data = itemdb->exists(sd->mail.inbox.msg[i].item.nameid)) == NULL)
return;
@@ -16148,58 +16144,53 @@ void clif_bg_xy_remove(struct map_session_data *sd)
/// Notifies clients of a battleground message (ZC_BATTLEFIELD_CHAT).
/// 02dc <packet len>.W <account id>.L <name>.24B <message>.?B
-void clif_bg_message(struct battleground_data *bgd, int src_id, const char *name, const char *mes, size_t len)
+void clif_bg_message(struct battleground_data *bgd, int src_id, const char *name, const char *mes)
{
struct map_session_data *sd;
unsigned char *buf;
+ int len;
nullpo_retv(bgd);
nullpo_retv(name);
nullpo_retv(mes);
- if( !bgd->count || (sd = bg->getavailablesd(bgd)) == NULL )
+
+ if (!bgd->count || (sd = bg->getavailablesd(bgd)) == NULL)
return;
+ len = (int)strlen(mes);
+ Assert_retv(len <= INT16_MAX - NAME_LENGTH - 8);
buf = (unsigned char*)aMalloc((len + NAME_LENGTH + 8)*sizeof(unsigned char));
WBUFW(buf,0) = 0x2dc;
WBUFW(buf,2) = len + NAME_LENGTH + 8;
WBUFL(buf,4) = src_id;
memcpy(WBUFP(buf,8), name, NAME_LENGTH);
- memcpy(WBUFP(buf,32), mes, len);
+ memcpy(WBUFP(buf,32), mes, len); // [!] no NUL terminator
clif->send(buf,WBUFW(buf,2), &sd->bl, BG);
aFree(buf);
}
-void clif_parse_BattleChat(int fd, struct map_session_data* sd) __attribute__((nonnull (2)));
-/// Validates and processes battlechat messages [pakpil] (CZ_BATTLEFIELD_CHAT).
-/// 0x2db <packet len>.W <text>.?B (<name> : <message>) 00
-void clif_parse_BattleChat(int fd, struct map_session_data* sd)
+/**
+ * Validates and processes battlechat messages [pakpil] (CZ_BATTLEFIELD_CHAT).
+ *
+ * @code
+ * 0x2db <packet len>.W <text>.?B (<name> : <message>) 00
+ * @endcode
+ *
+ * @param fd The incoming file descriptor.
+ * @param sd The related character.
+ */
+void clif_parse_BattleChat(int fd, struct map_session_data *sd) __attribute__((nonnull (2)));
+void clif_parse_BattleChat(int fd, struct map_session_data *sd)
{
- const char *text = RFIFOP(fd,4);
- int textlen = RFIFOW(fd,2) - 4;
-
- const char *name, *message;
- size_t namelen, messagelen;
-
- if( !clif->process_message(sd, 0, &name, &namelen, &message, &messagelen) )
- return;
-
- if( atcommand->exec(fd, sd, message, true) )
- return;
+ const struct packet_chat_message *packet = RP2PTR(fd);
+ char message[CHAT_SIZE_MAX + NAME_LENGTH + 3 + 1];
- if( !pc->can_talk(sd) )
+ if (clif->process_chat_message(sd, packet, message, sizeof message) == NULL)
return;
- if( battle_config.min_chat_delay ) {
- if( DIFF_TICK(sd->cantalk_tick, timer->gettick()) > 0 )
- return;
- sd->cantalk_tick = timer->gettick() + battle_config.min_chat_delay;
- }
-
- pc->update_idle_time(sd, BCIDLE_CHAT);
-
- bg->send_message(sd, text, textlen);
+ bg->send_message(sd, message);
}
/// Notifies client of a battleground score change (ZC_BATTLEFIELD_NOTIFY_POINT).
@@ -17694,26 +17685,27 @@ void clif_partytickack(struct map_session_data* sd, bool flag) {
WFIFOSET(sd->fd, packet_len(0x2c9));
}
-void clif_ShowScript(struct block_list* bl, const char* message) {
+void clif_ShowScript(struct block_list *bl, const char *message)
+{
char buf[256];
- size_t len;
+ int len;
nullpo_retv(bl);
- if(!message)
+ if (message == NULL)
return;
- len = strlen(message)+1;
+ len = (int)strlen(message)+1;
- if (len > sizeof(buf)-8) {
- ShowWarning("clif_ShowScript: Truncating too long message '%s' (len=%"PRIuS").\n", message, len);
- len = sizeof(buf)-8;
+ if (len > (int)sizeof(buf)-8) {
+ ShowWarning("clif_ShowScript: Truncating too long message '%s' (len=%d).\n", message, len);
+ len = (int)sizeof(buf)-8;
}
- WBUFW(buf,0)=0x8b3;
- WBUFW(buf,2)=len+8;
- WBUFL(buf,4)=bl->id;
+ WBUFW(buf,0) = 0x8b3;
+ WBUFW(buf,2) = len+8;
+ WBUFL(buf,4) = bl->id;
safestrncpy(WBUFP(buf,8),message,len);
- clif->send((unsigned char *) buf,WBUFW(buf,2),bl,ALL_CLIENT);
+ clif->send(buf,WBUFW(buf,2),bl,ALL_CLIENT);
}
void clif_status_change_end(struct block_list *bl, int tid, enum send_target target, int type) {
@@ -17808,7 +17800,6 @@ 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) {
clif->bgqueue_update_info(sd,sd->bg_queue.arena->id,bg->id2pos(sd->bg_queue.arena->queue_id,sd->status.account_id));
} else {
@@ -18059,7 +18050,7 @@ void clif_show_modifiers (struct map_session_data *sd) {
snprintf(output,128,"Base EXP : %d%% | Base Drop: %d%% | Base Death Penalty: %d%%",
sd->status.mod_exp,sd->status.mod_drop,sd->status.mod_death);
- clif->broadcast2(&sd->bl,output, strlen(output) + 1, 0xffbc90, 0x190, 12, 0, 0, SELF);
+ clif->broadcast2(&sd->bl, output, (int)strlen(output) + 1, 0xffbc90, 0x190, 12, 0, 0, SELF);
}
}
@@ -18404,7 +18395,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;
@@ -18439,7 +18430,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;
@@ -18760,6 +18751,22 @@ void clif_selectcart(struct map_session_data *sd)
#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 ) {
@@ -19346,7 +19353,8 @@ void clif_defaults(void) {
clif->message = clif_displaymessage;
clif->messageln = clif_displaymessage2;
clif->messages = clif_displaymessage_sprintf;
- clif->process_message = clif_process_message;
+ clif->process_chat_message = clif_process_chat_message;
+ clif->process_whisper_message = clif_process_whisper_message;
clif->wisexin = clif_wisexin;
clif->wisall = clif_wisall;
clif->PMIgnoreList = clif_PMIgnoreList;
@@ -19829,4 +19837,5 @@ void clif_defaults(void) {
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 ac0191210..4d22fd4af 100644
--- a/src/map/clif.h
+++ b/src/map/clif.h
@@ -60,7 +60,7 @@ struct view_data;
**/
#define packet_len(cmd) packet_db[cmd].len
#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 clif_disp_onlyself(sd, mes) clif->disp_message(&(sd)->bl, (mes), 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)
@@ -841,11 +841,11 @@ struct clif_interface {
void (*clearchat) (struct chat_data *cd,int fd);
void (*leavechat) (struct chat_data* cd, struct map_session_data* sd, bool flag);
void (*changechatstatus) (struct chat_data* cd);
- void (*wis_message) (int fd, const char* nick, const char* mes, size_t mes_len);
+ void (*wis_message) (int fd, const char *nick, const char *mes, int mes_len);
void (*wis_end) (int fd, int flag);
- void (*disp_message) (struct block_list* src, const char* mes, size_t len, enum send_target target);
- void (*broadcast) (struct block_list* bl, const char* mes, size_t len, int type, enum send_target target);
- void (*broadcast2) (struct block_list* bl, const char* mes, size_t len, unsigned int fontColor, short fontType, short fontSize, short fontAlign, short fontY, enum send_target target);
+ void (*disp_message) (struct block_list *src, const char *mes, enum send_target target);
+ void (*broadcast) (struct block_list *bl, const char *mes, int len, int type, enum send_target target);
+ void (*broadcast2) (struct block_list *bl, const char *mes, int len, unsigned int fontColor, short fontType, short fontSize, short fontAlign, short fontY, enum send_target target);
void (*messagecolor_self) (int fd, uint32 color, const char *msg);
void (*messagecolor) (struct block_list* bl, uint32 color, const char* msg);
void (*disp_overhead) (struct block_list *bl, const char* mes);
@@ -856,7 +856,8 @@ 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, const char **name_, size_t *namelen_, const char **message_, size_t *messagelen_);
+ const char *(*process_chat_message) (struct map_session_data *sd, const struct packet_chat_message *packet, char *out_buf, int out_buflen);
+ bool (*process_whisper_message) (struct map_session_data *sd, const struct packet_whisper_message *packet, char *out_name, char *out_message, int out_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);
@@ -942,7 +943,7 @@ struct clif_interface {
void (*bg_hp) (struct map_session_data *sd);
void (*bg_xy) (struct map_session_data *sd);
void (*bg_xy_remove) (struct map_session_data *sd);
- void (*bg_message) (struct battleground_data *bgd, int src_id, const char *name, const char *mes, size_t len);
+ void (*bg_message) (struct battleground_data *bgd, int src_id, const char *name, const char *mes);
void (*bg_updatescore) (int16 m);
void (*bg_updatescore_single) (struct map_session_data *sd);
void (*sendbgemblem_area) (struct map_session_data *sd);
@@ -1334,8 +1335,10 @@ struct clif_interface {
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);
+ 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/duel.c b/src/map/duel.c
index c658ea3e3..64991d39c 100644
--- a/src/map/duel.c
+++ b/src/map/duel.c
@@ -73,7 +73,7 @@ static int duel_showinfo_sub(struct map_session_data* sd, va_list va)
if (sd->duel_group != ssd->duel_group) return 0;
sprintf(output, " %d. %s", ++(*p), sd->status.name);
- clif_disp_onlyself(ssd, output, strlen(output));
+ clif_disp_onlyself(ssd, output);
return 1;
}
@@ -93,7 +93,7 @@ void duel_showinfo(const unsigned int did, struct map_session_data* sd) {
duel->list[did].members_count,
duel->list[did].members_count + duel->list[did].invites_count);
- clif_disp_onlyself(sd, output, strlen(output));
+ clif_disp_onlyself(sd, output);
map->foreachpc(duel_showinfo_sub, sd, &p);
}
@@ -113,7 +113,7 @@ int duel_create(struct map_session_data* sd, const unsigned int maxpl) {
duel->list[i].max_players_limit = maxpl;
safestrncpy(output, msg_sd(sd,372), sizeof(output)); // " -- Duel has been created (@invite/@leave) --"
- clif_disp_onlyself(sd, output, strlen(output));
+ clif_disp_onlyself(sd, output);
clif->map_property(sd, MAPPROPERTY_FREEPVPZONE);
clif->maptypeproperty2(&sd->bl,SELF);
@@ -127,14 +127,14 @@ void duel_invite(const unsigned int did, struct map_session_data* sd, struct map
nullpo_retv(target_sd);
// " -- Player %s invites %s to duel --"
sprintf(output, msg_sd(sd,373), sd->status.name, target_sd->status.name);
- clif->disp_message(&sd->bl, output, strlen(output), DUEL_WOS);
+ clif->disp_message(&sd->bl, output, DUEL_WOS);
target_sd->duel_invite = did;
duel->list[did].invites_count++;
// "Blue -- Player %s invites you to PVP duel (@accept/@reject) --"
sprintf(output, msg_sd(target_sd,374), sd->status.name);
- clif->broadcast(&target_sd->bl, output, strlen(output)+1, BC_BLUE, SELF);
+ clif->broadcast(&target_sd->bl, output, (int)strlen(output)+1, BC_BLUE, SELF);
}
static int duel_leave_sub(struct map_session_data* sd, va_list va)
@@ -152,7 +152,7 @@ void duel_leave(const unsigned int did, struct map_session_data* sd) {
nullpo_retv(sd);
// " <- Player %s has left duel --"
sprintf(output, msg_sd(sd,375), sd->status.name);
- clif->disp_message(&sd->bl, output, strlen(output), DUEL_WOS);
+ clif->disp_message(&sd->bl, output, DUEL_WOS);
duel->list[did].members_count--;
if(duel->list[did].members_count == 0) {
@@ -177,7 +177,7 @@ void duel_accept(const unsigned int did, struct map_session_data* sd) {
// " -> Player %s has accepted duel --"
sprintf(output, msg_sd(sd,376), sd->status.name);
- clif->disp_message(&sd->bl, output, strlen(output), DUEL_WOS);
+ clif->disp_message(&sd->bl, output, DUEL_WOS);
clif->map_property(sd, MAPPROPERTY_FREEPVPZONE);
clif->maptypeproperty2(&sd->bl,SELF);
@@ -189,7 +189,7 @@ void duel_reject(const unsigned int did, struct map_session_data* sd) {
nullpo_retv(sd);
// " -- Player %s has rejected duel --"
sprintf(output, msg_sd(sd,377), sd->status.name);
- clif->disp_message(&sd->bl, output, strlen(output), DUEL_WOS);
+ clif->disp_message(&sd->bl, output, DUEL_WOS);
duel->list[did].invites_count--;
sd->duel_invite = 0;
diff --git a/src/map/guild.c b/src/map/guild.c
index 13acfc0db..1929808ca 100644
--- a/src/map/guild.c
+++ b/src/map/guild.c
@@ -178,7 +178,7 @@ struct guild* guild_search(int guild_id)
struct guild* guild_searchname(char* str)
{
struct guild* g;
- DBIterator *iter = db_iterator(guild->db);
+ struct DBIterator *iter = db_iterator(guild->db);
nullpo_retr(NULL, str);
for( g = dbi_first(iter); dbi_exists(iter); g = dbi_next(iter) )
@@ -201,7 +201,7 @@ struct guild_castle* guild_castle_search(int gcid)
struct guild_castle* guild_mapindex2gc(short map_index)
{
struct guild_castle* gc;
- DBIterator *iter = db_iterator(guild->castle_db);
+ struct DBIterator *iter = db_iterator(guild->castle_db);
for( gc = dbi_first(iter); dbi_exists(iter); gc = dbi_next(iter) )
{
@@ -282,7 +282,8 @@ void guild_makemember(struct guild_member *m,struct map_session_data *sd)
* Server cache to be flushed to inter the Guild EXP
* @see DBApply
*/
-int guild_payexp_timer_sub(DBKey key, DBData *data, va_list ap) {
+int guild_payexp_timer_sub(union DBKey key, struct DBData *data, va_list ap)
+{
int i;
struct guild_expcache *c;
struct guild *g;
@@ -318,7 +319,7 @@ int guild_payexp_timer(int tid, int64 tick, int id, intptr_t data) {
* Taken from party_send_xy_timer_sub. [Skotlex]
* @see DBApply
*/
-int guild_send_xy_timer_sub(DBKey key, DBData *data, va_list ap)
+int guild_send_xy_timer_sub(union DBKey key, struct DBData *data, va_list ap)
{
struct guild *g = DB->data2ptr(data);
int i;
@@ -423,7 +424,7 @@ int guild_npc_request_info(int guild_id,const char *event)
if( event && *event )
{
struct eventlist *ev;
- DBData prev;
+ struct DBData prev;
ev=(struct eventlist *)aCalloc(sizeof(struct eventlist),1);
memcpy(ev->name,event,strlen(event));
//The one in the db (if present) becomes the next event from this.
@@ -481,7 +482,7 @@ int guild_recv_info(const struct guild *sg)
{
struct guild *g,before;
int i,bm,m;
- DBData data;
+ struct DBData data;
struct map_session_data *sd;
bool guild_new = false;
struct channel_data *aChSysSave = NULL;
@@ -1059,14 +1060,15 @@ int guild_recv_memberinfoshort(int guild_id,int account_id,int char_id,int onlin
/*====================================================
* Send a message to whole guild
*---------------------------------------------------*/
-int guild_send_message(struct map_session_data *sd,const char *mes,int len)
+int guild_send_message(struct map_session_data *sd, const char *mes)
{
+ int len = (int)strlen(mes);
nullpo_ret(sd);
- if(sd->status.guild_id==0)
+ if (sd->status.guild_id == 0)
return 0;
- intif->guild_message(sd->status.guild_id,sd->status.account_id,mes,len);
- guild->recv_message(sd->status.guild_id,sd->status.account_id,mes,len);
+ intif->guild_message(sd->status.guild_id, sd->status.account_id, mes, len);
+ guild->recv_message(sd->status.guild_id, sd->status.account_id, mes, len);
// Chat logging type 'G' / Guild Chat
logs->chat(LOG_CHAT_GUILD, sd->status.guild_id, sd->status.char_id, sd->status.account_id, mapindex_id2name(sd->mapindex), sd->bl.x, sd->bl.y, NULL, mes);
@@ -1224,7 +1226,7 @@ int guild_emblem_changed(int len,int guild_id,int emblem_id,const char *data)
}
}
{// update guardians (mobs)
- DBIterator* iter = db_iterator(guild->castle_db);
+ struct DBIterator *iter = db_iterator(guild->castle_db);
struct guild_castle* gc;
for( gc = (struct guild_castle*)dbi_first(iter) ; dbi_exists(iter); gc = (struct guild_castle*)dbi_next(iter) )
{
@@ -1262,7 +1264,7 @@ int guild_emblem_changed(int len,int guild_id,int emblem_id,const char *data)
/**
* @see DBCreateData
*/
-DBData create_expcache(DBKey key, va_list args)
+struct DBData create_expcache(union DBKey key, va_list args)
{
struct guild_expcache *c;
struct map_session_data *sd = va_arg(args, struct map_session_data*);
@@ -1720,7 +1722,7 @@ int guild_allianceack(int guild_id1,int guild_id2,int account_id1,int account_id
* Notification for the guild disbanded
* @see DBApply
*/
-int guild_broken_sub(DBKey key, DBData *data, va_list ap)
+int guild_broken_sub(union DBKey key, struct DBData *data, va_list ap)
{
struct guild *g = DB->data2ptr(data);
int guild_id=va_arg(ap,int);
@@ -1746,7 +1748,7 @@ int guild_broken_sub(DBKey key, DBData *data, va_list ap)
* Invoked on Castles when a guild is broken. [Skotlex]
* @see DBApply
*/
-int castle_guild_broken_sub(DBKey key, DBData *data, va_list ap)
+int castle_guild_broken_sub(union DBKey key, struct DBData *data, va_list ap)
{
struct guild_castle *gc = DB->data2ptr(data);
int guild_id = va_arg(ap, int);
@@ -1827,7 +1829,7 @@ int guild_gm_change(int guild_id, struct map_session_data *sd)
return 0;
//Notify servers that master has changed.
- intif->guild_change_gm(guild_id, sd->status.name, strlen(sd->status.name)+1);
+ intif->guild_change_gm(guild_id, sd->status.name, (int)strlen(sd->status.name)+1);
return 1;
}
@@ -1955,7 +1957,7 @@ void guild_castle_map_init(void)
if (num > 0) {
struct guild_castle* gc = NULL;
int *castle_ids, *cursor;
- DBIterator* iter = NULL;
+ struct DBIterator *iter = NULL;
CREATE(castle_ids, int, num);
cursor = castle_ids;
@@ -2153,7 +2155,7 @@ int guild_checkcastles(struct guild *g)
{
int nb_cas = 0;
struct guild_castle* gc = NULL;
- DBIterator *iter = db_iterator(guild->castle_db);
+ struct DBIterator *iter = db_iterator(guild->castle_db);
for (gc = dbi_first(iter); dbi_exists(iter); gc = dbi_next(iter)) {
if (gc->guild_id == g->guild_id) {
@@ -2222,7 +2224,8 @@ void guild_flag_remove(struct npc_data *nd) {
/**
* @see DBApply
*/
-int eventlist_db_final(DBKey key, DBData *data, va_list ap) {
+int eventlist_db_final(union DBKey key, struct DBData *data, va_list ap)
+{
struct eventlist *next = NULL;
struct eventlist *current = DB->data2ptr(data);
while (current != NULL) {
@@ -2236,7 +2239,8 @@ int eventlist_db_final(DBKey key, DBData *data, va_list ap) {
/**
* @see DBApply
*/
-int guild_expcache_db_final(DBKey key, DBData *data, va_list ap) {
+int guild_expcache_db_final(union DBKey key, struct DBData *data, va_list ap)
+{
ers_free(guild->expcache_ers, DB->data2ptr(data));
return 0;
}
@@ -2244,7 +2248,8 @@ int guild_expcache_db_final(DBKey key, DBData *data, va_list ap) {
/**
* @see DBApply
*/
-int guild_castle_db_final(DBKey key, DBData *data, va_list ap) {
+int guild_castle_db_final(union DBKey key, struct DBData *data, va_list ap)
+{
struct guild_castle* gc = DB->data2ptr(data);
if( gc->temp_guardians )
aFree(gc->temp_guardians);
@@ -2283,8 +2288,9 @@ void do_init_guild(bool minimal) {
timer->add_interval(timer->gettick()+GUILD_SEND_XY_INVERVAL,guild->send_xy_timer,0,0,GUILD_SEND_XY_INVERVAL);
}
-void do_final_guild(void) {
- DBIterator *iter = db_iterator(guild->db);
+void do_final_guild(void)
+{
+ struct DBIterator *iter = db_iterator(guild->db);
struct guild *g;
for( g = dbi_first(iter); dbi_exists(iter); g = dbi_next(iter) ) {
diff --git a/src/map/guild.h b/src/map/guild.h
index cd796adb3..4fe7106d3 100644
--- a/src/map/guild.h
+++ b/src/map/guild.h
@@ -71,10 +71,10 @@ struct guild_interface {
void (*init) (bool minimal);
void (*final) (void);
/* */
- DBMap* db; // int guild_id -> struct guild*
- DBMap* castle_db; // int castle_id -> struct guild_castle*
- DBMap* expcache_db; // int char_id -> struct guild_expcache*
- DBMap* infoevent_db; // int guild_id -> struct eventlist*
+ struct DBMap *db; // int guild_id -> struct guild*
+ struct DBMap *castle_db; // int castle_id -> struct guild_castle*
+ struct DBMap *expcache_db; // int char_id -> struct guild_expcache*
+ struct DBMap *infoevent_db; // int guild_id -> struct eventlist*
/* */
struct eri *expcache_ers; //For handling of guild exp payment.
/* */
@@ -135,7 +135,7 @@ struct guild_interface {
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);
int (*emblem_changed) (int len,int guild_id,int emblem_id,const char *data);
- int (*send_message) (struct map_session_data *sd,const char *mes,int len);
+ int (*send_message) (struct map_session_data *sd, const char *mes);
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);
@@ -166,15 +166,15 @@ struct guild_interface {
struct map_session_data *(*sd_check) (int guild_id, int account_id, int char_id);
bool (*read_guildskill_tree_db) (char* split[], int columns, int current);
bool (*read_castledb) (char* str[], int columns, int current);
- int (*payexp_timer_sub) (DBKey key, DBData *data, va_list ap);
- int (*send_xy_timer_sub) (DBKey key, DBData *data, va_list ap);
+ int (*payexp_timer_sub) (union DBKey key, struct DBData *data, va_list ap);
+ int (*send_xy_timer_sub) (union DBKey key, struct DBData *data, va_list ap);
int (*send_xy_timer) (int tid, int64 tick, int id, intptr_t data);
- DBData (*create_expcache) (DBKey key, va_list args);
- int (*eventlist_db_final) (DBKey key, DBData *data, va_list ap);
- int (*expcache_db_final) (DBKey key, DBData *data, va_list ap);
- int (*castle_db_final) (DBKey key, DBData *data, va_list ap);
- int (*broken_sub) (DBKey key, DBData *data, va_list ap);
- int (*castle_broken_sub) (DBKey key, DBData *data, va_list ap);
+ struct DBData (*create_expcache) (union DBKey key, va_list args);
+ int (*eventlist_db_final) (union DBKey key, struct DBData *data, va_list ap);
+ int (*expcache_db_final) (union DBKey key, struct DBData *data, va_list ap);
+ int (*castle_db_final) (union DBKey key, struct DBData *data, va_list ap);
+ int (*broken_sub) (union DBKey key, struct DBData *data, va_list ap);
+ int (*castle_broken_sub) (union DBKey key, struct DBData *data, va_list ap);
void (*makemember) (struct guild_member *m,struct map_session_data *sd);
int (*check_member) (const struct guild *g);
int (*get_alliance_count) (struct guild *g,int flag);
diff --git a/src/map/homunculus.c b/src/map/homunculus.c
index bda8fd9e6..66cce23e6 100644
--- a/src/map/homunculus.c
+++ b/src/map/homunculus.c
@@ -391,7 +391,7 @@ bool homunculus_levelup(struct homun_data *hd) {
growth_max_hp, growth_max_sp,
growth_str/10.0, growth_agi/10.0, growth_vit/10.0,
growth_int/10.0, growth_dex/10.0, growth_luk/10.0);
- clif_disp_onlyself(hd->master,output,strlen(output));
+ clif_disp_onlyself(hd->master, output);
}
return true;
}
diff --git a/src/map/instance.c b/src/map/instance.c
index a6700d486..fa2cfec16 100644
--- a/src/map/instance.c
+++ b/src/map/instance.c
@@ -551,7 +551,7 @@ void instance_destroy(int instance_id) {
struct party_data *p = NULL;
struct guild *g = NULL;
short *iptr = NULL;
- int type, j;
+ int type;
unsigned int now = (unsigned int)time(NULL);
if( !instance->valid(instance_id) )
@@ -596,9 +596,10 @@ void instance_destroy(int instance_id) {
}
if( iptr != NULL ) {
- ARR_FIND(0, *icptr, j, iptr[j] == instance_id);
- if( j != *icptr )
- iptr[j] = -1;
+ int i;
+ ARR_FIND(0, *icptr, i, iptr[i] == instance_id);
+ if (i != *icptr)
+ iptr[i] = -1;
}
if (instance->list[instance_id].map) {
diff --git a/src/map/intif.c b/src/map/intif.c
index 7d2493d46..2d6d39406 100644
--- a/src/map/intif.c
+++ b/src/map/intif.c
@@ -150,7 +150,7 @@ int intif_rename(struct map_session_data *sd, int type, const char *name)
}
// GM Send a message
-int intif_broadcast(const char* mes, size_t len, int type)
+int intif_broadcast(const char *mes, int len, int type)
{
int lp = (type&BC_COLOR_MASK) ? 4 : 0;
@@ -182,7 +182,7 @@ int intif_broadcast(const char* mes, size_t len, int type)
return 0;
}
-int intif_broadcast2(const char* mes, size_t len, unsigned int fontColor, short fontType, short fontSize, short fontAlign, short fontY)
+int intif_broadcast2(const char *mes, int len, unsigned int fontColor, short fontType, short fontSize, short fontAlign, short fontY)
{
nullpo_ret(mes);
Assert_ret(len < 32000);
@@ -222,7 +222,7 @@ int intif_main_message(struct map_session_data* sd, const char* message)
snprintf( output, sizeof(output), msg_txt(386), sd->status.name, message );
// send the message using the inter-server broadcast service
- intif->broadcast2( output, strlen(output) + 1, 0xFE000000, 0, 0, 0, 0 );
+ intif->broadcast2(output, (int)strlen(output) + 1, 0xFE000000, 0, 0, 0, 0);
// log the chat message
logs->chat( LOG_CHAT_MAINCHAT, 0, sd->status.char_id, sd->status.account_id, mapindex_id2name(sd->mapindex), sd->bl.x, sd->bl.y, NULL, message );
@@ -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, const char *nick, const char *mes, size_t mes_len)
+int intif_wis_message(struct map_session_data *sd, const char *nick, const char *mes, int mes_len)
{
if (intif->CheckForCharServer())
return 0;
@@ -279,12 +279,14 @@ int intif_wis_replay(int id, int flag)
// The transmission of GM only Wisp/Page from server to inter-server
int intif_wis_message_to_gm(char *wisp_name, int permission, char *mes)
{
- size_t mes_len;
+ int mes_len;
if (intif->CheckForCharServer())
return 0;
nullpo_ret(wisp_name);
nullpo_ret(mes);
- mes_len = strlen(mes) + 1; // + null
+ mes_len = (int)strlen(mes) + 1; // + null
+ Assert_ret(mes_len > 0 && mes_len <= INT16_MAX - 32);
+
WFIFOHEAD(inter_fd, mes_len + 32);
WFIFOW(inter_fd,0) = 0x3003;
WFIFOW(inter_fd,2) = mes_len + 32;
@@ -300,10 +302,11 @@ int intif_wis_message_to_gm(char *wisp_name, int permission, char *mes)
}
//Request for saving registry values.
-int intif_saveregistry(struct map_session_data *sd) {
- DBIterator *iter;
- DBKey key;
- DBData *data;
+int intif_saveregistry(struct map_session_data *sd)
+{
+ struct DBIterator *iter;
+ union DBKey key;
+ struct DBData *data;
int plen = 0;
size_t len;
@@ -657,7 +660,7 @@ int intif_guild_addmember(int guild_id,struct guild_member *m)
}
// Request a new leader for guild
-int intif_guild_change_gm(int guild_id, const char* name, size_t len)
+int intif_guild_change_gm(int guild_id, const char *name, int len)
{
if (intif->CheckForCharServer())
return 0;
@@ -985,7 +988,7 @@ void intif_parse_WisMessage(int fd) {
return;
}
//Success to send whisper.
- clif->wis_message(sd->fd, wisp_source, RFIFOP(fd,56),RFIFOW(fd,2)-56);
+ clif->wis_message(sd->fd, wisp_source, RFIFOP(fd,56),RFIFOW(fd,2)-57);
intif_wis_replay(id,0); // success
}
@@ -1004,7 +1007,8 @@ void intif_parse_WisEnd(int fd)
return;
}
-int mapif_parse_WisToGM_sub(struct map_session_data* sd,va_list va) {
+int intif_parse_WisToGM_sub(struct map_session_data *sd, va_list va)
+{
int permission = va_arg(va, int);
char *wisp_name;
char *message;
@@ -1022,22 +1026,22 @@ int mapif_parse_WisToGM_sub(struct map_session_data* sd,va_list va) {
// Received wisp message from map-server via char-server for ALL gm
// 0x3003/0x3803 <packet_len>.w <wispname>.24B <permission>.l <message>.?B
-void mapif_parse_WisToGM(int fd)
+void intif_parse_WisToGM(int fd)
{
int permission, mes_len;
char Wisp_name[NAME_LENGTH];
char mbuf[255] = { 0 };
char *message;
- mes_len = RFIFOW(fd,2) - 32;
+ mes_len = RFIFOW(fd,2) - 33; // Length not including the NUL terminator
Assert_retv(mes_len > 0 && mes_len < 32000);
- message = (char *) (mes_len >= 255 ? (char *) aMalloc(mes_len) : mbuf);
+ message = (mes_len >= 255 ? aMalloc(mes_len + 1) : mbuf);
permission = RFIFOL(fd,28);
safestrncpy(Wisp_name, RFIFOP(fd,4), NAME_LENGTH);
- safestrncpy(message, RFIFOP(fd,32), mes_len);
+ safestrncpy(message, RFIFOP(fd,32), mes_len + 1);
// information is sent to all online GM
- map->foreachpc(mapif_parse_WisToGM_sub, permission, Wisp_name, message, mes_len);
+ map->foreachpc(intif->pWisToGM_sub, permission, Wisp_name, message, mes_len);
if (message != mbuf)
aFree(message);
@@ -1110,7 +1114,7 @@ void intif_parse_Registers(int fd)
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);
+ script->set_reg(NULL,sd,reference_uid(script->add_str(key), index), key, sval, NULL);
}
/**
* Vessel!
@@ -1132,7 +1136,7 @@ void intif_parse_Registers(int fd)
ival = RFIFOL(fd, cursor);
cursor += 4;
- script->set_reg(NULL,sd,reference_uid(script->add_str(key), index), key, (void*)h64BPTRSIZE(ival), NULL);
+ script->set_reg(NULL,sd,reference_uid(script->add_str(key), index), key, (const void *)h64BPTRSIZE(ival), NULL);
}
}
script->parser_current_file = NULL;/* reset */
@@ -1653,7 +1657,7 @@ void intif_parse_MailInboxReceived(int fd) {
else if( battle_config.mail_show_status && ( battle_config.mail_show_status == 1 || sd->mail.inbox.unread ) ) {
char output[128];
sprintf(output, msg_sd(sd,510), sd->mail.inbox.unchecked, sd->mail.inbox.unread + sd->mail.inbox.unchecked);
- clif_disp_onlyself(sd, output, strlen(output));
+ clif_disp_onlyself(sd, output);
}
}
/*------------------------------------------
@@ -2488,8 +2492,8 @@ void intif_defaults(void) {
/* parse functions */
intif->pWisMessage = intif_parse_WisMessage;
intif->pWisEnd = intif_parse_WisEnd;
- intif->pWisToGM_sub = mapif_parse_WisToGM_sub;
- intif->pWisToGM = mapif_parse_WisToGM;
+ intif->pWisToGM_sub = intif_parse_WisToGM_sub;
+ intif->pWisToGM = intif_parse_WisToGM;
intif->pRegisters = intif_parse_Registers;
intif->pChangeNameOk = intif_parse_ChangeNameOk;
intif->pMessageToFD = intif_parse_MessageToFD;
diff --git a/src/map/intif.h b/src/map/intif.h
index dccd31d80..5e7f86fc2 100644
--- a/src/map/intif.h
+++ b/src/map/intif.h
@@ -59,10 +59,10 @@ struct intif_interface {
int (*parse) (int fd);
int (*create_pet)(int account_id, int char_id, short pet_type, short pet_lv, short pet_egg_id,
short pet_equip, short intimate, short hungry, char rename_flag, char incubate, char *pet_name);
- 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 (*broadcast) (const char *mes, int len, int type);
+ int (*broadcast2) (const char *mes, int 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, const char *nick, const char *mes, size_t mes_len);
+ int (*wis_message) (struct map_session_data *sd, const char *nick, const char *mes, int 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);
@@ -84,7 +84,7 @@ struct intif_interface {
int (*guild_memberinfoshort) (int guild_id, int account_id, int char_id, int online, int lv, int class_);
int (*guild_break) (int guild_id);
int (*guild_message) (int guild_id, int account_id, const char *mes, int len);
- int (*guild_change_gm) (int guild_id, const char* name, size_t len);
+ int (*guild_change_gm) (int guild_id, const char *name, int len);
int (*guild_change_basicinfo) (int guild_id, int type, const void *data, int len);
int (*guild_change_memberinfo) (int guild_id, int account_id, int char_id, int type, const void *data, int len);
int (*guild_position) (int guild_id, int idx, struct guild_position *p);
diff --git a/src/map/irc-bot.c b/src/map/irc-bot.c
index b520e9e91..5820ad2cf 100644
--- a/src/map/irc-bot.c
+++ b/src/map/irc-bot.c
@@ -48,10 +48,7 @@ struct irc_bot_interface *ircbot;
char send_string[IRC_MESSAGE_LENGTH];
-/**
- * Timer callback to (re-)connect to an IRC server
- * @see timer->do_timer
- */
+/// @copydoc irc_bot_interface::connect_timer()
int irc_connect_timer(int tid, int64 tick, int id, intptr_t data) {
struct hSockOpt opt;
if( ircbot->isOn || ++ircbot->fails >= 3 )
@@ -71,53 +68,43 @@ int irc_connect_timer(int tid, int64 tick, int id, intptr_t data) {
return 0;
}
-/**
- * Timer callback to send identification commands to an IRC server
- * @see timer->do_timer
- */
+/// @copydoc irc_bot_interface::identify_timer()
int irc_identify_timer(int tid, int64 tick, int id, intptr_t data) {
if( !ircbot->isOn )
return 0;
sprintf(send_string, "USER HerculesWS%d 8 * : Hercules IRC Bridge",rnd()%777);
- ircbot->send(send_string);
+ ircbot->send(send_string, true);
sprintf(send_string, "NICK %s", channel->config->irc_nick);
- ircbot->send(send_string);
+ ircbot->send(send_string, true);
timer->add(timer->gettick() + 3000, ircbot->join_timer, 0, 0);
return 0;
}
-/**
- * Timer callback to join channels (and optionally send NickServ commands)
- * @see timer->do_timer
- */
+/// @copydoc irc_bot_interface::join_timer()
int irc_join_timer(int tid, int64 tick, int id, intptr_t data) {
if( !ircbot->isOn )
return 0;
if (channel->config->irc_nick_pw[0] != '\0') {
sprintf(send_string, "PRIVMSG NICKSERV : IDENTIFY %s", channel->config->irc_nick_pw);
- ircbot->send(send_string);
+ ircbot->send(send_string, true);
if (channel->config->irc_use_ghost) {
sprintf(send_string, "PRIVMSG NICKSERV : GHOST %s %s", channel->config->irc_nick, channel->config->irc_nick_pw);
+ ircbot->send(send_string, true);
}
}
sprintf(send_string, "JOIN %s", channel->config->irc_channel);
- ircbot->send(send_string);
+ ircbot->send(send_string, true);
ircbot->isIn = true;
return 0;
}
-/**
- * Search the handler for a given IRC received command
- * @param function_name Name of the received IRC command
- * @return Function pointer to the command handler, NULL in case
- * of unhandled commands
- */
+/// @copydoc irc_bot_interface::func_search()
struct irc_func* irc_func_search(char* function_name) {
int i;
nullpo_retr(NULL, function_name);
@@ -129,10 +116,7 @@ struct irc_func* irc_func_search(char* function_name) {
return NULL;
}
-/**
- * Parser for the IRC server connection
- * @see do_sockets
- */
+/// @copydoc irc_bot_interface::parse()
int irc_parse(int fd) {
char *parse_string = NULL, *p = NULL, *str_safe = NULL;
@@ -166,16 +150,7 @@ int irc_parse(int fd) {
return 0;
}
-/**
- * Parse the source from a received irc message
- * @param source Source string, as reported by the server
- * @param nick Pointer to a string where to return the nick (may not be NULL,
- * needs to be able to fit an IRC_NICK_LENGTH long string)
- * @param ident Pointer to a string where to return the ident (may not be
- * NULL, needs to be able to fit an IRC_IDENT_LENGTH long string)
- * @param host Pointer to a string where to return the hostname (may not be
- * NULL, needs to be able to fit an IRC_HOST_LENGTH long string)
- */
+/// @copydoc irc_bot_interface::parse_source()
void irc_parse_source(char *source, char *nick, char *ident, char *host) {
int i, pos = 0;
size_t len;
@@ -199,12 +174,7 @@ void irc_parse_source(char *source, char *nick, char *ident, char *host) {
}
}
-/**
- * Parse a received message from the irc server, and do the appropriate action
- * for the detected command
- * @param fd IRC server connection file descriptor
- * @param str Raw received message
- */
+/// @copydoc irc_bot_interface::parse_sub()
void irc_parse_sub(int fd, char *str) {
char source[180], command[60], buf1[IRC_MESSAGE_LENGTH], buf2[IRC_MESSAGE_LENGTH];
char *target = buf1, *message = buf2;
@@ -234,35 +204,92 @@ void irc_parse_sub(int fd, char *str) {
func->func(fd,command,source,target,message);
}
-/**
- * Send a raw command to the irc server
- * @param str Command to send
- */
-void irc_send(char *str) {
+/// @copydoc irc_bot_interface::queue()
+void irc_queue(char *str)
+{
+ struct message_flood *queue_entry = NULL;
+
+ if (!ircbot->flood_protection_enabled) {
+ ircbot->send(str, true);
+ return;
+ }
+
+ if (ircbot->message_current == NULL) {
+ // No queue yet
+ if (ircbot->messages_burst_count < ircbot->flood_protection_burst) {
+ ircbot->send(str, true);
+ if (DIFF_TICK(timer->gettick(), ircbot->last_message_tick) <= ircbot->flood_protection_rate)
+ ircbot->messages_burst_count++;
+ else
+ ircbot->messages_burst_count = 0;
+ ircbot->last_message_tick = timer->gettick();
+ } else { //queue starts
+ CREATE(queue_entry, struct message_flood, 1);
+ safestrncpy(queue_entry->message, str, sizeof(queue_entry->message));
+ queue_entry->next = NULL;
+ ircbot->message_current = queue_entry;
+ ircbot->message_last = queue_entry;
+ ircbot->queue_tid = timer->add(timer->gettick() + ircbot->flood_protection_rate, ircbot->queue_timer, 0, 0); //start queue timer
+ ircbot->messages_burst_count = 0;
+ }
+ } else {
+ CREATE(queue_entry, struct message_flood, 1);
+ safestrncpy(queue_entry->message, str, sizeof(queue_entry->message));
+ queue_entry->next = NULL;
+ ircbot->message_last->next = queue_entry;
+ ircbot->message_last = queue_entry;
+ }
+}
+
+/// @copydoc irc_bot_interface::queue_timer()
+int irc_queue_timer(int tid, int64 tick, int id, intptr_t data)
+{
+ struct message_flood *queue_entry = ircbot->message_current;
+ nullpo_ret(queue_entry);
+
+ ircbot->send(queue_entry->message, true);
+ if (queue_entry->next != NULL) {
+ ircbot->message_current = queue_entry->next;
+ ircbot->queue_tid = timer->add(timer->gettick() + ircbot->flood_protection_rate, ircbot->queue_timer, 0, 0);
+ } else {
+ ircbot->message_current = NULL;
+ ircbot->message_last = NULL;
+ ircbot->queue_tid = INVALID_TIMER;
+ }
+
+ aFree(queue_entry);
+
+ return 0;
+}
+
+/// @copydoc irc_bot_interface::send()
+void irc_send(char *str, bool force)
+{
size_t len;
nullpo_retv(str);
len = strlen(str) + 2;
if (len > IRC_MESSAGE_LENGTH-3)
len = IRC_MESSAGE_LENGTH-3;
+
+ if (!force && ircbot->flood_protection_enabled) {
+ // Add to queue
+ ircbot->queue(str);
+ return;
+ }
+
WFIFOHEAD(ircbot->fd, len);
snprintf(WFIFOP(ircbot->fd,0),IRC_MESSAGE_LENGTH, "%s\r\n", str);
WFIFOSET(ircbot->fd, len);
}
-/**
- * Handler for the PING IRC command (send back a PONG)
- * @see irc_parse_sub
- */
+/// @copydoc irc_interface_bot::pong()
void irc_pong(int fd, char *cmd, char *source, char *target, char *msg) {
nullpo_retv(cmd);
snprintf(send_string, IRC_MESSAGE_LENGTH, "PONG %s", cmd);
- ircbot->send(send_string);
+ ircbot->send(send_string, false);
}
-/**
- * Handler for CTCP commands received via PRIVMSG
- * @see irc_privmsg
- */
+/// @copydoc irc_interface_bot::privmsg_ctcp()
void irc_privmsg_ctcp(int fd, char *cmd, char *source, char *target, char *msg) {
char source_nick[IRC_NICK_LENGTH], source_ident[IRC_IDENT_LENGTH], source_host[IRC_HOST_LENGTH];
@@ -283,7 +310,7 @@ void irc_privmsg_ctcp(int fd, char *cmd, char *source, char *target, char *msg)
// Ignore it
} else if( strcmpi(cmd,"PING") == 0 ) {
snprintf(send_string, IRC_MESSAGE_LENGTH, "NOTICE %s :\001PING %s\001",source_nick,msg);
- ircbot->send(send_string);
+ ircbot->send(send_string, false);
} else if( strcmpi(cmd,"TIME") == 0 ) {
time_t time_server; // variable for number of seconds (used with time() function)
struct tm *datetime; // variable for time in structure ->tm_mday, ->tm_sec, ...
@@ -297,10 +324,10 @@ void irc_privmsg_ctcp(int fd, char *cmd, char *source, char *target, char *msg)
strftime(temp, sizeof(temp)-1, msg_txt(230), datetime); // Server time (normal time): %A, %B %d %Y %X.
snprintf(send_string, IRC_MESSAGE_LENGTH, "NOTICE %s :\001TIME %s\001",source_nick,temp);
- ircbot->send(send_string);
+ ircbot->send(send_string, false);
} else if( strcmpi(cmd,"VERSION") == 0 ) {
snprintf(send_string, IRC_MESSAGE_LENGTH, "NOTICE %s :\001VERSION Hercules.ws IRC Bridge\001",source_nick);
- ircbot->send(send_string);
+ ircbot->send(send_string, false);
#ifdef IRCBOT_DEBUG
} else {
ShowWarning("Unknown CTCP command received %s (%s) from %s\n",cmd,msg,source);
@@ -308,10 +335,7 @@ void irc_privmsg_ctcp(int fd, char *cmd, char *source, char *target, char *msg)
}
}
-/**
- * Handler for the PRIVMSG IRC command (action depends on the message contents)
- * @see irc_parse_sub
- */
+/// @copydoc irc_bot_interface::privmsg()
void irc_privmsg(int fd, char *cmd, char *source, char *target, char *msg) {
size_t len = msg ? strlen(msg) : 0;
nullpo_retv(source);
@@ -322,7 +346,7 @@ void irc_privmsg(int fd, char *cmd, char *source, char *target, char *msg) {
command[0] = message[0] = '\0';
sscanf(msg, "\001%499[^\001\r\n ] %499[^\r\n\001]\001", command, message);
- irc_privmsg_ctcp(fd, command, source, target, message);
+ ircbot->privmsg_ctcp(fd, command, source, target, message);
#ifdef IRCBOT_DEBUG
} else if (strcmpi(target, channel->config->irc_nick) == 0) {
ShowDebug("irc_privmsg: Received message from %s: '%s'\n", source ? source : "(null)", msg);
@@ -349,11 +373,7 @@ void irc_privmsg(int fd, char *cmd, char *source, char *target, char *msg) {
}
}
-/**
- * Handler for the JOIN IRC command (notify an in-game channel of users joining
- * the IRC channel)
- * @see irc_parse_sub
- */
+/// @copydoc irc_bot_interface::userjoin()
void irc_userjoin(int fd, char *cmd, char *source, char *target, char *msg) {
char source_nick[IRC_NICK_LENGTH], source_ident[IRC_IDENT_LENGTH], source_host[IRC_HOST_LENGTH];
@@ -369,11 +389,7 @@ void irc_userjoin(int fd, char *cmd, char *source, char *target, char *msg) {
}
}
-/**
- * Handler for the PART and QUIT IRC commands (notify an in-game channel of
- * users leaving the IRC channel)
- * @see irc_parse_sub
- */
+/// @copydoc irc_bot_interface::userleave()
void irc_userleave(int fd, char *cmd, char *source, char *target, char *msg) {
char source_nick[IRC_NICK_LENGTH], source_ident[IRC_IDENT_LENGTH], source_host[IRC_HOST_LENGTH];
@@ -392,11 +408,7 @@ void irc_userleave(int fd, char *cmd, char *source, char *target, char *msg) {
}
}
-/**
- * Handler for the NICK IRC commands (notify an in-game channel of users
- * changing their name while in the IRC channel)
- * @see irc_parse_sub
- */
+/// @copydoc irc_bot_interface::usernick()
void irc_usernick(int fd, char *cmd, char *source, char *target, char *msg) {
char source_nick[IRC_NICK_LENGTH], source_ident[IRC_IDENT_LENGTH], source_host[IRC_HOST_LENGTH];
@@ -412,11 +424,7 @@ void irc_usernick(int fd, char *cmd, char *source, char *target, char *msg) {
}
}
-/**
- * Relay a chat message to the irc channel the bot is connected to
- * @param name Sender's name
- * @param msg Message text
- */
+/// @copydoc irc_bot_interface::relay()
void irc_relay(const char *name, const char *msg)
{
if (!ircbot->isIn)
@@ -428,12 +436,10 @@ void irc_relay(const char *name, const char *msg)
else
sprintf(send_string,"PRIVMSG %s :%s", channel->config->irc_channel, msg);
- ircbot->send(send_string);
+ ircbot->send(send_string, false);
}
-/**
- * IRC bot initializer
- */
+/// @copydoc irc_bot_interface::init()
void irc_bot_init(bool minimal) {
/// Command handlers
const struct irc_func irc_func_base[] = {
@@ -479,22 +485,31 @@ void irc_bot_init(bool minimal) {
ircbot->isOn = false;
timer->add_func_list(ircbot->connect_timer, "irc_connect_timer");
+ timer->add_func_list(ircbot->queue_timer, "irc_queue_timer");
+
timer->add(timer->gettick() + 7000, ircbot->connect_timer, 0, 0);
}
-/**
- * IRC bot finalizer
- */
+/// @copydoc irc_bot_interface::final()
void irc_bot_final(void) {
int i;
if (!channel->config->irc)
return;
if( ircbot->isOn ) {
- ircbot->send("QUIT :Hercules is shutting down");
+ ircbot->send("QUIT :Hercules is shutting down", true);
sockt->close(ircbot->fd);
}
+ if (ircbot->queue_tid != INVALID_TIMER)
+ timer->delete(ircbot->queue_tid, ircbot->queue_timer);
+
+ while (ircbot->message_current != NULL) {
+ struct message_flood *next = ircbot->message_current->next;
+ aFree(ircbot->message_current);
+ ircbot->message_current = next;
+ }
+
for( i = 0; i < ircbot->funcs.size; i++ ) {
aFree(ircbot->funcs.list[i]);
}
@@ -509,6 +524,15 @@ void ircbot_defaults(void) {
ircbot->channel = NULL;
+ ircbot->flood_protection_enabled = true;
+ ircbot->flood_protection_rate = 1000;
+ ircbot->flood_protection_burst = 3;
+ ircbot->last_message_tick = INVALID_TIMER;
+ ircbot->queue_tid = INVALID_TIMER;
+ ircbot->messages_burst_count = 0;
+ ircbot->message_current = NULL;
+ ircbot->message_last = NULL;
+
ircbot->init = irc_bot_init;
ircbot->final = irc_bot_final;
@@ -522,11 +546,14 @@ void ircbot_defaults(void) {
ircbot->identify_timer = irc_identify_timer;
ircbot->join_timer = irc_join_timer;
+ ircbot->queue_timer = irc_queue_timer;
+ ircbot->queue = irc_queue;
ircbot->send = irc_send;
ircbot->relay = irc_relay;
ircbot->pong = irc_pong;
ircbot->privmsg = irc_privmsg;
+ ircbot->privmsg_ctcp = irc_privmsg_ctcp;
ircbot->userjoin = irc_userjoin;
ircbot->userleave = irc_userleave;
diff --git a/src/map/irc-bot.h b/src/map/irc-bot.h
index dc67e2fe8..f73426693 100644
--- a/src/map/irc-bot.h
+++ b/src/map/irc-bot.h
@@ -39,6 +39,11 @@ struct irc_func {
void (*func)(int, char*, char*, char*, char*);
};
+struct message_flood {
+ char message[IRC_MESSAGE_LENGTH];
+ struct message_flood *next;
+};
+
struct irc_bot_interface {
int fd;
bool isIn, isOn;
@@ -46,6 +51,15 @@ struct irc_bot_interface {
unsigned char fails;
uint32 ip;
unsigned short port;
+ /* messages flood protection */
+ bool flood_protection_enabled;
+ int flood_protection_rate;
+ int flood_protection_burst;
+ int64 last_message_tick;
+ int messages_burst_count;
+ int queue_tid;
+ struct message_flood *message_current;
+ struct message_flood *message_last;
/* */
struct channel_data *channel;
/* */
@@ -53,27 +67,132 @@ struct irc_bot_interface {
struct irc_func **list;
unsigned int size;
} funcs;
- /* */
+
+ /**
+ * IRC bot initializer
+ */
void (*init) (bool minimal);
+
+ /**
+ * IRC bot finalizer
+ */
void (*final) (void);
- /* */
+
+ /**
+ * Parser for the IRC server connection
+ * @see do_sockets
+ */
int (*parse) (int fd);
+
+ /**
+ * Parse a received message from the irc server, and do the appropriate action
+ * for the detected command
+ * @param fd IRC server connection file descriptor
+ * @param str Raw received message
+ */
void (*parse_sub) (int fd, char *str);
+
+ /**
+ * Parse the source from a received irc message
+ * @param source Source string, as reported by the server
+ * @param nick Pointer to a string where to return the nick (may not be NULL,
+ * needs to be able to fit an IRC_NICK_LENGTH long string)
+ * @param ident Pointer to a string where to return the ident (may not be
+ * NULL, needs to be able to fit an IRC_IDENT_LENGTH long string)
+ * @param host Pointer to a string where to return the hostname (may not be
+ * NULL, needs to be able to fit an IRC_HOST_LENGTH long string)
+ */
void (*parse_source) (char *source, char *nick, char *ident, char *host);
- /* */
+
+ /**
+ * Search the handler for a given IRC received command
+ * @param function_name Name of the received IRC command
+ * @return Function pointer to the command handler, NULL in case
+ * of unhandled commands
+ */
struct irc_func* (*func_search) (char* function_name);
- /* */
+
+ /**
+ * Timer callback to (re-)connect to an IRC server
+ * @see timer_interface::do_timer
+ */
int (*connect_timer) (int tid, int64 tick, int id, intptr_t data);
+
+ /**
+ * Timer callback to send identification commands to an IRC server
+ * @see timer_interface::do_timer
+ */
int (*identify_timer) (int tid, int64 tick, int id, intptr_t data);
+
+ /**
+ * Timer callback to join channels (and optionally send NickServ commands)
+ * @see timer_interface::do_timer
+ */
int (*join_timer) (int tid, int64 tick, int id, intptr_t data);
- /* */
- void (*send)(char *str);
+
+ /**
+ * Timer callback to send queued IRC Commands
+ * @see timer_interface::do_timer
+ */
+ int (*queue_timer) (int tid, int64 tick, int id, intptr_t data);
+
+ /**
+ * Decides if an IRC Command should be queued or not, based on the flood protection settings.
+ *
+ * @param str Command to be checked
+ */
+ void (*queue) (char *str);
+
+ /**
+ * Send a raw command to the irc server
+ * @param str Command to send
+ */
+ void (*send)(char *str, bool force);
+
+ /**
+ * Relay a chat message to the irc channel the bot is connected to
+ * @param name Sender's name
+ * @param msg Message text
+ */
void (*relay) (const char *name, const char *msg);
- /* */
+
+ /**
+ * Handler for the PING IRC command (send back a PONG)
+ * @see irc_bot_interface::parse_sub
+ */
void (*pong) (int fd, char *cmd, char *source, char *target, char *msg);
+
+ /**
+ * Handler for the PRIVMSG IRC command (action depends on the message contents)
+ * @see irc_bot_interface::parse_sub
+ */
void (*privmsg) (int fd, char *cmd, char *source, char *target, char *msg);
+
+ /**
+ * Handler for CTCP commands received via PRIVMSG
+ * @see irc_bot_interface::privmsg
+ */
+ void (*privmsg_ctcp) (int fd, char *cmd, char *source, char *target, char *msg);
+
+ /**
+ * Handler for the JOIN IRC command (notify an in-game channel of users joining
+ * the IRC channel)
+ * @see irc_bot_interface::parse_sub
+ */
void (*userjoin) (int fd, char *cmd, char *source, char *target, char *msg);
+
+ /**
+ * Handler for the PART and QUIT IRC commands (notify an in-game channel of
+ * users leaving the IRC channel)
+ * @see irc_bot_interface::parse_sub
+ */
void (*userleave) (int fd, char *cmd, char *source, char *target, char *msg);
+
+ /**
+ * Handler for the NICK IRC commands (notify an in-game channel of users
+ * changing their name while in the IRC channel)
+ * @see irc_bot_interface::parse_sub
+ */
void (*usernick) (int fd, char *cmd, char *source, char *target, char *msg);
};
diff --git a/src/map/itemdb.c b/src/map/itemdb.c
index 630bc4488..c59f627cc 100644
--- a/src/map/itemdb.c
+++ b/src/map/itemdb.c
@@ -49,7 +49,7 @@ struct itemdb_interface *itemdb;
* name = item alias, so we should find items aliases first. if not found then look for "jname" (full name)
* @see DBApply
*/
-int itemdb_searchname_sub(DBKey key, DBData *data, va_list ap)
+int itemdb_searchname_sub(union DBKey key, struct DBData *data, va_list ap)
{
struct item_data *item = DB->data2ptr(data), **dst, **dst2;
char *str;
@@ -112,7 +112,7 @@ struct item_data* itemdb_name2id(const char *str) {
/**
* @see DBMatcher
*/
-int itemdb_searchname_array_sub(DBKey key, DBData data, va_list ap)
+int itemdb_searchname_array_sub(union DBKey key, struct DBData data, va_list ap)
{
struct item_data *item = DB->data2ptr(&data);
char *str;
@@ -170,10 +170,10 @@ int itemdb_searchname_array(struct item_data** data, int size, const char *str,
// search in the db
if( count < size )
{
- DBData *db_data[MAX_SEARCH];
+ struct DBData *db_data[MAX_SEARCH];
int db_count = 0;
size -= count;
- db_count = itemdb->other->getall(itemdb->other, (DBData**)&db_data, size, itemdb->searchname_array_sub, str);
+ db_count = itemdb->other->getall(itemdb->other, (struct DBData**)&db_data, size, itemdb->searchname_array_sub, str);
for (i = 0; i < db_count; i++)
data[count++] = DB->data2ptr(db_data[i]);
count += db_count;
@@ -2094,7 +2094,7 @@ uint64 itemdb_unique_id(struct map_session_data *sd) {
*/
void itemdb_read(bool minimal) {
int i;
- DBData prev;
+ struct DBData prev;
const char *filename[] = {
DBPATH"item_db.conf",
@@ -2171,7 +2171,7 @@ void destroy_item_data(struct item_data* self, int free_self)
/**
* @see DBApply
*/
-int itemdb_final_sub(DBKey key, DBData *data, va_list ap)
+int itemdb_final_sub(union DBKey key, struct DBData *data, va_list ap)
{
struct item_data *id = DB->data2ptr(data);
@@ -2307,8 +2307,9 @@ void itemdb_reload(void) {
}
mapit->free(iter);
}
-void itemdb_name_constants(void) {
- DBIterator *iter = db_iterator(itemdb->names);
+void itemdb_name_constants(void)
+{
+ struct DBIterator *iter = db_iterator(itemdb->names);
struct item_data *data;
#ifdef ENABLE_CASE_CHECK
@@ -2343,7 +2344,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) {
diff --git a/src/map/itemdb.h b/src/map/itemdb.h
index 47446d617..d33805174 100644
--- a/src/map/itemdb.h
+++ b/src/map/itemdb.h
@@ -589,10 +589,10 @@ struct itemdb_interface {
struct item_combo **combos;
unsigned short combo_count;
/* */
- DBMap *names;
+ struct DBMap *names;
/* */
struct item_data *array[MAX_ITEMDB];
- DBMap *other;// int nameid -> struct item_data*
+ struct DBMap *other;// int nameid -> struct item_data*
struct item_data dummy; //This is the default dummy item used for non-existant items. [Skotlex]
/* */
void (*read_groups) (void);
@@ -612,8 +612,8 @@ struct itemdb_interface {
int (*group_item) (struct item_group *group);
int (*chain_item) (unsigned short chain_id, int *rate);
void (*package_item) (struct map_session_data *sd, struct item_package *package);
- int (*searchname_sub) (DBKey key, DBData *data, va_list ap);
- int (*searchname_array_sub) (DBKey key, DBData data, va_list ap);
+ int (*searchname_sub) (union DBKey key, struct DBData *data, va_list ap);
+ int (*searchname_array_sub) (union DBKey key, struct DBData data, va_list ap);
int (*searchrandomid) (struct item_group *group);
const char* (*typename) (int type);
void (*jobmask2mapid) (uint64 *bclass, uint64 jobmask);
@@ -647,7 +647,7 @@ struct itemdb_interface {
uint64 (*unique_id) (struct map_session_data *sd);
void (*read) (bool minimal);
void (*destroy_item_data) (struct item_data *self, int free_self);
- int (*final_sub) (DBKey key, DBData *data, va_list ap);
+ int (*final_sub) (union DBKey key, struct DBData *data, va_list ap);
void (*clear) (bool total);
struct item_combo * (*id2combo) (unsigned short id);
bool (*is_item_usable) (struct item_data *item);
diff --git a/src/map/log.c b/src/map/log.c
index f757faf43..c19190d90 100644
--- a/src/map/log.c
+++ b/src/map/log.c
@@ -62,6 +62,16 @@ 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
}
@@ -109,8 +119,9 @@ bool should_log_item(int nameid, int amount, int refine, struct item_data *id) {
return false;
}
-void log_branch_sub_sql(struct map_session_data* sd) {
- SqlStmt* stmt;
+void log_branch_sub_sql(struct map_session_data* sd)
+{
+ struct SqlStmt *stmt;
nullpo_retv(sd);
stmt = SQL->StmtMalloc(logs->mysql_handle);
@@ -269,15 +280,16 @@ void log_mvpdrop(struct map_session_data* sd, int monster_id, int* log_mvp)
logs->mvpdrop_sub(sd,monster_id,log_mvp);
}
-void log_atcommand_sub_sql(struct map_session_data* sd, const char* message) {
- SqlStmt* stmt;
+void log_atcommand_sub_sql(struct map_session_data* sd, const char* message)
+{
+ struct SqlStmt *stmt;
nullpo_retv(sd);
nullpo_retv(message);
stmt = SQL->StmtMalloc(logs->mysql_handle);
if( SQL_SUCCESS != SQL->StmtPrepare(stmt, LOG_QUERY " INTO `%s` (`atcommand_date`, `account_id`, `char_id`, `char_name`, `map`, `command`) VALUES (NOW(), '%d', '%d', ?, '%s', ?)", logs->config.log_gm, sd->status.account_id, sd->status.char_id, mapindex_id2name(sd->mapindex) )
|| SQL_SUCCESS != SQL->StmtBindParam(stmt, 0, SQLDT_STRING, sd->status.name, strnlen(sd->status.name, NAME_LENGTH))
- || SQL_SUCCESS != SQL->StmtBindParam(stmt, 1, SQLDT_STRING, (char*)message, safestrnlen(message, 255))
+ || SQL_SUCCESS != SQL->StmtBindParam(stmt, 1, SQLDT_STRING, message, safestrnlen(message, 255))
|| SQL_SUCCESS != SQL->StmtExecute(stmt) )
{
SqlStmt_ShowDebug(stmt);
@@ -312,17 +324,18 @@ void log_atcommand(struct map_session_data* sd, const char* message)
logs->atcommand_sub(sd,message);
}
-void log_npc_sub_sql(struct map_session_data *sd, const char *message) {
- SqlStmt* stmt;
+void log_npc_sub_sql(struct map_session_data *sd, const char *message)
+{
+ struct SqlStmt *stmt;
nullpo_retv(sd);
nullpo_retv(message);
stmt = SQL->StmtMalloc(logs->mysql_handle);
- if( SQL_SUCCESS != SQL->StmtPrepare(stmt, LOG_QUERY " INTO `%s` (`npc_date`, `account_id`, `char_id`, `char_name`, `map`, `mes`) VALUES (NOW(), '%d', '%d', ?, '%s', ?)", logs->config.log_npc, sd->status.account_id, sd->status.char_id, mapindex_id2name(sd->mapindex) )
- || SQL_SUCCESS != SQL->StmtBindParam(stmt, 0, SQLDT_STRING, sd->status.name, strnlen(sd->status.name, NAME_LENGTH))
- || SQL_SUCCESS != SQL->StmtBindParam(stmt, 1, SQLDT_STRING, (char*)message, safestrnlen(message, 255))
- || SQL_SUCCESS != SQL->StmtExecute(stmt) )
- {
+ if (SQL_SUCCESS != SQL->StmtPrepare(stmt, LOG_QUERY " INTO `%s` (`npc_date`, `account_id`, `char_id`, `char_name`, `map`, `mes`) VALUES (NOW(), '%d', '%d', ?, '%s', ?)", logs->config.log_npc, sd->status.account_id, sd->status.char_id, mapindex_id2name(sd->mapindex) )
+ || SQL_SUCCESS != SQL->StmtBindParam(stmt, 0, SQLDT_STRING, sd->status.name, strnlen(sd->status.name, NAME_LENGTH))
+ || SQL_SUCCESS != SQL->StmtBindParam(stmt, 1, SQLDT_STRING, message, safestrnlen(message, 255))
+ || SQL_SUCCESS != SQL->StmtExecute(stmt)
+ ) {
SqlStmt_ShowDebug(stmt);
SQL->StmtFree(stmt);
return;
@@ -369,14 +382,14 @@ void log_npc(struct map_session_data* sd, const char* message)
*/
void log_chat_sub_sql(e_log_chat_type type, int type_id, int src_charid, int src_accid, const char *mapname, int x, int y, const char *dst_charname, const char *message)
{
- SqlStmt* stmt;
+ struct SqlStmt* stmt;
nullpo_retv(dst_charname);
nullpo_retv(message);
stmt = SQL->StmtMalloc(logs->mysql_handle);
if( SQL_SUCCESS != SQL->StmtPrepare(stmt, LOG_QUERY " INTO `%s` (`time`, `type`, `type_id`, `src_charid`, `src_accountid`, `src_map`, `src_map_x`, `src_map_y`, `dst_charname`, `message`) VALUES (NOW(), '%c', '%d', '%d', '%d', '%s', '%d', '%d', ?, ?)", logs->config.log_chat, logs->chattype2char(type), type_id, src_charid, src_accid, mapname, x, y)
- || SQL_SUCCESS != SQL->StmtBindParam(stmt, 0, SQLDT_STRING, (char*)dst_charname, safestrnlen(dst_charname, NAME_LENGTH))
- || SQL_SUCCESS != SQL->StmtBindParam(stmt, 1, SQLDT_STRING, (char*)message, safestrnlen(message, CHAT_SIZE_MAX))
+ || SQL_SUCCESS != SQL->StmtBindParam(stmt, 0, SQLDT_STRING, dst_charname, safestrnlen(dst_charname, NAME_LENGTH))
+ || SQL_SUCCESS != SQL->StmtBindParam(stmt, 1, SQLDT_STRING, message, safestrnlen(message, CHAT_SIZE_MAX))
|| SQL_SUCCESS != SQL->StmtExecute(stmt)
) {
SqlStmt_ShowDebug(stmt);
diff --git a/src/map/log.h b/src/map/log.h
index fbd0acc0e..0a5e13208 100644
--- a/src/map/log.h
+++ b/src/map/log.h
@@ -22,11 +22,11 @@
#define MAP_LOG_H
#include "common/hercules.h"
-#include "common/sql.h"
/**
* Declarations
**/
+struct Sql; // common/sql.h
struct item;
struct item_data;
struct map_session_data;
@@ -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
@@ -116,7 +127,7 @@ struct log_interface {
char db_id[32];
char db_pw[100];
char db_name[32];
- Sql* mysql_handle;
+ struct Sql *mysql_handle;
/* */
void (*pick_pc) (struct map_session_data* sd, e_log_pick_type type, int amount, struct item* itm, struct item_data *data);
void (*pick_mob) (struct mob_data* md, e_log_pick_type type, int amount, struct item* itm, struct item_data *data);
diff --git a/src/map/map.c b/src/map/map.c
index f2e47be74..3a7d752c3 100644
--- a/src/map/map.c
+++ b/src/map/map.c
@@ -69,6 +69,7 @@
#include "common/random.h"
#include "common/showmsg.h"
#include "common/socket.h" // WFIFO*()
+#include "common/sql.h"
#include "common/strlib.h"
#include "common/timer.h"
#include "common/utils.h"
@@ -192,6 +193,7 @@ void map_update_cell_bl( struct block_list *bl, bool increase ) {
#ifdef CELL_NOSTACK
int pos;
+ nullpo_retv(bl);
if( bl->m < 0 || bl->x < 0 || bl->x >= map->list[bl->m].xs
|| bl->y < 0 || bl->y >= map->list[bl->m].ys
|| !(bl->type&BL_CHAR) )
@@ -308,9 +310,14 @@ int map_delblock(struct block_list* bl)
* (which are executed by default on BL_CHAR types)
*------------------------------------------*/
int map_moveblock(struct block_list *bl, int x1, int y1, int64 tick) {
- int x0 = bl->x, y0 = bl->y;
struct status_change *sc = NULL;
- int moveblock = ( x0/BLOCK_SIZE != x1/BLOCK_SIZE || y0/BLOCK_SIZE != y1/BLOCK_SIZE);
+ int x0, y0;
+ int moveblock;
+
+ nullpo_ret(bl);
+ x0 = bl->x;
+ y0 = bl->y;
+ moveblock = ( x0/BLOCK_SIZE != x1/BLOCK_SIZE || y0/BLOCK_SIZE != y1/BLOCK_SIZE);
if (!bl->prev) {
//Block not in map, just update coordinates, but do naught else.
@@ -476,6 +483,8 @@ struct skill_unit* map_find_skill_unit_oncell(struct block_list* target,int16 x,
int16 m,bx,by;
struct block_list *bl;
struct skill_unit *su;
+
+ nullpo_retr(NULL, target);
m = target->m;
if (x < 0 || y < 0 || (x >= map->list[m].xs) || (y >= map->list[m].ys))
@@ -853,6 +862,9 @@ static int bl_vgetall_inshootrange(struct block_list *bl, va_list args)
struct block_list *center = va_arg(args, struct block_list*);
#ifdef CIRCULAR_AREA
int range = va_arg(args, int);
+ nullpo_ret(center);
+ nullpo_ret(bl);
+
if (!check_distance_bl(center, bl, range))
return 0;
#endif
@@ -1040,6 +1052,9 @@ static int bl_vgetall_inmovearea(struct block_list *bl, va_list args)
struct block_list *center = va_arg(args, struct block_list*);
int range = va_arg(args, int);
+ nullpo_ret(bl);
+ nullpo_ret(center);
+
if ((dx > 0 && bl->x < center->x - range + dx) ||
(dx < 0 && bl->x > center->x + range + dx) ||
(dy > 0 && bl->y < center->y - range + dy) ||
@@ -1202,11 +1217,15 @@ static int bl_vgetall_inpath(struct block_list *bl, va_list args)
int len_limit = va_arg(args, int);
int magnitude2 = va_arg(args, int);
- int xi = bl->x;
- int yi = bl->y;
+ int xi;
+ int yi;
int xu, yu;
+ int k;
- int k = ( xi - x0 ) * ( x1 - x0 ) + ( yi - y0 ) * ( y1 - y0 );
+ nullpo_ret(bl);
+ xi = bl->x;
+ yi = bl->y;
+ k = ( xi - x0 ) * ( x1 - x0 ) + ( yi - y0 ) * ( y1 - y0 );
if ( k < 0 || k > len_limit ) //Since more skills use this, check for ending point as well.
return 0;
@@ -1421,6 +1440,9 @@ int map_searchrandfreecell(int16 m, const struct block_list *bl, int16 *x, int16
int free_cell,i,j;
int free_cells[9][2];
+ nullpo_ret(x);
+ nullpo_ret(y);
+
for(free_cell=0,i=-1;i<=1;i++){
if(i+*y<0 || i+*y>=map->list[m].ys)
continue;
@@ -1467,6 +1489,9 @@ int map_search_freecell(struct block_list *src, int16 m, int16 *x,int16 *y, int1
int rx2 = 2*rx+1;
int ry2 = 2*ry+1;
+ nullpo_ret(x);
+ nullpo_ret(y);
+
if( !src && (!(flag&1) || flag&2) )
{
ShowDebug("map_search_freecell: Incorrect usage! When src is NULL, flag has to be &1 and can't have &2\n");
@@ -1477,6 +1502,7 @@ int map_search_freecell(struct block_list *src, int16 m, int16 *x,int16 *y, int1
bx = *x;
by = *y;
} else {
+ nullpo_ret(src);
bx = src->x;
by = src->y;
m = src->m;
@@ -1533,10 +1559,15 @@ int map_search_freecell(struct block_list *src, int16 m, int16 *x,int16 *y, int1
bool map_closest_freecell(int16 m, const struct block_list *bl, int16 *x, int16 *y, int type, int flag)
{
uint8 dir = 6;
- int16 tx = *x;
- int16 ty = *y;
+ int16 tx;
+ int16 ty;
int costrange = 10;
+ nullpo_ret(x);
+ nullpo_ret(y);
+ tx = *x;
+ ty = *y;
+
if(!map->count_oncell(m, tx, ty, type, flag))
return true; //Current cell is free
@@ -1657,7 +1688,7 @@ int map_addflooritem(const struct block_list *bl, struct item *item_data, int am
/**
* @see DBCreateData
*/
-DBData create_charid2nick(DBKey key, va_list args)
+struct DBData create_charid2nick(union DBKey key, va_list args)
{
struct charid2nick *p;
CREATE(p, struct charid2nick, 1);
@@ -1694,7 +1725,7 @@ void map_delnickdb(int charid, const char* name)
{
struct charid2nick* p;
struct charid_request* req;
- DBData data;
+ struct DBData data;
if (!map->nick_db->remove(map->nick_db, DB->i2key(charid), &data) || (p = DB->data2ptr(&data)) == NULL)
return;
@@ -1793,6 +1824,8 @@ void map_deliddb(struct block_list *bl)
int map_quit(struct map_session_data *sd) {
int i;
+ nullpo_ret(sd);
+
if(!sd->state.active) { //Removing a player that is not active.
struct auth_node *node = chrif->search(sd->status.account_id);
if (node && node->char_id == sd->status.char_id &&
@@ -2166,9 +2199,9 @@ struct map_session_data * map_nick2sd(const char *nick)
/*==========================================
* Convext Mirror
*------------------------------------------*/
-struct mob_data * map_getmob_boss(int16 m)
+struct mob_data *map_getmob_boss(int16 m)
{
- DBIterator* iter;
+ struct DBIterator *iter;
struct mob_data *md = NULL;
bool found = false;
@@ -2230,11 +2263,11 @@ uint32 map_race_id2mask(int race)
/// Applies func to all the players in the db.
/// Stops iterating if func returns -1.
-void map_vforeachpc(int (*func)(struct map_session_data* sd, va_list args), va_list args) {
- DBIterator* iter;
- struct map_session_data* sd;
+void map_vforeachpc(int (*func)(struct map_session_data* sd, va_list args), va_list args)
+{
+ struct DBIterator *iter = db_iterator(map->pc_db);
+ struct map_session_data *sd = NULL;
- iter = db_iterator(map->pc_db);
for( sd = dbi_first(iter); dbi_exists(iter); sd = dbi_next(iter) )
{
va_list argscopy;
@@ -2262,11 +2295,11 @@ void map_foreachpc(int (*func)(struct map_session_data* sd, va_list args), ...)
/// Applies func to all the mobs in the db.
/// Stops iterating if func returns -1.
-void map_vforeachmob(int (*func)(struct mob_data* md, va_list args), va_list args) {
- DBIterator* iter;
- struct mob_data* md;
+void map_vforeachmob(int (*func)(struct mob_data* md, va_list args), va_list args)
+{
+ struct DBIterator *iter = db_iterator(map->mobid_db);
+ struct mob_data *md = NULL;
- iter = db_iterator(map->mobid_db);
for (md = dbi_first(iter); dbi_exists(iter); md = dbi_next(iter)) {
va_list argscopy;
int ret;
@@ -2293,11 +2326,11 @@ void map_foreachmob(int (*func)(struct mob_data* md, va_list args), ...) {
/// Applies func to all the npcs in the db.
/// Stops iterating if func returns -1.
-void map_vforeachnpc(int (*func)(struct npc_data* nd, va_list args), va_list args) {
- DBIterator* iter;
- struct block_list* bl;
+void map_vforeachnpc(int (*func)(struct npc_data* nd, va_list args), va_list args)
+{
+ struct DBIterator *iter = db_iterator(map->id_db);
+ struct block_list *bl = NULL;
- iter = db_iterator(map->id_db);
for (bl = dbi_first(iter); dbi_exists(iter); bl = dbi_next(iter)) {
if (bl->type == BL_NPC) {
struct npc_data *nd = BL_UCAST(BL_NPC, bl);
@@ -2327,11 +2360,11 @@ void map_foreachnpc(int (*func)(struct npc_data* nd, va_list args), ...) {
/// Applies func to everything in the db.
/// Stops iterating gif func returns -1.
-void map_vforeachregen(int (*func)(struct block_list* bl, va_list args), va_list args) {
- DBIterator* iter;
- struct block_list* bl;
+void map_vforeachregen(int (*func)(struct block_list* bl, va_list args), va_list args)
+{
+ struct DBIterator *iter = db_iterator(map->regen_db);
+ struct block_list *bl = NULL;
- iter = db_iterator(map->regen_db);
for (bl = dbi_first(iter); dbi_exists(iter); bl = dbi_next(iter)) {
va_list argscopy;
int ret;
@@ -2358,11 +2391,11 @@ void map_foreachregen(int (*func)(struct block_list* bl, va_list args), ...) {
/// Applies func to everything in the db.
/// Stops iterating if func returns -1.
-void map_vforeachiddb(int (*func)(struct block_list* bl, va_list args), va_list args) {
- DBIterator* iter;
- struct block_list* bl;
+void map_vforeachiddb(int (*func)(struct block_list* bl, va_list args), va_list args)
+{
+ struct DBIterator *iter = db_iterator(map->id_db);
+ struct block_list *bl = NULL;
- iter = db_iterator(map->id_db);
for (bl = dbi_first(iter); dbi_exists(iter); bl = dbi_next(iter)) {
va_list argscopy;
int ret;
@@ -2389,11 +2422,10 @@ void map_foreachiddb(int (*func)(struct block_list* bl, va_list args), ...) {
/// Iterator.
/// Can filter by bl type.
-struct s_mapiterator
-{
- enum e_mapitflags flags;// flags for special behaviour
- enum bl_type types;// what bl types to return
- DBIterator* dbi;// database iterator
+struct s_mapiterator {
+ enum e_mapitflags flags; ///< flags for special behaviour
+ enum bl_type types; ///< what bl types to return
+ struct DBIterator *dbi; ///< database iterator
};
/// Returns true if the block_list matches the description in the iterator.
@@ -2547,6 +2579,7 @@ bool map_addnpc(int16 m,struct npc_data *nd) {
// Returns the index of successful, or -1 if the list was full.
int map_addmobtolist(unsigned short m, struct spawn_data *spawn) {
int i;
+ nullpo_retr(-1, spawn);
ARR_FIND( 0, MAX_MOB_LIST_PER_MAP, i, map->list[m].moblist[i] == NULL );
if( i < MAX_MOB_LIST_PER_MAP ) {
map->list[m].moblist[i] = spawn;
@@ -2628,6 +2661,7 @@ int map_removemobs_timer(int tid, int64 tick, int id, intptr_t data) {
}
void map_removemobs(int16 m) {
+ Assert_retv(m >= 0 && m < map->count);
if (map->list[m].mob_delete_timer != INVALID_TIMER) // should never happen
return; //Mobs are already scheduled for removal
@@ -2662,6 +2696,8 @@ int16 map_mapindex2mapid(unsigned short map_index) {
int map_mapname2ipport(unsigned short name, uint32* ip, uint16* port) {
struct map_data_other_server *mdos;
+ nullpo_retr(-1, ip);
+ nullpo_retr(-1, port);
mdos = (struct map_data_other_server*)uidb_get(map->map_db,(unsigned int)name);
if(mdos==NULL || mdos->cell) //If gat isn't null, this is a local map.
return -1;
@@ -2737,11 +2773,19 @@ uint8 map_calc_dir(struct block_list* src, int16 x, int16 y)
*------------------------------------------*/
int map_random_dir(struct block_list *bl, int16 *x, int16 *y)
{
- short xi = *x-bl->x;
- short yi = *y-bl->y;
+ short xi;
+ short yi;
short i=0;
- int dist2 = xi*xi + yi*yi;
- short dist = (short)sqrt((float)dist2);
+ int dist2;
+ short dist;
+
+ nullpo_ret(bl);
+ nullpo_ret(x);
+ nullpo_ret(y);
+ xi = *x-bl->x;
+ yi = *y-bl->y;
+ dist2 = xi*xi + yi*yi;
+ dist = (short)sqrt((float)dist2);
if (dist < 1) dist =1;
@@ -2794,7 +2838,10 @@ int map_cell2gat(struct mapcell cell) {
return 1; // default to 'wall'
}
void map_cellfromcache(struct map_data *m) {
- struct map_cache_map_info *info = (struct map_cache_map_info *)m->cellPos;
+ struct map_cache_map_info *info;
+
+ nullpo_retv(m);
+ info = (struct map_cache_map_info *)m->cellPos;
if (info) {
char decode_buffer[MAX_MAP_SIZE];
@@ -2897,6 +2944,7 @@ int map_getcellp(struct map_data* m, const struct block_list *bl, int16 x, int16
/* [Ind/Hercules] */
int map_sub_getcellp(struct map_data* m, const struct block_list *bl, int16 x, int16 y, cell_chk cellchk) {
+ nullpo_ret(m);
map->cellfromcache(m);
m->getcellp = map->getcellp;
m->setcell = map->setcell;
@@ -2963,6 +3011,9 @@ void map_setgatcell(int16 m, int16 x, int16 y, int gat) {
*------------------------------------------*/
void map_iwall_nextxy(int16 x, int16 y, int8 dir, int pos, int16 *x1, int16 *y1)
{
+ nullpo_retv(x1);
+ nullpo_retv(y1);
+
if( dir == 0 || dir == 4 )
*x1 = x; // Keep X
else if( dir > 0 && dir < 4 )
@@ -3022,12 +3073,15 @@ bool map_iwall_set(int16 m, int16 x, int16 y, int size, int8 dir, bool shootable
return true;
}
-void map_iwall_get(struct map_session_data *sd) {
+void map_iwall_get(struct map_session_data *sd)
+{
struct iwall_data *iwall;
- DBIterator* iter;
+ struct DBIterator *iter;
int16 x1, y1;
int i;
+ nullpo_retv(sd);
+
if( map->list[sd->bl.m].iwall_num < 1 )
return;
@@ -3068,7 +3122,7 @@ void map_iwall_remove(const char *wall_name)
/**
* @see DBCreateData
*/
-DBData create_map_data_other_server(DBKey key, va_list args)
+struct DBData create_map_data_other_server(union DBKey key, va_list args)
{
struct map_data_other_server *mdos;
unsigned short map_index = (unsigned short)key.ui;
@@ -3103,9 +3157,10 @@ int map_setipport(unsigned short map_index, uint32 ip, uint16 port)
* Delete all the other maps server management
* @see DBApply
*/
-int map_eraseallipport_sub(DBKey key, DBData *data, va_list va)
+int map_eraseallipport_sub(union DBKey key, struct DBData *data, va_list va)
{
struct map_data_other_server *mdos = DB->data2ptr(data);
+ nullpo_ret(mdos);
if(mdos->cell == NULL) {
db_remove(map->map_db,key);
aFree(mdos);
@@ -3192,6 +3247,9 @@ int map_readfromcache(struct map_data *m, char *buffer) {
struct map_cache_map_info *info = NULL;
char *p = buffer + sizeof(struct map_cache_main_header);
+ nullpo_ret(m);
+ nullpo_ret(buffer);
+
for(i = 0; i < header->map_count; i++) {
info = (struct map_cache_map_info *)p;
@@ -3233,6 +3291,7 @@ int map_addmap(const char* mapname) {
}
void map_delmapid(int id) {
+ Assert_retv(id >= 0 && id < map->count);
ShowNotice("Removing map [ %s ] from maplist"CL_CLL"\n",map->list[id].name);
memmove(map->list+id, map->list+id+1, sizeof(map->list[0])*(map->count-id-1));
map->count--;
@@ -3242,6 +3301,7 @@ int map_delmap(char* mapname) {
int i;
char map_name[MAP_NAME_LENGTH];
+ nullpo_ret(mapname);
if (strcmpi(mapname, "all") == 0) {
map->count = 0;
return 0;
@@ -3263,6 +3323,8 @@ int map_delmap(char* mapname) {
void map_zone_clear_single(struct map_zone_data *zone) {
int i;
+ nullpo_retv(zone);
+
for(i = 0; i < zone->disabled_skills_count; i++) {
aFree(zone->disabled_skills[i]);
}
@@ -3300,9 +3362,10 @@ void map_zone_clear_single(struct map_zone_data *zone) {
/**
*
**/
-void map_zone_db_clear(void) {
- struct map_zone_data *zone;
- DBIterator *iter = db_iterator(map->zone_db);
+void map_zone_db_clear(void)
+{
+ struct DBIterator *iter = db_iterator(map->zone_db);
+ struct map_zone_data *zone = NULL;
for(zone = dbi_first(iter); dbi_exists(iter); zone = dbi_next(iter)) {
map->zone_clear_single(zone);
@@ -3319,6 +3382,7 @@ void map_zone_db_clear(void) {
}
void map_clean(int i) {
int v;
+ Assert_retv(i >= 0 && i < map->count);
if(map->list[i].cell && map->list[i].cell != (struct mapcell *)0xdeadbeaf) aFree(map->list[i].cell);
if(map->list[i].block) aFree(map->list[i].block);
if(map->list[i].block_mob) aFree(map->list[i].block_mob);
@@ -3517,6 +3581,7 @@ int map_waterheight(char* mapname)
char fn[256];
char *rsw, *found;
+ nullpo_retr(NO_WATER, mapname);
//Look up for the rsw
snprintf(fn, sizeof(fn), "data\\%s.rsw", mapname);
@@ -3545,6 +3610,7 @@ int map_readgat (struct map_data* m)
int water_height;
size_t xy, off, num_cells;
+ nullpo_ret(m);
sprintf(filename, "data\\%s.gat", m->name);
gat = (uint8 *) grfio_read(filename);
@@ -3582,10 +3648,12 @@ int map_readgat (struct map_data* m)
* Add/Remove map to the map_db
*--------------------------------------*/
void map_addmap2db(struct map_data *m) {
+ nullpo_retv(m);
map->index2mapid[m->index] = m->m;
}
void map_removemapdb(struct map_data *m) {
+ nullpo_retv(m);
map->index2mapid[m->index] = -1;
}
@@ -3690,6 +3758,8 @@ int map_config_read(char *cfgName) {
char line[1024], w1[1024], w2[1024];
FILE *fp;
+ nullpo_retr(1, cfgName);
+
fp = fopen(cfgName,"r");
if( fp == NULL ) {
ShowError("Map configuration file not found at: %s\n", cfgName);
@@ -3784,6 +3854,7 @@ int map_config_read_sub(char *cfgName) {
char line[1024], w1[1024], w2[1024];
FILE *fp;
+ nullpo_retr(1, cfgName);
fp = fopen(cfgName,"r");
if (fp == NULL) {
ShowError("Map configuration file not found at: %s\n", cfgName);
@@ -3821,6 +3892,7 @@ void map_reloadnpc_sub(char *cfgName) {
char line[1024], w1[1024], w2[1024];
FILE *fp;
+ nullpo_retv(cfgName);
fp = fopen(cfgName,"r");
if (fp == NULL) {
ShowError("Map configuration file not found at: %s\n", cfgName);
@@ -3882,6 +3954,7 @@ int inter_config_read(char *cfgName) {
char line[1024],w1[1024],w2[1024];
FILE *fp;
+ nullpo_retr(1, cfgName);
if (!(fp = fopen(cfgName,"r"))) {
ShowError("File not found: %s\n",cfgName);
return 1;
@@ -3979,6 +4052,9 @@ struct map_zone_data *map_merge_zone(struct map_zone_data *main, struct map_zone
struct map_zone_data *zone = NULL;
int cursor, i, j;
+ nullpo_retr(NULL, main);
+ nullpo_retr(NULL, other);
+
sprintf(newzone, "%s+%s",main->name,other->name);
if( (zone = strdb_get(map->zone_db, newzone)) )
@@ -4072,6 +4148,7 @@ void map_zone_change2(int m, struct map_zone_data *zone)
{
const char *empty = "";
+ Assert_retv(m >= 0 && m < map->count);
if( map->list[m].zone == zone )
return;
@@ -4089,6 +4166,7 @@ void map_zone_change2(int m, struct map_zone_data *zone)
}
/* when changing from a mapflag to another during runtime */
void map_zone_change(int m, struct map_zone_data *zone, const char* start, const char* buffer, const char* filepath) {
+ Assert_retv(m >= 0 && m < map->count);
map->list[m].prev_zone = map->list[m].zone;
if( map->list[m].zone_mf_count )
@@ -4101,6 +4179,7 @@ void map_zone_remove(int m)
char flag[MAP_ZONE_MAPFLAG_LENGTH], params[MAP_ZONE_MAPFLAG_LENGTH];
unsigned short k;
const char *empty = "";
+ Assert_retv(m >= 0 && m < map->count);
for(k = 0; k < map->list[m].zone_mf_count; k++) {
size_t len = strlen(map->list[m].zone_mf[k]),j;
params[0] = '\0';
@@ -4123,6 +4202,7 @@ void map_zone_remove(int m)
map->list[m].zone_mf_count = 0;
}
static inline void map_zone_mf_cache_add(int m, char *rflag) {
+ Assert_retv(m >= 0 && m < map->count);
RECREATE(map->list[m].zone_mf, char *, ++map->list[m].zone_mf_count);
CREATE(map->list[m].zone_mf[map->list[m].zone_mf_count - 1], char, MAP_ZONE_MAPFLAG_LENGTH);
safestrncpy(map->list[m].zone_mf[map->list[m].zone_mf_count - 1], rflag, MAP_ZONE_MAPFLAG_LENGTH);
@@ -4133,6 +4213,10 @@ bool map_zone_mf_cache(int m, char *flag, char *params) {
char rflag[MAP_ZONE_MAPFLAG_LENGTH];
int state = 1;
+ nullpo_retr(false, flag);
+ nullpo_retr(false, params);
+ Assert_retr(false, m >= 0 && m < map->count);
+
if (params[0] != '\0' && !strcmpi(params, "off"))
state = 0;
@@ -4829,6 +4913,8 @@ void map_zone_apply(int m, struct map_zone_data *zone, const char* start, const
int i;
const char *empty = "";
char flag[MAP_ZONE_MAPFLAG_LENGTH], params[MAP_ZONE_MAPFLAG_LENGTH];
+ Assert_retv(m >= 0 && m < map->count);
+ nullpo_retv(zone);
map->list[m].zone = zone;
for(i = 0; i < zone->mapflags_count; i++) {
size_t len = strlen(zone->mapflags[i]);
@@ -4939,8 +5025,9 @@ unsigned short map_zone_str2skillid(const char *name) {
enum bl_type map_zone_bl_type(const char *entry, enum map_zone_skill_subtype *subtype) {
char temp[200], *parse;
enum bl_type bl = BL_NUL;
- *subtype = MZS_NONE;
+ nullpo_retr(BL_NUL, subtype);
+ *subtype = MZS_NONE;
if( !entry )
return BL_NUL;
@@ -5414,6 +5501,8 @@ int map_get_new_bonus_id (void) {
void map_add_questinfo(int m, struct questinfo *qi) {
unsigned short i;
+ nullpo_retv(qi);
+ Assert_retv(m >= 0 && m < map->count);
/* duplicate, override */
for(i = 0; i < map->list[m].qi_count; i++) {
if( map->list[m].qi_data[i].nd == qi->nd )
@@ -5429,6 +5518,7 @@ void map_add_questinfo(int m, struct questinfo *qi) {
bool map_remove_questinfo(int m, struct npc_data *nd) {
unsigned short i;
+ Assert_retr(false, m >= 0 && m < map->count);
for(i = 0; i < map->list[m].qi_count; i++) {
struct questinfo *qi = &map->list[m].qi_data[i];
if( qi->nd == nd ) {
@@ -5445,7 +5535,8 @@ bool map_remove_questinfo(int m, struct npc_data *nd) {
/**
* @see DBApply
*/
-int map_db_final(DBKey key, DBData *data, va_list ap) {
+int map_db_final(union DBKey key, struct DBData *data, va_list ap)
+{
struct map_data_other_server *mdos = DB->data2ptr(data);
if(mdos && iMalloc->verify_ptr(mdos) && mdos->cell == NULL)
@@ -5457,7 +5548,7 @@ int map_db_final(DBKey key, DBData *data, va_list ap) {
/**
* @see DBApply
*/
-int nick_db_final(DBKey key, DBData *data, va_list args)
+int nick_db_final(union DBKey key, struct DBData *data, va_list args)
{
struct charid2nick* p = DB->data2ptr(data);
struct charid_request* req;
@@ -5504,7 +5595,8 @@ int cleanup_sub(struct block_list *bl, va_list ap) {
/**
* @see DBApply
*/
-int cleanup_db_sub(DBKey key, DBData *data, va_list va) {
+int cleanup_db_sub(union DBKey key, struct DBData *data, va_list va)
+{
return map->cleanup_sub(DB->data2ptr(data), va);
}
diff --git a/src/map/map.h b/src/map/map.h
index ff7ca2d38..dbd30febf 100644
--- a/src/map/map.h
+++ b/src/map/map.h
@@ -27,11 +27,12 @@
#include "common/db.h"
#include "common/mapindex.h"
#include "common/mmo.h"
-#include "common/sql.h"
#include <stdio.h>
#include <stdarg.h>
+/* Forward Declarations */
+struct Sql; // common/sql.h
struct mob_data;
struct npc_data;
struct channel_data;
@@ -398,7 +399,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
@@ -993,7 +994,7 @@ struct map_interface {
char server_id[32];
char server_pw[100];
char server_db[32];
- Sql* mysql_handle;
+ struct Sql *mysql_handle;
int port;
int users;
@@ -1003,16 +1004,16 @@ struct map_interface {
int16 index2mapid[MAX_MAPINDEX];
/* */
- DBMap* id_db; // int id -> struct block_list*
- DBMap* pc_db; // int id -> struct map_session_data*
- DBMap* mobid_db; // int id -> struct mob_data*
- DBMap* bossid_db; // int id -> struct mob_data* (MVP db)
- DBMap* map_db; // unsigned int mapindex -> struct map_data_other_server*
- DBMap* nick_db; // int char_id -> struct charid2nick* (requested names of offline characters)
- DBMap* charid_db; // int char_id -> struct map_session_data*
- DBMap* regen_db; // int id -> struct block_list* (status_natural_heal processing)
- DBMap* zone_db; // string => struct map_zone_data
- DBMap* iwall_db;
+ struct DBMap *id_db; // int id -> struct block_list*
+ struct DBMap *pc_db; // int id -> struct map_session_data*
+ struct DBMap *mobid_db; // int id -> struct mob_data*
+ struct DBMap *bossid_db; // int id -> struct mob_data* (MVP db)
+ struct DBMap *map_db; // unsigned int mapindex -> struct map_data_other_server*
+ struct DBMap *nick_db; // int char_id -> struct charid2nick* (requested names of offline characters)
+ struct DBMap *charid_db; // int char_id -> struct map_session_data*
+ struct DBMap *regen_db; // int id -> struct block_list* (status_natural_heal processing)
+ struct DBMap *zone_db; // string => struct map_zone_data
+ struct DBMap *iwall_db;
struct block_list **block_free;
int block_free_count, block_free_lock, block_free_list_size;
struct block_list **bl_list;
@@ -1166,7 +1167,7 @@ END_ZEROED_BLOCK;
int (*freeblock_timer) (int tid, int64 tick, int id, intptr_t data);
int (*searchrandfreecell) (int16 m, const struct block_list *bl, int16 *x, int16 *y, int stack);
int (*count_sub) (struct block_list *bl, va_list ap);
- DBData (*create_charid2nick) (DBKey key, va_list args);
+ struct DBData (*create_charid2nick) (union DBKey key, va_list args);
int (*removemobs_sub) (struct block_list *bl, va_list ap);
struct mapcell (*gat2cell) (int gat);
int (*cell2gat) (struct mapcell cell);
@@ -1175,8 +1176,8 @@ END_ZEROED_BLOCK;
int (*sub_getcellp) (struct map_data *m, const struct block_list *bl, int16 x, int16 y, cell_chk cellchk);
void (*sub_setcell) (int16 m, int16 x, int16 y, cell_t cell, bool flag);
void (*iwall_nextxy) (int16 x, int16 y, int8 dir, int pos, int16 *x1, int16 *y1);
- DBData (*create_map_data_other_server) (DBKey key, va_list args);
- int (*eraseallipport_sub) (DBKey key, DBData *data, va_list va);
+ struct DBData (*create_map_data_other_server) (union DBKey key, va_list args);
+ int (*eraseallipport_sub) (union DBKey key, struct DBData *data, va_list va);
char* (*init_mapcache) (FILE *fp);
int (*readfromcache) (struct map_data *m, char *buffer);
int (*addmap) (const char *mapname);
@@ -1197,9 +1198,9 @@ END_ZEROED_BLOCK;
unsigned short (*zone_str2skillid) (const char *name);
enum bl_type (*zone_bl_type) (const char *entry, enum map_zone_skill_subtype *subtype);
void (*read_zone_db) (void);
- int (*db_final) (DBKey key, DBData *data, va_list ap);
- int (*nick_db_final) (DBKey key, DBData *data, va_list args);
- int (*cleanup_db_sub) (DBKey key, DBData *data, va_list va);
+ int (*db_final) (union DBKey key, struct DBData *data, va_list ap);
+ int (*nick_db_final) (union DBKey key, struct DBData *data, va_list args);
+ int (*cleanup_db_sub) (union DBKey key, struct DBData *data, va_list va);
int (*abort_sub) (struct map_session_data *sd, va_list ap);
void (*update_cell_bl) (struct block_list *bl, bool increase);
int (*get_new_bonus_id) (void);
diff --git a/src/map/mapreg.h b/src/map/mapreg.h
index dfe1dfb2d..d19b2bb80 100644
--- a/src/map/mapreg.h
+++ b/src/map/mapreg.h
@@ -59,7 +59,7 @@ struct mapreg_interface {
void (*load) (void);
void (*save) (void);
int (*save_timer) (int tid, int64 tick, int id, intptr_t data);
- int (*destroyreg) (DBKey key, DBData *data, va_list ap);
+ int (*destroyreg) (union DBKey key, struct DBData *data, va_list ap);
void (*reload) (void);
bool (*config_read) (const char *w1, const char *w2);
};
diff --git a/src/map/mapreg_sql.c b/src/map/mapreg_sql.c
index 46962ac14..82ce39d64 100644
--- a/src/map/mapreg_sql.c
+++ b/src/map/mapreg_sql.c
@@ -28,6 +28,7 @@
#include "common/db.h"
#include "common/ers.h"
#include "common/memmgr.h"
+#include "common/nullpo.h"
#include "common/showmsg.h"
#include "common/sql.h"
#include "common/strlib.h"
@@ -76,6 +77,7 @@ bool mapreg_setreg(int64 uid, int val) {
unsigned int i = script_getvaridx(uid);
const char* name = script->get_str(num);
+ nullpo_retr(true, name);
if( val != 0 ) {
if( (m = i64db_get(mapreg->regs.vars, uid)) ) {
m->u.i = val;
@@ -132,6 +134,8 @@ bool mapreg_setregstr(int64 uid, const char* str) {
unsigned int i = script_getvaridx(uid);
const char* name = script->get_str(num);
+ nullpo_retr(true, name);
+
if( str == NULL || *str == 0 ) {
if( i )
script->array_update(&mapreg->regs, uid, true);
@@ -190,7 +194,7 @@ void script_load_mapreg(void) {
| varname | index | value |
+-------------------------+
*/
- SqlStmt* stmt = SQL->StmtMalloc(map->mysql_handle);
+ struct SqlStmt *stmt = SQL->StmtMalloc(map->mysql_handle);
char varname[SCRIPT_VARNAME_LENGTH+1];
int index;
char value[255+1];
@@ -236,15 +240,17 @@ void script_load_mapreg(void) {
/**
* Saves permanent variables to database.
*/
-void script_save_mapreg(void) {
+void script_save_mapreg(void)
+{
if (mapreg->dirty) {
- DBIterator *iter = db_iterator(mapreg->regs.vars);
- struct mapreg_save *m;
+ struct DBIterator *iter = db_iterator(mapreg->regs.vars);
+ struct mapreg_save *m = NULL;
for (m = dbi_first(iter); dbi_exists(iter); m = dbi_next(iter)) {
if (m->save) {
int num = script_getvarid(m->uid);
int i = script_getvaridx(m->uid);
const char* name = script->get_str(num);
+ nullpo_retv(name);
if (!m->is_string) {
if( SQL_ERROR == SQL->Query(map->mysql_handle, "UPDATE `%s` SET `value`='%d' WHERE `varname`='%s' AND `index`='%d' LIMIT 1", mapreg->table, m->u.i, name, i) )
Sql_ShowDebug(map->mysql_handle);
@@ -277,7 +283,8 @@ int script_autosave_mapreg(int tid, int64 tick, int id, intptr_t data) {
*
* @see DBApply
*/
-int mapreg_destroyreg(DBKey key, DBData *data, va_list ap) {
+int mapreg_destroyreg(union DBKey key, struct DBData *data, va_list ap)
+{
struct mapreg_save *m = NULL;
if (data->type != DB_DATA_PTR) // Sanity check
@@ -344,6 +351,8 @@ void mapreg_init(void) {
* Loads the mapreg configuration file.
*/
bool mapreg_config_read(const char* w1, const char* w2) {
+ nullpo_retr(false, w1);
+ nullpo_retr(false, w2);
if(!strcmpi(w1, "mapreg_db"))
safestrncpy(mapreg->table, w2, sizeof(mapreg->table));
else
diff --git a/src/map/mercenary.c b/src/map/mercenary.c
index fa337e13b..0b055bedf 100644
--- a/src/map/mercenary.c
+++ b/src/map/mercenary.c
@@ -234,6 +234,7 @@ int mercenary_set_calls(struct mercenary_data *md, int value)
int mercenary_save(struct mercenary_data *md)
{
+ nullpo_retr(1, md);
md->mercenary.hp = md->battle_status.hp;
md->mercenary.sp = md->battle_status.sp;
md->mercenary.life_time = mercenary->get_lifetime(md);
@@ -265,7 +266,10 @@ int merc_contract_end_timer(int tid, int64 tick, int id, intptr_t data) {
int merc_delete(struct mercenary_data *md, int reply)
{
- struct map_session_data *sd = md->master;
+ struct map_session_data *sd;
+
+ nullpo_retr(0, md);
+ sd = md->master;
md->mercenary.life_time = 0;
mercenary->contract_stop(md);
@@ -299,6 +303,7 @@ void merc_contract_stop(struct mercenary_data *md)
void merc_contract_init(struct mercenary_data *md)
{
+ nullpo_retv(md);
if( md->contract_timer == INVALID_TIMER )
md->contract_timer = timer->add(timer->gettick() + md->mercenary.life_time, mercenary->contract_end_timer, md->master->bl.id, 0);
@@ -310,8 +315,10 @@ 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;
- int i = mercenary->search_index(merc->class_);
+ int i;
+ nullpo_ret(merc);
+ i = mercenary->search_index(merc->class_);
if( (sd = map->charid2sd(merc->char_id)) == NULL )
return 0;
if (!flag || i == INDEX_NOT_FOUND) {
@@ -370,6 +377,7 @@ int merc_data_received(const struct s_mercenary *merc, bool flag)
void mercenary_heal(struct mercenary_data *md, int hp, int sp)
{
+ nullpo_retv(md);
if( hp )
clif->mercenary_updatestatus(md->master, SP_HP);
if( sp )
@@ -387,12 +395,14 @@ int mercenary_killbonus(struct mercenary_data *md)
const enum sc_type scs[] = { SC_MER_FLEE, SC_MER_ATK, SC_MER_HP, SC_MER_SP, SC_MER_HIT };
int index = rnd() % ARRAYLENGTH(scs);
+ nullpo_ret(md);
sc_start(NULL,&md->bl, scs[index], 100, rnd() % 5, 600000);
return 0;
}
int mercenary_kills(struct mercenary_data *md)
{
+ nullpo_ret(md);
md->mercenary.kill_count++;
md->mercenary.kill_count = cap_value(md->mercenary.kill_count, 0, INT_MAX);
@@ -425,6 +435,8 @@ bool read_mercenarydb_sub(char* str[], int columns, int current) {
struct s_mercenary_db *db;
struct status_data *mstatus;
+ nullpo_retr(false, str);
+ Assert_retr(false, current >= 0 && current < MAX_MERCENARY_CLASS);
db = &mercenary->db[current];
db->class_ = atoi(str[0]);
safestrncpy(db->sprite, str[1], NAME_LENGTH);
@@ -486,6 +498,7 @@ bool read_mercenary_skilldb_sub(char* str[], int columns, int current)
int i, class_;
uint16 skill_id, skill_lv;
+ nullpo_retr(false, str);
class_ = atoi(str[0]);
ARR_FIND(0, MAX_MERCENARY_CLASS, i, class_ == mercenary->db[i].class_);
if( i == MAX_MERCENARY_CLASS )
diff --git a/src/map/mob.c b/src/map/mob.c
index 8d38fead7..19fee52a5 100644
--- a/src/map/mob.c
+++ b/src/map/mob.c
@@ -114,6 +114,8 @@ struct mob_chat *mob_chat(short id) {
int mobdb_searchname(const char *str)
{
int i;
+
+ nullpo_ret(str);
for(i=0;i<=MAX_MOB_DB;i++){
struct mob_db *monster = mob->db(i);
if(monster == mob->dummy) //Skip dummy mobs.
@@ -129,10 +131,13 @@ int mobdb_searchname(const char *str)
return 0;
}
int mobdb_searchname_array_sub(struct mob_db* monster, const char *str, int flag) {
+
+ nullpo_ret(monster);
if (monster == mob->dummy)
return 1;
if(!monster->base_exp && !monster->job_exp && monster->spawn[0].qty < 1)
return 1; // Monsters with no base/job exp and no spawn point are, by this criteria, considered "slave mobs" and excluded from search results
+ nullpo_ret(str);
if( !flag ) {
if(stristr(monster->jname,str))
return 0;
@@ -156,6 +161,7 @@ void mvptomb_create(struct mob_data *md, char *killer, time_t time)
{
struct npc_data *nd;
+ nullpo_retv(md);
if ( md->tomb_nid )
mob->mvptomb_destroy(md);
@@ -181,6 +187,7 @@ void mvptomb_create(struct mob_data *md, char *killer, time_t time)
void mvptomb_destroy(struct mob_data *md) {
struct npc_data *nd;
+ nullpo_retv(md);
if ( (nd = map->id2nd(md->tomb_nid)) ) {
int16 m, i;
@@ -212,6 +219,7 @@ int mobdb_searchname_array(struct mob_db** data, int size, const char *str, int
{
int count = 0, i;
struct mob_db* monster;
+ nullpo_ret(data);
for(i=0;i<=MAX_MOB_DB;i++){
monster = mob->db(i);
if (monster == mob->dummy || mob->is_clone(i) ) //keep clones out (or you leak player stats)
@@ -253,6 +261,7 @@ int mob_parse_dataset(struct spawn_data *data)
{
size_t len;
+ nullpo_ret(data);
if ((!mob->db_checkid(data->class_) && !mob->is_clone(data->class_)) || !data->num)
return 0;
@@ -276,6 +285,7 @@ int mob_parse_dataset(struct spawn_data *data)
*------------------------------------------*/
struct mob_data* mob_spawn_dataset(struct spawn_data *data) {
struct mob_data *md = NULL;
+ nullpo_retr(NULL, data);
CREATE(md, struct mob_data, 1);
md->bl.id= npc->get_new_npc_id();
md->bl.type = BL_MOB;
@@ -328,6 +338,7 @@ int mob_get_random_id(int type, int flag, int lv)
ShowError("mob_get_random_id: Invalid type (%d) of random monster.\n", type);
return 0;
}
+ Assert_ret(type >= 0 && type < MAX_RANDOMMONSTER);
do {
if (type)
class_ = summon[type].class_[rnd()%summon[type].qty];
@@ -410,7 +421,7 @@ bool mob_ksprotected(struct block_list *src, struct block_list *target) {
if( DIFF_TICK(sd->ks_floodprotect_tick, tick) <= 0 )
{
sprintf(output, "[KS Warning!! - Owner : %s]", pl_sd->status.name);
- clif_disp_onlyself(sd, output, strlen(output));
+ clif_disp_onlyself(sd, output);
sd->ks_floodprotect_tick = tick + 2000;
}
@@ -419,7 +430,7 @@ bool mob_ksprotected(struct block_list *src, struct block_list *target) {
if( DIFF_TICK(pl_sd->ks_floodprotect_tick, tick) <= 0 )
{
sprintf(output, "[Watch out! %s is trying to KS you!]", sd->status.name);
- clif_disp_onlyself(pl_sd, output, strlen(output));
+ clif_disp_onlyself(pl_sd, output);
pl_sd->ks_floodprotect_tick = tick + 2000;
}
@@ -634,6 +645,11 @@ int mob_spawn_guardian(const char* mapname, short x, short y, const char* mobnam
struct guild *g=NULL;
struct guild_castle *gc;
int16 m;
+
+ nullpo_ret(mapname);
+ nullpo_ret(mobname);
+ nullpo_ret(event);
+
memset(&data, 0, sizeof(struct spawn_data));
data.num = 1;
@@ -728,6 +744,10 @@ int mob_spawn_bg(const char* mapname, short x, short y, const char* mobname, int
struct spawn_data data;
int16 m;
+ nullpo_ret(mapname);
+ nullpo_ret(mobname);
+ nullpo_ret(event);
+
if( (m = map->mapname2mapid(mapname)) < 0 ) {
ShowWarning("mob_spawn_bg: Map [%s] not found.\n", mapname);
return 0;
@@ -846,6 +866,8 @@ int mob_setdelayspawn(struct mob_data *md)
uint32 mode;
struct mob_db *db;
+ nullpo_ret(md);
+
if (!md->spawn) //Doesn't has respawn data!
return unit->free(&md->bl,CLR_DEAD);
@@ -903,6 +925,7 @@ int mob_spawn (struct mob_data *md)
int64 tick = timer->gettick();
int64 c = 0;
+ nullpo_retr(1, md);
md->last_thinktime = tick;
if (md->bl.prev != NULL)
unit->remove_map(&md->bl,CLR_RESPAWN,ALC_MARK);
@@ -992,6 +1015,8 @@ int mob_spawn (struct mob_data *md)
*------------------------------------------*/
int mob_can_changetarget(const struct mob_data *md, const struct block_list *target, uint32 mode)
{
+ nullpo_ret(md);
+ nullpo_ret(target);
// if the monster was provoked ignore the above rule [celest]
if(md->state.provoke_flag)
{
@@ -1057,6 +1082,8 @@ int mob_ai_sub_hard_activesearch(struct block_list *bl, va_list ap)
md=va_arg(ap,struct mob_data *);
target= va_arg(ap,struct block_list**);
mode = va_arg(ap, uint32);
+ nullpo_ret(md);
+ nullpo_ret(target);
//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))
@@ -1111,8 +1138,10 @@ int mob_ai_sub_hard_changechase(struct block_list *bl,va_list ap) {
struct block_list **target;
nullpo_ret(bl);
- md=va_arg(ap,struct mob_data *);
- target= va_arg(ap,struct block_list**);
+ md = va_arg(ap,struct mob_data *);
+ target = va_arg(ap,struct block_list**);
+ nullpo_ret(md);
+ nullpo_ret(target);
//If can't seek yet, not an enemy, or you can't attack it, skip.
if( md->bl.id == bl->id || *target == bl
@@ -1139,6 +1168,8 @@ int mob_ai_sub_hard_bg_ally(struct block_list *bl,va_list ap) {
nullpo_ret(bl);
md=va_arg(ap,struct mob_data *);
target= va_arg(ap,struct block_list**);
+ nullpo_retr(1, md);
+ nullpo_retr(1, target);
if( status->check_skilluse(&md->bl, bl, 0, 0) && battle->check_target(&md->bl,bl,BCT_ENEMY)<=0 ) {
(*target) = bl;
@@ -1157,6 +1188,8 @@ int mob_ai_sub_hard_lootsearch(struct block_list *bl,va_list ap)
md=va_arg(ap,struct mob_data *);
target= va_arg(ap,struct block_list**);
+ nullpo_ret(md);
+ nullpo_ret(target);
dist=distance_bl(&md->bl, bl);
if(mob->can_reach(md,bl,dist+1, MSS_LOOT) &&
@@ -1177,6 +1210,9 @@ int mob_warpchase_sub(struct block_list *bl,va_list ap) {
struct npc_data *nd = NULL;
nullpo_ret(bl);
+ nullpo_ret(target);
+ nullpo_ret(target_nd);
+ nullpo_ret(min_distance);
Assert_ret(bl->type == BL_NPC);
nd = BL_UCAST(BL_NPC, bl);
@@ -1201,6 +1237,7 @@ int mob_warpchase_sub(struct block_list *bl,va_list ap) {
int mob_ai_sub_hard_slavemob(struct mob_data *md, int64 tick) {
struct block_list *bl;
+ nullpo_ret(md);
bl=map->id2bl(md->master_id);
if (!bl || status->isdead(bl)) {
@@ -1378,6 +1415,7 @@ int mob_warpchase(struct mob_data *md, struct block_list *target)
{
struct npc_data *warp = NULL;
int distance = AREA_SIZE;
+ nullpo_ret(md);
if (!(target && battle_config.mob_ai&0x40 && battle_config.mob_warp&1))
return 0; //Can't warp chase.
@@ -1405,6 +1443,7 @@ bool mob_ai_sub_hard(struct mob_data *md, int64 tick) {
uint32 mode;
int view_range, can_move;
+ nullpo_retr(false, md);
if(md->bl.prev == NULL || md->status.hp <= 0)
return false;
@@ -1702,6 +1741,7 @@ int mob_ai_sub_hard_timer(struct block_list *bl, va_list ap)
*------------------------------------------*/
int mob_ai_sub_foreachclient(struct map_session_data *sd, va_list ap) {
int64 tick;
+ nullpo_ret(sd);
tick=va_arg(ap, int64);
map->foreachinrange(mob->ai_sub_hard_timer,&sd->bl, AREA_SIZE+ACTIVE_AI_RANGE, BL_MOB,tick);
@@ -1810,7 +1850,10 @@ struct item_drop* mob_setdropitem(int nameid, int qty, struct item_data *data) {
*------------------------------------------*/
struct item_drop* mob_setlootitem(struct item* item)
{
- struct item_drop *drop = ers_alloc(item_drop_ers, struct item_drop);
+ struct item_drop *drop ;
+
+ nullpo_retr(NULL, item);
+ drop = ers_alloc(item_drop_ers, struct item_drop);
memcpy(&drop->item_data, item, sizeof(struct item));
drop->next = NULL;
return drop;
@@ -1847,6 +1890,9 @@ void mob_item_drop(struct mob_data *md, struct item_drop_list *dlist, struct ite
{
struct map_session_data *sd = NULL;
+ nullpo_retv(md);
+ nullpo_retv(dlist);
+ nullpo_retv(ditem);
//Logs items, dropped by mobs [Lupus]
logs->pick_mob(md, loot?LOG_TYPE_LOOT:LOG_TYPE_PICKDROP_MONSTER, -ditem->item_data.amount, &ditem->item_data, NULL);
@@ -1932,6 +1978,9 @@ void mob_log_damage(struct mob_data *md, struct block_list *src, int damage)
{
int char_id = 0, flag = MDLF_NORMAL;
+ nullpo_retv(md);
+ nullpo_retv(src);
+
if( damage < 0 )
return; //Do nothing for absorbed damage.
if( !damage && !(src->type&DEFAULT_ENEMY_TYPE(md)) )
@@ -2042,6 +2091,7 @@ void mob_log_damage(struct mob_data *md, struct block_list *src, int damage)
}
//Call when a mob has received damage.
void mob_damage(struct mob_data *md, struct block_list *src, int damage) {
+ nullpo_retv(md);
if (damage > 0) { //Store total damage...
if (UINT_MAX - (unsigned int)damage > md->tdmg)
md->tdmg+=damage;
@@ -2105,12 +2155,14 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) {
int id,zeny;
unsigned int base_exp,job_exp;
} pt[DAMAGELOG_SIZE] = { { 0 } };
- int i, temp, count, m = md->bl.m;
+ int i, temp, count, m;
int dmgbltypes = 0; // bitfield of all bl types, that caused damage to the mob and are eligible for exp distribution
unsigned int mvp_damage;
int64 tick = timer->gettick();
bool rebirth, homkillonly;
+ nullpo_retr(3, md);
+ m = md->bl.m;
mstatus = &md->status;
if( md->guardian_data && md->guardian_data->number >= 0 && md->guardian_data->number < MAX_GUARDIANS )
@@ -2395,14 +2447,16 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) {
char message[128];
sprintf (message, msg_txt(541), mvp_sd->status.name, md->name, it->jname, (float)drop_rate/100);
//MSG: "'%s' won %s's %s (chance: %0.02f%%)"
- intif->broadcast(message, strlen(message)+1, BC_DEFAULT);
+ intif->broadcast(message, (int)strlen(message)+1, BC_DEFAULT);
}
/* heres the thing we got the feature set up however we're still discussing how to best define the ids,
* so while we discuss, for a small period of time, the list is hardcoded (yes officially only those 2 use it,
* thus why we're unsure on how to best place the setting) */
/* temp, will not be hardcoded for long thudu. */
- if (it->nameid == ITEMID_GOLD_KEY77 || it->nameid == ITEMID_SILVER_KEY77) /* for when not hardcoded: add a check on mvp bonus drop as well */
+ // TODO: This should be a field in the item db.
+ if (mvp_sd != NULL
+ && (it->nameid == ITEMID_GOLD_KEY77 || it->nameid == ITEMID_SILVER_KEY77)) /* for when not hardcoded: add a check on mvp bonus drop as well */
clif->item_drop_announce(mvp_sd, it->nameid, md->name);
// Announce first, or else ditem will be freed. [Lance]
@@ -2502,60 +2556,62 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) {
pc->gainexp(mvp_sd, &md->bl, mexp,0, false);
log_mvp[1] = mexp;
- if( !(map->list[m].flag.nomvploot || type&1) ) {
+ if (!(map->list[m].flag.nomvploot || type&1)) {
/* pose them randomly in the list -- so on 100% drop servers it wont always drop the same item */
- int mdrop_id[MAX_MVP_DROP];
- int mdrop_p[MAX_MVP_DROP];
- struct item item;
-
- memset(&mdrop_id,0,MAX_MVP_DROP*sizeof(int));
-
- for(i = 0; i < MAX_MVP_DROP; i++) {
- while( 1 ) {
- int va = rnd()%MAX_MVP_DROP;
- if( !mdrop_id[va] || !md->db->mvpitem[i].nameid ) {
- mdrop_id[va] = md->db->mvpitem[i].nameid;
- mdrop_p[va] = md->db->mvpitem[i].p;
- break;
- }
- }
+ struct {
+ int nameid;
+ int p;
+ } mdrop[MAX_MVP_DROP] = { { 0 } };
+
+ for (i = 0; i < MAX_MVP_DROP; i++) {
+ int rpos;
+ if (md->db->mvpitem[i].nameid == 0)
+ continue;
+ do {
+ rpos = rnd()%MAX_MVP_DROP;
+ } while (mdrop[rpos].nameid != 0);
+
+ mdrop[rpos].nameid = md->db->mvpitem[i].nameid;
+ mdrop[rpos].p = md->db->mvpitem[i].p;
}
- for(i = 0; i < MAX_MVP_DROP; i++) {
- struct item_data *data;
- if(mdrop_id[i] <= 0)
+ for (i = 0; i < MAX_MVP_DROP; i++) {
+ struct item_data *data = NULL;
+ int rate = 0;
+
+ if (mdrop[i].nameid <= 0)
continue;
- if(! (data = itemdb->exists(mdrop_id[i])) )
+ if ((data = itemdb->exists(mdrop[i].nameid)) == NULL)
continue;
- temp = mdrop_p[i];
- if(temp <= 0 && !battle_config.drop_rate0item)
- temp = 1;
- if(temp <= rnd()%10000+1) //if ==0, then it doesn't drop
- continue;
+ rate = mdrop[i].p;
+ if (rate <= 0 && !battle_config.drop_rate0item)
+ rate = 1;
+ if (rate > rnd()%10000) {
+ struct item item = { 0 };
+
+ item.nameid = mdrop[i].nameid;
+ item.identify = itemdb->isidentified2(data);
+ clif->mvp_item(mvp_sd, item.nameid);
+ log_mvp[0] = item.nameid;
+
+ //A Rare MVP Drop Global Announce by Lupus
+ if (rate <= battle_config.rare_drop_announce) {
+ char message[128];
+ sprintf(message, msg_txt(541), mvp_sd->status.name, md->name, data->jname, rate/100.);
+ //MSG: "'%s' won %s's %s (chance: %0.02f%%)"
+ intif->broadcast(message, (int)strlen(message)+1, BC_DEFAULT);
+ }
- memset(&item,0,sizeof(item));
- item.nameid=mdrop_id[i];
- item.identify= itemdb->isidentified2(data);
- clif->mvp_item(mvp_sd,item.nameid);
- log_mvp[0] = item.nameid;
-
- //A Rare MVP Drop Global Announce by Lupus
- if(temp<=battle_config.rare_drop_announce) {
- char message[128];
- sprintf (message, msg_txt(541), mvp_sd->status.name, md->name, data->jname, temp/100.);
- //MSG: "'%s' won %s's %s (chance: %0.02f%%)"
- intif->broadcast(message, strlen(message)+1, BC_DEFAULT);
- }
+ if((temp = pc->additem(mvp_sd,&item,1,LOG_TYPE_PICKDROP_PLAYER)) != 0) {
+ clif->additem(mvp_sd,0,0,temp);
+ map->addflooritem(&md->bl, &item, 1, mvp_sd->bl.m, mvp_sd->bl.x, mvp_sd->bl.y, mvp_sd->status.char_id, (second_sd?second_sd->status.char_id : 0), (third_sd ? third_sd->status.char_id : 0), 1);
+ }
- if((temp = pc->additem(mvp_sd,&item,1,LOG_TYPE_PICKDROP_PLAYER)) != 0) {
- clif->additem(mvp_sd,0,0,temp);
- map->addflooritem(&md->bl, &item, 1, mvp_sd->bl.m, mvp_sd->bl.x, mvp_sd->bl.y, mvp_sd->status.char_id, (second_sd?second_sd->status.char_id : 0), (third_sd ? third_sd->status.char_id : 0), 1);
+ //Logs items, MVP prizes [Lupus]
+ logs->pick_mob(md, LOG_TYPE_MVP, -1, &item, data);
+ break;
}
-
- //Logs items, MVP prizes [Lupus]
- logs->pick_mob(md, LOG_TYPE_MVP, -1, &item, data);
- break;
}
}
@@ -2661,6 +2717,8 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) {
void mob_revive(struct mob_data *md, unsigned int hp)
{
int64 tick = timer->gettick();
+
+ nullpo_retv(md);
md->state.skillstate = MSS_IDLE;
md->last_thinktime = tick;
md->next_walktime = tick+rnd()%1000+MIN_RANDOMWALKTIME;
@@ -2808,6 +2866,7 @@ int mob_class_change (struct mob_data *md, int class_) {
*------------------------------------------*/
void mob_heal(struct mob_data *md, unsigned int heal)
{
+ nullpo_retv(md);
if (battle_config.show_mob_info&3)
clif->charnameack (0, &md->bl);
#if PACKETVER >= 20131223
@@ -2842,6 +2901,7 @@ int mob_warpslave_sub(struct block_list *bl, va_list ap)
range = va_arg(ap, int);
nullpo_ret(bl);
+ nullpo_ret(master);
Assert_ret(bl->type == BL_MOB);
md = BL_UCAST(BL_MOB, bl);
@@ -2859,6 +2919,7 @@ int mob_warpslave_sub(struct block_list *bl, va_list ap)
* appear in randomly.
*------------------------------------------*/
int mob_warpslave(struct block_list *bl, int range) {
+ nullpo_ret(bl);
if (range < 1)
range = 1; //Min range needed to avoid crashes and stuff. [Skotlex]
@@ -2886,6 +2947,7 @@ int mob_countslave_sub(struct block_list *bl, va_list ap)
* Counts the number of slaves a mob has on the map.
*------------------------------------------*/
int mob_countslave(struct block_list *bl) {
+ nullpo_ret(bl);
return map->foreachinmap(mob->countslave_sub, bl->m, BL_MOB,bl->id);
}
@@ -3014,6 +3076,8 @@ int mob_getfriendhprate_sub(struct block_list *bl,va_list ap)
struct mob_data *md;
md = va_arg(ap,struct mob_data *);
+ nullpo_ret(bl);
+ nullpo_ret(md);
min_rate=va_arg(ap,int);
max_rate=va_arg(ap,int);
fr=va_arg(ap,struct block_list **);
@@ -3324,6 +3388,8 @@ int mobskill_use(struct mob_data *md, int64 tick, int event) {
int mobskill_event(struct mob_data *md, struct block_list *src, int64 tick, int flag) {
int target_id, res = 0;
+ nullpo_ret(md);
+ nullpo_ret(src);
if(md->bl.prev == NULL || md->status.hp <= 0)
return 0;
@@ -3385,7 +3451,7 @@ int mob_clone_spawn(struct map_session_data *sd, int16 m, int16 x, int16 y, cons
return 0;
ARR_FIND( MOB_CLONE_START, MOB_CLONE_END, class_, mob->db_data[class_] == NULL );
- if(class_ >= MOB_CLONE_END)
+ if(class_ < 0 || class_ >= MOB_CLONE_END)
return 0;
db = mob->db_data[class_]=(struct mob_db*)aCalloc(1, sizeof(struct mob_db));
@@ -3575,7 +3641,10 @@ int mob_clone_spawn(struct map_session_data *sd, int16 m, int16 x, int16 y, cons
int mob_clone_delete(struct mob_data *md)
{
- const int class_ = md->class_;
+ int class_;
+
+ nullpo_ret(md);
+ class_ = md->class_;
if (class_ >= MOB_CLONE_START && class_ < MOB_CLONE_END
&& mob->db_data[class_]!=NULL) {
mob->destroy_mob_db(class_);
@@ -3665,6 +3734,7 @@ unsigned int mob_drop_adjust(int baserate, int rate_adjust, unsigned short rate_
*/
void item_dropratio_adjust(int nameid, int mob_id, int *rate_adjust)
{
+ nullpo_retv(rate_adjust);
if( item_drop_ratio_db[nameid] ) {
if( item_drop_ratio_db[nameid]->mob_id[0] ) { // only for listed mobs
int i;
@@ -3699,6 +3769,7 @@ static inline int mob_parse_dbrow_cap_value(int class_, int min, int max, int va
void mob_read_db_stats_sub(struct mob_db *entry, struct config_setting_t *t)
{
int i32;
+ nullpo_retv(entry);
if (mob->lookup_const(t, "Str", &i32) && i32 >= 0) {
entry->status.str = mob_parse_dbrow_cap_value(entry->mob_id, UINT16_MIN, UINT16_MAX, i32);
}
@@ -3782,6 +3853,7 @@ void mob_read_db_mvpdrops_sub(struct mob_db *entry, struct config_setting_t *t)
int idx = 0;
int i32;
+ nullpo_retv(entry);
while (idx < MAX_MVP_DROP && (drop = libconfig->setting_get_elem(t, i))) {
const char *name = config_setting_name(drop);
int rate_adjust = battle_config.item_rate_mvp;
@@ -3839,6 +3911,7 @@ void mob_read_db_drops_sub(struct mob_db *entry, struct config_setting_t *t)
int i32;
int k;
+ nullpo_retv(entry);
while (idx < MAX_MOB_DROP && (drop = libconfig->setting_get_elem(t, i))) {
const char *name = config_setting_name(drop);
int rate_adjust, type;
@@ -3960,6 +4033,7 @@ int mob_db_validate_entry(struct mob_db *entry, int n, const char *source)
{
struct mob_data data;
+ nullpo_ret(entry);
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;
@@ -4393,6 +4467,8 @@ bool mob_lookup_const(const struct config_setting_t *it, const char *name, int *
bool mob_get_const(const struct config_setting_t *it, int *value)
{
const char *str = config_setting_get_string(it);
+
+ nullpo_retr(false, value);
if (str && *str && script->get_constant(str, value))
return true;
@@ -4489,6 +4565,7 @@ bool mob_readdb_mobavail(char* str[], int columns, int current)
{
int class_, k;
+ nullpo_retr(false, str);
class_=atoi(str[0]);
if(mob->db(class_) == mob->dummy) {
@@ -4600,6 +4677,8 @@ bool mob_parse_row_chatdb(char** str, const char* source, int line, int* last_ms
int msg_id;
size_t len;
+ nullpo_retr(false, str);
+ nullpo_retr(false, last_msg_id);
msg_id = atoi(str[0]);
if (msg_id <= 0 || msg_id > MAX_MOB_CHAT)
@@ -4784,6 +4863,7 @@ bool mob_parse_row_mobskilldb(char** str, int columns, int current)
int i =0, j, tmp;
uint16 sidx = 0;
+ nullpo_retr(false, str);
mob_id = atoi(str[0]);
if (mob_id > 0 && mob->db(mob_id) == mob->dummy)
@@ -4999,6 +5079,7 @@ bool mob_readdb_race2(char* fields[], int columns, int current)
{
int race, i;
+ nullpo_retr(false, fields);
race = atoi(fields[0]);
if (race < RC2_NONE || race >= RC2_MAX) {
@@ -5023,6 +5104,8 @@ bool mob_readdb_race2(char* fields[], int columns, int current)
bool mob_readdb_itemratio(char* str[], int columns, int current)
{
int nameid, ratio, i;
+
+ nullpo_retr(false, str);
nameid = atoi(str[0]);
if( itemdb->exists(nameid) == NULL )
@@ -5124,7 +5207,9 @@ int do_init_mob(bool minimal) {
void mob_destroy_mob_db(int index)
{
- struct mob_db *data = mob->db_data[index];
+ struct mob_db *data;
+ Assert_retv(index >= 0 && index <= MAX_MOB_DB);
+ data = mob->db_data[index];
HPM->data_store_destroy(&data->hdata);
aFree(data);
mob->db_data[index] = NULL;
diff --git a/src/map/npc.c b/src/map/npc.c
index 2b1a541d8..6b55bf5ae 100644
--- a/src/map/npc.c
+++ b/src/map/npc.c
@@ -47,6 +47,7 @@
#include "common/nullpo.h"
#include "common/showmsg.h"
#include "common/socket.h"
+#include "common/sql.h"
#include "common/strlib.h"
#include "common/timer.h"
#include "common/utils.h"
@@ -61,17 +62,6 @@
struct npc_interface npc_s;
struct npc_interface *npc;
-static int npc_id=START_NPC_NUM;
-static int npc_warp=0;
-static int npc_shop=0;
-static int npc_script=0;
-static int npc_mob=0;
-static int npc_delay_mob=0;
-static int npc_cache_mob=0;
-
-static const char *npc_last_path;
-static const char *npc_last_ref;
-struct npc_path_data *npc_last_npd;
//For holding the view data of npc classes. [Skotlex]
static struct view_data npc_viewdb[MAX_NPC_CLASS];
@@ -131,15 +121,15 @@ bool npc_db_checkid(int id)
/// Returns a new npc id that isn't being used in id_db.
/// Fatal error if nothing is available.
int npc_get_new_npc_id(void) {
- if( npc_id >= START_NPC_NUM && !map->blid_exists(npc_id) )
- return npc_id++;// available
+ if (npc->npc_id >= START_NPC_NUM && !map->blid_exists(npc->npc_id))
+ return npc->npc_id++;// available
else {// find next id
- int base_id = npc_id;
- while( base_id != ++npc_id ) {
- if( npc_id < START_NPC_NUM )
- npc_id = START_NPC_NUM;
- if( !map->blid_exists(npc_id) )
- return npc_id++;// available
+ int base_id = npc->npc_id;
+ while (base_id != ++npc->npc_id) {
+ if (npc->npc_id < START_NPC_NUM)
+ npc->npc_id = START_NPC_NUM;
+ if (!map->blid_exists(npc->npc_id))
+ return npc->npc_id++;// available
}
// full loop, nothing available
ShowFatalError("npc_get_new_npc_id: All ids are taken. Exiting...");
@@ -176,6 +166,7 @@ int npc_ontouch_event(struct map_session_data *sd, struct npc_data *nd)
{
char name[EVENT_NAME_LENGTH];
+ nullpo_retr(1, nd);
if( nd->touching_id )
return 0; // Attached a player already. Can't trigger on anyone else.
@@ -190,6 +181,8 @@ int npc_ontouch2_event(struct map_session_data *sd, struct npc_data *nd)
{
char name[EVENT_NAME_LENGTH];
+ nullpo_retr(1, sd);
+ nullpo_retr(1, nd);
if (sd->areanpc_id == nd->bl.id)
return 0;
@@ -201,6 +194,8 @@ int npc_onuntouch_event(struct map_session_data *sd, struct npc_data *nd)
{
char name[EVENT_NAME_LENGTH];
+ nullpo_ret(sd);
+ nullpo_ret(nd);
if (sd->areanpc_id != nd->bl.id)
return 0;
@@ -366,7 +361,7 @@ int npc_event_dequeue(struct map_session_data* sd)
/**
* @see DBCreateData
*/
-DBData npc_event_export_create(DBKey key, va_list args)
+struct DBData npc_event_export_create(union DBKey key, va_list args)
{
struct linkdb_node** head_ptr;
CREATE(head_ptr, struct linkdb_node*, 1);
@@ -380,8 +375,12 @@ DBData npc_event_export_create(DBKey key, va_list args)
*------------------------------------------*/
int npc_event_export(struct npc_data *nd, int i)
{
- char* lname = nd->u.scr.label_list[i].name;
- int pos = nd->u.scr.label_list[i].pos;
+ char* lname;
+ int pos;
+ nullpo_ret(nd);
+ Assert_ret(i >= 0 && i < nd->u.scr.label_list_num);
+ lname = nd->u.scr.label_list[i].name;
+ pos = nd->u.scr.label_list[i].pos;
if ((lname[0] == 'O' || lname[0] == 'o') && (lname[1] == 'N' || lname[1] == 'n')) {
struct event_data *ev;
struct linkdb_node **label_linkdb = NULL;
@@ -434,6 +433,7 @@ void npc_event_doall_sub(void *key, void *data, va_list ap)
// runs the specified event (supports both single-npc and global events)
int npc_event_do(const char* name)
{
+ nullpo_ret(name);
if( name[0] == ':' && name[1] == ':' ) {
return npc->event_doall(name+2); // skip leading "::"
}
@@ -538,9 +538,12 @@ void npc_event_do_oninit( bool reload )
int npc_timerevent_export(struct npc_data *nd, int i)
{
int t = 0, len = 0;
- char *lname = nd->u.scr.label_list[i].name;
- int pos = nd->u.scr.label_list[i].pos;
- if (sscanf(lname, "OnTimer%d%n", &t, &len) == 1 && lname[len] == '\0') {
+ char *lname;
+ int pos;
+ nullpo_ret(nd);
+ lname = nd->u.scr.label_list[i].name;
+ pos = nd->u.scr.label_list[i].pos;
+ if (sscanf(lname, "OnTimer%d%n", &t, &len) == 1 && len < NAME_LENGTH && lname[len] == '\0') {
// Timer event
struct npc_timerevent_list *te = nd->u.scr.timer_event;
int j, k = nd->u.scr.timeramount;
@@ -580,6 +583,8 @@ int npc_timerevent(int tid, int64 tick, int id, intptr_t data)
struct timer_event_data *ted = (struct timer_event_data*)data;
struct map_session_data *sd=NULL;
+ nullpo_ret(ted);
+
if( nd == NULL ) {
ShowError("npc_timerevent: NPC not found??\n");
return 0;
@@ -732,6 +737,7 @@ void npc_timerevent_quit(struct map_session_data* sd)
struct npc_data* nd;
struct timer_event_data *ted;
+ nullpo_retv(sd);
// Check timer existence
if( sd->npc_timer_id == INVALID_TIMER )
return;
@@ -763,6 +769,7 @@ void npc_timerevent_quit(struct map_session_data* sd)
{
int old_rid,old_timer;
int64 old_tick;
+ nullpo_retv(ted);
//Set timer related info.
old_rid = (nd->u.scr.rid == sd->bl.id ? 0 : nd->u.scr.rid); // Detach rid if the last attached player logged off.
@@ -831,6 +838,8 @@ int npc_settimerevent_tick(struct npc_data* nd, int newtimer)
int npc_event_sub(struct map_session_data* sd, struct event_data* ev, const char* eventname)
{
+ nullpo_retr(2, sd);
+ nullpo_retr(2, eventname);
if ( sd->npc_id != 0 )
{
//Enqueue the event trigger.
@@ -915,9 +924,11 @@ int npc_touch_areanpc_sub(struct block_list *bl, va_list ap) {
* If not, it unsets it and searches for another player in range.
*------------------------------------------*/
int npc_touchnext_areanpc(struct map_session_data* sd, bool leavemap) {
- struct npc_data *nd = map->id2nd(sd->touching_id);
+ struct npc_data *nd;
short xs, ys;
+ nullpo_retr(1, sd);
+ nd = map->id2nd(sd->touching_id);
if( !nd || nd->touching_id != sd->bl.id )
return 1;
@@ -949,7 +960,7 @@ int npc_touch_areanpc(struct map_session_data* sd, int16 m, int16 x, int16 y)
int j, found_warp = 0;
nullpo_retr(1, sd);
-
+ Assert_retr(1, m >= 0 && m < map->count);
#if 0 // Why not enqueue it? [Inkfish]
if(sd->npc_id)
return 1;
@@ -1034,6 +1045,7 @@ int npc_untouch_areanpc(struct map_session_data* sd, int16 m, int16 x, int16 y)
{
struct npc_data *nd = NULL;
nullpo_retr(1, sd);
+ Assert_retr(1, m >= 0 && m < map->count);
if (!sd->areanpc_id)
return 0;
@@ -1053,11 +1065,16 @@ int npc_untouch_areanpc(struct map_session_data* sd, int16 m, int16 x, int16 y)
// Return 1 if Warped
int npc_touch_areanpc2(struct mob_data *md)
{
- int i, m = md->bl.m, x = md->bl.x, y = md->bl.y, id;
+ int i, m, x, y, id;
char eventname[EVENT_NAME_LENGTH];
struct event_data* ev;
int xs, ys;
+ nullpo_ret(md);
+ m = md->bl.m;
+ x = md->bl.x;
+ y = md->bl.y;
+
for( i = 0; i < map->list[m].npc_num; i++ ) {
if( map->list[m].npc[i]->option&OPTION_INVISIBLE )
continue;
@@ -1116,6 +1133,8 @@ int npc_check_areanpc(int flag, int16 m, int16 x, int16 y, int16 range) {
int x0,y0,x1,y1;
int xs,ys;
+ Assert_retr(1, m >= 0 && m < map->count);
+
if (range < 0) return 0;
x0 = max(x-range, 0);
y0 = max(y-range, 0);
@@ -1187,6 +1206,7 @@ struct npc_data* npc_checknear(struct map_session_data* sd, struct block_list* b
if (distance > nd->area_size)
distance = nd->area_size;
+ nullpo_retr(NULL, bl);
if (bl->m != sd->bl.m ||
bl->x < sd->bl.x - distance || bl->x > sd->bl.x + distance ||
bl->y < sd->bl.y - distance || bl->y > sd->bl.y + distance)
@@ -1208,6 +1228,9 @@ int npc_globalmessage(const char* name, const char* mes)
if (!nd)
return 0;
+ nullpo_ret(name);
+ nullpo_ret(mes);
+
snprintf(temp, sizeof(temp), "%s : %s", name, mes);
clif->GlobalMessage(&nd->bl,temp);
@@ -1219,6 +1242,7 @@ void run_tomb(struct map_session_data* sd, struct npc_data* nd) {
char buffer[200];
char time[10];
+ nullpo_retv(nd);
strftime(time, sizeof(time), "%H:%M", localtime(&nd->u.tomb.kill_time));
// TODO: Find exact color?
@@ -1393,6 +1417,8 @@ int npc_cashshop_buylist(struct map_session_data *sd, int points, struct itemlis
struct npc_item_list *shop = NULL;
unsigned short shop_size = 0;
+ nullpo_retr(ERROR_TYPE_SYSTEM, sd);
+ nullpo_retr(ERROR_TYPE_SYSTEM, item_list);
if( sd->state.trading )
return ERROR_TYPE_EXCHANGE;
@@ -1492,6 +1518,9 @@ int npc_buylist_sub(struct map_session_data *sd, struct itemlist *item_list, str
int key_nameid = 0;
int key_amount = 0;
+ nullpo_ret(item_list);
+ nullpo_ret(nd);
+
// discard old contents
script->cleararray_pc(sd, "@bought_nameid", (void*)0);
script->cleararray_pc(sd, "@bought_quantity", (void*)0);
@@ -1514,8 +1543,9 @@ int npc_buylist_sub(struct map_session_data *sd, struct itemlist *item_list, str
/**
* Loads persistent NPC Market Data from SQL
**/
-void npc_market_fromsql(void) {
- SqlStmt* stmt = SQL->StmtMalloc(map->mysql_handle);
+void npc_market_fromsql(void)
+{
+ struct SqlStmt *stmt = SQL->StmtMalloc(map->mysql_handle);
char name[NAME_LENGTH+1];
int itemid;
int amount;
@@ -1565,6 +1595,8 @@ void npc_market_fromsql(void) {
* Saves persistent NPC Market Data into SQL
**/
void npc_market_tosql(struct npc_data *nd, unsigned short index) {
+ nullpo_retv(nd);
+ Assert_retv(index < nd->u.scr.shop->items);
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);
@@ -1586,12 +1618,16 @@ void npc_market_delfromsql_sub(const char *npcname, unsigned short index) {
* Removes persistent NPC Market Data from SQL
**/
void npc_market_delfromsql(struct npc_data *nd, unsigned short index) {
+ nullpo_retv(nd);
+ Assert_retv(index == USHRT_MAX || index < nd->u.scr.shop->items);
npc->market_delfromsql_sub(nd->exname, index == USHRT_MAX ? index : nd->u.scr.shop->item[index].nameid);
}
/**
* Judges whether to allow and spawn a trader's window.
**/
bool npc_trader_open(struct map_session_data *sd, struct npc_data *nd) {
+ nullpo_retr(false, sd);
+ nullpo_retr(false, nd);
if( !nd->u.scr.shop || !nd->u.scr.shop->items )
return false;
@@ -1630,7 +1666,7 @@ bool npc_trader_open(struct map_session_data *sd, struct npc_data *nd) {
* @param master id of the original npc
**/
void npc_trader_update(int master) {
- DBIterator* iter;
+ struct DBIterator *iter;
struct block_list* bl;
struct npc_data *master_nd = map->id2nd(master);
@@ -1657,6 +1693,9 @@ void npc_trader_count_funds(struct npc_data *nd, struct map_session_data *sd) {
char evname[EVENT_NAME_LENGTH];
struct event_data *ev = NULL;
+ nullpo_retv(nd);
+ nullpo_retv(sd);
+
npc->trader_funds[0] = npc->trader_funds[1] = 0;/* clear */
switch( nd->u.scr.shop->type ) {
@@ -1694,6 +1733,8 @@ bool npc_trader_pay(struct npc_data *nd, struct map_session_data *sd, int price,
char evname[EVENT_NAME_LENGTH];
struct event_data *ev = NULL;
+ nullpo_retr(false, nd);
+ nullpo_retr(false, sd);
npc->trader_ok = false;/* clear */
snprintf(evname, EVENT_NAME_LENGTH, "%s::OnPayFunds",nd->exname);
@@ -1716,6 +1757,7 @@ int npc_cashshop_buy(struct map_session_data *sd, int nameid, int amount, int po
int i, price, w;
unsigned short shop_size = 0;
+ nullpo_retr(ERROR_TYPE_SYSTEM, sd);
if( amount <= 0 )
return ERROR_TYPE_ITEM_ID;
@@ -2055,6 +2097,10 @@ int npc_selllist_sub(struct map_session_data *sd, struct itemlist *item_list, st
int key_identify = 0;
int key_card[MAX_SLOTS];
+ nullpo_ret(sd);
+ nullpo_ret(item_list);
+ nullpo_ret(nd);
+
// discard old contents
script->cleararray_pc(sd, "@sold_nameid", (void*)0);
script->cleararray_pc(sd, "@sold_quantity", (void*)0);
@@ -2222,7 +2268,7 @@ int npc_remove_map(struct npc_data* nd) {
/**
* @see DBApply
*/
-int npc_unload_ev(DBKey key, DBData *data, va_list ap)
+int npc_unload_ev(union DBKey key, struct DBData *data, va_list ap)
{
struct event_data* ev = DB->data2ptr(data);
char* npcname = va_arg(ap, char *);
@@ -2237,7 +2283,7 @@ int npc_unload_ev(DBKey key, DBData *data, va_list ap)
/**
* @see DBApply
*/
-int npc_unload_ev_label(DBKey key, DBData *data, va_list ap)
+int npc_unload_ev_label(union DBKey key, struct DBData *data, va_list ap)
{
struct linkdb_node **label_linkdb = DB->data2ptr(data);
struct npc_data* nd = va_arg(ap, struct npc_data *);
@@ -2253,6 +2299,7 @@ int npc_unload_dup_sub(struct npc_data* nd, va_list args)
{
int src_id;
+ nullpo_ret(nd);
src_id = va_arg(args, int);
if (nd->src_id == src_id)
npc->unload(nd, true);
@@ -2261,6 +2308,7 @@ int npc_unload_dup_sub(struct npc_data* nd, va_list args)
//Removes all npcs that are duplicates of the passed one. [Skotlex]
void npc_unload_duplicates(struct npc_data* nd) {
+ nullpo_retv(nd);
map->foreachnpc(npc->unload_dup_sub,nd->bl.id);
}
@@ -2384,6 +2432,7 @@ void npc_addsrcfile(const char* name)
struct npc_src_list* file;
struct npc_src_list* file_prev = NULL;
+ nullpo_retv(name);
if( strcmpi(name, "clear") == 0 )
{
npc->clearsrcfile();
@@ -2415,6 +2464,7 @@ void npc_delsrcfile(const char* name)
struct npc_src_list* file = npc->src_files;
struct npc_src_list* file_prev = NULL;
+ nullpo_retv(name);
if( strcmpi(name, "all") == 0 )
{
npc->clearsrcfile();
@@ -2448,10 +2498,10 @@ const char *npc_retainpathreference(const char *filepath)
struct npc_path_data * npd = NULL;
nullpo_ret(filepath);
- if (npc_last_path == filepath) {
- if (npc_last_npd != NULL)
- npc_last_npd->references++;
- return npc_last_ref;
+ if (npc->npc_last_path == filepath) {
+ if (npc->npc_last_npd != NULL)
+ npc->npc_last_npd->references++;
+ return npc->npc_last_ref;
}
if ((npd = strdb_get(npc->path_db,filepath)) == NULL) {
@@ -2466,9 +2516,9 @@ const char *npc_retainpathreference(const char *filepath)
npd->references++;
- npc_last_npd = npd;
- npc_last_ref = npd->path;
- npc_last_path = filepath;
+ npc->npc_last_npd = npd;
+ npc->npc_last_ref = npd->path;
+ npc->npc_last_path = filepath;
return npd->path;
}
@@ -2484,7 +2534,7 @@ void npc_releasepathreference(const char *filepath)
nullpo_retv(filepath);
- if (filepath != npc_last_ref) {
+ if (filepath != npc->npc_last_ref) {
npd = strdb_get(npc->path_db, filepath);
}
@@ -2502,6 +2552,8 @@ void npc_parsename(struct npc_data* nd, const char* name, const char* start, con
struct npc_data* dnd;// duplicate npc
char newname[NAME_LENGTH];
+ nullpo_retv(nd);
+ nullpo_retv(name);
// parse name
p = strstr(name,"::");
if( p ) { // <Display name>::<Unique name>
@@ -2557,6 +2609,7 @@ int npc_parseview(const char* w4, const char* start, const char* buffer, const c
int val = FAKE_NPC, i = 0;
char viewid[1024]; // Max size of name from constants.conf, see script->read_constdb.
+ nullpo_retr(FAKE_NPC, w4);
// Extract view ID / constant
while (w4[i] != '\0') {
if (ISSPACE(w4[i]) || w4[i] == '/' || w4[i] == ',')
@@ -2588,6 +2641,7 @@ int npc_parseview(const char* w4, const char* start, const char* buffer, const c
// Checks if given view is an ID or constant.
bool npc_viewisid(const char * viewid)
{
+ nullpo_retr(false, viewid);
if (atoi(viewid) != FAKE_NPC) {
// Loop through view, looking for non-numeric character.
while (*viewid) {
@@ -2634,6 +2688,8 @@ struct npc_data* npc_add_warp(char* name, short from_mapid, short from_x, short
int i, flag = 0;
struct npc_data *nd;
+ nullpo_retr(NULL, name);
+
nd = npc->create_npc(WARP, from_mapid, from_x, from_y, 0, battle_config.warp_point_debug ? WARP_DEBUG_CLASS : WARP_CLASS);
safestrncpy(nd->exname, name, ARRAYLENGTH(nd->exname));
@@ -2682,6 +2738,9 @@ const char *npc_parse_warp(const char *w1, const char *w2, const char *w3, const
char mapname[32], to_mapname[32];
struct npc_data *nd;
+ nullpo_retr(strchr(start,'\n'), w1);
+ nullpo_retr(strchr(start,'\n'), w4);
+
// w1=<from map name>,<fromX>,<fromY>,<facing>
// w4=<spanx>,<spany>,<to map name>,<toX>,<toY>
if( sscanf(w1, "%31[^,],%d,%d", mapname, &x, &y) != 3
@@ -2715,7 +2774,7 @@ const char *npc_parse_warp(const char *w1, const char *w2, const char *w3, const
nd->u.warp.y = to_y;
nd->u.warp.xs = xs;
nd->u.warp.ys = ys;
- npc_warp++;
+ npc->npc_warp++;
npc->add_to_location(nd);
@@ -2753,6 +2812,8 @@ const char *npc_parse_shop(const char *w1, const char *w2, const char *w3, const
struct npc_data *nd;
enum npc_subtype type;
+ nullpo_retr(strchr(start,'\n'), w1);
+ nullpo_retr(strchr(start,'\n'), w4);
if( strcmp(w1,"-") == 0 ) {
// 'floating' shop
x = y = dir = 0;
@@ -2858,7 +2919,7 @@ const char *npc_parse_shop(const char *w1, const char *w2, const char *w3, const
npc->parsename(nd, w3, start, buffer, filepath);
nd->path = npc->retainpathreference(filepath);
- ++npc_shop;
+ ++npc->npc_shop;
npc->add_to_location(nd);
return strchr(start,'\n');// continue
@@ -2867,6 +2928,7 @@ const char *npc_parse_shop(const char *w1, const char *w2, const char *w3, const
void npc_convertlabel_db(struct npc_label_list* label_list, const char *filepath) {
int i;
+ nullpo_retv(label_list);
for( i = 0; i < script->label_count; i++ ) {
const char* lname = script->get_str(script->labels[i].key);
int lpos = script->labels[i].pos;
@@ -2993,6 +3055,7 @@ const char *npc_parse_script(const char *w1, const char *w2, const char *w3, con
int label_list_num;
struct npc_data* nd;
+ nullpo_retr(NULL, w1);
if (strcmp(w1, "-") == 0) {
// floating npc
x = 0;
@@ -3062,7 +3125,7 @@ const char *npc_parse_script(const char *w1, const char *w2, const char *w3, con
if( options&NPO_TRADER )
nd->u.scr.trader = true;
nd->u.scr.shop = NULL;
- ++npc_script;
+ ++npc->npc_script;
npc->add_to_location(nd);
//-----------------------------------------
@@ -3129,7 +3192,10 @@ bool npc_duplicate_script_sub(struct npc_data *nd, const struct npc_data *snd, i
int i;
bool retval = true;
- ++npc_script;
+ nullpo_retr(false, nd);
+ nullpo_retr(false, snd);
+
+ ++npc->npc_script;
nd->u.scr.xs = xs;
nd->u.scr.ys = ys;
nd->u.scr.script = snd->u.scr.script;
@@ -3173,7 +3239,10 @@ bool npc_duplicate_script_sub(struct npc_data *nd, const struct npc_data *snd, i
*/
bool npc_duplicate_shop_sub(struct npc_data *nd, const struct npc_data *snd, int xs, int ys, int options)
{
- ++npc_shop;
+ nullpo_retr(false, nd);
+ nullpo_retr(false, snd);
+
+ ++npc->npc_shop;
nd->u.shop.shop_item = snd->u.shop.shop_item;
nd->u.shop.count = snd->u.shop.count;
@@ -3188,7 +3257,10 @@ bool npc_duplicate_shop_sub(struct npc_data *nd, const struct npc_data *snd, int
*/
bool npc_duplicate_warp_sub(struct npc_data *nd, const struct npc_data *snd, int xs, int ys, int options)
{
- ++npc_warp;
+ nullpo_retr(false, nd);
+ nullpo_retr(false, snd);
+
+ ++npc->npc_warp;
nd->u.warp.xs = xs;
nd->u.warp.ys = ys;
nd->u.warp.mapindex = snd->u.warp.mapindex;
@@ -3217,6 +3289,9 @@ bool npc_duplicate_warp_sub(struct npc_data *nd, const struct npc_data *snd, int
*/
bool npc_duplicate_sub(struct npc_data *nd, const struct npc_data *snd, int xs, int ys, int options)
{
+ nullpo_retr(false, nd);
+ nullpo_retr(false, snd);
+
nd->src_id = snd->bl.id;
switch (nd->subtype) {
case SCRIPT:
@@ -3282,6 +3357,8 @@ const char *npc_parse_duplicate(const char *w1, const char *w2, const char *w3,
struct npc_data* dnd;
end = strchr(start,'\n');
+ nullpo_retr(end, w2);
+ nullpo_retr(end, w4);
length = strlen(w2);
// get the npc being duplicated
@@ -3366,7 +3443,13 @@ int npc_duplicate4instance(struct npc_data *snd, int16 m)
int dm = -1, im = -1, xs = -1, ys = -1;
struct npc_data *nd = NULL;
- if( m == -1 || map->list[m].instance_id == -1 )
+ if (m == -1)
+ return 1;
+
+ Assert_retr(1, m >= 0 && m < map->count);
+ nullpo_retr(1, snd);
+
+ if (map->list[m].instance_id == -1)
return 1;
snprintf(newname, ARRAYLENGTH(newname), "dup_%d_%d", map->list[m].instance_id, snd->bl.id);
@@ -3410,10 +3493,15 @@ int npc_duplicate4instance(struct npc_data *snd, int16 m)
}
//Set mapcell CELL_NPC to trigger event later
-void npc_setcells(struct npc_data* nd) {
- int16 m = nd->bl.m, x = nd->bl.x, y = nd->bl.y, xs, ys;
+void npc_setcells(struct npc_data* nd)
+{
+ int16 m, x, y, xs, ys;
int i,j;
+ nullpo_retv(nd);
+ m = nd->bl.m;
+ x = nd->bl.x;
+ y = nd->bl.y;
switch(nd->subtype) {
case WARP:
xs = nd->u.warp.xs;
@@ -3455,9 +3543,13 @@ int npc_unsetcells_sub(struct block_list *bl, va_list ap)
}
void npc_unsetcells(struct npc_data* nd) {
- int16 m = nd->bl.m, x = nd->bl.x, y = nd->bl.y, xs, ys;
+ int16 m, x, y, xs, ys;
int i,j, x0, x1, y0, y1;
+ nullpo_retv(nd);
+ m = nd->bl.m;
+ x = nd->bl.x;
+ y = nd->bl.y;
switch(nd->subtype) {
case WARP:
xs = nd->u.warp.xs;
@@ -3492,7 +3584,9 @@ void npc_unsetcells(struct npc_data* nd) {
void npc_movenpc(struct npc_data* nd, int16 x, int16 y)
{
- const int16 m = nd->bl.m;
+ int16 m;
+ nullpo_retv(nd);
+ m = nd->bl.m;
if (m < 0 || nd->bl.prev == NULL) return; //Not on a map.
x = cap_value(x, 0, map->list[m].xs-1);
@@ -3510,6 +3604,7 @@ void npc_movenpc(struct npc_data* nd, int16 x, int16 y)
void npc_setdisplayname(struct npc_data* nd, const char* newname)
{
nullpo_retv(nd);
+ nullpo_retv(newname);
safestrncpy(nd->name, newname, sizeof(nd->name));
if( map->list[nd->bl.m].users )
@@ -3544,6 +3639,7 @@ int npc_do_atcmd_event(struct map_session_data* sd, const char* command, const c
size_t len;
nullpo_ret(sd);
+ nullpo_ret(message);
if( ev == NULL || (nd = ev->nd) == NULL ) {
ShowError("npc_event: event not found [%s]\n", eventname);
@@ -3567,7 +3663,7 @@ int npc_do_atcmd_event(struct map_session_data* sd, const char* command, const c
}
st = script->alloc_state(ev->nd->u.scr.script, ev->pos, sd->bl.id, ev->nd->bl.id);
- script->setd_sub(st, NULL, ".@atcmd_command$", 0, (void *)command, NULL);
+ script->setd_sub(st, NULL, ".@atcmd_command$", 0, command, NULL);
len = strlen(message);
if (len) {
@@ -3623,12 +3719,19 @@ int npc_do_atcmd_event(struct map_session_data* sd, const char* command, const c
*/
const char *npc_parse_function(const char *w1, const char *w2, const char *w3, const char *w4, const char *start, const char *buffer, const char *filepath, int *retval)
{
- DBMap* func_db;
- DBData old_data;
+ struct DBMap *func_db;
+ struct DBData old_data;
struct script_code *scriptroot;
const char* end;
const char* script_start;
+ nullpo_retr(NULL, w1);
+ nullpo_retr(NULL, w2);
+ nullpo_retr(NULL, w3);
+ nullpo_retr(NULL, w4);
+ nullpo_retr(NULL, start);
+ nullpo_retr(NULL, retval);
+
script_start = strstr(start,"\t{");
end = strchr(start,'\n');
if( *w4 != '{' || script_start == NULL || (end != NULL && script_start > end) ) {
@@ -3672,6 +3775,7 @@ void npc_parse_mob2(struct spawn_data* mobspawn)
{
int i;
+ nullpo_retv(mobspawn);
for( i = mobspawn->active; i < mobspawn->num; ++i ) {
struct mob_data* md = mob->spawn_dataset(mobspawn);
md->spawn = mobspawn;
@@ -3705,6 +3809,11 @@ const char *npc_parse_mob(const char *w1, const char *w2, const char *w3, const
struct spawn_data mobspawn, *data;
struct mob_db* db;
+ nullpo_retr(strchr(start,'\n'), w1);
+ nullpo_retr(strchr(start,'\n'), w2);
+ nullpo_retr(strchr(start,'\n'), w3);
+ nullpo_retr(strchr(start,'\n'), w4);
+
memset(&mobspawn, 0, sizeof(struct spawn_data));
mobspawn.state.boss = (strcmp(w2,"boss_monster") == 0 ? 1 : 0);
@@ -3847,7 +3956,7 @@ const char *npc_parse_mob(const char *w1, const char *w2, const char *w3, const
// spawn / cache the new mobs
if( battle_config.dynamic_mobs && map->addmobtolist(data->m, data) >= 0 ) {
data->state.dynamic = true;
- npc_cache_mob += data->num;
+ npc->npc_cache_mob += data->num;
// check if target map has players
// (usually shouldn't occur when map server is just starting,
@@ -3858,10 +3967,10 @@ const char *npc_parse_mob(const char *w1, const char *w2, const char *w3, const
} else {
data->state.dynamic = false;
npc->parse_mob2(data);
- npc_delay_mob += data->num;
+ npc->npc_delay_mob += data->num;
}
- npc_mob++;
+ npc->npc_mob++;
return strchr(start,'\n');// continue
}
@@ -3911,6 +4020,9 @@ const char *npc_parse_mapflag(const char *w1, const char *w2, const char *w3, co
char mapname[32];
int state = 1;
+ nullpo_retr(strchr(start,'\n'), w1);
+ nullpo_retr(strchr(start,'\n'), w3);
+
// w1=<mapname>
if( sscanf(w1, "%31[^,]", mapname) != 1 )
{
@@ -4335,6 +4447,7 @@ const char *npc_parse_mapflag(const char *w1, const char *w2, const char *w3, co
*/
const char *npc_parse_unknown_object(const char *w1, const char *w2, const char *w3, const char *w4, const char *start, const char *buffer, const char *filepath, int *retval)
{
+ nullpo_retr(start, retval);
ShowError("npc_parsesrcfile: Unable to parse, probably a missing or extra TAB in file '%s', line '%d'. Skipping line...\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4);
start = strchr(start,'\n');// skip and continue
*retval = EXIT_FAILURE;
@@ -4359,6 +4472,8 @@ int npc_parsesrcfile(const char* filepath, bool runOnInit) {
char* buffer;
const char* p;
+ nullpo_retr(EXIT_FAILURE, filepath);
+
// read whole file to buffer
fp = fopen(filepath, "rb");
if( fp == NULL ) {
@@ -4567,11 +4682,10 @@ void npc_read_event_script(void)
{"Kill NPC Event",script->config.kill_mob_event_name},
};
- for (i = 0; i < NPCE_MAX; i++)
- {
- DBIterator* iter;
- DBKey key;
- DBData *data;
+ for (i = 0; i < NPCE_MAX; i++) {
+ struct DBIterator *iter;
+ union DBKey key;
+ struct DBData *data;
char name[64]="::";
safestrncpy(name+2,config[i].event_name,62);
@@ -4614,9 +4728,10 @@ void npc_read_event_script(void)
/**
* @see DBApply
*/
-int npc_path_db_clear_sub(DBKey key, DBData *data, va_list args)
+int npc_path_db_clear_sub(union DBKey key, struct DBData *data, va_list args)
{
struct npc_path_data *npd = DB->data2ptr(data);
+ nullpo_ret(npd);
if (npd->path)
aFree(npd->path);
return 0;
@@ -4625,7 +4740,7 @@ int npc_path_db_clear_sub(DBKey key, DBData *data, va_list args)
/**
* @see DBApply
*/
-int npc_ev_label_db_clear_sub(DBKey key, DBData *data, va_list args)
+int npc_ev_label_db_clear_sub(union DBKey key, struct DBData *data, va_list args)
{
struct linkdb_node **label_linkdb = DB->data2ptr(data);
linkdb_final(label_linkdb); // linked data (struct event_data*) is freed when clearing ev_db
@@ -4652,12 +4767,12 @@ void npc_process_files( int npc_min ) {
"\t-'"CL_WHITE"%d"CL_RESET"' Spawn sets\n"
"\t-'"CL_WHITE"%d"CL_RESET"' Mobs Cached\n"
"\t-'"CL_WHITE"%d"CL_RESET"' Mobs Not Cached\n",
- npc_id - npc_min, npc_warp, npc_shop, npc_script, npc_mob, npc_cache_mob, npc_delay_mob);
+ npc->npc_id - npc_min, npc->npc_warp, npc->npc_shop, npc->npc_script, npc->npc_mob, npc->npc_cache_mob, npc->npc_delay_mob);
}
//Clear then reload npcs files
int npc_reload(void) {
- int npc_new_min = npc_id;
+ int npc_new_min = npc->npc_id;
struct s_mapiterator* iter;
struct block_list* bl;
@@ -4673,9 +4788,9 @@ int npc_reload(void) {
db_clear(npc->ev_db);
npc->ev_label_db->clear(npc->ev_label_db, npc->ev_label_db_clear_sub);
- npc_last_npd = NULL;
- npc_last_path = NULL;
- npc_last_ref = NULL;
+ npc->npc_last_npd = NULL;
+ npc->npc_last_path = NULL;
+ npc->npc_last_ref = NULL;
//Remove all npcs/mobs. [Skotlex]
iter = mapit_geteachiddb();
@@ -4715,8 +4830,8 @@ int npc_reload(void) {
// clear mob spawn lookup index
mob->clear_spawninfo();
- npc_warp = npc_shop = npc_script = 0;
- npc_mob = npc_cache_mob = npc_delay_mob = 0;
+ npc->npc_warp = npc->npc_shop = npc->npc_script = 0;
+ npc->npc_mob = npc->npc_cache_mob = npc->npc_delay_mob = 0;
// reset mapflags
map->flags_init();
@@ -4754,11 +4869,14 @@ int npc_reload(void) {
}
//Unload all npc in the given file
-bool npc_unloadfile( const char* filepath ) {
- DBIterator * iter = db_iterator(npc->name_db);
+bool npc_unloadfile(const char *filepath)
+{
+ struct DBIterator *iter = db_iterator(npc->name_db);
struct npc_data* nd = NULL;
bool found = false;
+ nullpo_retr(false, filepath);
+
for( nd = dbi_first(iter); dbi_exists(iter); nd = dbi_next(iter) ) {
if( nd->path && strcasecmp(nd->path,filepath) == 0 ) { // FIXME: This can break in case-sensitive file systems
found = true;
@@ -4797,6 +4915,9 @@ int do_final_npc(void) {
void npc_debug_warps_sub(struct npc_data* nd) {
int16 m;
+
+ nullpo_retv(nd);
+
if (nd->bl.type != BL_NPC || nd->subtype != WARP || nd->bl.m < 0)
return;
@@ -4833,14 +4954,8 @@ static void npc_debug_warps(void) {
int do_init_npc(bool minimal) {
int i;
- memset(&npc->base_ud, 0, sizeof( struct unit_data) );
- npc->base_ud.bl = NULL;
- npc->base_ud.walktimer = INVALID_TIMER;
- npc->base_ud.skilltimer = INVALID_TIMER;
- npc->base_ud.attacktimer = INVALID_TIMER;
- npc->base_ud.attackabletime =
- npc->base_ud.canact_tick =
- npc->base_ud.canmove_tick = timer->gettick();
+ unit->init_ud(&npc->base_ud);
+ npc->base_ud.bl = NULL;
//Stock view data for normal npcs.
memset(&npc_viewdb, 0, sizeof(npc_viewdb));
@@ -4856,9 +4971,9 @@ int do_init_npc(bool minimal) {
npc->name_db = strdb_alloc(DB_OPT_BASE, NAME_LENGTH);
npc->path_db = strdb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA, 0);
- npc_last_npd = NULL;
- npc_last_path = NULL;
- npc_last_ref = NULL;
+ npc->npc_last_npd = NULL;
+ npc->npc_last_path = NULL;
+ npc->npc_last_ref = NULL;
// Should be loaded before npc processing, otherwise labels could overwrite constant values
// and lead to undefined behavior [Panikon]
@@ -4902,7 +5017,7 @@ int do_init_npc(bool minimal) {
strcpy(npc->fake_nd->name,"FAKE_NPC");
memcpy(npc->fake_nd->exname, npc->fake_nd->name, 9);
- npc_script++;
+ npc->npc_script++;
npc->fake_nd->bl.type = BL_NPC;
npc->fake_nd->subtype = SCRIPT;
@@ -4916,6 +5031,17 @@ int do_init_npc(bool minimal) {
void npc_defaults(void) {
npc = &npc_s;
+ npc->npc_id = START_NPC_NUM;
+ npc->npc_warp = 0;
+ npc->npc_shop = 0;
+ npc->npc_script = 0;
+ npc->npc_mob = 0;
+ npc->npc_delay_mob = 0;
+ npc->npc_cache_mob = 0;
+ npc->npc_last_path = NULL;
+ npc->npc_last_ref = NULL;
+ npc->npc_last_npd = NULL;
+
npc->motd = NULL;
npc->ev_db = NULL;
npc->ev_label_db = NULL;
diff --git a/src/map/npc.h b/src/map/npc.h
index 965a34f94..24ea9ea59 100644
--- a/src/map/npc.h
+++ b/src/map/npc.h
@@ -177,10 +177,10 @@ struct npc_path_data {
struct npc_interface {
/* */
struct npc_data *motd;
- DBMap *ev_db; // const char* event_name -> struct event_data*
- DBMap *ev_label_db; // const char* label_name (without leading "::") -> struct linkdb_node** (key: struct npc_data*; data: struct event_data*)
- DBMap *name_db; // const char* npc_name -> struct npc_data*
- DBMap *path_db;
+ struct DBMap *ev_db; // const char* event_name -> struct event_data*
+ struct DBMap *ev_label_db; // const char* label_name (without leading "::") -> struct linkdb_node** (key: struct npc_data*; data: struct event_data*)
+ struct DBMap *name_db; // const char* npc_name -> struct npc_data*
+ struct DBMap *path_db;
struct eri *timer_event_ers; //For the npc timer data. [Skotlex]
struct npc_data *fake_nd;
struct npc_src_list *src_files;
@@ -188,6 +188,16 @@ struct npc_interface {
/* npc trader global data, for ease of transition between the script, cleared on every usage */
bool trader_ok;
int trader_funds[2];
+ int npc_id;
+ int npc_warp;
+ int npc_shop;
+ int npc_script;
+ int npc_mob;
+ int npc_delay_mob;
+ int npc_cache_mob;
+ const char *npc_last_path;
+ const char *npc_last_ref;
+ struct npc_path_data *npc_last_npd;
/* */
int (*init) (bool minimal);
int (*final) (void);
@@ -203,7 +213,7 @@ struct npc_interface {
int (*enable) (const char *name, int flag);
struct npc_data* (*name2id) (const char *name);
int (*event_dequeue) (struct map_session_data *sd);
- DBData (*event_export_create) (DBKey key, va_list args);
+ struct DBData (*event_export_create) (union DBKey key, va_list args);
int (*event_export) (struct npc_data *nd, int i);
int (*event_sub) (struct map_session_data *sd, struct event_data *ev, const char *eventname);
void (*event_doall_sub) (void *key, void *data, va_list ap);
@@ -239,8 +249,8 @@ struct npc_interface {
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);
+ int (*unload_ev) (union DBKey key, struct DBData *data, va_list ap);
+ int (*unload_ev_label) (union DBKey key, struct DBData *data, va_list ap);
int (*unload_dup_sub) (struct npc_data *nd, va_list args);
void (*unload_duplicates) (struct npc_data *nd);
int (*unload) (struct npc_data *nd, bool single);
@@ -282,8 +292,8 @@ struct npc_interface {
int (*parsesrcfile) (const char *filepath, bool runOnInit);
int (*script_event) (struct map_session_data *sd, enum npce_event type);
void (*read_event_script) (void);
- int (*path_db_clear_sub) (DBKey key, DBData *data, va_list args);
- int (*ev_label_db_clear_sub) (DBKey key, DBData *data, va_list args);
+ int (*path_db_clear_sub) (union DBKey key, struct DBData *data, va_list args);
+ int (*ev_label_db_clear_sub) (union DBKey key, struct DBData *data, va_list args);
int (*reload) (void);
bool (*unloadfile) (const char *filepath);
void (*do_clear_npc) (void);
diff --git a/src/map/packets_struct.h b/src/map/packets_struct.h
index f23cefb26..e461eebe9 100644
--- a/src/map/packets_struct.h
+++ b/src/map/packets_struct.h
@@ -2,7 +2,7 @@
* This file is part of Hercules.
* http://herc.ws - http://github.com/HerculesWS/Hercules
*
- * Copyright (C) 2013-2015 Hercules Dev Team
+ * Copyright (C) 2013-2016 Hercules Dev Team
*
* Hercules is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -26,6 +26,11 @@
#include "common/cbasetypes.h"
#include "common/mmo.h"
+// Packet DB
+#define MIN_PACKET_DB 0x0064
+#define MAX_PACKET_DB 0x0F00
+#define MAX_PACKET_POS 20
+
/**
*
**/
@@ -307,134 +312,134 @@ enum packet_headers {
* structs for data
*/
struct EQUIPSLOTINFO {
- unsigned short card[4];
+ uint16 card[4];
} __attribute__((packed));
struct NORMALITEM_INFO {
- short index;
- unsigned short ITID;
- unsigned char type;
+ int16 index;
+ uint16 ITID;
+ uint8 type;
#if PACKETVER < 20120925
uint8 IsIdentified;
#endif
- short count;
+ int16 count;
#if PACKETVER >= 20120925
- unsigned int WearState;
+ uint32 WearState;
#else
- unsigned short WearState;
+ uint16 WearState;
#endif
#if PACKETVER >= 5
struct EQUIPSLOTINFO slot;
#endif
#if PACKETVER >= 20080102
- int HireExpireDate;
+ int32 HireExpireDate;
#endif
#if PACKETVER >= 20120925
struct {
- unsigned char IsIdentified : 1;
- unsigned char PlaceETCTab : 1;
- unsigned char SpareBits : 6;
+ uint8 IsIdentified : 1;
+ uint8 PlaceETCTab : 1;
+ uint8 SpareBits : 6;
} Flag;
#endif
} __attribute__((packed));
struct RndOptions {
- short index;
- short value;
- unsigned char param;
+ int16 index;
+ int16 value;
+ uint8 param;
} __attribute__((packed));
struct EQUIPITEM_INFO {
- short index;
- unsigned short ITID;
- unsigned char type;
+ int16 index;
+ uint16 ITID;
+ uint8 type;
#if PACKETVER < 20120925
uint8 IsIdentified;
#endif
#if PACKETVER >= 20120925
- unsigned int location;
- unsigned int WearState;
+ uint32 location;
+ uint32 WearState;
#else
- unsigned short location;
- unsigned short WearState;
+ uint16 location;
+ uint16 WearState;
#endif
#if PACKETVER < 20120925
uint8 IsDamaged;
#endif
- unsigned char RefiningLevel;
+ uint8 RefiningLevel;
struct EQUIPSLOTINFO slot;
#if PACKETVER >= 20071002
- int HireExpireDate;
+ int32 HireExpireDate;
#endif
#if PACKETVER >= 20080102
- unsigned short bindOnEquipType;
+ uint16 bindOnEquipType;
#endif
#if PACKETVER >= 20100629
- unsigned short wItemSpriteNumber;
+ uint16 wItemSpriteNumber;
#endif
#if PACKETVER >= 20150226
- unsigned char option_count;
+ uint8 option_count;
struct RndOptions option_data[5];
#endif
#if PACKETVER >= 20120925
struct {
- unsigned char IsIdentified : 1;
- unsigned char IsDamaged : 1;
- unsigned char PlaceETCTab : 1;
- unsigned char SpareBits : 5;
+ uint8 IsIdentified : 1;
+ uint8 IsDamaged : 1;
+ uint8 PlaceETCTab : 1;
+ uint8 SpareBits : 5;
} Flag;
#endif
} __attribute__((packed));
struct packet_authok {
- short PacketType;
- unsigned int startTime;
- unsigned char PosDir[3];
- unsigned char xSize;
- unsigned char ySize;
+ int16 PacketType;
+ uint32 startTime;
+ uint8 PosDir[3];
+ uint8 xSize;
+ uint8 ySize;
#if PACKETVER >= 20080102
- short font;
+ int16 font;
#endif
#if PACKETVER >= 20141022
- unsigned char sex;
+ uint8 sex;
#endif
} __attribute__((packed));
struct packet_monster_hp {
- short PacketType;
- unsigned int GID;
- int HP;
- int MaxHP;
+ int16 PacketType;
+ uint32 GID;
+ int32 HP;
+ int32 MaxHP;
} __attribute__((packed));
struct packet_sc_notick {
- short PacketType;
- short index;
- unsigned int AID;
- unsigned char state;
+ int16 PacketType;
+ int16 index;
+ uint32 AID;
+ uint8 state;
} __attribute__((packed));
struct packet_additem {
- short PacketType;
- unsigned short Index;
- unsigned short count;
- unsigned short nameid;
+ int16 PacketType;
+ uint16 Index;
+ uint16 count;
+ uint16 nameid;
uint8 IsIdentified;
uint8 IsDamaged;
- unsigned char refiningLevel;
+ uint8 refiningLevel;
struct EQUIPSLOTINFO slot;
#if PACKETVER >= 20120925
- unsigned int location;
+ uint32 location;
#else
- unsigned short location;
+ uint16 location;
#endif
- unsigned char type;
- unsigned char result;
+ uint8 type;
+ uint8 result;
#if PACKETVER >= 20061218
- int HireExpireDate;
+ int32 HireExpireDate;
#endif
#if PACKETVER >= 20071002
- unsigned short bindOnEquipType;
+ uint16 bindOnEquipType;
#endif
#if PACKETVER >= 20150226
struct RndOptions option_data[5];
@@ -442,51 +447,51 @@ struct packet_additem {
} __attribute__((packed));
struct packet_dropflooritem {
- short PacketType;
- unsigned int ITAID;
- unsigned short ITID;
+ int16 PacketType;
+ uint32 ITAID;
+ uint16 ITID;
#if PACKETVER >= 20130000 /* not sure date */
- unsigned short type;
+ uint16 type;
#endif
uint8 IsIdentified;
- short xPos;
- short yPos;
- unsigned char subX;
- unsigned char subY;
- short count;
+ int16 xPos;
+ int16 yPos;
+ uint8 subX;
+ uint8 subY;
+ int16 count;
} __attribute__((packed));
struct packet_idle_unit2 {
#if PACKETVER < 20091103
- short PacketType;
+ int16 PacketType;
#if PACKETVER >= 20071106
- unsigned char objecttype;
-#endif
- unsigned int GID;
- short speed;
- short bodyState;
- short healthState;
- short effectState;
- short job;
- short head;
- short weapon;
- short accessory;
- short shield;
- short accessory2;
- short accessory3;
- short headpalette;
- short bodypalette;
- short headDir;
- unsigned int GUID;
- short GEmblemVer;
- short honor;
- short virtue;
+ uint8 objecttype;
+#endif
+ uint32 GID;
+ int16 speed;
+ int16 bodyState;
+ int16 healthState;
+ int16 effectState;
+ int16 job;
+ int16 head;
+ int16 weapon;
+ int16 accessory;
+ int16 shield;
+ int16 accessory2;
+ int16 accessory3;
+ int16 headpalette;
+ int16 bodypalette;
+ int16 headDir;
+ uint32 GUID;
+ int16 GEmblemVer;
+ int16 honor;
+ int16 virtue;
uint8 isPKModeON;
- unsigned char sex;
- unsigned char PosDir[3];
- unsigned char xSize;
- unsigned char ySize;
- unsigned char state;
- short clevel;
+ uint8 sex;
+ uint8 PosDir[3];
+ uint8 xSize;
+ uint8 ySize;
+ uint8 state;
+ int16 clevel;
#else // ! PACKETVER < 20091103
UNAVAILABLE_STRUCT;
#endif // PACKETVER < 20091103
@@ -494,470 +499,473 @@ struct packet_idle_unit2 {
struct packet_spawn_unit2 {
#if PACKETVER < 20091103
- short PacketType;
+ int16 PacketType;
#if PACKETVER >= 20071106
- unsigned char objecttype;
-#endif
- unsigned int GID;
- short speed;
- short bodyState;
- short healthState;
- short effectState;
- short head;
- short weapon;
- short accessory;
- short job;
- short shield;
- short accessory2;
- short accessory3;
- short headpalette;
- short bodypalette;
- short headDir;
+ uint8 objecttype;
+#endif
+ uint32 GID;
+ int16 speed;
+ int16 bodyState;
+ int16 healthState;
+ int16 effectState;
+ int16 head;
+ int16 weapon;
+ int16 accessory;
+ int16 job;
+ int16 shield;
+ int16 accessory2;
+ int16 accessory3;
+ int16 headpalette;
+ int16 bodypalette;
+ int16 headDir;
uint8 isPKModeON;
- unsigned char sex;
- unsigned char PosDir[3];
- unsigned char xSize;
- unsigned char ySize;
+ uint8 sex;
+ uint8 PosDir[3];
+ uint8 xSize;
+ uint8 ySize;
#else // ! PACKETVER < 20091103
UNAVAILABLE_STRUCT;
#endif // PACKETVER < 20091103
} __attribute__((packed));
struct packet_spawn_unit {
- short PacketType;
+ int16 PacketType;
#if PACKETVER >= 20091103
- short PacketLength;
- unsigned char objecttype;
+ int16 PacketLength;
+ uint8 objecttype;
#endif
#if PACKETVER >= 20131223
- unsigned int AID;
+ uint32 AID;
#endif
- unsigned int GID;
- short speed;
- short bodyState;
- short healthState;
+ uint32 GID;
+ int16 speed;
+ int16 bodyState;
+ int16 healthState;
#if PACKETVER < 20080102
- short effectState;
+ int16 effectState;
#else
- int effectState;
+ int32 effectState;
#endif
- short job;
- short head;
+ int16 job;
+ int16 head;
#if PACKETVER < 7
- short weapon;
+ int16 weapon;
#else
- int weapon;
+ int32 weapon;
#endif
- short accessory;
+ int16 accessory;
#if PACKETVER < 7
- short shield;
+ int16 shield;
#endif
- short accessory2;
- short accessory3;
- short headpalette;
- short bodypalette;
- short headDir;
+ int16 accessory2;
+ int16 accessory3;
+ int16 headpalette;
+ int16 bodypalette;
+ int16 headDir;
#if PACKETVER >= 20101124
- short robe;
+ int16 robe;
#endif
- unsigned int GUID;
- short GEmblemVer;
- short honor;
+ uint32 GUID;
+ int16 GEmblemVer;
+ int16 honor;
#if PACKETVER > 7
- int virtue;
+ int32 virtue;
#else
- short virtue;
+ int16 virtue;
#endif
uint8 isPKModeON;
- unsigned char sex;
- unsigned char PosDir[3];
- unsigned char xSize;
- unsigned char ySize;
- short clevel;
+ uint8 sex;
+ uint8 PosDir[3];
+ uint8 xSize;
+ uint8 ySize;
+ int16 clevel;
#if PACKETVER >= 20080102
- short font;
+ int16 font;
#endif
#if PACKETVER >= 20120221
- int maxHP;
- int HP;
- unsigned char isBoss;
+ int32 maxHP;
+ int32 HP;
+ uint8 isBoss;
#endif
#if PACKETVER >= 20150513
- short body;
+ int16 body;
+ char name[NAME_LENGTH];
#endif
} __attribute__((packed));
struct packet_unit_walking {
- short PacketType;
+ int16 PacketType;
#if PACKETVER >= 20091103
- short PacketLength;
+ int16 PacketLength;
#endif
#if PACKETVER > 20071106
- unsigned char objecttype;
+ uint8 objecttype;
#endif
#if PACKETVER >= 20131223
- unsigned int AID;
+ uint32 AID;
#endif
- unsigned int GID;
- short speed;
- short bodyState;
- short healthState;
+ uint32 GID;
+ int16 speed;
+ int16 bodyState;
+ int16 healthState;
#if PACKETVER < 7
- short effectState;
+ int16 effectState;
#else
- int effectState;
+ int32 effectState;
#endif
- short job;
- short head;
+ int16 job;
+ int16 head;
#if PACKETVER < 7
- short weapon;
+ int16 weapon;
#else
- int weapon;
+ int32 weapon;
#endif
- short accessory;
- unsigned int moveStartTime;
+ int16 accessory;
+ uint32 moveStartTime;
#if PACKETVER < 7
- short shield;
+ int16 shield;
#endif
- short accessory2;
- short accessory3;
- short headpalette;
- short bodypalette;
- short headDir;
+ int16 accessory2;
+ int16 accessory3;
+ int16 headpalette;
+ int16 bodypalette;
+ int16 headDir;
#if PACKETVER >= 20101124
- short robe;
+ int16 robe;
#endif
- unsigned int GUID;
- short GEmblemVer;
- short honor;
+ uint32 GUID;
+ int16 GEmblemVer;
+ int16 honor;
#if PACKETVER > 7
- int virtue;
+ int32 virtue;
#else
- short virtue;
+ int16 virtue;
#endif
uint8 isPKModeON;
- unsigned char sex;
- unsigned char MoveData[6];
- unsigned char xSize;
- unsigned char ySize;
- short clevel;
+ uint8 sex;
+ uint8 MoveData[6];
+ uint8 xSize;
+ uint8 ySize;
+ int16 clevel;
#if PACKETVER >= 20080102
- short font;
+ int16 font;
#endif
#if PACKETVER >= 20120221
- int maxHP;
- int HP;
- unsigned char isBoss;
+ int32 maxHP;
+ int32 HP;
+ uint8 isBoss;
#endif
#if PACKETVER >= 20150513
- short body;
+ int16 body;
+ char name[NAME_LENGTH];
#endif
} __attribute__((packed));
struct packet_idle_unit {
- short PacketType;
+ int16 PacketType;
#if PACKETVER >= 20091103
- short PacketLength;
- unsigned char objecttype;
+ int16 PacketLength;
+ uint8 objecttype;
#endif
#if PACKETVER >= 20131223
- unsigned int AID;
+ uint32 AID;
#endif
- unsigned int GID;
- short speed;
- short bodyState;
- short healthState;
+ uint32 GID;
+ int16 speed;
+ int16 bodyState;
+ int16 healthState;
#if PACKETVER < 20080102
- short effectState;
+ int16 effectState;
#else
- int effectState;
+ int32 effectState;
#endif
- short job;
- short head;
+ int16 job;
+ int16 head;
#if PACKETVER < 7
- short weapon;
+ int16 weapon;
#else
- int weapon;
+ int32 weapon;
#endif
- short accessory;
+ int16 accessory;
#if PACKETVER < 7
- short shield;
+ int16 shield;
#endif
- short accessory2;
- short accessory3;
- short headpalette;
- short bodypalette;
- short headDir;
+ int16 accessory2;
+ int16 accessory3;
+ int16 headpalette;
+ int16 bodypalette;
+ int16 headDir;
#if PACKETVER >= 20101124
- short robe;
+ int16 robe;
#endif
- unsigned int GUID;
- short GEmblemVer;
- short honor;
+ uint32 GUID;
+ int16 GEmblemVer;
+ int16 honor;
#if PACKETVER > 7
- int virtue;
+ int32 virtue;
#else
- short virtue;
+ int16 virtue;
#endif
uint8 isPKModeON;
- unsigned char sex;
- unsigned char PosDir[3];
- unsigned char xSize;
- unsigned char ySize;
- unsigned char state;
- short clevel;
+ uint8 sex;
+ uint8 PosDir[3];
+ uint8 xSize;
+ uint8 ySize;
+ uint8 state;
+ int16 clevel;
#if PACKETVER >= 20080102
- short font;
+ int16 font;
#endif
#if PACKETVER >= 20120221
- int maxHP;
- int HP;
- unsigned char isBoss;
+ int32 maxHP;
+ int32 HP;
+ uint8 isBoss;
#endif
#if PACKETVER >= 20150513
- short body;
+ int16 body;
+ char name[NAME_LENGTH];
#endif
} __attribute__((packed));
struct packet_status_change {
- short PacketType;
- short index;
- unsigned int AID;
- unsigned char state;
+ int16 PacketType;
+ int16 index;
+ uint32 AID;
+ uint8 state;
#if PACKETVER >= 20120618
- unsigned int Total;
+ uint32 Total;
#endif
#if PACKETVER >= 20090121
- unsigned int Left;
- int val1;
- int val2;
- int val3;
+ uint32 Left;
+ int32 val1;
+ int32 val2;
+ int32 val3;
#endif
} __attribute__((packed));
struct packet_status_change_end {
- short PacketType;
- short index;
- unsigned int AID;
- unsigned char state;
+ int16 PacketType;
+ int16 index;
+ uint32 AID;
+ uint8 state;
} __attribute__((packed));
struct packet_status_change2 {
- short PacketType;
- short index;
- unsigned int AID;
- unsigned char state;
- unsigned int Left;
- int val1;
- int val2;
- int val3;
+ int16 PacketType;
+ int16 index;
+ uint32 AID;
+ uint8 state;
+ uint32 Left;
+ int32 val1;
+ int32 val2;
+ int32 val3;
} __attribute__((packed));
struct packet_maptypeproperty2 {
- short PacketType;
- short type;
+ int16 PacketType;
+ int16 type;
struct {
- unsigned int party : 1; // Show attack cursor on non-party members (PvP)
- unsigned int guild : 1; // Show attack cursor on non-guild members (GvG)
- unsigned int siege : 1; // Show emblem over characters' heads when in GvG (WoE castle)
- unsigned int mineffect : 1; // Automatically enable /mineffect
- unsigned int nolockon : 1; // TODO: What does this do? (shows attack cursor on non-party members)
- unsigned int countpk : 1; /// Show the PvP counter
- unsigned int nopartyformation : 1; /// Prevent party creation/modification
- unsigned int bg : 1; // TODO: What does this do? Probably related to Battlegrounds, but I'm not sure on the effect
- unsigned int nocostume : 1; /// Does not show costume sprite.
- unsigned int usecart : 1; /// Allow opening cart inventory
- unsigned int summonstarmiracle : 1; // TODO: What does this do? Related to Taekwon Masters, but I have no idea.
- unsigned int SpareBits : 15; /// Currently ignored, reserved for future updates
+ uint32 party : 1; // Show attack cursor on non-party members (PvP)
+ uint32 guild : 1; // Show attack cursor on non-guild members (GvG)
+ uint32 siege : 1; // Show emblem over characters' heads when in GvG (WoE castle)
+ uint32 mineffect : 1; // Automatically enable /mineffect
+ uint32 nolockon : 1; // TODO: What does this do? (shows attack cursor on non-party members)
+ uint32 countpk : 1; /// Show the PvP counter
+ uint32 nopartyformation : 1; /// Prevent party creation/modification
+ uint32 bg : 1; // TODO: What does this do? Probably related to Battlegrounds, but I'm not sure on the effect
+ uint32 nocostume : 1; /// Does not show costume sprite.
+ uint32 usecart : 1; /// Allow opening cart inventory
+ uint32 summonstarmiracle : 1; // TODO: What does this do? Related to Taekwon Masters, but I have no idea.
+ uint32 SpareBits : 15; /// Currently ignored, reserved for future updates
} flag;
} __attribute__((packed));
struct packet_bgqueue_ack {
- short PacketType;
- unsigned char type;
+ int16 PacketType;
+ uint8 type;
char bg_name[NAME_LENGTH];
} __attribute__((packed));
struct packet_bgqueue_notice_delete {
- short PacketType;
- unsigned char type;
+ int16 PacketType;
+ uint8 type;
char bg_name[NAME_LENGTH];
} __attribute__((packed));
struct packet_bgqueue_register {
- short PacketType;
- short type;
+ int16 PacketType;
+ int16 type;
char bg_name[NAME_LENGTH];
} __attribute__((packed));
struct packet_bgqueue_update_info {
- short PacketType;
+ int16 PacketType;
char bg_name[NAME_LENGTH];
- int position;
+ int32 position;
} __attribute__((packed));
struct packet_bgqueue_checkstate {
- short PacketType;
+ int16 PacketType;
char bg_name[NAME_LENGTH];
} __attribute__((packed));
struct packet_bgqueue_revoke_req {
- short PacketType;
+ int16 PacketType;
char bg_name[NAME_LENGTH];
} __attribute__((packed));
struct packet_bgqueue_battlebegin_ack {
- short PacketType;
- unsigned char result;
+ int16 PacketType;
+ uint8 result;
char bg_name[NAME_LENGTH];
char game_name[NAME_LENGTH];
} __attribute__((packed));
struct packet_bgqueue_notify_entry {
- short PacketType;
+ int16 PacketType;
char name[NAME_LENGTH];
- int position;
+ int32 position;
} __attribute__((packed));
struct packet_bgqueue_battlebegins {
- short PacketType;
+ int16 PacketType;
char bg_name[NAME_LENGTH];
char game_name[NAME_LENGTH];
} __attribute__((packed));
struct packet_script_clear {
- short PacketType;
- unsigned int NpcID;
+ int16 PacketType;
+ uint32 NpcID;
} __attribute__((packed));
/* made possible thanks to Yommy!! */
struct packet_package_item_announce {
- short PacketType;
- short PacketLength;
- unsigned char type;
- unsigned short ItemID;
- char len;
+ int16 PacketType;
+ int16 PacketLength;
+ uint8 type;
+ uint16 ItemID;
+ int8 len;
char Name[NAME_LENGTH];
- char unknown;
- unsigned short BoxItemID;
+ int8 unknown;
+ uint16 BoxItemID;
} __attribute__((packed));
/* made possible thanks to Yommy!! */
struct packet_item_drop_announce {
- short PacketType;
- short PacketLength;
- unsigned char type;
- unsigned short ItemID;
- char len;
+ int16 PacketType;
+ int16 PacketLength;
+ uint8 type;
+ uint16 ItemID;
+ int8 len;
char Name[NAME_LENGTH];
char monsterNameLen;
char monsterName[NAME_LENGTH];
} __attribute__((packed));
struct packet_cart_additem_ack {
- short PacketType;
- char result;
+ int16 PacketType;
+ int8 result;
} __attribute__((packed));
struct packet_banking_check {
- short PacketType;
+ int16 PacketType;
int64 Money;
- short Reason;
+ int16 Reason;
} __attribute__((packed));
struct packet_banking_deposit_req {
- short PacketType;
- unsigned int AID;
- int Money;
+ int16 PacketType;
+ uint32 AID;
+ int32 Money;
} __attribute__((packed));
struct packet_banking_withdraw_req {
- short PacketType;
- unsigned int AID;
- int Money;
+ int16 PacketType;
+ uint32 AID;
+ int32 Money;
} __attribute__((packed));
struct packet_banking_deposit_ack {
- short PacketType;
- short Reason;
+ int16 PacketType;
+ int16 Reason;
int64 Money;
- int Balance;
+ int32 Balance;
} __attribute__((packed));
struct packet_banking_withdraw_ack {
- short PacketType;
- short Reason;
+ int16 PacketType;
+ int16 Reason;
int64 Money;
- int Balance;
+ int32 Balance;
} __attribute__((packed));
/* Roulette System [Yommy/Hercules] */
struct packet_roulette_open_ack {
- short PacketType;
- char Result;
- int Serial;
- char Step;
- char Idx;
- short AdditionItemID;
- int GoldPoint;
- int SilverPoint;
- int BronzePoint;
+ int16 PacketType;
+ int8 Result;
+ int32 Serial;
+ int8 Step;
+ int8 Idx;
+ int16 AdditionItemID;
+ int32 GoldPoint;
+ int32 SilverPoint;
+ int32 BronzePoint;
} __attribute__((packed));
struct packet_roulette_info_ack {
- short PacketType;
- short PacketLength;
- unsigned int RouletteSerial;
+ int16 PacketType;
+ int16 PacketLength;
+ uint32 RouletteSerial;
struct {
- unsigned short Row;
- unsigned short Position;
- unsigned short ItemId;
- unsigned short Count;
+ uint16 Row;
+ uint16 Position;
+ uint16 ItemId;
+ uint16 Count;
} ItemInfo[42];
} __attribute__((packed));
struct packet_roulette_close_ack {
- short PacketType;
- unsigned char Result;
+ int16 PacketType;
+ uint8 Result;
} __attribute__((packed));
struct packet_roulette_generate_ack {
- short PacketType;
- unsigned char Result;
- unsigned short Step;
- unsigned short Idx;
- unsigned short AdditionItemID;
- int RemainGold;
- int RemainSilver;
- int RemainBronze;
+ int16 PacketType;
+ uint8 Result;
+ uint16 Step;
+ uint16 Idx;
+ uint16 AdditionItemID;
+ int32 RemainGold;
+ int32 RemainSilver;
+ int32 RemainBronze;
} __attribute__((packed));
struct packet_roulette_itemrecv_req {
- short PacketType;
- unsigned char Condition;
+ int16 PacketType;
+ uint8 Condition;
} __attribute__((packed));
struct packet_roulette_itemrecv_ack {
- short PacketType;
- unsigned char Result;
- unsigned short AdditionItemID;
+ int16 PacketType;
+ uint8 Result;
+ uint16 AdditionItemID;
} __attribute__((packed));
struct packet_itemlist_normal {
- short PacketType;
- short PacketLength;
+ int16 PacketType;
+ int16 PacketLength;
struct NORMALITEM_INFO list[MAX_ITEMLIST];
} __attribute__((packed));
struct packet_itemlist_equip {
- short PacketType;
- short PacketLength;
+ int16 PacketType;
+ int16 PacketLength;
struct EQUIPITEM_INFO list[MAX_ITEMLIST];
} __attribute__((packed));
struct packet_storelist_normal {
- short PacketType;
- short PacketLength;
+ int16 PacketType;
+ int16 PacketLength;
#if PACKETVER >= 20120925
char name[NAME_LENGTH];
#endif
@@ -965,8 +973,8 @@ struct packet_storelist_normal {
} __attribute__((packed));
struct packet_storelist_equip {
- short PacketType;
- short PacketLength;
+ int16 PacketType;
+ int16 PacketLength;
#if PACKETVER >= 20120925
char name[NAME_LENGTH];
#endif
@@ -974,124 +982,124 @@ struct packet_storelist_equip {
} __attribute__((packed));
struct packet_equip_item {
- short PacketType;
- unsigned short index;
+ int16 PacketType;
+ uint16 index;
#if PACKETVER >= 20120925
- unsigned int wearLocation;
+ uint32 wearLocation;
#else
- unsigned short wearLocation;
+ uint16 wearLocation;
#endif
} __attribute__((packed));
struct packet_equipitem_ack {
- short PacketType;
- unsigned short index;
+ int16 PacketType;
+ uint16 index;
#if PACKETVER >= 20120925
- unsigned int wearLocation;
+ uint32 wearLocation;
#else
- unsigned short wearLocation;
+ uint16 wearLocation;
#endif
#if PACKETVER >= 20100629
- unsigned short wItemSpriteNumber;
+ uint16 wItemSpriteNumber;
#endif
- unsigned char result;
+ uint8 result;
} __attribute__((packed));
struct packet_unequipitem_ack {
- short PacketType;
- unsigned short index;
+ int16 PacketType;
+ uint16 index;
#if PACKETVER >= 20120925
- unsigned int wearLocation;
+ uint32 wearLocation;
#else
- unsigned short wearLocation;
+ uint16 wearLocation;
#endif
- unsigned char result;
+ uint8 result;
} __attribute__((packed));
struct packet_viewequip_ack {
- short PacketType;
- short PacketLength;
+ int16 PacketType;
+ int16 PacketLength;
char characterName[NAME_LENGTH];
- short job;
- short head;
- short accessory;
- short accessory2;
- short accessory3;
+ int16 job;
+ int16 head;
+ int16 accessory;
+ int16 accessory2;
+ int16 accessory3;
#if PACKETVER >= 20101124
- short robe;
+ int16 robe;
#endif
- short headpalette;
- short bodypalette;
- unsigned char sex;
+ int16 headpalette;
+ int16 bodypalette;
+ uint8 sex;
struct EQUIPITEM_INFO list[MAX_INVENTORY];
} __attribute__((packed));
struct packet_notify_bounditem {
- short PacketType;
- unsigned short index;
+ int16 PacketType;
+ uint16 index;
} __attribute__((packed));
struct packet_skill_entry {
- short PacketType;
+ int16 PacketType;
#if PACKETVER >= 20110718
- short PacketLength;
+ int16 PacketLength;
#endif
- unsigned int AID;
- unsigned int creatorAID;
- short xPos;
- short yPos;
+ uint32 AID;
+ uint32 creatorAID;
+ int16 xPos;
+ int16 yPos;
#if PACKETVER >= 20121212
- int job;
+ int32 job;
#else
- unsigned char job;
+ uint8 job;
#endif
#if PACKETVER >= 20110718
- char RadiusRange;
+ int8 RadiusRange;
#endif
- unsigned char isVisible;
+ uint8 isVisible;
#if PACKETVER >= 20130731
- unsigned char level;
+ uint8 level;
#endif
} __attribute__((packed));
struct packet_graffiti_entry {
- short PacketType;
- unsigned int AID;
- unsigned int creatorAID;
- short xPos;
- short yPos;
- unsigned char job;
- unsigned char isVisible;
- unsigned char isContens;
+ int16 PacketType;
+ uint32 AID;
+ uint32 creatorAID;
+ int16 xPos;
+ int16 yPos;
+ uint8 job;
+ uint8 isVisible;
+ uint8 isContens;
char msg[80];
} __attribute__((packed));
struct packet_damage {
- short PacketType;
- unsigned int GID;
- unsigned int targetGID;
- unsigned int startTime;
- int attackMT;
- int attackedMT;
+ int16 PacketType;
+ uint32 GID;
+ uint32 targetGID;
+ uint32 startTime;
+ int32 attackMT;
+ int32 attackedMT;
#if PACKETVER < 20071113
- short damage;
+ int16 damage;
#else
- int damage;
+ int32 damage;
#endif
#if PACKETVER >= 20131223
- unsigned char is_sp_damaged;
+ uint8 is_sp_damaged;
#endif
- short count;
- unsigned char action;
+ int16 count;
+ uint8 action;
#if PACKETVER < 20071113
- short leftDamage;
+ int16 leftDamage;
#else
- int leftDamage;
+ int32 leftDamage;
#endif
} __attribute__((packed));
struct packet_gm_monster_item {
- short PacketType;
+ int16 PacketType;
#if PACKETVER >= 20131218
char str[100];
#else
@@ -1100,35 +1108,35 @@ struct packet_gm_monster_item {
} __attribute__((packed));
struct packet_npc_market_purchase {
- short PacketType;
- short PacketLength;
+ int16 PacketType;
+ int16 PacketLength;
struct {
- unsigned short ITID;
- int qty;
+ uint16 ITID;
+ int32 qty;
} 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 {
- short PacketType;
- short PacketLength;
- unsigned char result;
+ int16 PacketType;
+ int16 PacketLength;
+ uint8 result;
struct {
- unsigned short ITID;
- unsigned short qty;
- unsigned int price;
+ uint16 ITID;
+ uint16 qty;
+ uint32 price;
} 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. */
} __attribute__((packed));
struct packet_npc_market_open {
- short PacketType;
- short PacketLength;
+ int16 PacketType;
+ int16 PacketLength;
/* inner struct figured by Ind after some annoying hour of debugging (data Thanks to Yommy) */
struct {
- unsigned short nameid;
- unsigned char type;
- unsigned int price;
- unsigned int qty;
- unsigned short view;
+ uint16 nameid;
+ uint8 type;
+ uint32 price;
+ uint32 qty;
+ uint16 view;
// It seems that the client doesn't have any hard-coded limit for this list
// it's possible to send up to 1890 items without dropping a packet that's
// too large [Panikon]
@@ -1136,30 +1144,30 @@ struct packet_npc_market_open {
} __attribute__((packed));
struct packet_wis_end {
- short PacketType;
- char result;
+ int16 PacketType;
+ int8 result;
#if PACKETVER >= 20131223
- unsigned int unknown;/* maybe AID, not sure what for (works sending as 0) */
+ uint32 unknown;/* maybe AID, not sure what for (works sending as 0) */
#endif
} __attribute__((packed));
struct packet_party_leader_changed {
- short PacketType;
- unsigned int prev_leader_aid;
- unsigned int new_leader_aid;
+ int16 PacketType;
+ uint32 prev_leader_aid;
+ uint32 new_leader_aid;
} __attribute__((packed));
struct packet_hotkey {
#ifdef HOTKEY_SAVING
- short PacketType;
+ int16 PacketType;
#if PACKETVER >= 20141022
- char Rotate;
+ int8 Rotate;
#endif
struct {
- char isSkill; // 0: Item, 1:Skill
- unsigned int ID; // Item/Skill ID
- short count; // Item Quantity/Skill Level
+ int8 isSkill; // 0: Item, 1:Skill
+ uint32 ID; // Item/Skill ID
+ int16 count; // Item Quantity/Skill Level
} hotkey[MAX_HOTKEYS];
#else // not HOTKEY_SAVING
UNAVAILABLE_STRUCT;
@@ -1207,6 +1215,19 @@ struct packet_quest_list_header {
//struct packet_quest_list_info list[]; // Variable-length
} __attribute__((packed));
+struct packet_chat_message {
+ uint16 packet_id;
+ int16 packet_len;
+ char message[];
+} __attribute__((packed));
+
+struct packet_whisper_message {
+ uint16 packet_id;
+ int16 packet_len;
+ char name[NAME_LENGTH];
+ char message[];
+} __attribute__((packed));
+
#if !defined(sun) && (!defined(__NETBSD__) || __NetBSD_Version__ >= 600000000) // NetBSD 5 and Solaris don't like pragma pack but accept the packed attribute
#pragma pack(pop)
#endif // not NetBSD < 6 / Solaris
diff --git a/src/map/party.c b/src/map/party.c
index 77f3c2b0b..dbb7b6ae2 100644
--- a/src/map/party.c
+++ b/src/map/party.c
@@ -122,7 +122,8 @@ struct map_session_data *party_sd_check(int party_id, int account_id, int char_i
return sd;
}
-int party_db_final(DBKey key, DBData *data, va_list ap) {
+int party_db_final(union DBKey key, struct DBData *data, va_list ap)
+{
struct party_data *p;
if ((p = DB->data2ptr(data))) {
@@ -146,9 +147,8 @@ struct party_data* party_searchname(const char* str)
{
struct party_data* p;
- DBIterator *iter = db_iterator(party->db);
- for( p = dbi_first(iter); dbi_exists(iter); p = dbi_next(iter) )
- {
+ struct DBIterator *iter = db_iterator(party->db);
+ for (p = dbi_first(iter); dbi_exists(iter); p = dbi_next(iter)) {
if( strncmpi(p->party.name,str,NAME_LENGTH) == 0 )
break;
}
@@ -798,12 +798,16 @@ int party_send_logout(struct map_session_data *sd)
return 1;
}
-int party_send_message(struct map_session_data *sd,const char *mes,int len)
+int party_send_message(struct map_session_data *sd, const char *mes)
{
- if(sd->status.party_id==0)
+ int len = (int)strlen(mes);
+
+ nullpo_ret(sd);
+
+ if (sd->status.party_id == 0)
return 0;
- intif->party_message(sd->status.party_id,sd->status.account_id,mes,len);
- party->recv_message(sd->status.party_id,sd->status.account_id,mes,len);
+ intif->party_message(sd->status.party_id, sd->status.account_id, mes, len);
+ party->recv_message(sd->status.party_id, sd->status.account_id, mes, len);
// Chat logging type 'P' / Party Chat
logs->chat(LOG_CHAT_PARTY, sd->status.party_id, sd->status.char_id, sd->status.account_id, mapindex_id2name(sd->mapindex), sd->bl.x, sd->bl.y, NULL, mes);
@@ -871,10 +875,11 @@ int party_skill_check(struct map_session_data *sd, int party_id, uint16 skill_id
return 0;
}
-int party_send_xy_timer(int tid, int64 tick, int id, intptr_t data) {
+int party_send_xy_timer(int tid, int64 tick, int id, intptr_t data)
+{
+ struct DBIterator *iter = db_iterator(party->db);
struct party_data* p;
- DBIterator *iter = db_iterator(party->db);
// for each existing party,
for( p = dbi_first(iter); dbi_exists(iter); p = dbi_next(iter) )
{
@@ -1284,7 +1289,7 @@ void party_recruit_search(struct map_session_data *sd, short level, short mapid,
int count = 0;
struct party_booking_ad_info* result_list[PARTY_BOOKING_RESULTS];
bool more_result = false;
- DBIterator* iter = db_iterator(party->booking_db);
+ struct DBIterator *iter = db_iterator(party->booking_db);
memset(result_list, 0, sizeof(result_list));
@@ -1315,7 +1320,7 @@ void party_booking_search(struct map_session_data *sd, short level, short mapid,
int count = 0;
struct party_booking_ad_info* result_list[PARTY_BOOKING_RESULTS];
bool more_result = false;
- DBIterator* iter = db_iterator(party->booking_db);
+ struct DBIterator *iter = db_iterator(party->booking_db);
memset(result_list, 0, sizeof(result_list));
diff --git a/src/map/party.h b/src/map/party.h
index b66a9770c..05037eb04 100644
--- a/src/map/party.h
+++ b/src/map/party.h
@@ -85,8 +85,8 @@ struct party_booking_ad_info {
* created by Susu
*-------------------------------------*/
struct party_interface {
- DBMap* db; // int party_id -> struct party_data* (releases data)
- DBMap* booking_db; // int char_id -> struct party_booking_ad_info* (releases data) // Party Booking [Spiria]
+ struct DBMap *db; // int party_id -> struct party_data* (releases data)
+ struct DBMap *booking_db; // int char_id -> struct party_booking_ad_info* (releases data) // Party Booking [Spiria]
unsigned int booking_nextid;
/* funcs */
void (*init) (bool minimal);
@@ -117,7 +117,7 @@ struct party_interface {
void (*send_movemap) (struct map_session_data *sd);
void (*send_levelup) (struct map_session_data *sd);
int (*send_logout) (struct map_session_data *sd);
- int (*send_message) (struct map_session_data *sd,const char *mes,int len);
+ int (*send_message) (struct map_session_data *sd, const char *mes);
int (*recv_message) (int party_id,int account_id,const char *mes,int len);
int (*skill_check) (struct map_session_data *sd, int party_id, uint16 skill_id, uint16 skill_lv);
int (*send_xy_clear) (struct party_data *p);
@@ -145,7 +145,7 @@ struct party_interface {
struct map_session_data *(*sd_check) (int party_id, int account_id, int char_id);
void (*check_state) (struct party_data *p);
struct party_booking_ad_info* (*create_booking_data) (void);
- int (*db_final) (DBKey key, DBData *data, va_list ap);
+ int (*db_final) (union DBKey key, struct DBData *data, va_list ap);
};
#ifdef HERCULES_CORE
diff --git a/src/map/path.c b/src/map/path.c
index 543497c33..0df9708d8 100644
--- a/src/map/path.c
+++ b/src/map/path.c
@@ -254,7 +254,7 @@ static int add_path(struct node_heap *heap, struct path_node *tp, int16 x, int16
*------------------------------------------*/
bool path_search(struct walkpath_data *wpd, struct block_list *bl, int16 m, int16 x0, int16 y0, int16 x1, int16 y1, int flag, cell_chk cell)
{
- register int i, j, x, y, dx, dy;
+ register int i, x, y, dx, dy;
struct map_data *md;
struct walkpath_data s_wpd;
@@ -315,8 +315,7 @@ bool path_search(struct walkpath_data *wpd, struct block_list *bl, int16 m, int1
}
return false; // easy path unsuccessful
- }
- else { // !(flag&1)
+ } else { // !(flag&1)
// A* (A-star) pathfinding
// We always use A* for finding walkpaths because it is what game client uses.
// Easy pathfinding cuts corners of non-walkable cells, but client always walks around it.
@@ -331,6 +330,7 @@ bool path_search(struct walkpath_data *wpd, struct block_list *bl, int16 m, int1
int xs = md->xs - 1;
int ys = md->ys - 1;
int len = 0;
+ int j;
memset(tp, 0, sizeof(tp));
// Start node
@@ -407,7 +407,7 @@ bool path_search(struct walkpath_data *wpd, struct block_list *bl, int16 m, int1
}
for (it = current; it->parent != NULL; it = it->parent, len++);
- if (len > sizeof(wpd->path)) {
+ if (len > (int)sizeof(wpd->path)) {
return false;
}
diff --git a/src/map/pc.c b/src/map/pc.c
index 7b4d47db2..1c635e5cf 100644
--- a/src/map/pc.c
+++ b/src/map/pc.c
@@ -63,6 +63,7 @@
#include "common/random.h"
#include "common/showmsg.h"
#include "common/socket.h"
+#include "common/sql.h"
#include "common/strlib.h" // safestrncpy()
#include "common/sysinfo.h"
#include "common/timer.h"
@@ -539,7 +540,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)
{
@@ -1863,8 +1864,8 @@ int pc_disguise(struct map_session_data *sd, int class_) {
clif->cartlist(sd);
clif->updatestatus(sd,SP_CARTINFO);
}
- if (sd->chatID) {
- struct chat_data *cd = map->id2cd(sd->chatID);
+ if (sd->chat_id != 0) {
+ struct chat_data *cd = map->id2cd(sd->chat_id);
if (cd != NULL)
clif->dispchat(cd,0);
@@ -4136,7 +4137,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);
}
@@ -4146,9 +4147,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;
}
@@ -4275,7 +4276,7 @@ int pc_payzeny(struct map_session_data *sd,int zeny, enum e_log_pick_type type,
if( zeny > 0 && sd->state.showzeny ) {
char output[255];
sprintf(output, "Removed %dz.", zeny);
- clif_disp_onlyself(sd,output,strlen(output));
+ clif_disp_onlyself(sd, output);
}
return 0;
@@ -4317,7 +4318,7 @@ int pc_paycash(struct map_session_data *sd, int price, int points)
{
char output[128];
sprintf(output, msg_sd(sd,504), points, cash, sd->kafraPoints, sd->cashPoints);
- clif_disp_onlyself(sd, output, strlen(output));
+ clif_disp_onlyself(sd, output);
}
return cash+points;
}
@@ -4342,7 +4343,7 @@ int pc_getcash(struct map_session_data *sd, int cash, int points)
if( battle_config.cashshop_show_points )
{
sprintf(output, msg_sd(sd,505), cash, sd->cashPoints);
- clif_disp_onlyself(sd, output, strlen(output));
+ clif_disp_onlyself(sd, output);
}
return cash;
}
@@ -4365,7 +4366,7 @@ int pc_getcash(struct map_session_data *sd, int cash, int points)
if( battle_config.cashshop_show_points )
{
sprintf(output, msg_sd(sd,506), points, sd->kafraPoints);
- clif_disp_onlyself(sd, output, strlen(output));
+ clif_disp_onlyself(sd, output);
}
return points;
}
@@ -4403,7 +4404,7 @@ int pc_getzeny(struct map_session_data *sd,int zeny, enum e_log_pick_type type,
if( zeny > 0 && sd->state.showzeny ) {
char output[255];
sprintf(output, "Gained %dz.", zeny);
- clif_disp_onlyself(sd,output,strlen(output));
+ clif_disp_onlyself(sd, output);
}
return 0;
@@ -5340,7 +5341,7 @@ int pc_steal_item(struct map_session_data *sd,struct block_list *bl, uint16 skil
char message[128];
sprintf (message, msg_txt(542), sd->status.name, md->db->jname, data->jname, (float)md->db->dropitem[i].p / 100);
//MSG: "'%s' stole %s's %s (chance: %0.02f%%)"
- intif->broadcast(message, strlen(message)+1, BC_DEFAULT);
+ intif->broadcast(message, (int)strlen(message)+1, BC_DEFAULT);
}
return 1;
}
@@ -6725,7 +6726,7 @@ bool pc_gainexp(struct map_session_data *sd, struct block_list *src, unsigned in
char output[256];
sprintf(output,
"Experience Gained Base:%u (%.2f%%) Job:%u (%.2f%%)",base_exp,nextbp*(float)100,job_exp,nextjp*(float)100);
- clif_disp_onlyself(sd,output,strlen(output));
+ clif_disp_onlyself(sd, output);
}
return true;
@@ -8990,7 +8991,7 @@ char* pc_readregstr(struct map_session_data* sd, int64 reg) {
void pc_setregstr(struct map_session_data* sd, int64 reg, const char* str) {
struct script_reg_str *p = NULL;
unsigned int index = script_getvaridx(reg);
- DBData prev;
+ struct DBData prev;
if( str[0] ) {
p = ers_alloc(pc->str_reg_ers, struct script_reg_str);
@@ -9113,7 +9114,7 @@ int pc_setregistry(struct map_session_data *sd, int64 reg, int val) {
if( !pc->reg_load )
p->flag.update = 1;/* either way, it will require either delete or replace */
} else if( val ) {
- DBData prev;
+ struct DBData prev;
if( index )
script->array_update(&sd->regs, reg, false);
@@ -9166,7 +9167,7 @@ int pc_setregistry_str(struct map_session_data *sd, int64 reg, const char *val)
if( !pc->reg_load )
p->flag.update = 1;/* either way, it will require either delete or replace */
} else if( val[0] ) {
- DBData prev;
+ struct DBData prev;
if( index )
script->array_update(&sd->regs, reg, false);
@@ -9905,7 +9906,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;
}
@@ -9921,7 +9922,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;
}
@@ -10139,9 +10140,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);
@@ -10334,7 +10335,7 @@ int map_day_timer(int tid, int64 tick, int id, intptr_t data) {
map->night_flag = 0; // 0=day, 1=night [Yor]
map->foreachpc(pc->daynight_timer_sub);
safestrncpy(tmp_soutput, (data == 0) ? msg_txt(502) : msg_txt(60), sizeof(tmp_soutput)); // The day has arrived!
- intif->broadcast(tmp_soutput, strlen(tmp_soutput) + 1, BC_DEFAULT);
+ intif->broadcast(tmp_soutput, (int)strlen(tmp_soutput) + 1, BC_DEFAULT);
return 0;
}
@@ -10354,7 +10355,7 @@ int map_night_timer(int tid, int64 tick, int id, intptr_t data) {
map->night_flag = 1; // 0=day, 1=night [Yor]
map->foreachpc(pc->daynight_timer_sub);
safestrncpy(tmp_soutput, (data == 0) ? msg_txt(503) : msg_txt(59), sizeof(tmp_soutput)); // The night has fallen...
- intif->broadcast(tmp_soutput, strlen(tmp_soutput) + 1, BC_DEFAULT);
+ intif->broadcast(tmp_soutput, (int)strlen(tmp_soutput) + 1, BC_DEFAULT);
return 0;
}
@@ -11013,18 +11014,18 @@ int pc_readdb(void) {
ShowError("can't read %s\n", line);
return 1;
}
- while(fgets(line, sizeof(line), fp))
- {
+ while (fgets(line, sizeof(line), fp)) {
char *split[10];
int lv,n;
- if(line[0]=='/' && line[1]=='/')
+ if (line[0]=='/' && line[1]=='/')
continue;
- for(j=0,p=line;j<3 && p;j++){
- split[j]=p;
- p=strchr(p,',');
- if(p) *p++=0;
+ for (j = 0, p = line; j < 3 && p != NULL; j++) {
+ split[j] = p;
+ p = strchr(p,',');
+ if (p != NULL)
+ *p++ = 0;
}
- if( j < 2 )
+ if (j < 2)
continue;
lv=atoi(split[0]);
@@ -11036,8 +11037,8 @@ int pc_readdb(void) {
if(line[0]=='/' && line[1]=='/')
continue;
- for ( j = ELE_NEUTRAL, p = line; j<n && j<ELE_MAX && p; j++ ) {
- while(*p==32 && *p>0)
+ for (j = ELE_NEUTRAL, p = line; j < n && j < ELE_MAX && p != NULL; j++) {
+ while (*p == ' ')
p++;
battle->attr_fix_table[lv-1][i][j]=atoi(p);
#ifndef RENEWAL
@@ -11045,7 +11046,8 @@ int pc_readdb(void) {
battle->attr_fix_table[lv-1][i][j] = 0;
#endif
p=strchr(p,',');
- if(p) *p++=0;
+ if (p != NULL)
+ *p++ = 0;
}
i++;
@@ -11194,7 +11196,7 @@ void pc_scdata_received(struct map_session_data *sd) {
time_t exp_time = sd->expiration_time;
char tmpstr[1024];
strftime(tmpstr, sizeof(tmpstr) - 1, msg_sd(sd,501), localtime(&exp_time)); // "Your account time limit is: %d-%m-%Y %H:%M:%S."
- clif->wis_message(sd->fd, map->wisp_server_name, tmpstr, strlen(tmpstr)+1);
+ clif->wis_message(sd->fd, map->wisp_server_name, tmpstr, (int)strlen(tmpstr));
pc->expire_check(sd);
}
@@ -11474,7 +11476,8 @@ void pc_autotrade_populate(struct map_session_data *sd) {
/**
* @see DBApply
*/
-int pc_autotrade_final(DBKey key, DBData *data, va_list ap) {
+int pc_autotrade_final(union DBKey key, struct DBData *data, va_list ap)
+{
struct autotrade_vending* at_v = DB->data2ptr(data);
HPM->data_store_destroy(&at_v->hdata);
return 0;
@@ -11514,6 +11517,87 @@ int pc_have_magnifier(struct map_session_data *sd)
return n;
}
+/**
+ * Verifies a chat message, searching for atcommands, checking if the sender
+ * character can chat, and updating the idle timer.
+ *
+ * @param sd The sender character.
+ * @param message The message text.
+ * @return Whether the message is a valid chat message.
+ */
+bool pc_process_chat_message(struct map_session_data *sd, const char *message)
+{
+ if (atcommand->exec(sd->fd, sd, message, true)) {
+ return false;
+ }
+
+ if (!pc->can_talk(sd)) {
+ return false;
+ }
+
+ if (battle_config.min_chat_delay != 0) {
+ if (DIFF_TICK(sd->cantalk_tick, timer->gettick()) > 0) {
+ return false;
+ }
+ sd->cantalk_tick = timer->gettick() + battle_config.min_chat_delay;
+ }
+
+ pc->update_idle_time(sd, BCIDLE_CHAT);
+
+ return true;
+}
+
+/**
+ * Checks a chat message, scanning for the Super Novice prayer sequence.
+ *
+ * If a match is found, the angel is invoked or the counter is incremented as
+ * appropriate.
+ *
+ * @param sd The sender character.
+ * @param message The message text.
+ */
+void pc_check_supernovice_call(struct map_session_data *sd, const char *message)
+{
+ unsigned int next = pc->nextbaseexp(sd);
+ int percent = 0;
+
+ if ((sd->class_&MAPID_UPPERMASK) != MAPID_SUPER_NOVICE)
+ return;
+ if (next == 0)
+ next = pc->thisbaseexp(sd);
+ if (next == 0)
+ return;
+
+ // 0%, 10%, 20%, ...
+ percent = (int)( ( (float)sd->status.base_exp/(float)next )*1000. );
+ if ((battle_config.snovice_call_type != 0 || percent != 0) && (percent%100) == 0) {
+ // 10.0%, 20.0%, ..., 90.0%
+ switch (sd->state.snovice_call_flag) {
+ case 0:
+ if (strstr(message, msg_txt(1479))) // "Dear angel, can you hear my voice?"
+ sd->state.snovice_call_flag = 1;
+ break;
+ case 1:
+ {
+ char buf[256];
+ snprintf(buf, 256, msg_txt(1480), sd->status.name);
+ if (strstr(message, buf)) // "I am %s Super Novice~"
+ sd->state.snovice_call_flag = 2;
+ }
+ break;
+ case 2:
+ if (strstr(message, msg_txt(1481))) // "Help me out~ Please~ T_T"
+ sd->state.snovice_call_flag = 3;
+ break;
+ case 3:
+ sc_start(NULL, &sd->bl, status->skill2sc(MO_EXPLOSIONSPIRITS), 100, 17, skill->get_time(MO_EXPLOSIONSPIRITS, 5)); //Lv17-> +50 critical (noted by Poki) [Skotlex]
+ clif->skill_nodamage(&sd->bl, &sd->bl, MO_EXPLOSIONSPIRITS, 5, 1); // prayer always shows successful Lv5 cast and disregards noskill restrictions
+ sd->state.snovice_call_flag = 0;
+ break;
+ }
+ }
+}
+
void do_final_pc(void) {
db_destroy(pc->itemcd_db);
pc->at_db->destroy(pc->at_db,pc->autotrade_final);
@@ -11869,6 +11953,9 @@ void pc_defaults(void) {
pc->db_checkid = pc_db_checkid;
pc->validate_levels = pc_validate_levels;
+ pc->check_supernovice_call = pc_check_supernovice_call;
+ pc->process_chat_message = pc_process_chat_message;
+
/**
* Autotrade persistency [Ind/Hercules <3]
**/
diff --git a/src/map/pc.h b/src/map/pc.h
index 0d2bca84d..58f7a2266 100644
--- a/src/map/pc.h
+++ b/src/map/pc.h
@@ -33,8 +33,9 @@
#include "map/status.h" // enum sc_type, OPTION_*
#include "map/unit.h" // struct unit_data, struct view_data
#include "map/vending.h" // struct s_vending
-#include "common/hercules.h"
+#include "common/db.h"
#include "common/ers.h" // struct eri
+#include "common/hercules.h"
#include "common/mmo.h" // JOB_*, MAX_FAME_LIST, struct fame_list, struct mmo_charstatus, NEW_CARTS
/**
@@ -257,7 +258,7 @@ struct map_session_data {
struct script_state *st;
char npc_str[CHATBOX_SIZE]; // for passing npc input box text to script engine
int npc_timer_id; //For player attached npc timers. [Skotlex]
- unsigned int chatID;
+ int chat_id;
int64 idletime;
struct {
int npc_id;
@@ -530,7 +531,7 @@ END_ZEROED_BLOCK;
unsigned char channel_count;
struct channel_data *gcbind;
unsigned char fontcolor;
- unsigned int fontcolor_tid;
+ int fontcolor_tid;
int64 hchsysch_tick;
/* [Ind/Hercules] */
@@ -609,15 +610,15 @@ END_ZEROED_BLOCK;
#define pc_setsit(sd) ( (sd)->state.dead_sit = (sd)->vd.dead_sit = 2 )
#define pc_isdead(sd) ( (sd)->state.dead_sit == 1 )
#define pc_issit(sd) ( (sd)->vd.dead_sit == 2 )
-#define pc_isidle(sd) ( (sd)->chatID || (sd)->state.vending || (sd)->state.buyingstore || DIFF_TICK(sockt->last_tick, (sd)->idletime) >= battle->bc->idle_no_share )
+#define pc_isidle(sd) ( (sd)->chat_id != 0 || (sd)->state.vending || (sd)->state.buyingstore || DIFF_TICK(sockt->last_tick, (sd)->idletime) >= battle->bc->idle_no_share )
#define pc_istrading(sd) ( (sd)->npc_id || (sd)->state.vending || (sd)->state.buyingstore || (sd)->state.trading )
-#define pc_cant_act(sd) ( (sd)->npc_id || (sd)->state.vending || (sd)->state.buyingstore || (sd)->chatID || ((sd)->sc.opt1 && (sd)->sc.opt1 != OPT1_BURNING) || (sd)->state.trading || (sd)->state.storage_flag || (sd)->state.prevend )
+#define pc_cant_act(sd) ( (sd)->npc_id || (sd)->state.vending || (sd)->state.buyingstore || (sd)->chat_id != 0 || ((sd)->sc.opt1 && (sd)->sc.opt1 != OPT1_BURNING) || (sd)->state.trading || (sd)->state.storage_flag || (sd)->state.prevend )
/* equals pc_cant_act except it doesn't check for chat rooms */
#define pc_cant_act2(sd) ( (sd)->npc_id || (sd)->state.buyingstore || ((sd)->sc.opt1 && (sd)->sc.opt1 != OPT1_BURNING) || (sd)->state.trading || (sd)->state.storage_flag || (sd)->state.prevend )
#define pc_setdir(sd,b,h) ( (sd)->ud.dir = (b) ,(sd)->head_dir = (h) )
-#define pc_setchatid(sd,n) ( (sd)->chatID = n )
+#define pc_setchatid(sd,n) ( (sd)->chat_id = (n) )
#define pc_ishiding(sd) ( (sd)->sc.option&(OPTION_HIDE|OPTION_CLOAK|OPTION_CHASEWALK) )
#define pc_iscloaking(sd) ( !((sd)->sc.option&OPTION_CHASEWALK) && ((sd)->sc.option&OPTION_CLOAK) )
#define pc_ischasewalk(sd) ( (sd)->sc.option&OPTION_CHASEWALK )
@@ -657,7 +658,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 "+")
@@ -784,9 +785,9 @@ struct autotrade_vending {
struct pc_interface {
/* */
- DBMap *at_db;/* char id -> struct autotrade_vending */
+ struct DBMap *at_db;/* char id -> struct autotrade_vending */
/* */
- DBMap* itemcd_db;
+ struct DBMap *itemcd_db;
/* */
int day_timer_tid;
int night_timer_tid;
@@ -1084,12 +1085,15 @@ END_ZEROED_BLOCK; /* End */
void (*autotrade_start) (struct map_session_data *sd);
void (*autotrade_prepare) (struct map_session_data *sd);
void (*autotrade_populate) (struct map_session_data *sd);
- int (*autotrade_final) (DBKey key, DBData *data, va_list ap);
+ int (*autotrade_final) (union DBKey key, struct DBData *data, va_list ap);
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);
+
+ bool (*process_chat_message) (struct map_session_data *sd, const char *message);
+ void (*check_supernovice_call) (struct map_session_data *sd, const char *message);
};
#ifdef HERCULES_CORE
diff --git a/src/map/pc_groups.c b/src/map/pc_groups.c
index b325a8ed7..ccda34b1c 100644
--- a/src/map/pc_groups.c
+++ b/src/map/pc_groups.c
@@ -75,7 +75,7 @@ static void read_config(void) {
if (groups != NULL) {
GroupSettings *group_settings = NULL;
- DBIterator *iter = NULL;
+ struct DBIterator *iter = NULL;
int i, loop = 0;
group_count = libconfig->setting_length(groups);
@@ -465,7 +465,7 @@ void do_init_pc_groups(void) {
/**
* @see DBApply
*/
-static int group_db_clear_sub(DBKey key, DBData *data, va_list args)
+static int group_db_clear_sub(union DBKey key, struct DBData *data, va_list args)
{
GroupSettings *group = DB->data2ptr(data);
if (group->name)
diff --git a/src/map/pc_groups.h b/src/map/pc_groups.h
index 3f95237b7..27eac7284 100644
--- a/src/map/pc_groups.h
+++ b/src/map/pc_groups.h
@@ -22,9 +22,9 @@
#define MAP_PC_GROUPS_H
#include "common/hercules.h"
-#include "common/db.h"
/* Forward Declarations */
+struct DBMap; // common/db.h
struct config_setting_t;
/// PC permissions
@@ -91,8 +91,8 @@ struct pc_groups_new_permission {
struct pc_groups_interface {
/* */
- DBMap* db; // id -> GroupSettings
- DBMap* name_db; // name -> GroupSettings
+ struct DBMap *db; // id -> GroupSettings
+ struct DBMap *name_db; // name -> GroupSettings
/* */
struct pc_groups_permission_table *permissions;
unsigned char permission_count;
diff --git a/src/map/pet.c b/src/map/pet.c
index 256324d29..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) {
@@ -703,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);
@@ -734,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);
}
diff --git a/src/map/quest.c b/src/map/quest.c
index bf0a76b16..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);
}
diff --git a/src/map/script.c b/src/map/script.c
index 7d5ce7d43..07b37571e 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -56,6 +56,7 @@
#include "map/unit.h"
#include "common/cbasetypes.h"
#include "common/conf.h"
+#include "common/db.h"
#include "common/memmgr.h"
#include "common/md5calc.h"
#include "common/mmo.h" // NEW_CARTS
@@ -63,6 +64,7 @@
#include "common/random.h"
#include "common/showmsg.h"
#include "common/socket.h" // usage: getcharip
+#include "common/sql.h"
#include "common/strlib.h"
#include "common/sysinfo.h"
#include "common/timer.h"
@@ -235,9 +237,9 @@ void script_reportsrc(struct script_state *st) {
break;
default:
if( bl->m >= 0 )
- ShowDebug("Source (Non-NPC type %u): 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 %u): 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;
}
}
@@ -2349,6 +2351,8 @@ void read_constdb(void)
} 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);
}
script->constdb_comment(NULL);
@@ -2367,6 +2371,49 @@ 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) \
@@ -2652,13 +2699,13 @@ struct script_code* parse_script(const char *src,const char *file,int line,int o
#endif
#ifdef SCRIPT_DEBUG_DISASM
i = 0;
- while(i < script->pos) {
- int j = i;
- c_op op = script->get_com(script->buf,&i);
+ while (i < script->pos) {
+ c_op op = script->get_com(script->buf, &i);
+ int j = i; // Note: i is modified in the line above.
ShowMessage("%06x %s", i, script->op2name(op));
- j = i;
- switch(op) {
+
+ switch (op) {
case C_INT:
ShowMessage(" %d", script->get_num(script->buf,&i));
break;
@@ -2819,43 +2866,46 @@ struct script_data *get_val(struct script_state* st, struct script_data* data) {
}
}
- if( postfix == '$' ) {// string variable
+ if (postfix == '$') {
+ // string variable
+ const char *str = NULL;
- switch( prefix ) {
+ switch (prefix) {
case '@':
- data->u.str = pc->readregstr(sd, data->u.num);
+ str = pc->readregstr(sd, data->u.num);
break;
case '$':
- data->u.str = mapreg->readregstr(data->u.num);
+ str = mapreg->readregstr(data->u.num);
break;
case '#':
- if( name[1] == '#' )
- data->u.str = pc_readaccountreg2str(sd, data->u.num);// global
+ if (name[1] == '#')
+ str = pc_readaccountreg2str(sd, data->u.num);// global
else
- data->u.str = pc_readaccountregstr(sd, data->u.num);// local
+ str = pc_readaccountregstr(sd, data->u.num);// local
break;
case '.':
if (data->ref)
- data->u.str = script->get_val_ref_str(st, data->ref, data);
+ str = script->get_val_ref_str(st, data->ref, data);
else if (name[1] == '@')
- data->u.str = script->get_val_scope_str(st, &st->stack->scope, data);
+ str = script->get_val_scope_str(st, &st->stack->scope, data);
else
- data->u.str = script->get_val_npc_str(st, &st->script->local, data);
+ str = script->get_val_npc_str(st, &st->script->local, data);
break;
case '\'':
- data->u.str = script->get_val_instance_str(st, name, data);
+ str = script->get_val_instance_str(st, name, data);
break;
default:
- data->u.str = pc_readglobalreg_str(sd, data->u.num);
+ str = pc_readglobalreg_str(sd, data->u.num);
break;
}
- if( data->u.str == NULL || data->u.str[0] == '\0' ) {// empty string
+ if (str == NULL || str[0] == '\0') {
+ // empty string
data->type = C_CONSTSTR;
data->u.str = "";
} else {// duplicate string
data->type = C_STR;
- data->u.str = aStrdup(data->u.str);
+ data->u.mutstr = aStrdup(str);
}
} else {// integer variable
@@ -2912,12 +2962,16 @@ struct script_data *get_val(struct script_state* st, struct script_data* data) {
* @param ref[in] the container to look up the reference into.
* @return the retrieved value of the reference.
*/
-void* get_val2(struct script_state* st, int64 uid, struct reg_db *ref) {
+const void *get_val2(struct script_state *st, int64 uid, struct reg_db *ref)
+{
struct script_data* data;
script->push_val(st->stack, C_NAME, uid, ref);
data = script_getdatatop(st, -1);
script->get_val(st, data);
- return (data->type == C_INT ? (void*)h64BPTRSIZE((int32)data->u.num) : (void*)h64BPTRSIZE(data->u.str)); // u.num is int32 because it comes from script->get_val
+ if (data->type == C_INT) // u.num is int32 because it comes from script->get_val
+ return (const void *)h64BPTRSIZE((int32)data->u.num);
+ else
+ return (const void *)h64BPTRSIZE(data->u.str);
}
/**
* Because, currently, array members with key 0 are indifferenciable from normal variables, we should ensure its actually in
@@ -2934,8 +2988,8 @@ void script_array_ensure_zero(struct script_state *st, struct map_session_data *
insert = true;
} else {
if( is_string_variable(name) ) {
- char* str = (char*)script->get_val2(st, uid, ref);
- if( str && *str )
+ const char *str = script->get_val2(st, uid, ref);
+ if (str != NULL && *str != '\0')
insert = true;
script_removetop(st, -1, 0);
} else {
@@ -2999,7 +3053,8 @@ unsigned int script_array_highest_key(struct script_state *st, struct map_sessio
}
return 0;
}
-int script_free_array_db(DBKey key, DBData *data, va_list ap) {
+int script_free_array_db(union DBKey key, struct DBData *data, va_list ap)
+{
struct script_array *sa = DB->data2ptr(data);
aFree(sa->members);
ers_free(script->array_ers, sa);
@@ -3306,59 +3361,59 @@ int set_var(struct map_session_data *sd, char *name, void *val)
return script->set_reg(NULL, sd, reference_uid(script->add_str(name),0), name, val, NULL);
}
-void setd_sub(struct script_state *st, struct map_session_data *sd, const char *varname, int elem, void *value, struct reg_db *ref)
+void setd_sub(struct script_state *st, struct map_session_data *sd, const char *varname, int elem, const void *value, struct reg_db *ref)
{
script->set_reg(st, sd, reference_uid(script->add_str(varname),elem), varname, value, ref);
}
/// Converts the data to a string
-const char* conv_str(struct script_state* st, struct script_data* data)
+const char *conv_str(struct script_state *st, struct script_data* data)
{
- char* p;
-
script->get_val(st, data);
- if( data_isstring(data) )
- {// nothing to convert
+ if (data_isstring(data)) {
+ // nothing to convert
+ return data->u.str;
}
- else if( data_isint(data) )
- {// int -> string
+ if (data_isint(data)) {
+ // int -> string
+ char *p;
CREATE(p, char, ITEM_NAME_LENGTH);
snprintf(p, ITEM_NAME_LENGTH, "%"PRId64"", data->u.num);
p[ITEM_NAME_LENGTH-1] = '\0';
data->type = C_STR;
- data->u.str = p;
+ data->u.mutstr = p;
+ return data->u.mutstr;
}
- else if( data_isreference(data) )
- {// reference -> string
+ if (data_isreference(data)) {
+ // reference -> string
//##TODO when does this happen (check script->get_val) [FlavioJS]
data->type = C_CONSTSTR;
data->u.str = reference_getname(data);
- }
- else
- {// unsupported data type
- ShowError("script:conv_str: cannot convert to string, defaulting to \"\"\n");
- script->reportdata(data);
- script->reportsrc(st);
- data->type = C_CONSTSTR;
- data->u.str = "";
- }
+ return data->u.str;
+ }
+ // unsupported data type
+ ShowError("script:conv_str: cannot convert to string, defaulting to \"\"\n");
+ script->reportdata(data);
+ script->reportsrc(st);
+ data->type = C_CONSTSTR;
+ data->u.str = "";
return data->u.str;
}
/// Converts the data to an int
-int conv_num(struct script_state* st, struct script_data* data) {
- char* p;
+int conv_num(struct script_state *st, struct script_data *data)
+{
long num;
script->get_val(st, data);
- if( data_isint(data) )
- {// nothing to convert
+ if (data_isint(data)) {
+ // nothing to convert
+ return (int)data->u.num;
}
- else if( data_isstring(data) )
- {// string -> int
+ if (data_isstring(data)) {
+ // string -> int
// the result does not overflow or underflow, it is capped instead
// ex: 999999999999 is capped to INT_MAX (2147483647)
- p = data->u.str;
errno = 0;
num = strtol(data->u.str, NULL, 10);// change radix to 0 to support octal numbers "o377" and hex numbers "0xFF"
if( errno == ERANGE
@@ -3380,22 +3435,21 @@ int conv_num(struct script_state* st, struct script_data* data) {
script->reportdata(data);
script->reportsrc(st);
}
- if( data->type == C_STR )
- aFree(p);
+ if (data->type == C_STR)
+ aFree(data->u.mutstr);
data->type = C_INT;
data->u.num = (int)num;
+ return (int)data->u.num;
}
#if 0
+ // unsupported data type
// FIXME this function is being used to retrieve the position of labels and
// probably other stuff [FlavioJS]
- else
- {// unsupported data type
- ShowError("script:conv_num: cannot convert to number, defaulting to 0\n");
- script->reportdata(data);
- script->reportsrc(st);
- data->type = C_INT;
- data->u.num = 0;
- }
+ ShowError("script:conv_num: cannot convert to number, defaulting to 0\n");
+ script->reportdata(data);
+ script->reportsrc(st);
+ data->type = C_INT;
+ data->u.num = 0;
#endif
return (int)data->u.num;
}
@@ -3425,11 +3479,23 @@ struct script_data* push_val(struct script_stack* stack, enum c_op type, int64 v
}
/// Pushes a string into the stack
-struct script_data* push_str(struct script_stack* stack, enum c_op type, char* str)
+struct script_data *push_str(struct script_stack *stack, char *str)
{
if( stack->sp >= stack->sp_max )
script->stack_expand(stack);
- stack->stack_data[stack->sp].type = type;
+ stack->stack_data[stack->sp].type = C_STR;
+ stack->stack_data[stack->sp].u.mutstr = str;
+ stack->stack_data[stack->sp].ref = NULL;
+ stack->sp++;
+ return &stack->stack_data[stack->sp-1];
+}
+
+/// Pushes a constant string into the stack
+struct script_data *push_conststr(struct script_stack *stack, const char *str)
+{
+ if( stack->sp >= stack->sp_max )
+ script->stack_expand(stack);
+ stack->stack_data[stack->sp].type = C_CONSTSTR;
stack->stack_data[stack->sp].u.str = str;
stack->stack_data[stack->sp].ref = NULL;
stack->sp++;
@@ -3451,10 +3517,10 @@ struct script_data* push_retinfo(struct script_stack* stack, struct script_retin
struct script_data* push_copy(struct script_stack* stack, int pos) {
switch( stack->stack_data[pos].type ) {
case C_CONSTSTR:
- return script->push_str(stack, C_CONSTSTR, stack->stack_data[pos].u.str);
+ return script->push_conststr(stack, stack->stack_data[pos].u.str);
break;
case C_STR:
- return script->push_str(stack, C_STR, aStrdup(stack->stack_data[pos].u.str));
+ return script->push_str(stack, aStrdup(stack->stack_data[pos].u.mutstr));
break;
case C_RETINFO:
ShowFatalError("script:push_copy: can't create copies of C_RETINFO. Exiting...\n");
@@ -3488,8 +3554,8 @@ void pop_stack(struct script_state* st, int start, int end) {
for( i = start; i < end; i++ )
{
data = &stack->stack_data[i];
- if( data->type == C_STR )
- aFree(data->u.str);
+ if (data->type == C_STR)
+ aFree(data->u.mutstr);
if( data->type == C_RETINFO )
{
struct script_retinfo* ri = data->u.ri;
@@ -3541,7 +3607,8 @@ void pop_stack(struct script_state* st, int start, int end) {
/*==========================================
* Release script dependent variable, dependent variable of function
*------------------------------------------*/
-void script_free_vars(struct DBMap* var_storage) {
+void script_free_vars(struct DBMap *var_storage)
+{
if( var_storage ) {
// destroy the storage construct containing the variables
db_destroy(var_storage);
@@ -3720,12 +3787,11 @@ void op_3(struct script_state* st, int op)
data = script_getdatatop(st, -3);
script->get_val(st, data);
- if( data_isstring(data) )
- flag = data->u.str[0];// "" -> false
- else if( data_isint(data) )
+ if (data_isstring(data)) {
+ flag = data->u.str[0]; // "" -> false
+ } else if (data_isint(data)) {
flag = data->u.num == 0 ? 0 : 1;// 0 -> false
- else
- {
+ } else {
ShowError("script:op_3: invalid data for the ternary operator test\n");
script->reportdata(data);
script->reportsrc(st);
@@ -3768,7 +3834,7 @@ void op_2str(struct script_state* st, int op, const char* s1, const char* s2)
pcre *compiled_regex;
pcre_extra *extra_regex;
const char *pcre_error, *pcre_match;
- int pcre_erroroffset, offsetcount, i;
+ int pcre_erroroffset, offsetcount;
int offsets[256*3]; // (max_capturing_groups+1)*3
compiled_regex = libpcre->compile(s2, 0, &pcre_error, &pcre_erroroffset, NULL);
@@ -3809,8 +3875,9 @@ void op_2str(struct script_state* st, int op, const char* s1, const char* s2)
return;
}
- if( op == C_RE_EQ ) {
- for( i = 0; i < offsetcount; i++ ) {
+ if (op == C_RE_EQ) {
+ int i;
+ for (i = 0; i < offsetcount; i++) {
libpcre->get_substring(s1, offsets, offsetcount, i, &pcre_match);
mapreg->setregstr(reference_uid(script->add_str("$@regexmatch$"), i), pcre_match);
libpcre->free_substring(pcre_match);
@@ -3946,10 +4013,9 @@ void op_2(struct script_state *st, int op)
script->op_2str(st, op, left->u.str, right->u.str);
script_removetop(st, leftref.type == C_NOP ? -3 : -2, -1);// pop the two values before the top one
- if (leftref.type != C_NOP)
- {
+ if (leftref.type != C_NOP) {
if (left->type == C_STR) // don't free C_CONSTSTR
- aFree(left->u.str);
+ aFree(left->u.mutstr);
*left = leftref;
}
}
@@ -4198,8 +4264,9 @@ void run_script(struct script_code *rootscript, int pos, int rid, int oid) {
script->run_main(st);
}
-void script_stop_instances(struct script_code *code) {
- DBIterator *iter;
+void script_stop_instances(struct script_code *code)
+{
+ struct DBIterator *iter;
struct script_state* st;
if( !script->active_scripts )
@@ -4347,7 +4414,7 @@ void run_script_main(struct script_state *st) {
script->push_val(stack,c,0,NULL);
break;
case C_STR:
- script->push_str(stack,C_CONSTSTR,(char*)(st->script->script_buf+st->pos));
+ script->push_conststr(stack, (const char *)(st->script->script_buf+st->pos));
while(st->script->script_buf[st->pos++]);
break;
case C_LSTR:
@@ -4359,7 +4426,7 @@ void run_script_main(struct script_state *st) {
st->pos += sizeof(int) + sizeof(uint8);
if( (!st->rid || !(lsd = map->id2sd(st->rid)) || !lsd->lang_id) && !map->default_lang_id )
- script->push_str(stack,C_CONSTSTR,script->string_list+string_id);
+ script->push_conststr(stack, script->string_list+string_id);
else {
uint8 k, wlang_id = lsd ? lsd->lang_id : map->default_lang_id;
int offset = st->pos;
@@ -4371,8 +4438,10 @@ void run_script_main(struct script_state *st) {
break;
offset += sizeof(char*);
}
- script->push_str(stack,C_CONSTSTR,
- ( k == translations ) ? script->string_list+string_id : *(char**)(&st->script->script_buf[offset]) );
+ if (k == translations)
+ script->push_conststr(stack, script->string_list+string_id);
+ else
+ script->push_conststr(stack, *(const char**)(&st->script->script_buf[offset]) );
}
st->pos += ( ( sizeof(char*) + sizeof(uint8) ) * translations );
}
@@ -4531,7 +4600,7 @@ int script_config_read(char *cfgName) {
/**
* @see DBApply
*/
-int db_script_free_code_sub(DBKey key, DBData *data, va_list ap)
+int db_script_free_code_sub(union DBKey key, struct DBData *data, va_list ap)
{
struct script_code *code = DB->data2ptr(data);
if (code)
@@ -4607,7 +4676,8 @@ void script_setarray_pc(struct map_session_data* sd, const char* varname, uint32
/**
* Clears persistent variables from memory
**/
-int script_reg_destroy(DBKey key, DBData *data, va_list ap) {
+int script_reg_destroy(union DBKey key, struct DBData *data, va_list ap)
+{
struct script_reg_state *src;
if( data->type != DB_DATA_PTR )/* got no need for those! */
@@ -4657,9 +4727,10 @@ void script_generic_ui_array_expand (unsigned int plus) {
/*==========================================
* Destructor
*------------------------------------------*/
-void do_final_script(void) {
+void do_final_script(void)
+{
int i;
- DBIterator *iter;
+ struct DBIterator *iter;
struct script_state *st;
#ifdef SCRIPT_DEBUG_HASH
@@ -4850,9 +4921,8 @@ void script_load_translations(void) {
libconfig->destroy(&translations_conf);
if( total ) {
- DBIterator *main_iter;
- DBIterator *sub_iter;
- DBMap *string_db;
+ struct DBIterator *main_iter;
+ struct DBMap *string_db;
struct string_translation *st = NULL;
uint32 j = 0;
@@ -4860,9 +4930,9 @@ void script_load_translations(void) {
script->translation_buf_size = total;
main_iter = db_iterator(script->translation_db);
- for( string_db = dbi_first(main_iter); dbi_exists(main_iter); string_db = dbi_next(main_iter) ) {
- sub_iter = db_iterator(string_db);
- for( st = dbi_first(sub_iter); dbi_exists(sub_iter); st = dbi_next(sub_iter) ) {
+ for (string_db = dbi_first(main_iter); dbi_exists(main_iter); string_db = dbi_next(main_iter)) {
+ struct DBIterator *sub_iter = db_iterator(string_db);
+ for (st = dbi_first(sub_iter); dbi_exists(sub_iter); st = dbi_next(sub_iter)) {
script->translation_buf[j++] = st->buf;
}
dbi_destroy(sub_iter);
@@ -4887,8 +4957,8 @@ void script_load_translations(void) {
/**
*
**/
-const char * script_get_translation_file_name(const char *file) {
- static char file_name[200];
+const char *script_get_translation_file_name(const char *file)
+{
int i, len = (int)strlen(file), last_bar = -1, last_dot = -1;
for(i = 0; i < len; i++) {
@@ -4899,6 +4969,7 @@ const char * script_get_translation_file_name(const char *file) {
}
if( last_bar != -1 || last_dot != -1 ) {
+ static char file_name[200];
if( last_bar != -1 && last_dot < last_bar )
last_dot = -1;
safestrncpy(file_name, file+(last_bar >= 0 ? last_bar+1 : 0), ( last_dot >= 0 ? ( last_bar >= 0 ? last_dot - last_bar : last_dot ) : sizeof(file_name) ));
@@ -4915,7 +4986,7 @@ void script_load_translation(const char *file, uint8 lang_id, uint32 *total) {
uint32 translations = 0;
char line[1024];
char msgctxt[NAME_LENGTH*2+1] = { 0 };
- DBMap *string_db;
+ struct DBMap *string_db;
size_t i;
FILE *fp;
struct script_string_buf msgid = { 0 }, msgstr = { 0 };
@@ -4930,7 +5001,7 @@ void script_load_translation(const char *file, uint8 lang_id, uint32 *total) {
atcommand->expand_message_table();
while(fgets(line, sizeof(line), fp)) {
- size_t len = strlen(line), cursor = 0;
+ size_t len = strlen(line);
if( len <= 1 )
continue;
@@ -4939,6 +5010,7 @@ void script_load_translation(const char *file, uint8 lang_id, uint32 *total) {
continue;
if( strncasecmp(line,"msgctxt \"", 9) == 0 ) {
+ int cursor = 0;
msgctxt[0] = '\0';
for(i = 9; i < len - 2; i++) {
if( line[i] == '\\' && line[i+1] == '"' ) {
@@ -4946,7 +5018,7 @@ void script_load_translation(const char *file, uint8 lang_id, uint32 *total) {
i++;
} else
msgctxt[cursor] = line[i];
- if( ++cursor >= sizeof(msgctxt) - 1 )
+ if (++cursor >= (int)sizeof(msgctxt) - 1)
break;
}
msgctxt[cursor] = '\0';
@@ -5066,12 +5138,13 @@ void script_clear_translations(bool reload) {
/**
*
**/
-int script_translation_db_destroyer(DBKey key, DBData *data, va_list ap) {
- DBMap *string_db = DB->data2ptr(data);
+int script_translation_db_destroyer(union DBKey key, struct DBData *data, va_list ap)
+{
+ struct DBMap *string_db = DB->data2ptr(data);
if( db_size(string_db) ) {
struct string_translation *st = NULL;
- DBIterator *iter = db_iterator(string_db);
+ struct DBIterator *iter = db_iterator(string_db);
for( st = dbi_first(iter); dbi_exists(iter); st = dbi_next(iter) ) {
aFree(st);
@@ -5141,6 +5214,7 @@ void do_init_script(bool minimal) {
script->parse_builtin();
script->read_constdb();
+ script->load_parameters();
script->hardcoded_constants();
if (minimal)
@@ -5150,9 +5224,10 @@ void do_init_script(bool minimal) {
script->load_translations();
}
-int script_reload(void) {
+int script_reload(void)
+{
int i;
- DBIterator *iter;
+ struct DBIterator *iter;
struct script_state *st;
#ifdef ENABLE_CASE_CHECK
@@ -6291,7 +6366,7 @@ BUILDIN(jobchange)
BUILDIN(jobname)
{
int class_=script_getnum(st,2);
- script_pushconststr(st, (char*)pc->job_name(class_));
+ script_pushconststr(st, pc->job_name(class_));
return true;
}
@@ -6340,16 +6415,13 @@ BUILDIN(input)
} else {
// take received text/value and store it in the designated variable
sd->state.menu_or_input = 0;
- if( is_string_variable(name) )
- {
+ if (is_string_variable(name)) {
int len = (int)strlen(sd->npc_str);
- script->set_reg(st, sd, uid, name, (void*)sd->npc_str, script_getref(st,2));
+ script->set_reg(st, sd, uid, name, sd->npc_str, script_getref(st,2));
script_pushint(st, (len > max ? 1 : len < min ? -1 : 0));
- }
- else
- {
+ } else {
int amount = sd->npc_amount;
- script->set_reg(st, sd, uid, name, (void*)h64BPTRSIZE(cap_value(amount,min,max)), script_getref(st,2));
+ script->set_reg(st, sd, uid, name, (const void *)h64BPTRSIZE(cap_value(amount,min,max)), script_getref(st,2));
script_pushint(st, (amount > max ? 1 : amount < min ? -1 : 0));
}
st->state = RUN;
@@ -6436,9 +6508,9 @@ BUILDIN(__setr)
}
if (is_string_variable(name))
- script->set_reg(st,sd,num,name,(void*)script_getstr(st,3),script_getref(st,2));
+ script->set_reg(st, sd, num, name, script_getstr(st, 3), script_getref(st, 2));
else
- script->set_reg(st,sd,num,name,(void*)h64BPTRSIZE(script_getnum(st,3)),script_getref(st,2));
+ script->set_reg(st, sd, num, name, (const void *)h64BPTRSIZE(script_getnum(st, 3)), script_getref(st, 2));
return true;
}
@@ -6485,15 +6557,14 @@ BUILDIN(setarray)
if( end > SCRIPT_MAX_ARRAYSIZE )
end = SCRIPT_MAX_ARRAYSIZE;
- if( is_string_variable(name) )
- {// string array
- for( i = 3; start < end; ++start, ++i )
- script->set_reg(st, sd, reference_uid(id, start), name, (void*)script_getstr(st,i), reference_getref(data));
- }
- else
- {// int array
- for( i = 3; start < end; ++start, ++i )
- script->set_reg(st, sd, reference_uid(id, start), name, (void*)h64BPTRSIZE(script_getnum(st,i)), reference_getref(data));
+ if (is_string_variable(name)) {
+ // string array
+ for (i = 3; start < end; ++start, ++i)
+ script->set_reg(st, sd, reference_uid(id, start), name, script_getstr(st, i), reference_getref(data));
+ } else {
+ // int array
+ for (i = 3; start < end; ++start, ++i)
+ script->set_reg(st, sd, reference_uid(id, start), name, (const void *)h64BPTRSIZE(script_getnum(st, i)), reference_getref(data));
}
return true;
}
@@ -6509,7 +6580,7 @@ BUILDIN(cleararray)
uint32 start;
uint32 end;
int32 id;
- void* v;
+ const void *v = NULL;
struct map_session_data *sd = NULL;
data = script_getdata(st, 2);
@@ -6532,10 +6603,10 @@ BUILDIN(cleararray)
return true;// no player attached
}
- if( is_string_variable(name) )
- v = (void*)script_getstr(st, 3);
+ if (is_string_variable(name))
+ v = script_getstr(st, 3);
else
- v = (void*)h64BPTRSIZE(script_getnum(st, 3));
+ v = (const void *)h64BPTRSIZE(script_getnum(st, 3));
end = start + script_getnum(st, 4);
if( end > SCRIPT_MAX_ARRAYSIZE )
@@ -6560,7 +6631,6 @@ BUILDIN(copyarray)
int32 idx2;
int32 id1;
int32 id2;
- void* v;
int32 i;
uint32 count;
struct map_session_data *sd = NULL;
@@ -6608,20 +6678,25 @@ BUILDIN(copyarray)
if( is_same_reference(data1, data2) && idx1 > idx2 ) {
// destination might be overlapping the source - copy in reverse order
for( i = count - 1; i >= 0; --i ) {
- v = script->get_val2(st, reference_uid(id2, idx2 + i), reference_getref(data2));
- script->set_reg(st, sd, reference_uid(id1, idx1 + i), name1, v, reference_getref(data1));
+ const void *value = script->get_val2(st, reference_uid(id2, idx2 + i), reference_getref(data2));
+ script->set_reg(st, sd, reference_uid(id1, idx1 + i), name1, value, reference_getref(data1));
script_removetop(st, -1, 0);
}
} else {
// normal copy
for( i = 0; i < count; ++i ) {
if( idx2 + i < SCRIPT_MAX_ARRAYSIZE ) {
- v = script->get_val2(st, reference_uid(id2, idx2 + i), reference_getref(data2));
- script->set_reg(st, sd, reference_uid(id1, idx1 + i), name1, v, reference_getref(data1));
+ const void *value = script->get_val2(st, reference_uid(id2, idx2 + i), reference_getref(data2));
+ script->set_reg(st, sd, reference_uid(id1, idx1 + i), name1, value, reference_getref(data1));
script_removetop(st, -1, 0);
} else {
// out of range - assume ""/0
- script->set_reg(st, sd, reference_uid(id1, idx1 + i), name1, (is_string_variable(name1)?(void*)"":(void*)0), reference_getref(data1));
+ const void *value;
+ if (is_string_variable(name1))
+ value = "";
+ else
+ value = (const void *)0;
+ script->set_reg(st, sd, reference_uid(id1, idx1 + i), name1, value, reference_getref(data1));
}
}
}
@@ -6650,8 +6725,9 @@ BUILDIN(getarraysize)
script_pushint(st, script->array_highest_key(st,st->rid ? script->rid2sd(st) : NULL,reference_getname(data),reference_getref(data)));
return true;
}
-int script_array_index_cmp(const void *a, const void *b) {
- return ( *(const unsigned int*)a - *(const unsigned int*)b );
+int script_array_index_cmp(const void *a, const void *b)
+{
+ return (*(const unsigned int *)a - *(const unsigned int *)b); // FIXME: Is the unsigned difference really intended here?
}
/// Deletes count or all the elements in an array, from the starting index.
@@ -6724,7 +6800,7 @@ BUILDIN(deletearray)
// Better to iterate directly on the array, no speed-up from using sa
for( ; start + count < end; ++start ) {
// Compact and overwrite
- void* v = script->get_val2(st, reference_uid(id, start + count), reference_getref(data));
+ const void *v = script->get_val2(st, reference_uid(id, start + count), reference_getref(data));
script->set_reg(st, sd, reference_uid(id, start), name, v, reference_getref(data));
script_removetop(st, -1, 0);
}
@@ -6748,7 +6824,7 @@ BUILDIN(deletearray)
for( ; i < size && list[i] < end; i++ ) {
// Move back count positions any entries between start+count to fill the gaps
- void* v = script->get_val2(st, reference_uid(id, list[i]), reference_getref(data));
+ const void *v = script->get_val2(st, reference_uid(id, list[i]), reference_getref(data));
script->set_reg(st, sd, reference_uid(id, list[i]-count), name, v, reference_getref(data));
script_removetop(st, -1, 0);
// Clear their originals
@@ -10012,6 +10088,7 @@ int buildin_killmonsterall_sub_strip(struct block_list *bl,va_list ap)
struct mob_data *md;
md = BL_CAST(BL_MOB, bl);
+ nullpo_ret(md);
if (md->npc_event[0])
md->npc_event[0] = 0;
@@ -10434,7 +10511,8 @@ BUILDIN(playerattached) {
/*==========================================
*------------------------------------------*/
-BUILDIN(announce) {
+BUILDIN(announce)
+{
const char *mes = script_getstr(st,2);
int flag = script_getnum(st,3);
const char *fontColor = script_hasdata(st,4) ? script_getstr(st,4) : NULL;
@@ -10442,6 +10520,8 @@ BUILDIN(announce) {
int fontSize = script_hasdata(st,6) ? script_getnum(st,6) : 12; // default fontSize
int fontAlign = script_hasdata(st,7) ? script_getnum(st,7) : 0; // default fontAlign
int fontY = script_hasdata(st,8) ? script_getnum(st,8) : 0; // default fontY
+ size_t len = strlen(mes);
+ Assert_retr(false, len < INT_MAX);
if( flag&(BC_TARGET_MASK|BC_SOURCE_MASK) ) {
// Broadcast source or broadcast region defined
@@ -10466,14 +10546,14 @@ BUILDIN(announce) {
}
if (fontColor)
- clif->broadcast2(bl, mes, (int)strlen(mes)+1, (unsigned int)strtoul(fontColor, (char **)NULL, 0), fontType, fontSize, fontAlign, fontY, target);
+ clif->broadcast2(bl, mes, (int)len+1, (unsigned int)strtoul(fontColor, (char **)NULL, 0), fontType, fontSize, fontAlign, fontY, target);
else
- clif->broadcast(bl, mes, (int)strlen(mes)+1, flag&BC_COLOR_MASK, target);
+ clif->broadcast(bl, mes, (int)len+1, flag&BC_COLOR_MASK, target);
} else {
if (fontColor)
- intif->broadcast2(mes, (int)strlen(mes)+1, (unsigned int)strtoul(fontColor, (char **)NULL, 0), fontType, fontSize, fontAlign, fontY);
+ intif->broadcast2(mes, (int)len+1, (unsigned int)strtoul(fontColor, (char **)NULL, 0), fontType, fontSize, fontAlign, fontY);
else
- intif->broadcast(mes, (int)strlen(mes)+1, flag&BC_COLOR_MASK);
+ intif->broadcast(mes, (int)len+1, flag&BC_COLOR_MASK);
}
return true;
}
@@ -10481,10 +10561,10 @@ BUILDIN(announce) {
*------------------------------------------*/
int buildin_announce_sub(struct block_list *bl, va_list ap)
{
- char *mes = va_arg(ap, char *);
+ const char *mes = va_arg(ap, const char *);
int len = va_arg(ap, int);
int type = va_arg(ap, int);
- char *fontColor = va_arg(ap, char *);
+ const char *fontColor = va_arg(ap, const char *);
short fontType = (short)va_arg(ap, int);
short fontSize = (short)va_arg(ap, int);
short fontAlign = (short)va_arg(ap, int);
@@ -10531,7 +10611,8 @@ BUILDIN(itemeffect)
return true;
}
-BUILDIN(mapannounce) {
+BUILDIN(mapannounce)
+{
const char *mapname = script_getstr(st,2);
const char *mes = script_getstr(st,3);
int flag = script_getnum(st,4);
@@ -10541,17 +10622,20 @@ BUILDIN(mapannounce) {
int fontAlign = script_hasdata(st,8) ? script_getnum(st,8) : 0; // default fontAlign
int fontY = script_hasdata(st,9) ? script_getnum(st,9) : 0; // default fontY
int16 m;
+ size_t len = strlen(mes);
+ Assert_retr(false, len < INT_MAX);
if ((m = map->mapname2mapid(mapname)) < 0)
return true;
map->foreachinmap(script->buildin_announce_sub, m, BL_PC,
- mes, strlen(mes)+1, flag&BC_COLOR_MASK, fontColor, fontType, fontSize, fontAlign, fontY);
+ mes, (int)len+1, flag&BC_COLOR_MASK, fontColor, fontType, fontSize, fontAlign, fontY);
return true;
}
/*==========================================
*------------------------------------------*/
-BUILDIN(areaannounce) {
+BUILDIN(areaannounce)
+{
const char *mapname = script_getstr(st,2);
int x0 = script_getnum(st,3);
int y0 = script_getnum(st,4);
@@ -10565,12 +10649,14 @@ BUILDIN(areaannounce) {
int fontAlign = script_hasdata(st,12) ? script_getnum(st,12) : 0; // default fontAlign
int fontY = script_hasdata(st,13) ? script_getnum(st,13) : 0; // default fontY
int16 m;
+ size_t len = strlen(mes);
+ Assert_retr(false, len < INT_MAX);
if ((m = map->mapname2mapid(mapname)) < 0)
return true;
map->foreachinarea(script->buildin_announce_sub, m, x0, y0, x1, y1, BL_PC,
- mes, strlen(mes)+1, flag&BC_COLOR_MASK, fontColor, fontType, fontSize, fontAlign, fontY);
+ mes, (int)len+1, flag&BC_COLOR_MASK, fontColor, fontType, fontSize, fontAlign, fontY);
return true;
}
@@ -11008,9 +11094,9 @@ BUILDIN(getstatus)
case 4: script_pushint(st, sd->sc.data[id]->val4); break;
case 5:
{
- const struct TimerData* td = (const struct TimerData*)timer->get(sd->sc.data[id]->timer);
+ const struct TimerData *td = timer->get(sd->sc.data[id]->timer);
- if( td ) {
+ if (td != NULL) {
// return the amount of time remaining
script_pushint(st, (int)(td->tick - timer->gettick())); // TODO: change this to int64 when we'll support 64 bit script values
}
@@ -13585,25 +13671,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;
@@ -13707,7 +13795,7 @@ BUILDIN(dispbottom)
int color = script_getnum(st,3);
clif->messagecolor_self(sd->fd, color, message);
} else {
- clif_disp_onlyself(sd, message, (int)strlen(message));
+ clif_disp_onlyself(sd, message);
}
return true;
@@ -14359,7 +14447,7 @@ BUILDIN(getmapxy)
sd=script->rid2sd(st);
else
sd=NULL;
- script->set_reg(st,sd,num,name,(void*)mapname,script_getref(st,2));
+ script->set_reg(st, sd, num, name, mapname, script_getref(st, 2));
//Set MapX
num=st->stack->stack_data[st->start+3].u.num;
@@ -14370,7 +14458,7 @@ BUILDIN(getmapxy)
sd=script->rid2sd(st);
else
sd=NULL;
- script->set_reg(st,sd,num,name,(void*)h64BPTRSIZE(x),script_getref(st,3));
+ script->set_reg(st, sd, num, name, (const void *)h64BPTRSIZE(x), script_getref(st, 3));
//Set MapY
num=st->stack->stack_data[st->start+4].u.num;
@@ -14381,7 +14469,7 @@ BUILDIN(getmapxy)
sd=script->rid2sd(st);
else
sd=NULL;
- script->set_reg(st,sd,num,name,(void*)h64BPTRSIZE(y),script_getref(st,4));
+ script->set_reg(st, sd, num, name, (const void *)h64BPTRSIZE(y), script_getref(st, 4));
//Return Success value
script_pushint(st,0);
@@ -15041,7 +15129,7 @@ BUILDIN(explode)
if (str[i] == delimiter && (int64)start + k < (int64)(SCRIPT_MAX_ARRAYSIZE-1)) { // FIXME[Haru]: SCRIPT_MAX_ARRAYSIZE should really be unsigned (and INT32_MAX)
//break at delimiter but ignore after reaching last array index
temp[j] = '\0';
- script->set_reg(st, sd, reference_uid(id, start + k), name, (void*)temp, reference_getref(data));
+ script->set_reg(st, sd, reference_uid(id, start + k), name, temp, reference_getref(data));
k++;
j = 0;
} else {
@@ -15050,7 +15138,7 @@ BUILDIN(explode)
}
//set last string
temp[j] = '\0';
- script->set_reg(st, sd, reference_uid(id, start + k), name, (void*)temp, reference_getref(data));
+ script->set_reg(st, sd, reference_uid(id, start + k), name, temp, reference_getref(data));
aFree(temp);
@@ -15111,7 +15199,7 @@ BUILDIN(implode)
size_t len = 0, glue_len = 0, k = 0;
const char *glue = NULL, *temp;
for(i = 0; i <= array_size; ++i) {
- temp = (char*) script->get_val2(st, reference_uid(id, i), reference_getref(data));
+ temp = script->get_val2(st, reference_uid(id, i), reference_getref(data));
len += strlen(temp);
script_removetop(st, -1, 0);
}
@@ -15126,7 +15214,7 @@ BUILDIN(implode)
//build output
for(i = 0; i < array_size; ++i) {
- temp = (char*) script->get_val2(st, reference_uid(id, i), reference_getref(data));
+ temp = script->get_val2(st, reference_uid(id, i), reference_getref(data));
len = strlen(temp);
memcpy(&output[k], temp, len);
k += len;
@@ -15136,7 +15224,7 @@ BUILDIN(implode)
}
script_removetop(st, -1, 0);
}
- temp = (char*) script->get_val2(st, reference_uid(id, array_size), reference_getref(data));
+ temp = script->get_val2(st, reference_uid(id, array_size), reference_getref(data));
len = strlen(temp);
memcpy(&output[k], temp, len);
k += len;
@@ -15370,12 +15458,12 @@ BUILDIN(sscanf) {
if(sscanf(str, buf, ref_str)==0) {
break;
}
- script->set_reg(st, sd, reference_uid( reference_getid(data), reference_getindex(data) ), buf_p, (void *)(ref_str), reference_getref(data));
+ script->set_reg(st, sd, reference_uid( reference_getid(data), reference_getindex(data) ), buf_p, ref_str, reference_getref(data));
} else { // Number
if(sscanf(str, buf, &ref_int)==0) {
break;
}
- script->set_reg(st, sd, reference_uid( reference_getid(data), reference_getindex(data) ), buf_p, (void *)h64BPTRSIZE(ref_int), reference_getref(data));
+ script->set_reg(st, sd, reference_uid( reference_getid(data), reference_getindex(data) ), buf_p, (const void *)h64BPTRSIZE(ref_int), reference_getref(data));
}
arg++;
@@ -15815,8 +15903,8 @@ BUILDIN(swap)
value2 = script_getstr(st,3);
if (strcmpi(value1, value2)) {
- script->set_reg(st, sd, uid1, varname1, (void*)(value2), script_getref(st,3));
- script->set_reg(st, sd, uid2, varname2, (void*)(value1), script_getref(st,2));
+ script->set_reg(st, sd, uid1, varname1, value2, script_getref(st,3));
+ script->set_reg(st, sd, uid2, varname2, value1, script_getref(st,2));
}
}
else {
@@ -15826,8 +15914,8 @@ BUILDIN(swap)
value2 = script_getnum(st,3);
if (value1 != value2) {
- script->set_reg(st, sd, uid1, varname1, (void*)h64BPTRSIZE(value2), script_getref(st,3));
- script->set_reg(st, sd, uid2, varname2, (void*)h64BPTRSIZE(value1), script_getref(st,2));
+ script->set_reg(st, sd, uid1, varname1, (const void *)h64BPTRSIZE(value2), script_getref(st,3));
+ script->set_reg(st, sd, uid2, varname2, (const void *)h64BPTRSIZE(value1), script_getref(st,2));
}
}
return true;
@@ -15856,16 +15944,16 @@ BUILDIN(setd)
}
}
- if( is_string_variable(varname) ) {
- script->setd_sub(st, sd, varname, elem, (void *)script_getstr(st, 3), NULL);
+ if (is_string_variable(varname)) {
+ script->setd_sub(st, sd, varname, elem, script_getstr(st, 3), NULL);
} else {
- script->setd_sub(st, sd, varname, elem, (void *)h64BPTRSIZE(script_getnum(st, 3)), NULL);
+ script->setd_sub(st, sd, varname, elem, (const void *)h64BPTRSIZE(script_getnum(st, 3)), NULL);
}
return true;
}
-int buildin_query_sql_sub(struct script_state* st, Sql* handle)
+int buildin_query_sql_sub(struct script_state *st, struct Sql *handle)
{
int i, j;
struct map_session_data *sd = NULL;
@@ -16404,7 +16492,7 @@ BUILDIN(checkchatting) {
sd = script->rid2sd(st);
if (sd != NULL)
- script_pushint(st,(sd->chatID != 0));
+ script_pushint(st, (sd->chat_id != 0));
else
script_pushint(st,0);
@@ -16481,7 +16569,7 @@ BUILDIN(searchitem)
for( i = 0; i < count; ++start, ++i )
{// Set array
- void* v = (void*)h64BPTRSIZE((int)items[i]->nameid);
+ const void *v = (const void *)h64BPTRSIZE((int)items[i]->nameid);
script->set_reg(st, sd, reference_uid(id, start), name, v, reference_getref(data));
}
@@ -16770,8 +16858,12 @@ BUILDIN(unittalk) {
bl = map->id2bl(unit_id);
if( bl != NULL ) {
struct StringBuf sbuf;
+ char blname[NAME_LENGTH];
StrBuf->Init(&sbuf);
- StrBuf->Printf(&sbuf, "%s : %s", status->get_name(bl), message);
+ safestrncpy(blname, clif->get_bl_name(bl), sizeof(blname));
+ if(bl->type == BL_NPC)
+ strtok(blname, "#");
+ StrBuf->Printf(&sbuf, "%s : %s", blname, message);
clif->disp_overhead(bl, StrBuf->Value(&sbuf));
StrBuf->Destroy(&sbuf);
}
@@ -16924,8 +17016,9 @@ BUILDIN(sleep2) {
/// Awakes all the sleep timers of the target npc
///
/// awake "<npc name>";
-BUILDIN(awake) {
- DBIterator *iter;
+BUILDIN(awake)
+{
+ struct DBIterator *iter;
struct script_state *tst;
struct npc_data* nd;
@@ -17937,7 +18030,8 @@ BUILDIN(instance_init) {
return true;
}
-BUILDIN(instance_announce) {
+BUILDIN(instance_announce)
+{
int instance_id = script_getnum(st,2);
const char *mes = script_getstr(st,3);
int flag = script_getnum(st,4);
@@ -17946,8 +18040,9 @@ BUILDIN(instance_announce) {
int fontSize = script_hasdata(st,7) ? script_getnum(st,7) : 12; // default fontSize
int fontAlign = script_hasdata(st,8) ? script_getnum(st,8) : 0; // default fontAlign
int fontY = script_hasdata(st,9) ? script_getnum(st,9) : 0; // default fontY
-
int i;
+ size_t len = strlen(mes);
+ Assert_retr(false, len < INT_MAX);
if( instance_id == -1 ) {
if( st->instance_id >= 0 )
@@ -17961,7 +18056,7 @@ BUILDIN(instance_announce) {
for( i = 0; i < instance->list[instance_id].num_map; i++ )
map->foreachinmap(script->buildin_announce_sub, instance->list[instance_id].map[i], BL_PC,
- mes, strlen(mes)+1, flag&BC_COLOR_MASK, fontColor, fontType, fontSize, fontAlign, fontY);
+ mes, (int)len+1, flag&BC_COLOR_MASK, fontColor, fontType, fontSize, fontAlign, fontY);
return true;
}
@@ -18551,22 +18646,11 @@ BUILDIN(getcharip) {
return false;
}
- /* check for IP */
- if (!sockt->session[sd->fd]->client_addr) {
+ if (sd->fd == 0 || sockt->session[sd->fd] == NULL || sockt->session[sd->fd]->client_addr == 0) {
script_pushconststr(st, "");
- return true;
- }
-
- /* return the client ip_addr converted for output */
- if (sd && sd->fd && sockt->session[sd->fd])
- {
- /* initiliaze */
- const char *ip_addr = NULL;
- uint32 ip;
-
- /* set ip, ip_addr and convert to ip and push str */
- ip = sockt->session[sd->fd]->client_addr;
- ip_addr = sockt->ip2str(ip, NULL);
+ } else {
+ uint32 ip = sockt->session[sd->fd]->client_addr;
+ const char *ip_addr = sockt->ip2str(ip, NULL);
script_pushstrcopy(st, ip_addr);
}
@@ -18789,68 +18873,6 @@ BUILDIN(useatcmd) {
return true;
}
-BUILDIN(checkre)
-{
- int num;
-
- num=script_getnum(st,2);
- switch(num) {
- case 0:
-#ifdef RENEWAL
- script_pushint(st, 1);
-#else
- script_pushint(st, 0);
-#endif
- break;
- case 1:
-#ifdef RENEWAL_CAST
- script_pushint(st, 1);
-#else
- script_pushint(st, 0);
-#endif
- break;
- case 2:
-#ifdef RENEWAL_DROP
- script_pushint(st, 1);
-#else
- script_pushint(st, 0);
-#endif
- break;
- case 3:
-#ifdef RENEWAL_EXP
- script_pushint(st, 1);
-#else
- script_pushint(st, 0);
-#endif
- break;
- case 4:
-#ifdef RENEWAL_LVDMG
- script_pushint(st, 1);
-#else
- script_pushint(st, 0);
-#endif
- break;
- case 5:
-#ifdef RENEWAL_EDP
- script_pushint(st, 1);
-#else
- script_pushint(st, 0);
-#endif
- break;
- case 6:
-#ifdef RENEWAL_ASPD
- script_pushint(st, 1);
-#else
- script_pushint(st, 0);
-#endif
- break;
- default:
- ShowWarning("buildin_checkre: unknown parameter.\n");
- break;
- }
- return true;
-}
-
/* getrandgroupitem <container_item_id>,<quantity> */
BUILDIN(getrandgroupitem) {
struct item_data *data = NULL;
@@ -19695,9 +19717,10 @@ BUILDIN(checkbound)
/* bg_match_over( arena_name {, optional canceled } ) */
/* returns 0 when successful, 1 otherwise */
-BUILDIN(bg_match_over) {
+BUILDIN(bg_match_over)
+{
bool canceled = script_hasdata(st,3) ? true : false;
- struct bg_arena *arena = bg->name2arena((const char*)script_getstr(st, 2));
+ struct bg_arena *arena = bg->name2arena(script_getstr(st, 2));
if( arena ) {
bg->match_over(arena,canceled);
@@ -21098,6 +21121,7 @@ void script_defaults(void) {
script->get_val_npc_num = get_val_npcscope_num;
script->get_val_instance_num = get_val_instance_num;
script->push_str = push_str;
+ script->push_conststr = push_conststr;
script->push_copy = push_copy;
script->pop_stack = pop_stack;
script->set_constant = script_set_constant;
@@ -21161,6 +21185,7 @@ void script_defaults(void) {
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 351ccd02a..a1fbe31f0 100644
--- a/src/map/script.h
+++ b/src/map/script.h
@@ -25,7 +25,6 @@
#include "common/hercules.h"
#include "common/db.h"
#include "common/mmo.h" // struct item
-#include "common/sql.h" // Sql
#include "common/strlib.h" //StringBuf
#include <errno.h>
@@ -34,6 +33,7 @@
/**
* Declarations
**/
+struct Sql; // common/sql.h
struct eri;
struct item_data;
@@ -94,11 +94,11 @@ struct item_data;
/// Pushes an int into the stack
#define script_pushint(st,val) (script->push_val((st)->stack, C_INT, (val),NULL))
/// Pushes a string into the stack (script engine frees it automatically)
-#define script_pushstr(st,val) (script->push_str((st)->stack, C_STR, (val)))
+#define script_pushstr(st,val) (script->push_str((st)->stack, (val)))
/// Pushes a copy of a string into the stack
-#define script_pushstrcopy(st,val) (script->push_str((st)->stack, C_STR, aStrdup(val)))
+#define script_pushstrcopy(st,val) (script->push_str((st)->stack, aStrdup(val)))
/// Pushes a constant string into the stack (must never change or be freed)
-#define script_pushconststr(st,val) (script->push_str((st)->stack, C_CONSTSTR, (val)))
+#define script_pushconststr(st,val) (script->push_conststr((st)->stack, (val)))
/// Pushes a nil into the stack
#define script_pushnil(st) (script->push_val((st)->stack, C_NOP, 0,NULL))
/// Pushes a copy of the data in the target index
@@ -380,14 +380,18 @@ struct script_retinfo {
int defsp; ///< default stack pointer
};
+/**
+ * Represents a variable in the script stack.
+ */
struct script_data {
- enum c_op type;
+ enum c_op type; ///< Data type
union script_data_val {
- int64 num;
- char *str;
- struct script_retinfo* ri;
- } u;
- struct reg_db *ref;
+ int64 num; ///< Numeric data
+ char *mutstr; ///< Mutable string
+ const char *str; ///< Constant string
+ struct script_retinfo *ri; ///< Function return information
+ } u; ///< Data (field depends on `type`)
+ struct reg_db *ref; ///< Reference to the scope's variables
};
// Moved defsp from script_state to script_stack since
@@ -490,8 +494,8 @@ struct script_syntax_data {
int last_func; // buildin index of the last parsed function
unsigned int nested_call; //Dont really know what to call this
bool lang_macro_active;
- DBMap *strings; // string map parsed (used when exporting strings only)
- DBMap *translation_db; //non-null if this npc has any translated strings to be linked
+ struct DBMap *strings; // string map parsed (used when exporting strings only)
+ struct DBMap *translation_db; //non-null if this npc has any translated strings to be linked
};
struct casecheck_data {
@@ -530,7 +534,7 @@ struct string_translation {
**/
struct script_interface {
/* */
- DBMap *st_db;
+ struct DBMap *st_db;
unsigned int active_scripts;
unsigned int next_id;
struct eri *st_ers;
@@ -598,8 +602,8 @@ struct script_interface {
/* */
/* Caches compiled autoscript item code. */
/* Note: This is not cleared when reloading itemdb. */
- DBMap* autobonus_db; // char* script -> char* bytecode
- DBMap* userfunc_db; // const char* func_name -> struct script_code*
+ struct DBMap *autobonus_db; // char* script -> char* bytecode
+ struct DBMap *userfunc_db; // const char* func_name -> struct script_code*
/* */
int potion_flag; //For use on Alchemist improved potions/Potion Pitcher. [Skotlex]
int potion_hp, potion_per_hp, potion_sp, potion_per_sp;
@@ -617,7 +621,7 @@ struct script_interface {
int buildin_select_offset;
int buildin_lang_macro_offset;
/* */
- DBMap *translation_db;/* npc_name => DBMap (strings) */
+ struct DBMap *translation_db;/* npc_name => DBMap (strings) */
char **translation_buf;/* */
uint32 translation_buf_size;
/* */
@@ -660,9 +664,10 @@ struct script_interface {
int (*get_val_scope_num) (struct script_state* st, struct reg_db *n, struct script_data* data);
int (*get_val_npc_num) (struct script_state* st, struct reg_db *n, struct script_data* data);
int (*get_val_instance_num) (struct script_state* st, const char* name, struct script_data* data);
- void* (*get_val2) (struct script_state* st, int64 uid, struct reg_db *ref);
- 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);
+ const void *(*get_val2) (struct script_state *st, int64 uid, struct reg_db *ref);
+ struct script_data *(*push_str) (struct script_stack *stack, char *str);
+ struct script_data *(*push_conststr) (struct script_stack *stack, const 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 is_parameter, bool is_deprecated);
void (*set_constant2) (const char *name, int value, bool is_parameter, bool is_deprecated);
@@ -687,7 +692,7 @@ struct script_interface {
int (*add_str) (const char* p);
const char* (*get_str) (int id);
int (*search_str) (const char* p);
- void (*setd_sub) (struct script_state *st, struct map_session_data *sd, const char *varname, int elem, void *value, struct reg_db *ref);
+ void (*setd_sub) (struct script_state *st, struct map_session_data *sd, const char *varname, int elem, const void *value, struct reg_db *ref);
void (*attach_state) (struct script_state* st);
/* */
struct script_queue *(*queue) (int idx);
@@ -725,6 +730,7 @@ struct script_interface {
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);
@@ -745,7 +751,7 @@ struct script_interface {
void (*op_1) (struct script_state *st, int op);
void (*check_buildin_argtype) (struct script_state *st, int func);
void (*detach_state) (struct script_state *st, bool dequeue_event);
- int (*db_free_code_sub) (DBKey key, DBData *data, va_list ap);
+ int (*db_free_code_sub) (union DBKey key, struct DBData *data, va_list ap);
void (*add_autobonus) (const char *autobonus);
int (*menu_countoptions) (const char *str, int max_count, int *total);
int (*buildin_areawarp_sub) (struct block_list *bl, va_list ap);
@@ -767,7 +773,7 @@ struct script_interface {
int (*playbgm_sub) (struct block_list *bl, va_list ap);
int (*playbgm_foreachpc_sub) (struct map_session_data *sd, va_list args);
int (*soundeffect_sub) (struct block_list *bl, va_list ap);
- int (*buildin_query_sql_sub) (struct script_state *st, Sql *handle);
+ int (*buildin_query_sql_sub) (struct script_state *st, struct Sql *handle);
int (*buildin_instance_warpall_sub) (struct block_list *bl, va_list ap);
int (*buildin_mobuseskill_sub) (struct block_list *bl, va_list ap);
int (*cleanfloor_sub) (struct block_list *bl, va_list ap);
@@ -788,11 +794,11 @@ struct script_interface {
void (*array_add_member) (struct script_array *sa, unsigned int idx);
unsigned int (*array_size) (struct script_state *st, struct map_session_data *sd, const char *name, struct reg_db *ref);
unsigned int (*array_highest_key) (struct script_state *st, struct map_session_data *sd, const char *name, struct reg_db *ref);
- int (*array_free_db) (DBKey key, DBData *data, va_list ap);
+ int (*array_free_db) (union DBKey key, struct DBData *data, va_list ap);
void (*array_ensure_zero) (struct script_state *st, struct map_session_data *sd, int64 uid, struct reg_db *ref);
/* */
void (*reg_destroy_single) (struct map_session_data *sd, int64 reg, struct script_reg_state *data);
- int (*reg_destroy) (DBKey key, DBData *data, va_list ap);
+ int (*reg_destroy) (union DBKey key, struct DBData *data, va_list ap);
/* */
void (*generic_ui_array_expand) (unsigned int plus);
unsigned int *(*array_cpy_list) (struct script_array *sa);
@@ -802,7 +808,7 @@ struct script_interface {
int (*string_dup) (char *str);
void (*load_translations) (void);
void (*load_translation) (const char *file, uint8 lang_id, uint32 *total);
- int (*translation_db_destroyer) (DBKey key, DBData *data, va_list ap);
+ int (*translation_db_destroyer) (union DBKey key, struct DBData *data, va_list ap);
void (*clear_translations) (bool reload);
int (*parse_cleanup_timer) (int tid, int64 tick, int id, intptr_t data);
uint8 (*add_language) (const char *name);
diff --git a/src/map/skill.c b/src/map/skill.c
index de5368cdf..51d0792e3 100644
--- a/src/map/skill.c
+++ b/src/map/skill.c
@@ -7505,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);
}
@@ -7517,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);
}
@@ -9280,7 +9280,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
improv_skill_lv = 4 + skill_lv;
clif->skill_nodamage (src, bl, skill_id, skill_lv, 1);
- if (sd == NULL) {
+ if (sd != NULL) {
sd->state.abra_flag = 2;
sd->skillitem = improv_skill_id;
sd->skillitemlv = improv_skill_lv;
@@ -9667,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;
@@ -9847,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;
@@ -10588,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;
@@ -10833,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;
@@ -11716,7 +11716,7 @@ int skill_unit_onplace(struct skill_unit *src, struct block_list *bl, int64 tick
if (bl->type == BL_PC && !working) {
struct map_session_data *sd = BL_UCAST(BL_PC, bl);
- if ((!sd->chatID || battle_config.chat_warpportal) && sd->ud.to_x == src->bl.x && sd->ud.to_y == src->bl.y) {
+ if ((sd->chat_id == 0 || battle_config.chat_warpportal) && sd->ud.to_x == src->bl.x && sd->ud.to_y == src->bl.y) {
int x = sg->val2>>16;
int y = sg->val2&0xffff;
int count = sg->val1>>16;
@@ -13122,7 +13122,8 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
nullpo_ret(sd);
- if (sd->chatID) return 0;
+ if (sd->chat_id != 0)
+ return 0;
if (pc_has_permission(sd, PC_PERM_SKILL_UNCONDITIONAL) && sd->skillitem != skill_id) {
//GMs don't override the skillItem check, otherwise they can use items without them being consumed! [Skotlex]
@@ -14088,7 +14089,7 @@ int skill_check_condition_castend(struct map_session_data* sd, uint16 skill_id,
nullpo_ret(sd);
- if( sd->chatID )
+ if (sd->chat_id != 0)
return 0;
if( pc_has_permission(sd, PC_PERM_SKILL_UNCONDITIONAL) && sd->skillitem != skill_id ) {
@@ -15313,12 +15314,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);
@@ -15351,7 +15352,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);
}
@@ -15994,14 +15995,14 @@ int skill_enchant_elemental_end (struct block_list *bl, int type) {
bool skill_check_cloaking(struct block_list *bl, struct status_change_entry *sce)
{
- static int dx[] = { 0, 1, 0, -1, -1, 1, 1, -1};
- static int dy[] = {-1, 0, 1, 0, -1, -1, 1, 1};
bool wall = true;
if( (bl->type == BL_PC && battle_config.pc_cloak_check_type&1)
|| (bl->type != BL_PC && battle_config.monster_cloak_check_type&1)
) {
//Check for walls.
+ static int dx[] = { 0, 1, 0, -1, -1, 1, 1, -1};
+ static int dy[] = {-1, 0, 1, 0, -1, -1, 1, 1};
int i;
ARR_FIND( 0, 8, i, map->getcell(bl->m, bl, bl->x+dx[i], bl->y+dy[i], CELL_CHKNOPASS) != 0 );
if( i == 8 )
@@ -16059,11 +16060,11 @@ int skill_check_cloaking_end(struct block_list *bl, va_list ap)
bool skill_check_camouflage(struct block_list *bl, struct status_change_entry *sce)
{
- static int dx[] = { 0, 1, 0, -1, -1, 1, 1, -1};
- static int dy[] = {-1, 0, 1, 0, -1, -1, 1, 1};
bool wall = true;
if( bl->type == BL_PC ) { //Check for walls.
+ static int dx[] = { 0, 1, 0, -1, -1, 1, 1, -1};
+ static int dy[] = {-1, 0, 1, 0, -1, -1, 1, 1};
int i;
ARR_FIND( 0, 8, i, map->getcell(bl->m, bl, bl->x+dx[i], bl->y+dy[i], CELL_CHKNOPASS) != 0 );
if( i == 8 )
@@ -16554,7 +16555,8 @@ int skill_unit_timer_sub_onplace(struct block_list* bl, va_list ap) {
/**
* @see DBApply
*/
-int skill_unit_timer_sub(DBKey key, DBData *data, va_list ap) {
+int skill_unit_timer_sub(union DBKey key, struct DBData *data, va_list ap)
+{
struct skill_unit* su = DB->data2ptr(data);
struct skill_unit_group* group = su->group;
int64 tick = va_arg(ap,int64);
diff --git a/src/map/skill.h b/src/map/skill.h
index fb2acfb62..35fddafa4 100644
--- a/src/map/skill.h
+++ b/src/map/skill.h
@@ -1856,12 +1856,12 @@ struct skill_interface {
void (*reload) (void);
void (*read_db) (bool minimal);
/* */
- DBMap* cd_db; // char_id -> struct skill_cd
- DBMap* name2id_db;
- DBMap* unit_db; // int id -> struct skill_unit*
- DBMap* usave_db; // char_id -> struct skill_unit_save
- DBMap* group_db;// int group_id -> struct skill_unit_group*
- DBMap* bowling_db;// int mob_id -> struct mob_data*s
+ struct DBMap *cd_db; // char_id -> struct skill_cd
+ struct DBMap *name2id_db;
+ struct DBMap *unit_db; // int id -> struct skill_unit*
+ struct DBMap *usave_db; // char_id -> struct skill_unit_save
+ struct DBMap *group_db;// int group_id -> struct skill_unit_group*
+ struct DBMap *bowling_db;// int mob_id -> struct mob_data*s
/* */
struct eri *unit_ers; //For handling skill_unit's [Skotlex]
struct eri *timer_ers; //For handling skill_timerskills [Skotlex]
@@ -2031,7 +2031,7 @@ struct skill_interface {
int (*blockmerc_end) (int tid, int64 tick, int id, intptr_t data);
int (*split_atoi) (char *str, int *val);
int (*unit_timer) (int tid, int64 tick, int id, intptr_t data);
- int (*unit_timer_sub) (DBKey key, DBData *data, va_list ap);
+ int (*unit_timer_sub) (union DBKey key, struct DBData *data, va_list ap);
void (*init_unit_layout) (void);
bool (*parse_row_skilldb) (char* split[], int columns, int current);
bool (*parse_row_requiredb) (char* split[], int columns, int current);
diff --git a/src/map/status.c b/src/map/status.c
index 82c427317..34bfd06b5 100644
--- a/src/map/status.c
+++ b/src/map/status.c
@@ -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];
@@ -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
@@ -3518,10 +3520,18 @@ void status_calc_regen_rate(struct block_list *bl, struct regen_data *regen, str
regen->flag &=~RGN_SP; //No natural SP regen
}
+
+ // Tension relax allows the user to recover HP while overweight
+ // at 1x speed. Other SC ignored? [csnv]
if (sc->data[SC_TENSIONRELAX]) {
- regen->rate.hp += 2;
- if (regen->sregen)
- regen->sregen->rate.hp += 3;
+ if (sc->data[SC_WEIGHTOVER50] || sc->data[SC_WEIGHTOVER90]) {
+ regen->flag &= ~RGN_SP;
+ regen->rate.hp = 1;
+ } else {
+ regen->rate.hp += 2;
+ if (regen->sregen)
+ regen->sregen->rate.hp += 3;
+ }
}
if (sc->data[SC_MAGNIFICAT]) {
@@ -4189,10 +4199,10 @@ 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:
@@ -4215,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
@@ -5566,9 +5576,9 @@ unsigned short status_calc_speed(struct block_list *bl, struct status_change *sc
{
int val = 0;
- if( sd && sc->data[SC_HIDING] && pc->checkskill(sd,RG_TUNNELDRIVE) > 0 )
+ if ( sd && sc->data[SC_HIDING] && pc->checkskill(sd,RG_TUNNELDRIVE) > 0 ) {
val = 120 - 6 * pc->checkskill(sd,RG_TUNNELDRIVE);
- else
+ } else {
if( sd && sc->data[SC_CHASEWALK] && sc->data[SC_CHASEWALK]->val3 < 0 )
val = sc->data[SC_CHASEWALK]->val3;
else
@@ -5638,8 +5648,8 @@ unsigned short status_calc_speed(struct block_list *bl, struct status_change *sc
if( sd && sd->bonus.speed_rate + sd->bonus.speed_add_rate > 0 ) // permanent item-based speedup
val = max( val, sd->bonus.speed_rate + sd->bonus.speed_add_rate );
}
-
- speed_rate += val;
+ }
+ speed_rate += val;
}
//GetMoveHasteValue1()
@@ -6241,7 +6251,13 @@ uint32 status_calc_mode(const struct block_list *bl, const struct status_change
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) {
@@ -6257,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;
}
/*==========================================
@@ -6266,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) {
@@ -6286,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) {
@@ -6376,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:
@@ -6431,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) {
@@ -6497,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:
@@ -6558,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)
@@ -6568,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)
@@ -7477,8 +7495,9 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
if (tick == 1) return 1; //Minimal duration: Only strip without causing the SC
break;
case SC_NOEQUIPSHIELD:
- if( val2 == 1 ) val2 = 0; //GX effect. Do not take shield off..
- else
+ if (val2 == 1) {
+ val2 = 0; //GX effect. Do not take shield off..
+ } else {
if (sd && !(flag&SCFLAG_LOADED)) {
int i;
if(sd->bonus.unstripable_equip&EQP_SHIELD)
@@ -7488,8 +7507,10 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
return 0;
pc->unequipitem(sd, i, PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE);
}
- if (tick == 1) return 1; //Minimal duration: Only strip without causing the SC
- break;
+ }
+ if (tick == 1)
+ return 1; //Minimal duration: Only strip without causing the SC
+ break;
case SC_NOEQUIPARMOR:
if (sd && !(flag&SCFLAG_LOADED)) {
int i;
@@ -11592,7 +11613,7 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) {
if( --(sce->val4) > 0 ) {
struct block_list *src = map->id2bl(sce->val2);
int damage;
- if( !src || (src && (status->isdead(src) || src->m != bl->m || distance_bl(src, bl) >= 12)) )
+ if (src == NULL || (status->isdead(src) || src->m != bl->m || distance_bl(src, bl) >= 12))
break;
map->freeblock_lock();
damage = sce->val3;
@@ -12432,8 +12453,10 @@ int status_natural_heal(struct block_list* bl, va_list args) {
}
}
- if (flag && regen->state.overweight)
- flag=0;
+ // SC_TENSIONRELAX allows HP to be recovered even when overweight. [csnv]
+ if (flag && regen->state.overweight && (sc == NULL || sc->data[SC_TENSIONRELAX] == NULL)) {
+ flag = 0;
+ }
ud = unit->bl2ud(bl);
@@ -12603,7 +12626,7 @@ void status_read_job_db_sub(int idx, const char *name, struct config_setting_t *
{ "FuumaShuriken", W_HUUMA },
{ "TwoHandRod", W_2HSTAFF },
#ifdef RENEWAL_ASPD
- { "Shield", MAX_WEAPON_TYPE }
+ { "Shield", MAX_SINGLE_WEAPON_TYPE }
#endif
};
@@ -12941,7 +12964,7 @@ int status_readdb_refine_libconfig(const char *filename) {
struct config_t refine_db_conf;
struct config_setting_t *r;
char filepath[256];
- int i = 0, count = 0,type = 0;
+ int i = 0, count = 0;
sprintf(filepath, "%s/%s", map->db_path, filename);
if (!libconfig->load_file(&refine_db_conf, filepath))
@@ -12951,10 +12974,13 @@ int status_readdb_refine_libconfig(const char *filename) {
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))) {
- if( duplicate[type-1] ) {
+ int type = status->readdb_refine_libconfig_sub(r, name, filename);
+ if (type != 0) {
+ if (duplicate[type-1]) {
ShowWarning("status_readdb_refine_libconfig: duplicate entry for %s in \"%s\", overwriting previous entry...\n", name, filename);
- } else duplicate[type-1] = true;
+ } else {
+ duplicate[type-1] = true;
+ }
count++;
}
}
@@ -12999,10 +13025,10 @@ 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
}
diff --git a/src/map/status.h b/src/map/status.h
index 4e2f1bdc0..2b932b149 100644
--- a/src/map/status.h
+++ b/src/map/status.h
@@ -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,7 +1808,6 @@ enum e_joint_break
BREAK_FLAGS = BREAK_ANKLE | BREAK_WRIST | BREAK_KNEE | BREAK_SHOULDER | BREAK_WAIST | BREAK_NECK,
};
-
/**
* Mob mode definitions. [Skotlex]
*
@@ -2159,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
@@ -2216,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);
@@ -2272,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);
diff --git a/src/map/storage.c b/src/map/storage.c
index ceac85916..91b37eb19 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_)
{
- const struct item *i1 = (const struct item *)i1_;
- const struct item *i2 = (const struct item *)i2_;
+ const struct item *i1 = i1_;
+ const struct item *i2 = i2_;
if (i1->nameid == i2->nameid)
return 0;
@@ -79,7 +79,7 @@ void storage_sortitem(struct item* items, unsigned int size)
* Parses storage and saves 'dirty' ones upon reconnect. [Skotlex]
* @see DBApply
*/
-int storage_reconnect_sub(DBKey key, DBData *data, va_list ap)
+int storage_reconnect_sub(union DBKey key, struct DBData *data, va_list ap)
{
struct guild_storage *stor = DB->data2ptr(data);
if (stor->dirty && stor->storage_status == 0) //Save closed storages.
@@ -366,7 +366,7 @@ void storage_storage_quit(struct map_session_data* sd, int flag) {
/**
* @see DBCreateData
*/
-DBData create_guildstorage(DBKey key, va_list args)
+struct DBData create_guildstorage(union DBKey key, va_list args)
{
struct guild_storage *gs = NULL;
gs = (struct guild_storage *) aCalloc(sizeof(struct guild_storage), 1);
diff --git a/src/map/storage.h b/src/map/storage.h
index bddd03770..94512c456 100644
--- a/src/map/storage.h
+++ b/src/map/storage.h
@@ -52,11 +52,11 @@ struct storage_interface {
void (*pc_quit) (struct map_session_data *sd, int flag);
int (*comp_item) (const void *i1_, const void *i2_);
void (*sortitem) (struct item* items, unsigned int size);
- int (*reconnect_sub) (DBKey key, DBData *data, va_list ap);
+ int (*reconnect_sub) (union DBKey key, struct DBData *data, va_list ap);
};
struct guild_storage_interface {
- struct DBMap* db; // int guild_id -> struct guild_storage*
+ struct DBMap *db; // int guild_id -> struct guild_storage*
/* */
struct guild_storage *(*ensure) (int guild_id);
/* */
@@ -75,7 +75,7 @@ struct guild_storage_interface {
int (*pc_quit) (struct map_session_data *sd,int flag);
int (*save) (int account_id, int guild_id, int flag);
int (*saved) (int guild_id); //Ack from char server that guild store was saved.
- DBData (*create) (DBKey key, va_list args);
+ struct DBData (*create) (union DBKey key, va_list args);
};
#ifdef HERCULES_CORE
diff --git a/src/map/unit.c b/src/map/unit.c
index 9a698b77e..ac1e3e9b5 100644
--- a/src/map/unit.c
+++ b/src/map/unit.c
@@ -1220,6 +1220,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui
ud = unit->bl2ud(src);
if(ud == NULL) return 0;
+
sc = status->get_sc(src);
if (sc && !sc->count)
sc = NULL; //Unneeded
@@ -2289,11 +2290,18 @@ int unit_skillcastcancel(struct block_list *bl,int type)
// unit_data initialization process
void unit_dataset(struct block_list *bl) {
- struct unit_data *ud;
- nullpo_retv(ud = unit->bl2ud(bl));
+ struct unit_data *ud = unit->bl2ud(bl);
+ nullpo_retv(ud);
+
+ unit->init_ud(ud);
+ ud->bl = bl;
+}
+
+void unit_init_ud(struct unit_data *ud)
+{
+ nullpo_retv(ud);
- memset( ud, 0, sizeof( struct unit_data) );
- ud->bl = bl;
+ memset (ud, 0, sizeof(struct unit_data));
ud->walktimer = INVALID_TIMER;
ud->skilltimer = INVALID_TIMER;
ud->attacktimer = INVALID_TIMER;
@@ -2433,7 +2441,7 @@ int unit_remove_map(struct block_list *bl, clr_type clrtype, const char* file, i
status_change_end(d_bl,SC__SHADOWFORM,INVALID_TIMER);
}
//Leave/reject all invitations.
- if(sd->chatID)
+ if (sd->chat_id != 0)
chat->leave(sd, false);
if(sd->trade_partner)
trade->cancel(sd);
@@ -2895,6 +2903,7 @@ void unit_defaults(void) {
/* */
unit->bl2ud = unit_bl2ud;
unit->bl2ud2 = unit_bl2ud2;
+ unit->init_ud = unit_init_ud;
unit->attack_timer = unit_attack_timer;
unit->walktoxy_timer = unit_walktoxy_timer;
unit->walktoxy_sub = unit_walktoxy_sub;
diff --git a/src/map/unit.h b/src/map/unit.h
index 0279d73c1..8c4c34696 100644
--- a/src/map/unit.h
+++ b/src/map/unit.h
@@ -105,6 +105,7 @@ struct unit_interface {
/* */
struct unit_data* (*bl2ud) (struct block_list *bl);
struct unit_data* (*bl2ud2) (struct block_list *bl);
+ void (*init_ud) (struct unit_data *ud);
int (*attack_timer) (int tid, int64 tick, int id, intptr_t data);
int (*walktoxy_timer) (int tid, int64 tick, int id, intptr_t data);
int (*walktoxy_sub) (struct block_list *bl);
diff --git a/src/map/vending.c b/src/map/vending.c
index 2346932ba..e3a62bea7 100644
--- a/src/map/vending.c
+++ b/src/map/vending.c
@@ -118,7 +118,7 @@ void vending_purchasereq(struct map_session_data* sd, int aid, unsigned int uid,
// some checks
z = 0; // zeny counter
w = 0; // weight counter
- for( i = 0; i < count; i++ ) {
+ for (i = 0; i < count; i++) {
short amount = *(const uint16*)(data + 4*i + 0);
short idx = *(const uint16*)(data + 4*i + 2);
idx -= 2;
@@ -184,7 +184,7 @@ void vending_purchasereq(struct map_session_data* sd, int aid, unsigned int uid,
z -= apply_percentrate64(z, battle_config.vending_tax, 10000);
pc->getzeny(vsd, (int)z, LOG_TYPE_VENDING, sd);
- for( i = 0; i < count; i++ ) {
+ for (i = 0; i < count; i++) {
short amount = *(const uint16*)(data + 4*i + 0);
short idx = *(const uint16*)(data + 4*i + 2);
idx -= 2;
@@ -199,7 +199,7 @@ void vending_purchasereq(struct map_session_data* sd, int aid, unsigned int uid,
if( battle_config.buyer_name ) {
char temp[256];
sprintf(temp, msg_sd(vsd,265), sd->status.name);
- clif_disp_onlyself(vsd,temp,strlen(temp));
+ clif_disp_onlyself(vsd, temp);
}
}
@@ -265,7 +265,7 @@ void vending_openvending(struct map_session_data* sd, const char* message, const
// filter out invalid items
i = 0;
- for( j = 0; j < count; j++ ) {
+ for (j = 0; j < count; j++) {
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);
diff --git a/src/map/vending.h b/src/map/vending.h
index 6684ed256..1d2135076 100644
--- a/src/map/vending.h
+++ b/src/map/vending.h
@@ -22,8 +22,9 @@
#define MAP_VENDING_H
#include "common/hercules.h"
-#include "common/db.h"
+/* Forward Declarations */
+struct DBMap; // common/db.h
struct map_session_data;
struct s_search_store_search;
@@ -35,7 +36,7 @@ struct s_vending {
struct vending_interface {
unsigned int next_id;/* next vender id */
- DBMap *db;
+ struct DBMap *db;
/* */
void (*init) (bool minimal);
void (*final) (void);