summaryrefslogtreecommitdiff
path: root/src/map
diff options
context:
space:
mode:
Diffstat (limited to 'src/map')
-rw-r--r--src/map/Makefile.in2
-rw-r--r--src/map/atcommand.c57
-rw-r--r--src/map/atcommand.h5
-rw-r--r--src/map/battle.c79
-rw-r--r--src/map/battle.h2
-rw-r--r--src/map/battleground.c7
-rw-r--r--src/map/battleground.h2
-rw-r--r--src/map/channel.c77
-rw-r--r--src/map/chat.c18
-rw-r--r--src/map/chrif.c2
-rw-r--r--src/map/clif.c1011
-rw-r--r--src/map/clif.h48
-rw-r--r--src/map/duel.c16
-rw-r--r--src/map/guild.c18
-rw-r--r--src/map/guild.h2
-rw-r--r--src/map/homunculus.c2
-rw-r--r--src/map/instance.c9
-rw-r--r--src/map/intif.c37
-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.c4
-rw-r--r--src/map/map.c19
-rw-r--r--src/map/mob.c103
-rw-r--r--src/map/npc.c112
-rw-r--r--src/map/npc.h10
-rw-r--r--src/map/npc_chat.c36
-rw-r--r--src/map/packets_struct.h885
-rw-r--r--src/map/party.c76
-rw-r--r--src/map/party.h2
-rw-r--r--src/map/path.c13
-rw-r--r--src/map/pc.c349
-rw-r--r--src/map/pc.h13
-rw-r--r--src/map/script.c1401
-rw-r--r--src/map/script.h63
-rw-r--r--src/map/skill.c125
-rw-r--r--src/map/skill.h3
-rw-r--r--src/map/status.c796
-rw-r--r--src/map/status.h12
-rw-r--r--src/map/unit.c19
-rw-r--r--src/map/unit.h1
-rw-r--r--src/map/vending.c4
42 files changed, 3215 insertions, 2577 deletions
diff --git a/src/map/Makefile.in b/src/map/Makefile.in
index ff582d2f9..3c6a3f806 100644
--- a/src/map/Makefile.in
+++ b/src/map/Makefile.in
@@ -23,7 +23,7 @@ CONFIG_D = ../config
CONFIG_H = $(wildcard $(CONFIG_D)/*.h) $(wildcard $(CONFIG_D)/*/*.h)
COMMON_D = ../common
-COMMON_H = $(filter-out %.p.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..
diff --git a/src/map/atcommand.c b/src/map/atcommand.c
index 3da5c203f..eef67189a 100644
--- a/src/map/atcommand.c
+++ b/src/map/atcommand.c
@@ -132,7 +132,6 @@ bool msg_config_read(const char *cfg_name, bool allow_override) {
int msg_number;
char line[1024], w1[1024], w2[1024];
FILE *fp;
- static int called = 1;
nullpo_retr(false, cfg_name);
if ((fp = fopen(cfg_name, "r")) == NULL) {
@@ -170,21 +169,6 @@ bool msg_config_read(const char *cfg_name, bool allow_override) {
}
fclose(fp);
- if( ++called == 1 ) { //Original
- if( script->lang_export_fp ) {
- int i;
- for(i = 0; i < MAX_MSG;i++) {
- if( atcommand->msg_table[0][i] != NULL ) {
- fprintf(script->lang_export_fp, "msgctxt \"messages.conf\"\n"
- "msgid \"%s\"\n"
- "msgstr \"\"\n",
- atcommand->msg_table[0][i]
- );
- }
- }
- }
- }
-
return true;
}
@@ -266,22 +250,22 @@ ACMD(send)
clif->message(fd, atcmd_output);
return false;
}
-
+
if (len) {
// show packet length
safesnprintf(atcmd_output, sizeof(atcmd_output), msg_fd(fd,904), type, clif->packet(type)->len); // Packet 0x%x length: %d
clif->message(fd, atcmd_output);
return true;
}
-
+
len = clif->packet(type)->len;
-
+
if (len == -1) {
// dynamic packet
len = SHRT_MAX-4; // maximum length
off = 4;
}
-
+
WFIFOHEAD(sd->fd, len);
WFIFOW(sd->fd,0)=TOW(type);
@@ -1091,9 +1075,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 +1088,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;
}
@@ -3748,7 +3732,7 @@ ACMD(reloadscript) {
* 1 = Show users in that map and their location
* 2 = Shows NPCs in that map
* 3 = Shows the chats in that map
- TODO# add the missing mapflags e.g. adjust_skill_damage to display
+ * TODO# add the missing mapflags e.g. adjust_skill_damage to display
*------------------------------------------*/
ACMD(mapinfo)
{
@@ -3793,7 +3777,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++;
}
}
@@ -3972,7 +3956,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);
@@ -4153,8 +4137,9 @@ ACMD(repairall)
count = 0;
for (i = 0; i < MAX_INVENTORY; i++) {
- if (sd->status.inventory[i].nameid && sd->status.inventory[i].attribute == 1) {
- sd->status.inventory[i].attribute = 0;
+ if (sd->status.inventory[i].nameid && (sd->status.inventory[i].attribute & ATTR_BROKEN) != 0) {
+ sd->status.inventory[i].attribute |= ATTR_BROKEN;
+ sd->status.inventory[i].attribute ^= ATTR_BROKEN;
clif->produce_effect(sd, 0, sd->status.inventory[i].nameid);
count++;
}
@@ -4911,7 +4896,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;
}
@@ -4930,7 +4915,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;
}
@@ -6779,7 +6764,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 )
@@ -7836,7 +7821,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
@@ -7844,7 +7829,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.
@@ -7855,7 +7840,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
@@ -7863,7 +7848,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.
@@ -7958,7 +7943,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;
}
diff --git a/src/map/atcommand.h b/src/map/atcommand.h
index 0e7895825..ef8be7807 100644
--- a/src/map/atcommand.h
+++ b/src/map/atcommand.h
@@ -152,7 +152,8 @@ void atcommand_defaults(void);
HPShared struct atcommand_interface *atcommand;
/* stay here */
-#define ACMD(x) static bool atcommand_ ## x (const int fd, struct map_session_data* sd, const char* command, const char* message, struct AtCommandInfo *info) __attribute__((nonnull (2, 3, 4, 5))); \
- static bool atcommand_ ## x (const int fd, struct map_session_data* sd, const char* command, const char* message, struct AtCommandInfo *info)
+#define ACMD(x) \
+ static bool atcommand_ ## x (const int fd, struct map_session_data* sd, const char* command, const char* message, struct AtCommandInfo *info) __attribute__((nonnull (2, 3, 4, 5))); \
+ static bool atcommand_ ## x (const int fd, struct map_session_data* sd, const char* command, const char* message, struct AtCommandInfo *info)
#endif /* MAP_ATCOMMAND_H */
diff --git a/src/map/battle.c b/src/map/battle.c
index a7a6f4719..944271efa 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.
@@ -6010,6 +6009,46 @@ int battle_damage_area(struct block_list *bl, va_list ap) {
return 0;
}
+
+bool battle_check_arrows(struct map_session_data *sd)
+{
+ int index = sd->equip_index[EQI_AMMO];
+ if (index < 0) {
+ if (sd->weapontype1 > W_KATAR && sd->weapontype1 < W_HUUMA)
+ clif->skill_fail(sd, 0, USESKILL_FAIL_NEED_MORE_BULLET, 0);
+ else
+ clif->arrow_fail(sd, 0);
+ return false;
+ }
+ //Ammo check by Ishizu-chan
+ if (sd->inventory_data[index]) {
+ switch (sd->status.weapon) {
+ case W_BOW:
+ if (sd->inventory_data[index]->look != A_ARROW) {
+ clif->arrow_fail(sd, 0);
+ return false;
+ }
+ break;
+ case W_REVOLVER:
+ case W_RIFLE:
+ case W_GATLING:
+ case W_SHOTGUN:
+ if (sd->inventory_data[index]->look != A_BULLET) {
+ clif->skill_fail(sd, 0, USESKILL_FAIL_NEED_MORE_BULLET, 0);
+ return false;
+ }
+ break;
+ case W_GRENADE:
+ if (sd->inventory_data[index]->look != A_GRENADE) {
+ clif->skill_fail(sd, 0, USESKILL_FAIL_NEED_MORE_BULLET, 0);
+ return false;
+ }
+ break;
+ }
+ }
+ return true;
+}
+
/*==========================================
* Do a basic physical attack (call trough unit_attack_timer)
*------------------------------------------*/
@@ -6047,39 +6086,8 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
sd->state.arrow_atk = (sd->status.weapon == W_BOW || (sd->status.weapon >= W_REVOLVER && sd->status.weapon <= W_GRENADE));
if (sd->state.arrow_atk)
{
- int index = sd->equip_index[EQI_AMMO];
- if (index<0) {
- if ( sd->weapontype1 > W_KATAR && sd->weapontype1 < W_HUUMA )
- clif->skill_fail(sd, 0, USESKILL_FAIL_NEED_MORE_BULLET, 0);
- else
- clif->arrow_fail(sd, 0);
+ if (battle->check_arrows(sd) == false)
return ATK_NONE;
- }
- //Ammo check by Ishizu-chan
- if (sd->inventory_data[index])
- switch (sd->status.weapon) {
- case W_BOW:
- if (sd->inventory_data[index]->look != A_ARROW) {
- clif->arrow_fail(sd,0);
- return ATK_NONE;
- }
- break;
- case W_REVOLVER:
- case W_RIFLE:
- case W_GATLING:
- case W_SHOTGUN:
- if (sd->inventory_data[index]->look != A_BULLET) {
- clif->skill_fail(sd, 0, USESKILL_FAIL_NEED_MORE_BULLET, 0);
- return ATK_NONE;
- }
- break;
- case W_GRENADE:
- if (sd->inventory_data[index]->look != A_GRENADE) {
- clif->skill_fail(sd, 0, USESKILL_FAIL_NEED_MORE_BULLET, 0);
- return ATK_NONE;
- }
- break;
- }
}
}
if (sc && sc->count) {
@@ -7606,6 +7614,7 @@ void battle_defaults(void) {
battle->calc_gvg_damage = battle_calc_gvg_damage;
battle->calc_bg_damage = battle_calc_bg_damage;
battle->weapon_attack = battle_weapon_attack;
+ battle->check_arrows = battle_check_arrows;
battle->calc_weapon_attack = battle_calc_weapon_attack;
battle->delay_damage = battle_delay_damage;
battle->drain = battle_drain;
diff --git a/src/map/battle.h b/src/map/battle.h
index 49abdc730..6fa600ada 100644
--- a/src/map/battle.h
+++ b/src/map/battle.h
@@ -593,6 +593,8 @@ struct battle_interface {
int64 (*calc_bg_damage) (struct block_list *src, struct block_list *bl, int64 damage, int div_, uint16 skill_id, uint16 skill_lv, int flag);
/* normal weapon attack */
enum damage_lv (*weapon_attack) (struct block_list *bl, struct block_list *target, int64 tick, int flag);
+ /* check is equipped ammo and this ammo allowed */
+ bool (*check_arrows) (struct map_session_data *sd);
/* calculate weapon attack */
struct Damage (*calc_weapon_attack) (struct block_list *src,struct block_list *target,uint16 skill_id,uint16 skill_lv,int wflag);
/* delays damage or skills by a timer */
diff --git a/src/map/battleground.c b/src/map/battleground.c
index 629122c87..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,14 +265,15 @@ 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;
}
diff --git a/src/map/battleground.h b/src/map/battleground.h
index 8657beaf8..4c3d4878f 100644
--- a/src/map/battleground.h
+++ b/src/map/battleground.h
@@ -130,7 +130,7 @@ 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);
+ 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);
diff --git a/src/map/channel.c b/src/map/channel.c
index 3d1b3f975..ee8242b23 100644
--- a/src/map/channel.c
+++ b/src/map/channel.c
@@ -609,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";
@@ -640,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)
@@ -699,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 )
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/chrif.c b/src/map/chrif.c
index 52af1137e..51e8e5143 100644
--- a/src/map/chrif.c
+++ b/src/map/chrif.c
@@ -236,11 +236,13 @@ void chrif_setpasswd(char *pwd) {
// security check, prints warning if using default password
void chrif_checkdefaultlogin(void) {
+#ifndef BUILDBOT
if (strcmp(chrif->userid, "s1")==0 && strcmp(chrif->passwd, "p1")==0) {
ShowWarning("Using the default user/password s1/p1 is NOT RECOMMENDED.\n");
ShowNotice("Please edit your 'login' table to create a proper inter-server user/password (gender 'S')\n");
ShowNotice("and then edit your user/password in conf/map-server.conf (or conf/import/map_conf.txt)\n");
}
+#endif
}
// sets char-server's ip address
diff --git a/src/map/clif.c b/src/map/clif.c
index e1b4be8f4..0f6e985fd 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -190,7 +190,7 @@ static inline void RFIFOPOS2(int fd, unsigned short pos, short* x0, short* y0, s
#endif // 0
//To identify disguised characters.
-static inline bool disguised(struct block_list* bl)
+bool clif_isdisguised(struct block_list* bl)
{
struct map_session_data *sd = BL_CAST(BL_PC, bl);
if (sd == NULL || sd->disguise == -1)
@@ -265,24 +265,50 @@ uint32 clif_refresh_ip(void)
return 0;
}
+unsigned char clif_bl_type(struct block_list *bl)
+{
#if PACKETVER >= 20071106
-static inline unsigned char clif_bl_type(struct block_list *bl) {
- nullpo_retr(0x1, bl);
+ struct view_data *vd;
+ nullpo_retr(CLUT_NPC, bl);
+
switch (bl->type) {
- case BL_PC: return (disguised(bl) && !pc->db_checkid(status->get_viewdata(bl)->class_))? 0x1:0x0; //PC_TYPE
- case BL_ITEM: return 0x2; //ITEM_TYPE
- case BL_SKILL: return 0x3; //SKILL_TYPE
- case BL_CHAT: return 0x4; //UNKNOWN_TYPE
- case BL_MOB: return pc->db_checkid(status->get_viewdata(bl)->class_)?0x0:0x5; //NPC_MOB_TYPE
- case BL_NPC: return pc->db_checkid(status->get_viewdata(bl)->class_)?0x0:0x6; //NPC_EVT_TYPE
- case BL_PET: return pc->db_checkid(status->get_viewdata(bl)->class_)?0x0:0x7; //NPC_PET_TYPE
- case BL_HOM: return 0x8; //NPC_HOM_TYPE
- case BL_MER: return 0x9; //NPC_MERSOL_TYPE
- case BL_ELEM: return 0xa; //NPC_ELEMENTAL_TYPE
- default: return 0x1; //NPC_TYPE
+ case BL_PC:
+ vd = status->get_viewdata(bl);
+ nullpo_retr(CLUT_NPC, vd);
+
+ if (clif->isdisguised(bl) && !pc->db_checkid(vd->class_))
+ return CLUT_NPC;
+ return CLUT_PC;
+ case BL_ITEM:
+ return CLUT_ITEM;
+ case BL_SKILL:
+ return CLUT_SKILL;
+ case BL_CHAT:
+ return CLUT_UNKNOWN;
+ case BL_MOB:
+ vd = status->get_viewdata(bl);
+ nullpo_retr(CLUT_NPC, vd);
+ return pc->db_checkid(vd->class_) ? CLUT_PC : CLUT_MOB;
+ case BL_NPC:
+ vd = status->get_viewdata(bl);
+ nullpo_retr(CLUT_NPC, vd);
+ return pc->db_checkid(vd->class_) ? CLUT_PC : CLUT_EVENT;
+ case BL_PET:
+ vd = status->get_viewdata(bl);
+ nullpo_retr(CLUT_NPC, vd);
+ return pc->db_checkid(vd->class_) ? CLUT_PC : CLUT_PET;
+ case BL_HOM:
+ return CLUT_HOMNUCLUS;
+ case BL_MER:
+ return CLUT_MERCNARY;
+ case BL_ELEM:
+ return CLUT_ELEMENTAL;
+ default:
+ return CLUT_NPC;
}
-}
#endif
+ return CLUT_UNKNOWN;
+}
/*==========================================
* sub process of clif_send
@@ -319,17 +345,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 +461,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);
}
@@ -823,7 +849,7 @@ void clif_clearunit_area(struct block_list* bl, clr_type type)
clif->send(buf, packet_len(0x80), bl, type == CLR_DEAD ? AREA : AREA_WOS);
- if(disguised(bl)) {
+ if (clif->isdisguised(bl)) {
WBUFL(buf,2) = -bl->id;
clif->send(buf, packet_len(0x80), bl, SELF);
}
@@ -928,7 +954,7 @@ void clif_set_unit_idle2(struct block_list* bl, struct map_session_data *tsd, en
p.PacketType = idle_unit2Type;
#if PACKETVER >= 20071106
- p.objecttype = clif_bl_type(bl);
+ p.objecttype = clif->bl_type(bl);
#endif
p.GID = bl->id;
p.speed = status->get_speed(bl);
@@ -990,7 +1016,7 @@ void clif_set_unit_idle(struct block_list* bl, struct map_session_data *tsd, enu
p.PacketType = idle_unitType;
#if PACKETVER >= 20091103
p.PacketLength = sizeof(p);
- p.objecttype = clif_bl_type(bl);
+ p.objecttype = clif->bl_type(bl);
#endif
#if PACKETVER >= 20131223
p.AID = bl->id;
@@ -1054,7 +1080,7 @@ void clif_set_unit_idle(struct block_list* bl, struct map_session_data *tsd, enu
clif->send(&p,sizeof(p),tsd?&tsd->bl:bl,target);
- if( disguised(bl) ) {
+ if (clif->isdisguised(bl)) {
#if PACKETVER >= 20091103
p.objecttype = pc->db_checkid(status->get_viewdata(bl)->class_) ? 0x0 : 0x5; //PC_TYPE : NPC_MOB_TYPE
p.GID = -bl->id;
@@ -1079,7 +1105,7 @@ void clif_spawn_unit2(struct block_list* bl, enum send_target target) {
p.PacketType = spawn_unit2Type;
#if PACKETVER >= 20071106
- p.objecttype = clif_bl_type(bl);
+ p.objecttype = clif->bl_type(bl);
#endif
p.GID = bl->id;
p.speed = status->get_speed(bl);
@@ -1132,7 +1158,7 @@ void clif_spawn_unit(struct block_list* bl, enum send_target target) {
p.PacketType = spawn_unitType;
#if PACKETVER >= 20091103
p.PacketLength = sizeof(p);
- p.objecttype = clif_bl_type(bl);
+ p.objecttype = clif->bl_type(bl);
#endif
#if PACKETVER >= 20131223
p.AID = bl->id;
@@ -1192,7 +1218,7 @@ void clif_spawn_unit(struct block_list* bl, enum send_target target) {
p.body = vd->body_style;
safestrncpy(p.name, clif->get_bl_name(bl), NAME_LENGTH);
#endif
- if( disguised(bl) ) {
+ if (clif->isdisguised(bl)) {
nullpo_retv(sd);
if( sd->status.class_ != sd->disguise )
clif->send(&p,sizeof(p),bl,target);
@@ -1228,7 +1254,7 @@ void clif_set_unit_walking(struct block_list* bl, struct map_session_data *tsd,
p.PacketLength = sizeof(p);
#endif
#if PACKETVER >= 20071106
- p.objecttype = clif_bl_type(bl);
+ p.objecttype = clif->bl_type(bl);
#endif
#if PACKETVER >= 20131223
p.AID = bl->id;
@@ -1287,7 +1313,7 @@ void clif_set_unit_walking(struct block_list* bl, struct map_session_data *tsd,
clif->send(&p,sizeof(p),tsd?&tsd->bl:bl,target);
- if( disguised(bl) ) {
+ if (clif->isdisguised(bl)) {
#if PACKETVER >= 20091103
p.objecttype = pc->db_checkid(status->get_viewdata(bl)->class_) ? 0x0 : 0x5; //PC_TYPE : NPC_MOB_TYPE
p.GID = -bl->id;
@@ -1756,7 +1782,7 @@ void clif_move(struct unit_data *ud)
clif->send(buf, packet_len(0x86), bl, AREA_WOS);
- if (disguised(bl)) {
+ if (clif->isdisguised(bl)) {
WBUFL(buf,2)=-bl->id;
clif->send(buf, packet_len(0x86), bl, SELF);
}
@@ -1849,7 +1875,7 @@ void clif_fixpos(struct block_list *bl) {
WBUFW(buf,8) = bl->y;
clif->send(buf, packet_len(0x88), bl, AREA);
- if( disguised(bl) ) {
+ if (clif->isdisguised(bl)) {
WBUFL(buf,2) = -bl->id;
clif->send(buf, packet_len(0x88), bl, SELF);
}
@@ -1957,21 +1983,38 @@ 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;
+#ifdef SCRIPT_MES_STRIP_LINEBREAK
+ char *stripmes = NULL;
+ int i;
+#endif
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;
+#ifdef SCRIPT_MES_STRIP_LINEBREAK
+ stripmes = aStrdup(mes);
+ for (i = 0; stripmes[i] != '\0'; ++i) {
+ if (stripmes[i] == '\r')
+ stripmes[i] = ' ';
+ }
+ memcpy(WFIFOP(fd,8), stripmes, slen-8);
+ aFree(stripmes);
+#else // ! SCRIPT_MES_STRIP_LINEBREAK
memcpy(WFIFOP(fd,8), mes, slen-8);
+#endif // SCRIPT_MES_STRIP_LINEBREAK
WFIFOSET(fd,WFIFOW(fd,2));
}
@@ -2072,24 +2115,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));
}
@@ -2359,7 +2405,7 @@ void clif_additem(struct map_session_data *sd, int n, int amount, int fail) {
p.nameid = sd->status.inventory[n].nameid;
p.IsIdentified = sd->status.inventory[n].identify ? 1 : 0;
- p.IsDamaged = sd->status.inventory[n].attribute ? 1 : 0;
+ p.IsDamaged = (sd->status.inventory[n].attribute & ATTR_BROKEN) != 0 ? 1 : 0;
p.refiningLevel =sd->status.inventory[n].refine;
clif->addcards2(&p.slot.card[0], &sd->status.inventory[n]);
p.location = pc->equippoint(sd,n);
@@ -2474,7 +2520,7 @@ void clif_item_equip(short idx, struct EQUIPITEM_INFO *p, struct item *i, struct
p->location = eqp_pos;
p->WearState = i->equip;
#if PACKETVER < 20120925
- p->IsDamaged = i->attribute ? 1 : 0;
+ p->IsDamaged = (i->attribute & ATTR_BROKEN) != 0 ? 1 : 0;
#endif
p->RefiningLevel = i->refine;
@@ -2494,7 +2540,7 @@ void clif_item_equip(short idx, struct EQUIPITEM_INFO *p, struct item *i, struct
#if PACKETVER >= 20120925
p->Flag.IsIdentified = i->identify ? 1 : 0;
- p->Flag.IsDamaged = i->attribute ? 1 : 0;
+ p->Flag.IsDamaged = (i->attribute & ATTR_BROKEN) != 0 ? 1 : 0;
p->Flag.PlaceETCTab = i->favorite ? 1 : 0;
p->Flag.SpareBits = 0;
#endif
@@ -3192,7 +3238,7 @@ void clif_changelook(struct block_list *bl,int type,int val)
}
// prevent leaking the presence of GM-hidden objects
- if( sc && sc->option&OPTION_INVISIBLE && !disguised(bl) )
+ if (sc && sc->option&OPTION_INVISIBLE && !clif->isdisguised(bl))
target = SELF;
#if PACKETVER < 4
clif->sendlook(bl, bl->id, type, val, 0, target);
@@ -3203,11 +3249,12 @@ void clif_changelook(struct block_list *bl,int type,int val)
val = vd->weapon;
val2 = vd->shield;
}
- if( disguised(bl) ) {
+ if (clif->isdisguised(bl)) {
clif->sendlook(bl, bl->id, type, val, val2, AREA_WOS);
clif->sendlook(bl, -bl->id, type, val, val2, SELF);
- } else
+ } else {
clif->sendlook(bl, bl->id, type, val, val2, target);
+ }
#endif
}
@@ -3488,15 +3535,16 @@ void clif_changeoption(struct block_list* bl)
WBUFW(buf,8) = (sc) ? sc->opt2 : 0;
WBUFL(buf,10) = (sc != NULL) ? sc->option : ((bl->type == BL_NPC) ? BL_UCCAST(BL_NPC, bl)->option : 0);
WBUFB(buf,14) = (sd)? sd->status.karma : 0;
- if(disguised(bl)) {
+ if (clif->isdisguised(bl)) {
clif->send(buf,packet_len(0x229),bl,AREA_WOS);
WBUFL(buf,2) = -bl->id;
clif->send(buf,packet_len(0x229),bl,SELF);
WBUFL(buf,2) = bl->id;
WBUFL(buf,10) = OPTION_INVISIBLE;
clif->send(buf,packet_len(0x229),bl,SELF);
- } else
+ } else {
clif->send(buf,packet_len(0x229),bl,AREA);
+ }
#else
WBUFW(buf,0) = 0x119;
WBUFL(buf,2) = bl->id;
@@ -3504,15 +3552,16 @@ void clif_changeoption(struct block_list* bl)
WBUFW(buf,8) = (sc) ? sc->opt2 : 0;
WBUFL(buf,10) = (sc != NULL) ? sc->option : ((bl->type == BL_NPC) ? BL_UCCAST(BL_NPC, bl)->option : 0);
WBUFB(buf,12) = (sd)? sd->status.karma : 0;
- if(disguised(bl)) {
+ if (clif->isdisguised(bl)) {
clif->send(buf,packet_len(0x119),bl,AREA_WOS);
WBUFL(buf,2) = -bl->id;
clif->send(buf,packet_len(0x119),bl,SELF);
WBUFL(buf,2) = bl->id;
WBUFW(buf,10) = OPTION_INVISIBLE;
clif->send(buf,packet_len(0x119),bl,SELF);
- } else
+ } else {
clif->send(buf,packet_len(0x119),bl,AREA);
+ }
#endif
}
@@ -3530,15 +3579,16 @@ void clif_changeoption2(struct block_list* bl) {
WBUFL(buf,6) = (sc != NULL) ? sc->option : ((bl->type == BL_NPC) ? BL_UCCAST(BL_NPC, bl)->option : 0);
WBUFL(buf,10) = clif_setlevel(bl);
WBUFL(buf,14) = (sc) ? sc->opt3 : 0;
- if(disguised(bl)) {
+ if (clif->isdisguised(bl)) {
clif->send(buf,packet_len(0x28a),bl,AREA_WOS);
WBUFL(buf,2) = -bl->id;
clif->send(buf,packet_len(0x28a),bl,SELF);
WBUFL(buf,2) = bl->id;
WBUFL(buf,6) = OPTION_INVISIBLE;
clif->send(buf,packet_len(0x28a),bl,SELF);
- } else
+ } else {
clif->send(buf,packet_len(0x28a),bl,AREA);
+ }
}
/// Notifies the client about the result of an item use request.
@@ -3610,26 +3660,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));
@@ -3647,10 +3700,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;
@@ -3658,15 +3712,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);
}
@@ -4115,8 +4171,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 )
@@ -4320,16 +4376,17 @@ int clif_damage(struct block_list* src, struct block_list* dst, int sdelay, int
p.is_sp_damaged = 0; // TODO: IsSPDamage - Displays blue digits.
#endif
- if(disguised(dst)) {
+ if (clif->isdisguised(dst)) {
clif->send(&p,sizeof(p),dst,AREA_WOS);
p.targetGID = -dst->id;
clif->send(&p,sizeof(p),dst,SELF);
- } else
+ } else {
clif->send(&p,sizeof(p),dst,AREA);
+ }
- if(disguised(src)) {
+ if (clif->isdisguised(src)) {
p.GID = -src->id;
- if (disguised(dst))
+ if (clif->isdisguised(dst))
p.targetGID = dst->id;
if(damage > 0) p.damage = -1;
@@ -4378,7 +4435,7 @@ void clif_sitting(struct block_list* bl)
WBUFB(buf,26) = 2;
clif->send(buf, packet_len(0x8a), bl, AREA);
- if(disguised(bl)) {
+ if (clif->isdisguised(bl)) {
WBUFL(buf, 2) = - bl->id;
clif->send(buf, packet_len(0x8a), bl, SELF);
}
@@ -4397,7 +4454,7 @@ void clif_standing(struct block_list* bl)
WBUFB(buf,26) = 3;
clif->send(buf, packet_len(0x8a), bl, AREA);
- if(disguised(bl)) {
+ if (clif->isdisguised(bl)) {
WBUFL(buf, 2) = - bl->id;
clif->send(buf, packet_len(0x8a), bl, SELF);
}
@@ -4618,9 +4675,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 )
@@ -4895,12 +4952,13 @@ void clif_skillcasting(struct block_list* bl, int src_id, int dst_id, int dst_x,
WBUFB(buf,24) = 0; // isDisposable
#endif
- if (disguised(bl)) {
+ if (clif->isdisguised(bl)) {
clif->send(buf,packet_len(cmd), bl, AREA_WOS);
WBUFL(buf,2) = -src_id;
clif->send(buf,packet_len(cmd), bl, SELF);
- } else
+ } else {
clif->send(buf,packet_len(cmd), bl, AREA);
+ }
}
/// Notifies clients in area, that an object canceled casting (ZC_DISPEL).
@@ -5030,16 +5088,17 @@ int clif_skill_damage(struct block_list *src, struct block_list *dst, int64 tick
WBUFW(buf, 26) = skill_lv;
WBUFW(buf, 28) = div;
WBUFB(buf, 30) = type;
- if (disguised(dst)) {
+ if (clif->isdisguised(dst)) {
clif->send(buf, packet_len(0x114), dst, AREA_WOS);
WBUFL(buf, 8) = -dst->id;
clif->send(buf, packet_len(0x114), dst, SELF);
- } else
+ } else {
clif->send(buf, packet_len(0x114), dst, AREA);
+ }
- if (disguised(src)) {
+ if (clif->isdisguised(src)) {
WBUFL(buf, 4) = -src->id;
- if (disguised(dst))
+ if (clif->isdisguised(dst))
WBUFL(buf, 8) = dst->id;
if (damage > 0)
WBUFW(buf, 24) = -1;
@@ -5069,16 +5128,17 @@ int clif_skill_damage(struct block_list *src, struct block_list *dst, int64 tick
#else
WBUFB(buf, 32) = (type == BDT_SKILL) ? BDT_MULTIHIT : type;
#endif
- if (disguised(dst)) {
+ if (clif->isdisguised(dst)) {
clif->send(buf, packet_len(0x1de), dst, AREA_WOS);
WBUFL(buf,8)=-dst->id;
clif->send(buf, packet_len(0x1de), dst, SELF);
- } else
+ } else {
clif->send(buf, packet_len(0x1de), dst, AREA);
+ }
- if (disguised(src)) {
+ if (clif->isdisguised(src)) {
WBUFL(buf, 4) = -src->id;
- if (disguised(dst))
+ if (clif->isdisguised(dst))
WBUFL(buf, 8) = dst->id;
if (damage > 0)
WBUFL(buf, 24) = -1;
@@ -5127,15 +5187,15 @@ int clif_skill_damage2(struct block_list *src, struct block_list *dst, int64 tic
WBUFW(buf,32)=div;
WBUFB(buf,34)=type;
clif->send(buf,packet_len(0x115),src,AREA);
- if(disguised(src)) {
+ if (clif->isdisguised(src)) {
WBUFL(buf,4)=-src->id;
if(damage > 0)
WBUFW(buf,28)=-1;
clif->send(buf,packet_len(0x115),src,SELF);
}
- if (disguised(dst)) {
+ if (clif->isdisguised(dst)) {
WBUFL(buf,8)=-dst->id;
- if (disguised(src))
+ if (clif->isdisguised(src))
WBUFL(buf,4)=src->id;
else if(damage > 0)
WBUFW(buf,28)=-1;
@@ -5162,16 +5222,16 @@ int clif_skill_nodamage(struct block_list *src,struct block_list *dst,uint16 ski
WBUFL(buf,10)=src?src->id:0;
WBUFB(buf,14)=fail;
- if (disguised(dst)) {
+ if (clif->isdisguised(dst)) {
clif->send(buf,packet_len(0x11a),dst,AREA_WOS);
WBUFL(buf,6)=-dst->id;
clif->send(buf,packet_len(0x11a),dst,SELF);
} else
clif->send(buf,packet_len(0x11a),dst,AREA);
- if(src && disguised(src)) {
+ if (src && clif->isdisguised(src)) {
WBUFL(buf,10)=-src->id;
- if (disguised(dst))
+ if (clif->isdisguised(dst))
WBUFL(buf,6)=dst->id;
clif->send(buf,packet_len(0x11a),src,SELF);
}
@@ -5193,12 +5253,13 @@ void clif_skill_poseffect(struct block_list *src, uint16 skill_id, int val, int
WBUFW(buf,10)=x;
WBUFW(buf,12)=y;
WBUFL(buf,14)=(uint32)tick;
- if(disguised(src)) {
+ if (clif->isdisguised(src)) {
clif->send(buf,packet_len(0x117),src,AREA_WOS);
WBUFL(buf,4)=-src->id;
clif->send(buf,packet_len(0x117),src,SELF);
- } else
+ } else {
clif->send(buf,packet_len(0x117),src,AREA);
+ }
}
/// Presents a list of available warp destinations (ZC_WARPLIST).
@@ -5478,23 +5539,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);
}
@@ -5516,7 +5578,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 ) {
@@ -5570,7 +5632,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;
@@ -5594,38 +5656,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;
@@ -5669,7 +5731,7 @@ void clif_resurrection(struct block_list *bl,int type)
WBUFW(buf,6)=0;
clif->send(buf,packet_len(0x148),bl, type == 1 ? AREA : AREA_WOS);
- if (disguised(bl)) {
+ if (clif->isdisguised(bl)) {
struct map_session_data *sd = BL_UCAST(BL_PC, bl);
if (sd->fontcolor) {
WBUFL(buf,2)=-bl->id;
@@ -5793,7 +5855,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;
@@ -5802,21 +5864,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
}
@@ -5966,7 +6028,7 @@ void clif_item_repair_list(struct map_session_data *sd,struct map_session_data *
WFIFOW(fd,0)=0x1fc;
for (i = c = 0; i < MAX_INVENTORY; i++) {
int nameid = dstsd->status.inventory[i].nameid;
- if (nameid > 0 && dstsd->status.inventory[i].attribute != 0) { // && skill_can_repair(sd,nameid)) {
+ if (nameid > 0 && (dstsd->status.inventory[i].attribute & ATTR_BROKEN) != 0) { // && skill_can_repair(sd,nameid)) {
WFIFOW(fd,c*13+4) = i;
WFIFOW(fd,c*13+6) = nameid;
WFIFOB(fd,c*13+8) = dstsd->status.inventory[i].refine;
@@ -6602,7 +6664,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;
@@ -6610,22 +6672,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);
}
}
@@ -7937,19 +8001,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;
@@ -8154,7 +8220,7 @@ void clif_specialeffect(struct block_list* bl, int type, enum send_target target
clif->send(buf, packet_len(0x1f3), bl, target);
- if (disguised(bl)) {
+ if (clif->isdisguised(bl)) {
WBUFL(buf,2) = -bl->id;
clif->send(buf, packet_len(0x1f3), bl, SELF);
}
@@ -8186,8 +8252,7 @@ void clif_specialeffect_value(struct block_list* bl, int effect_id, int num, sen
clif->send(buf, packet_len(0x284), bl, target);
- if( disguised(bl) )
- {
+ if (clif->isdisguised(bl)) {
WBUFL(buf,2) = -bl->id;
clif->send(buf, packet_len(0x284), bl, SELF);
}
@@ -8203,10 +8268,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;
@@ -8226,17 +8292,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;
@@ -8316,7 +8384,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);
@@ -8332,7 +8400,7 @@ void clif_refresh(struct map_session_data *sd)
mail->clear(sd);
- if( disguised(&sd->bl) ) {/* refresh-da */
+ if (clif->isdisguised(&sd->bl)) {/* refresh-da */
short disguise = sd->disguise;
pc->disguise(sd, -1);
pc->disguise(sd, disguise);
@@ -8547,8 +8615,7 @@ void clif_slide(struct block_list *bl, int x, int y)
WBUFW(buf, 8) = y;
clif->send(buf, packet_len(0x1ff), bl, AREA);
- if( disguised(bl) )
- {
+ if (clif->isdisguised(bl)) {
WBUFL(buf,2) = -bl->id;
clif->send(buf, packet_len(0x1ff), bl, SELF);
}
@@ -8556,34 +8623,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);
}
-
}
/*==========================
@@ -8867,105 +8933,137 @@ 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;
+ }
- message = name + namelen + 3;
- messagelen = textlen - namelen - 3; // this should be the message length (w/ zero byte included)
+ srcmessage = packet->message + namelen + 3; // <name> " : " <message>
+ messagelen = textlen - namelen - 3;
+
+ 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;
}
@@ -8973,14 +9071,15 @@ void clif_channel_msg(struct channel_data *chan, struct map_session_data *sd, ch
{
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);
@@ -9008,13 +9107,14 @@ void clif_channel_msg2(struct channel_data *chan, char *msg)
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;
@@ -9380,7 +9480,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
@@ -9687,7 +9787,7 @@ void clif_parse_GetCharNameRequest(int fd, struct map_session_data *sd) {
// 'see people in GM hide' cheat detection
#if 0 /* disabled due to false positives (network lag + request name of char that's about to hide = race condition) */
sc = status->get_sc(bl);
- if (sc && sc->option&OPTION_INVISIBLE && !disguised(bl) &&
+ if (sc && sc->option&OPTION_INVISIBLE && !clif->isdisguised(bl) &&
bl->type != BL_NPC && //Skip hidden NPCs which can be seen using Maya Purple
pc_get_group_level(sd) < battle_config.hack_info_GM_level
) {
@@ -9712,144 +9812,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 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;
- const char *name = NULL, *message = NULL;
- char *fakename = NULL;
- size_t namelen, messagelen;
-
- 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)));
@@ -9893,7 +9957,7 @@ void clif_changed_dir(struct block_list *bl, enum send_target target)
clif->send(buf, packet_len(0x9c), bl, target);
- if (disguised(bl)) {
+ if (clif->isdisguised(bl)) {
WBUFL(buf,2) = -bl->id;
WBUFW(buf,6) = 0;
clif->send(buf, packet_len(0x9c), bl, SELF);
@@ -10122,37 +10186,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;
+ char target[NAME_LENGTH], message[CHAT_SIZE_MAX + 1];
+ const struct packet_whisper_message *packet = RP2PTR(fd);
- if ( atcommand->exec(fd, sd, message, true) )
+ if (!clif->process_whisper_message(sd, packet, target, message, sizeof message))
return;
- // Statuses that prevent the player from whispering
- if( !pc->can_talk(sd) )
- 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);
@@ -10222,7 +10277,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;
}
@@ -10236,10 +10291,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;
}
@@ -10256,7 +10311,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)));
@@ -10373,7 +10428,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]
@@ -10733,10 +10788,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)));
@@ -10747,7 +10802,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]
@@ -11145,7 +11200,7 @@ void clif_parse_UseSkillToId(int fd, struct map_session_data *sd)
sd->skillitem = sd->skillitemlv = 0;
- if( skill_id >= GD_SKILLBASE ) {
+ if (skill_id >= GD_SKILLBASE && skill_id < GD_MAX) {
if( sd->state.gmaster_flag )
skill_lv = guild->checkskill(sd->guild, skill_id);
else
@@ -11519,10 +11574,10 @@ void clif_parse_OneClick_ItemIdentify(int fd, struct map_session_data *sd)
int cmd = RFIFOW(fd,0);
short idx = RFIFOW(fd, packet_db[cmd].pos[0]) - 2;
int n;
-
+
if (idx < 0 || idx >= MAX_INVENTORY || sd->inventory_data[idx] == NULL || sd->status.inventory[idx].nameid <= 0)
return;
-
+
if ((n = pc->have_magnifier(sd) ) != INDEX_NOT_FOUND &&
pc->delitem(sd, n, 1, 0, DELITEM_NORMAL, LOG_TYPE_CONSUME) == 0)
skill->identify(sd, idx);
@@ -11952,36 +12007,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 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);
-
- 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)));
@@ -12823,7 +12868,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)
@@ -13060,39 +13105,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)));
@@ -14674,7 +14709,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);
}
}
@@ -14712,11 +14747,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;
@@ -14744,7 +14784,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);
@@ -14778,7 +14818,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;
@@ -14802,6 +14841,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;
@@ -16151,58 +16191,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;
+ const struct packet_chat_message *packet = RP2PTR(fd);
+ char message[CHAT_SIZE_MAX + NAME_LENGTH + 3 + 1];
- 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);
-
- bg->send_message(sd, text, textlen);
+ bg->send_message(sd, message);
}
/// Notifies client of a battleground score change (ZC_BATTLEFIELD_NOTIFY_POINT).
@@ -17697,26 +17732,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) {
@@ -17811,7 +17847,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 {
@@ -18062,7 +18097,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);
}
}
@@ -19365,7 +19400,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;
@@ -19602,6 +19638,9 @@ void clif_defaults(void) {
clif->ackmergeitems = clif_ackmergeitems;
/* Cart Deco */
clif->selectcart = clif_selectcart;
+ /* */
+ clif->isdisguised = clif_isdisguised;
+ clif->bl_type = clif_bl_type;
/*------------------------
*- Parse Incoming Packet
diff --git a/src/map/clif.h b/src/map/clif.h
index f930e4ca1..df8b8f59c 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)
@@ -520,7 +520,7 @@ enum CLOSE_ROULETTE_ACK {
/**
* Reason for item deletion (clif->delitem)
- */
+ **/
enum delitem_reason {
DELITEM_NORMAL = 0, /// Normal
DELITEM_SKILLUSE = 1, /// Item used for a skill
@@ -532,9 +532,9 @@ enum delitem_reason {
DELITEM_ANALYSIS = 7, /// Consumed by Four Spirit Analysis (SO_EL_ANALYSIS) skill
};
-/*
-* Merge items reasons
-*/
+/**
+ * Merge items reasons
+ **/
enum mergeitem_reason {
MERGEITEM_SUCCESS = 0x0,
@@ -543,6 +543,23 @@ enum mergeitem_reason {
};
/**
+ * Clif Unit Type
+ **/
+enum clif_unittype {
+ CLUT_PC = 0x0,
+ CLUT_NPC = 0x1,
+ CLUT_ITEM = 0x2,
+ CLUT_SKILL = 0x3,
+ CLUT_UNKNOWN = 0x4,
+ CLUT_MOB = 0x5,
+ CLUT_EVENT = 0x6,
+ CLUT_PET = 0x7,
+ CLUT_HOMNUCLUS = 0x8,
+ CLUT_MERCNARY = 0x9,
+ CLUT_ELEMENTAL = 0xa,
+};
+
+/**
* Structures
**/
typedef void (*pFunc)(int, struct map_session_data *); //cant help but put it first
@@ -563,8 +580,8 @@ struct cdelayed_damage {
};
struct merge_item {
- int16 position;
- int16 nameid;
+ int16 position;
+ int16 nameid;
};
/**
@@ -841,11 +858,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 +873,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 +960,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);
@@ -1090,7 +1108,9 @@ struct clif_interface {
void (*cancelmergeitem) (int fd, struct map_session_data *sd);
int (*comparemergeitem) (const void *a, const void *b);
void (*ackmergeitems) (int fd, struct map_session_data *sd);
-
+ /* */
+ bool (*isdisguised) (struct block_list* bl);
+ unsigned char (*bl_type) (struct block_list *bl);
/*------------------------
*- Parse Incoming Packet
*------------------------*/
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 39d580bb7..ae3887aca 100644
--- a/src/map/guild.c
+++ b/src/map/guild.c
@@ -399,8 +399,11 @@ int guild_created(int account_id,int guild_id) {
//struct guild *g;
sd->status.guild_id=guild_id;
clif->guild_created(sd,0); // Success
- if(battle_config.guild_emperium_check)
- pc->delitem(sd, pc->search_inventory(sd, ITEMID_EMPERIUM), 1, 0, DELITEM_NORMAL, LOG_TYPE_CONSUME); //emperium consumption
+ if (battle_config.guild_emperium_check) {
+ int n = pc->search_inventory(sd, ITEMID_EMPERIUM);
+ if (n != INDEX_NOT_FOUND)
+ pc->delitem(sd, n, 1, 0, DELITEM_NORMAL, LOG_TYPE_CONSUME); //emperium consumption
+ }
return 0;
}
@@ -1060,14 +1063,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);
@@ -1828,7 +1832,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;
}
diff --git a/src/map/guild.h b/src/map/guild.h
index 1f3b74543..4fe7106d3 100644
--- a/src/map/guild.h
+++ b/src/map/guild.h
@@ -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);
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 ec0251dad..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;
@@ -658,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;
@@ -986,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
}
@@ -1005,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;
@@ -1023,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);
@@ -1654,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);
}
}
/*------------------------------------------
@@ -2489,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..54f462e35 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 c59f627cc..350697a08 100644
--- a/src/map/itemdb.c
+++ b/src/map/itemdb.c
@@ -342,7 +342,7 @@ const char* itemdb_typename(int type)
return "Unknown Type";
}
- /**
+/**
* Converts the JobID to the format used by map-server to check item
* restriction as per job.
*
@@ -1658,7 +1658,7 @@ int itemdb_validate_entry(struct item_data *entry, int n, const char *source) {
void itemdb_readdb_additional_fields(int itemid, struct config_setting_t *it, int n, const char *source)
{
- // do nothing. plugins can do own work
+ // do nothing. plugins can do own work
}
/**
diff --git a/src/map/map.c b/src/map/map.c
index 3a7d752c3..30c849ed1 100644
--- a/src/map/map.c
+++ b/src/map/map.c
@@ -6002,22 +6002,6 @@ static CMDLINEARG(loadscript)
}
/**
- * --generate-translations
- *
- * Creates "./generated_translations.pot"
- * @see cmdline->exec
- **/
-static CMDLINEARG(generatetranslations) {
- script->lang_export_file = aStrdup("./generated_translations.pot");
-
- if( !(script->lang_export_fp = fopen(script->lang_export_file,"wb")) ) {
- ShowError("export-dialog: failed to open '%s' for writing\n",script->lang_export_file);
- }
- core->runflag = CORE_ST_STOP;
- return true;
-}
-
-/**
* Defines the local command line arguments
*/
void cmdline_args_init_local(void)
@@ -6033,7 +6017,6 @@ void cmdline_args_init_local(void)
CMDLINEARG_DEF2(log-config, logconfig, "Alternative logging configuration.", CMDLINE_OPT_NORMAL|CMDLINE_OPT_PARAM);
CMDLINEARG_DEF2(script-check, scriptcheck, "Doesn't run the server, only tests the scripts passed through --load-script.", CMDLINE_OPT_SILENT);
CMDLINEARG_DEF2(load-script, loadscript, "Loads an additional script (can be repeated).", CMDLINE_OPT_NORMAL|CMDLINE_OPT_PARAM);
- CMDLINEARG_DEF2(generate-translations, generatetranslations, "Creates './generated_translations.pot' file with all translateable strings from scripts, server terminates afterwards.", CMDLINE_OPT_NORMAL);
}
int do_init(int argc, char *argv[])
@@ -6079,7 +6062,9 @@ int do_init(int argc, char *argv[])
char ip_str[16];
sockt->ip2str(sockt->addr_[0], ip_str);
+#ifndef BUILDBOT
ShowWarning("Not all IP addresses in /conf/map-server.conf configured, auto-detecting...\n");
+#endif
if (sockt->naddr_ == 0)
ShowError("Unable to determine your IP address...\n");
diff --git a/src/map/mob.c b/src/map/mob.c
index c765e7d63..b6b36dd61 100644
--- a/src/map/mob.c
+++ b/src/map/mob.c
@@ -421,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;
}
@@ -430,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;
}
@@ -2337,11 +2337,6 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) {
if(flag) {
if(base_exp || job_exp) {
if( md->dmglog[i].flag != MDLF_PET || battle_config.pet_attack_exp_to_master ) {
-#ifdef RENEWAL_EXP
- int rate = pc->level_penalty_mod(md->level - (tmpsd[i])->status.base_level, md->status.race, md->status.mode, 1);
- base_exp = (unsigned int)cap_value(base_exp * rate / 100, 1, UINT_MAX);
- job_exp = (unsigned int)cap_value(job_exp * rate / 100, 1, UINT_MAX);
-#endif
pc->gainexp(tmpsd[i], &md->bl, base_exp, job_exp, false);
}
}
@@ -2447,7 +2442,7 @@ 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,
@@ -2556,60 +2551,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;
}
}
diff --git a/src/map/npc.c b/src/map/npc.c
index 1b784b0c8..945a84957 100644
--- a/src/map/npc.c
+++ b/src/map/npc.c
@@ -62,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];
@@ -132,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...");
@@ -2509,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) {
@@ -2527,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;
}
@@ -2545,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);
}
@@ -2785,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);
@@ -2930,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
@@ -3136,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);
//-----------------------------------------
@@ -3206,7 +3195,7 @@ bool npc_duplicate_script_sub(struct npc_data *nd, const struct npc_data *snd, i
nullpo_retr(false, nd);
nullpo_retr(false, snd);
- ++npc_script;
+ ++npc->npc_script;
nd->u.scr.xs = xs;
nd->u.scr.ys = ys;
nd->u.scr.script = snd->u.scr.script;
@@ -3253,7 +3242,7 @@ bool npc_duplicate_shop_sub(struct npc_data *nd, const struct npc_data *snd, int
nullpo_retr(false, nd);
nullpo_retr(false, snd);
- ++npc_shop;
+ ++npc->npc_shop;
nd->u.shop.shop_item = snd->u.shop.shop_item;
nd->u.shop.count = snd->u.shop.count;
@@ -3271,7 +3260,7 @@ bool npc_duplicate_warp_sub(struct npc_data *nd, const struct npc_data *snd, int
nullpo_retr(false, nd);
nullpo_retr(false, snd);
- ++npc_warp;
+ ++npc->npc_warp;
nd->u.warp.xs = xs;
nd->u.warp.ys = ys;
nd->u.warp.mapindex = snd->u.warp.mapindex;
@@ -3770,7 +3759,7 @@ const char *npc_parse_function(const char *w1, const char *w2, const char *w3, c
struct script_code *oldscript = (struct script_code*)DB->data2ptr(&old_data);
ShowWarning("npc_parse_function: Overwriting user function [%s] in file '%s', line '%d'.\n", w3, filepath, strline(buffer,start-buffer));
script->free_vars(oldscript->local.vars);
- aFree(oldscript->script_buf);
+ VECTOR_CLEAR(oldscript->script_buf);
aFree(oldscript);
}
@@ -3967,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,
@@ -3978,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
}
@@ -4778,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;
@@ -4799,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();
@@ -4841,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();
@@ -4965,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));
@@ -4988,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]
@@ -5019,12 +5002,6 @@ int do_init_npc(bool minimal) {
timer->add_func_list(npc->timerevent,"npc_timerevent");
}
- if( script->lang_export_fp ) {
- ShowInfo("Lang exported to '%s'\n",script->lang_export_file);
- fclose(script->lang_export_fp);
- script->lang_export_fp = NULL;
- }
-
// Init dummy NPC
CREATE(npc->fake_nd, struct npc_data, 1);
npc->fake_nd->bl.m = -1;
@@ -5034,7 +5011,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;
@@ -5048,6 +5025,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 8ee59e410..24ea9ea59 100644
--- a/src/map/npc.h
+++ b/src/map/npc.h
@@ -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);
diff --git a/src/map/npc_chat.c b/src/map/npc_chat.c
index 6726c65a9..4bd7d416d 100644
--- a/src/map/npc_chat.c
+++ b/src/map/npc_chat.c
@@ -100,6 +100,7 @@ struct pcre_interface *libpcre;
*/
void finalize_pcrematch_entry(struct pcrematch_entry* e)
{
+ nullpo_retv(e);
libpcre->free(e->pcre_);
libpcre->free(e->pcre_extra_);
aFree(e->pattern);
@@ -111,7 +112,10 @@ void finalize_pcrematch_entry(struct pcrematch_entry* e)
*/
struct pcrematch_set* lookup_pcreset(struct npc_data* nd, int setid) {
struct pcrematch_set *pcreset;
- struct npc_parse *npcParse = nd->chatdb;
+ struct npc_parse *npcParse;
+
+ nullpo_retr(NULL, nd);
+ npcParse = nd->chatdb;
if (npcParse == NULL)
nd->chatdb = npcParse = (struct npc_parse *)aCalloc(sizeof(struct npc_parse), 1);
@@ -151,7 +155,9 @@ struct pcrematch_set* lookup_pcreset(struct npc_data* nd, int setid) {
void activate_pcreset(struct npc_data* nd, int setid)
{
struct pcrematch_set *pcreset;
- struct npc_parse *npcParse = nd->chatdb;
+ struct npc_parse *npcParse;
+ nullpo_retv(nd);
+ npcParse = nd->chatdb;
if (npcParse == NULL)
return; // Nothing to activate...
pcreset = npcParse->inactive;
@@ -184,7 +190,9 @@ void activate_pcreset(struct npc_data* nd, int setid)
void deactivate_pcreset(struct npc_data* nd, int setid)
{
struct pcrematch_set *pcreset;
- struct npc_parse *npcParse = nd->chatdb;
+ struct npc_parse *npcParse;
+ nullpo_retv(nd);
+ npcParse = nd->chatdb;
if (npcParse == NULL)
return; // Nothing to deactivate...
if (setid == -1) {
@@ -221,7 +229,9 @@ void delete_pcreset(struct npc_data* nd, int setid)
{
int active = 1;
struct pcrematch_set *pcreset;
- struct npc_parse *npcParse = nd->chatdb;
+ struct npc_parse *npcParse;
+ nullpo_retv(nd);
+ npcParse = nd->chatdb;
if (npcParse == NULL)
return; // Nothing to deactivate...
pcreset = npcParse->active;
@@ -269,8 +279,12 @@ void delete_pcreset(struct npc_data* nd, int setid)
*/
struct pcrematch_entry* create_pcrematch_entry(struct pcrematch_set* set)
{
- struct pcrematch_entry * e = (struct pcrematch_entry *) aCalloc(sizeof(struct pcrematch_entry), 1);
- struct pcrematch_entry * last = set->head;
+ struct pcrematch_entry *e;
+ struct pcrematch_entry *last;
+
+ nullpo_retr(NULL, set);
+ e = (struct pcrematch_entry *)aCalloc(sizeof(struct pcrematch_entry), 1);
+ last = set->head;
// Normally we would have just stuck it at the end of the list but
// this doesn't sink up with peoples usage pattern. They wanted
@@ -303,6 +317,7 @@ void npc_chat_def_pattern(struct npc_data* nd, int setid, const char* pattern, c
struct pcrematch_set * s = npc_chat->lookup_pcreset(nd, setid);
struct pcrematch_entry *e = npc_chat->create_pcrematch_entry(s);
+ nullpo_retv(e);
e->pattern = aStrdup(pattern);
e->label = aStrdup(label);
e->pcre_ = libpcre->compile(pattern, PCRE_CASELESS, &err, &erroff, NULL);
@@ -317,7 +332,10 @@ void npc_chat_def_pattern(struct npc_data* nd, int setid, const char* pattern, c
*/
void npc_chat_finalize(struct npc_data* nd)
{
- struct npc_parse *npcParse = nd->chatdb;
+ struct npc_parse *npcParse;
+
+ nullpo_retv(nd);
+ npcParse = nd->chatdb;
if (npcParse == NULL)
return;
@@ -358,6 +376,8 @@ int npc_chat_sub(struct block_list* bl, va_list ap)
len = va_arg(ap,int);
sd = va_arg(ap,struct map_session_data *);
+ nullpo_ret(sd);
+
// iterate across all active sets
for (pcreset = npcParse->active; pcreset != NULL; pcreset = pcreset->next)
{
@@ -373,7 +393,7 @@ int npc_chat_sub(struct block_list* bl, va_list ap)
// save out the matched strings
for (i = 0; i < r; i++)
{
- char var[6], val[255];
+ char var[12], val[255];
snprintf(var, sizeof(var), "$@p%i$", i);
libpcre->copy_substring(msg, offsets, r, i, val, sizeof(val));
script->set_var(sd, var, val);
diff --git a/src/map/packets_struct.h b/src/map/packets_struct.h
index 25b20cddf..e461eebe9 100644
--- a/src/map/packets_struct.h
+++ b/src/map/packets_struct.h
@@ -312,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];
@@ -447,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
@@ -499,473 +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
@@ -973,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
@@ -982,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
@@ -1108,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]
@@ -1144,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;
@@ -1215,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 551c4d56f..d0d466083 100644
--- a/src/map/party.c
+++ b/src/map/party.c
@@ -58,6 +58,9 @@ struct party_interface *party;
* Used when creating/adding people to a party. [Skotlex]
*------------------------------------------*/
void party_fill_member(struct party_member* member, struct map_session_data* sd, unsigned int leader) {
+ nullpo_retv(member);
+ nullpo_retv(sd);
+
member->account_id = sd->status.account_id;
member->char_id = sd->status.char_id;
safestrncpy(member->name, sd->status.name, NAME_LENGTH);
@@ -162,6 +165,9 @@ int party_create(struct map_session_data *sd, const char *name,int item,int item
struct party_member leader;
char tname[NAME_LENGTH];
+ nullpo_retr(0, sd);
+ nullpo_retr(0, name);
+
safestrncpy(tname, name, NAME_LENGTH);
trim(tname);
@@ -228,6 +234,7 @@ int party_recv_noinfo(int party_id, int char_id) {
void party_check_state(struct party_data *p) {
int i;
+ nullpo_retv(p);
memset(&p->state, 0, sizeof(p->state));
for (i = 0; i < MAX_PARTY; i ++) {
if (!p->party.member[i].online) continue; //Those not online shouldn't apart to skill usage and all that.
@@ -407,6 +414,8 @@ void party_reply_invite(struct map_session_data *sd,int party_id,int flag) {
struct map_session_data* tsd;
struct party_member member;
+ nullpo_retv(sd);
+
if( sd->party_invite != party_id )
{// forged
sd->party_invite = 0;
@@ -436,8 +445,11 @@ void party_reply_invite(struct map_session_data *sd,int party_id,int flag) {
//- Player must be authed/active and belong to a party before calling this method
void party_member_joined(struct map_session_data *sd)
{
- struct party_data* p = party->search(sd->status.party_id);
+ struct party_data* p;
int i;
+
+ nullpo_retv(sd);
+ p = party->search(sd->status.party_id);
if (!p) {
party->request_info(sd->status.party_id, sd->status.char_id);
return;
@@ -536,6 +548,7 @@ int party_removemember(struct map_session_data* sd, int account_id, const char *
if( !p->party.member[i].leader )
return 0; // only party leader may remove members
+ nullpo_retr(0, name);
ARR_FIND( 0, MAX_PARTY, i, p->party.member[i].account_id == account_id && strncmp(p->party.member[i].name,name,NAME_LENGTH) == 0 );
if( i == MAX_PARTY )
return 0; // no such char in party
@@ -550,6 +563,7 @@ int party_leave(struct map_session_data *sd)
struct party_data *p;
int i;
+ nullpo_ret(sd);
p = party->search(sd->status.party_id);
if( p == NULL )
return 0;
@@ -743,6 +757,8 @@ void party_send_movemap(struct map_session_data *sd)
{
struct party_data *p;
+ nullpo_retv(sd);
+
if( sd->status.party_id==0 )
return;
@@ -782,6 +798,8 @@ int party_send_logout(struct map_session_data *sd)
struct party_data *p;
int i;
+ nullpo_ret(sd);
+
if(!sd->status.party_id)
return 0;
@@ -798,12 +816,19 @@ 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;
+
+ nullpo_ret(sd);
+ nullpo_ret(mes);
+
+ len = (int)strlen(mes);
+
+ 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);
@@ -843,6 +868,8 @@ int party_skill_check(struct map_session_data *sd, int party_id, uint16 skill_id
return 0; //Unknown case?
}
+ nullpo_ret(sd);
+
for(i=0;i<MAX_PARTY;i++){
if ((p_sd = p->data[i].sd) == NULL)
continue;
@@ -930,11 +957,9 @@ int party_exp_share(struct party_data* p, struct block_list* src, unsigned int b
{
struct map_session_data* sd[MAX_PARTY];
unsigned int i, c;
-#ifdef RENEWAL_EXP
- unsigned int job_exp_bonus, base_exp_bonus;
-#endif
nullpo_ret(p);
+ nullpo_ret(src);
// count the number of players eligible for exp sharing
for (i = c = 0; i < MAX_PARTY; i++) {
@@ -959,21 +984,7 @@ int party_exp_share(struct party_data* p, struct block_list* src, unsigned int b
zeny = (unsigned int) cap_value(zeny * bonus/100, INT_MIN, INT_MAX);
}
-#ifdef RENEWAL_EXP
- base_exp_bonus = base_exp;
- job_exp_bonus = job_exp;
-#endif
-
for (i = 0; i < c; i++) {
-#ifdef RENEWAL_EXP
- struct mob_data *md = BL_CAST(BL_MOB, src);
- if (md != NULL && md->db->mexp == 0) {
- int rate = pc->level_penalty_mod(md->level - (sd[i])->status.base_level, md->status.race, md->status.mode, 1);
-
- base_exp = (unsigned int)cap_value(base_exp_bonus * rate / 100, 1, UINT_MAX);
- job_exp = (unsigned int)cap_value(job_exp_bonus * rate / 100, 1, UINT_MAX);
- }
-#endif
pc->gainexp(sd[i], src, base_exp, job_exp, false);
if (zeny) // zeny from mobs [Valaris]
@@ -987,8 +998,12 @@ int party_share_loot(struct party_data* p, struct map_session_data* sd, struct i
{
struct map_session_data *target = NULL;
int i;
+
+ nullpo_ret(item_data);
+
if (p && p->party.item&2 && (first_charid || !(battle_config.party_share_type&1)))
{
+ nullpo_ret(sd);
//item distribution to party members.
if (battle_config.party_share_type&2) {
//Round Robin
@@ -1050,6 +1065,7 @@ int party_share_loot(struct party_data* p, struct map_session_data* sd, struct i
int party_send_dot_remove(struct map_session_data *sd)
{
+ nullpo_ret(sd);
if (sd->status.party_id)
clif->party_xy_remove(sd);
return 0;
@@ -1065,6 +1081,7 @@ int party_sub_count(struct block_list *bl, va_list ap)
nullpo_ret(bl);
Assert_ret(bl->type == BL_PC);
sd = BL_UCCAST(BL_PC, bl);
+ nullpo_ret(sd);
if (sd->state.autotrade)
return 0;
@@ -1177,6 +1194,9 @@ void party_recruit_register(struct map_session_data *sd, short level, const char
#ifdef PARTY_RECRUIT
struct party_booking_ad_info *pb_ad;
+ nullpo_retv(sd);
+ nullpo_retv(notice);
+
pb_ad = (struct party_booking_ad_info*)idb_get(party->booking_db, sd->status.char_id);
if( pb_ad == NULL )
@@ -1207,6 +1227,9 @@ void party_booking_register(struct map_session_data *sd, short level, short mapi
struct party_booking_ad_info *pb_ad;
int i;
+ nullpo_retv(sd);
+ nullpo_retv(job);
+
pb_ad = (struct party_booking_ad_info*)idb_get(party->booking_db, sd->status.char_id);
if( pb_ad == NULL )
{
@@ -1240,6 +1263,7 @@ void party_recruit_update(struct map_session_data *sd, const char *notice) {
#ifdef PARTY_RECRUIT
struct party_booking_ad_info *pb_ad;
+ nullpo_retv(sd);
pb_ad = (struct party_booking_ad_info*)idb_get(party->booking_db, sd->status.char_id);
if( pb_ad == NULL )
@@ -1261,6 +1285,9 @@ void party_booking_update(struct map_session_data *sd, short* job) {
int i;
struct party_booking_ad_info *pb_ad;
+ nullpo_retv(sd);
+ nullpo_retv(job);
+
pb_ad = (struct party_booking_ad_info*)idb_get(party->booking_db, sd->status.char_id);
if( pb_ad == NULL )
@@ -1287,6 +1314,7 @@ void party_recruit_search(struct map_session_data *sd, short level, short mapid,
bool more_result = false;
struct DBIterator *iter = db_iterator(party->booking_db);
+ nullpo_retv(sd);
memset(result_list, 0, sizeof(result_list));
for( pb_ad = dbi_first(iter); dbi_exists(iter); pb_ad = dbi_next(iter) )
@@ -1318,6 +1346,8 @@ void party_booking_search(struct map_session_data *sd, short level, short mapid,
bool more_result = false;
struct DBIterator *iter = db_iterator(party->booking_db);
+ nullpo_retv(sd);
+
memset(result_list, 0, sizeof(result_list));
for( pb_ad = dbi_first(iter); dbi_exists(iter); pb_ad = dbi_next(iter) ) {
@@ -1353,6 +1383,8 @@ bool party_booking_delete(struct map_session_data *sd)
{
struct party_booking_ad_info* pb_ad;
+ nullpo_retr(false, sd);
+
if((pb_ad = (struct party_booking_ad_info*)idb_get(party->booking_db, sd->status.char_id))!=NULL)
{
#ifdef PARTY_RECRUIT
diff --git a/src/map/party.h b/src/map/party.h
index 253f074bb..05037eb04 100644
--- a/src/map/party.h
+++ b/src/map/party.h
@@ -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);
diff --git a/src/map/path.c b/src/map/path.c
index 543497c33..f5e08d4df 100644
--- a/src/map/path.c
+++ b/src/map/path.c
@@ -89,6 +89,7 @@ int path_blownpos(struct block_list *bl, int16 m,int16 x0,int16 y0,int16 dx,int1
{
struct map_data *md;
+ Assert_retr(-1, m >= 0 && m < map->count);
if( !map->list[m].cell )
return -1;
md = &map->list[m];
@@ -126,6 +127,8 @@ bool path_search_long(struct shootpath_data *spd,struct block_list *bl,int16 m,i
struct map_data *md;
struct shootpath_data s_spd;
+ Assert_retr(false, m >= 0 && m < map->count);
+
if( spd == NULL )
spd = &s_spd; // use dummy output variable
@@ -254,10 +257,12 @@ 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;
+ Assert_retr(false, m >= 0 && m < map->count);
+
if (wpd == NULL)
wpd = &s_wpd; // use dummy output variable
@@ -315,8 +320,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 +335,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 +412,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 57b2fe19a..2206dbb80 100644
--- a/src/map/pc.c
+++ b/src/map/pc.c
@@ -81,8 +81,10 @@ struct pc_interface *pc;
//Note that it does not do a validity check for speed purposes, where parsing
//player input make sure to use a pc->db_checkid first!
int pc_class2idx(int class_) {
- if (class_ >= JOB_NOVICE_HIGH)
- return class_- JOB_NOVICE_HIGH+JOB_MAX_BASIC;
+ if (class_ >= JOB_NOVICE_HIGH) {
+ class_ += - JOB_NOVICE_HIGH + JOB_MAX_BASIC;
+ }
+ Assert_ret(class_ >= 0 && class_ < CLASS_COUNT);
return class_;
}
@@ -109,6 +111,7 @@ struct map_session_data* pc_get_dummy_sd(void)
int pc_set_group(struct map_session_data *sd, int group_id)
{
GroupSettings *group = pcg->id2group(group_id);
+ nullpo_retr(1, sd);
if (group == NULL)
return 1;
sd->group_id = group_id;
@@ -121,6 +124,7 @@ int pc_set_group(struct map_session_data *sd, int group_id)
*/
bool pc_should_log_commands(struct map_session_data *sd)
{
+ nullpo_retr(true, sd);
return pcg->should_log_commands(sd->group);
}
@@ -141,7 +145,8 @@ int pc_invincible_timer(int tid, int64 tick, int id, intptr_t data)
return 0;
}
-void pc_setinvincibletimer(struct map_session_data* sd, int val) {
+void pc_setinvincibletimer(struct map_session_data* sd, int val)
+{
nullpo_retv(sd);
val += map->list[sd->bl.m].invincible_time_inc;
@@ -466,6 +471,7 @@ int pc_inventory_rental_end(int tid, int64 tick, int id, intptr_t data) {
int pc_inventory_rental_clear(struct map_session_data *sd)
{
+ nullpo_ret(sd);
if( sd->rental_timer != INVALID_TIMER )
{
timer->delete(sd->rental_timer, pc->inventory_rental_end);
@@ -476,7 +482,11 @@ int pc_inventory_rental_clear(struct map_session_data *sd)
}
/* assumes i is valid (from default areas where it is called, it is) */
void pc_rental_expire(struct map_session_data *sd, int i) {
- short nameid = sd->status.inventory[i].nameid;
+ short nameid;
+
+ nullpo_retv(sd);
+ Assert_retv(i >= 0 && i < MAX_INVENTORY);
+ nameid = sd->status.inventory[i].nameid;
/* Soon to be dropped, we got plans to integrate it with item db */
switch( nameid ) {
@@ -547,6 +557,7 @@ void pc_inventory_rentals(struct map_session_data *sd)
int i, c = 0;
int64 expire_tick, next_tick = INT64_MAX;
+ nullpo_retv(sd);
for( i = 0; i < MAX_INVENTORY; i++ )
{ // Check for Rentals on Inventory
if( sd->status.inventory[i].nameid == 0 )
@@ -686,6 +697,7 @@ int pc_equippoint(struct map_session_data *sd,int n)
int ep = 0;
nullpo_ret(sd);
+ Assert_ret(n >= 0 && n < MAX_INVENTORY);
if(!sd->inventory_data[n])
return 0;
@@ -812,6 +824,7 @@ bool pc_isequipped(struct map_session_data *sd, int nameid)
{
int i, j;
+ nullpo_retr(false, sd);
for (i = 0; i < EQI_MAX; i++) {
int index = sd->equip_index[i];
if( index < 0 ) continue;
@@ -891,6 +904,7 @@ bool pc_adoption(struct map_session_data *p1_sd, struct map_session_data *p2_sd,
if( !pc->can_Adopt(p1_sd, p2_sd, b_sd) )
return false;
+ nullpo_retr(false, b_sd);
// Preserve current job levels and progress
joblevel = b_sd->status.job_level;
jobexp = b_sd->status.job_exp;
@@ -1039,7 +1053,10 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim
{
int i;
int64 tick = timer->gettick();
- uint32 ip = sockt->session[sd->fd]->client_addr;
+ uint32 ip;
+
+ nullpo_retr(false, sd);
+ ip = sockt->session[sd->fd]->client_addr;
sd->login_id2 = login_id2;
@@ -1269,6 +1286,7 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim
*------------------------------------------*/
void pc_authfail(struct map_session_data *sd)
{
+ nullpo_retv(sd);
clif->authfail_fd(sd->fd, 0);
return;
}
@@ -1306,6 +1324,7 @@ int pc_reg_received(struct map_session_data *sd)
{
int i, idx = 0;
+ nullpo_ret(sd);
sd->vars_ok = true;
sd->change_level_2nd = pc_readglobalreg(sd,script->add_str("jobchange_level"));
@@ -1632,6 +1651,7 @@ void pc_check_skilltree(struct map_session_data *sd, int skill_id)
if(battle_config.skillfree)
return; //Function serves no purpose if this is set
+ nullpo_retv(sd);
i = pc->calc_skilltree_normalize_job(sd);
c = pc->mapid2jobid(i, sd->status.sex);
if (c == -1) { //Unable to normalize job??
@@ -1697,6 +1717,7 @@ void pc_check_skilltree(struct map_session_data *sd, int skill_id)
int pc_clean_skilltree(struct map_session_data *sd)
{
int i;
+ nullpo_ret(sd);
for (i = 0; i < MAX_SKILL; i++){
if (sd->status.skill[i].flag == SKILL_FLAG_TEMPORARY || sd->status.skill[i].flag == SKILL_FLAG_PLAGIARIZED) {
sd->status.skill[i].id = 0;
@@ -1714,8 +1735,10 @@ int pc_clean_skilltree(struct map_session_data *sd)
int pc_calc_skilltree_normalize_job(struct map_session_data *sd)
{
int skill_point, novice_skills;
- int c = sd->class_;
+ int c;
+ nullpo_ret(sd);
+ c = sd->class_;
if (!battle_config.skillup_limit || pc_has_permission(sd, PC_PERM_ALL_SKILL))
return c;
@@ -1822,6 +1845,7 @@ int pc_updateweightstatus(struct map_session_data *sd)
}
int pc_disguise(struct map_session_data *sd, int class_) {
+ nullpo_ret(sd);
if (class_ == -1 && sd->disguise == -1)
return 0;
if (class_ >= 0 && sd->disguise == class_)
@@ -1864,8 +1888,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);
@@ -1881,6 +1905,8 @@ int pc_bonus_autospell(struct s_autospell *spell, int max, short id, short lv, s
if( !rate )
return 0;
+ nullpo_ret(spell);
+ Assert_ret(max <= 15); // autospell array size
for( i = 0; i < max && spell[i].id; i++ )
{
if( (spell[i].card_id == card_id || spell[i].rate < 0 || rate < 0) && spell[i].id == id && spell[i].lv == lv )
@@ -1917,6 +1943,8 @@ int pc_bonus_autospell_onskill(struct s_autospell *spell, int max, short src_ski
if( !rate )
return 0;
+ nullpo_ret(spell);
+ Assert_ret(max <= 15); // autospell array size
for( i = 0; i < max && spell[i].id; i++ )
{
; // each autospell works independently
@@ -1952,6 +1980,8 @@ int pc_bonus_autospell_onskill(struct s_autospell *spell, int max, short src_ski
int pc_bonus_addeff(struct s_addeffect* effect, int max, enum sc_type id, int16 rate, int16 arrow_rate, uint8 flag, uint16 duration)
{
int i;
+
+ nullpo_ret(effect);
if (!(flag&(ATF_SHORT|ATF_LONG)))
flag|=ATF_SHORT|ATF_LONG; //Default range: both
if (!(flag&(ATF_TARGET|ATF_SELF)))
@@ -1981,6 +2011,8 @@ int pc_bonus_addeff(struct s_addeffect* effect, int max, enum sc_type id, int16
int pc_bonus_addeff_onskill(struct s_addeffectonskill* effect, int max, enum sc_type id, short rate, short skill_id, unsigned char target) {
int i;
+
+ nullpo_ret(effect);
for( i = 0; i < max && effect[i].skill; i++ ) {
if( effect[i].id == id && effect[i].skill == skill_id && effect[i].target == target ) {
effect[i].rate += rate;
@@ -2001,6 +2033,7 @@ int pc_bonus_addeff_onskill(struct s_addeffectonskill* effect, int max, enum sc_
int pc_bonus_item_drop(struct s_add_drop *drop, const short max, short id, short group, int race_mask, int rate) {
int i;
+ nullpo_ret(drop);
//Apply config rate adjustment settings.
if (rate >= 0) { //Absolute drop.
if (battle_config.item_rate_adddrop != 100)
@@ -2048,6 +2081,8 @@ int pc_bonus_item_drop(struct s_add_drop *drop, const short max, short id, short
int pc_addautobonus(struct s_autobonus *bonus,char max,const char *bonus_script,short rate,unsigned int dur,short flag,const char *other_script,unsigned short pos,bool onskill) {
int i;
+ nullpo_ret(bonus);
+ nullpo_ret(bonus_script);
ARR_FIND(0, max, i, bonus[i].rate == 0);
if( i == max )
{
@@ -2084,6 +2119,7 @@ int pc_delautobonus(struct map_session_data* sd, struct s_autobonus *autobonus,c
{
int i;
nullpo_ret(sd);
+ nullpo_ret(autobonus);
for( i = 0; i < max; i++ )
{
@@ -2155,6 +2191,7 @@ int pc_bonus_addele(struct map_session_data* sd, unsigned char ele, short rate,
int i;
struct weapon_data* wd;
+ nullpo_ret(sd);
wd = (sd->state.lr_flag ? &sd->left_weapon : &sd->right_weapon);
ARR_FIND(0, MAX_PC_BONUS, i, wd->addele2[i].rate == 0);
@@ -2188,6 +2225,7 @@ int pc_bonus_subele(struct map_session_data* sd, unsigned char ele, short rate,
{
int i;
+ nullpo_ret(sd);
ARR_FIND(0, MAX_PC_BONUS, i, sd->subele2[i].rate == 0);
if (i == MAX_PC_BONUS)
@@ -4093,7 +4131,7 @@ bool pc_can_insert_card_into(struct map_session_data* sd, int idx_card, int idx_
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 false; // no free slots
- return true;
+ return true;
}
/**
@@ -4113,7 +4151,7 @@ bool pc_can_insert_card(struct map_session_data* sd, int idx_card)
return false; // target card missing
if (sd->inventory_data[idx_card]->type != IT_CARD)
return false; // must be a card
- return true;
+ return true;
}
/*==========================================
@@ -4276,7 +4314,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;
@@ -4318,7 +4356,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;
}
@@ -4343,7 +4381,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;
}
@@ -4366,7 +4404,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;
}
@@ -4404,7 +4442,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;
@@ -4563,6 +4601,7 @@ int pc_additem(struct map_session_data *sd,struct item *item_data,int amount,e_l
int pc_delitem(struct map_session_data *sd,int n,int amount,int type, short reason, e_log_pick_type log_type)
{
nullpo_retr(1, sd);
+ Assert_retr(1, n >= 0 && n < MAX_INVENTORY);
if(sd->status.inventory[n].nameid==0 || amount <= 0 || sd->status.inventory[n].amount<amount || sd->inventory_data[n] == NULL)
return 1;
@@ -4706,6 +4745,7 @@ int pc_isUseitem(struct map_session_data *sd,int n)
int nameid;
nullpo_ret(sd);
+ Assert_ret(n >= 0 && n < MAX_INVENTORY);
item = sd->inventory_data[n];
nameid = sd->status.inventory[n].nameid;
@@ -4892,6 +4932,7 @@ int pc_useitem(struct map_session_data *sd,int n) {
bool removeItem = false;
nullpo_ret(sd);
+ Assert_ret(n >= 0 && n < MAX_INVENTORY);
if( sd->npc_id || sd->state.workinprogress&1 ){
/* TODO: add to clif->messages enum */
@@ -5112,6 +5153,7 @@ int pc_cart_additem(struct map_session_data *sd,struct item *item_data,int amoun
int pc_cart_delitem(struct map_session_data *sd,int n,int amount,int type,e_log_pick_type log_type) {
struct item_data * data;
nullpo_retr(1, sd);
+ Assert_retr(1, n >= 0 && n < MAX_INVENTORY);
if( sd->status.cart[n].nameid == 0 || sd->status.cart[n].amount < amount || !(data = itemdb->exists(sd->status.cart[n].nameid)) )
return 1;
@@ -5170,6 +5212,7 @@ int pc_cartitem_amount(struct map_session_data* sd, int idx, int amount)
struct item* item_data;
nullpo_retr(-1, sd);
+ Assert_retr(-1, idx >= 0 && idx < MAX_CART);
item_data = &sd->status.cart[idx];
if( item_data->nameid == 0 || item_data->amount == 0 )
@@ -5204,9 +5247,12 @@ int pc_getitemfromcart(struct map_session_data *sd,int idx,int amount)
return flag;
}
-void pc_bound_clear(struct map_session_data *sd, enum e_item_bound_type type) {
+
+void pc_bound_clear(struct map_session_data *sd, enum e_item_bound_type type)
+{
int i;
+ nullpo_retv(sd);
switch( type ) {
/* both restricted to inventory */
case IBT_PARTY:
@@ -5341,7 +5387,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;
}
@@ -6440,6 +6486,7 @@ int pc_check_job_name(const char *name) {
{ "Rebellion", JOB_REBELLION },
};
+ nullpo_retr(-1, name);
len = ARRAYLENGTH(names);
ARR_FIND(0, len, i, strcmpi(names[i].name, name) == 0);
@@ -6506,6 +6553,7 @@ int pc_stop_following (struct map_session_data *sd)
int pc_follow(struct map_session_data *sd,int target_id) {
struct block_list *bl = map->id2bl(target_id);
+ nullpo_retr(1, sd);
if (bl == NULL /*|| bl->type != BL_PC*/)
return 1;
if (sd->followtimer != INVALID_TIMER)
@@ -6520,6 +6568,7 @@ int pc_follow(struct map_session_data *sd,int target_id) {
int pc_checkbaselevelup(struct map_session_data *sd) {
unsigned int next = pc->nextbaseexp(sd);
+ nullpo_ret(sd);
if (!next || sd->status.base_exp < next)
return 0;
@@ -6569,6 +6618,7 @@ int pc_checkbaselevelup(struct map_session_data *sd) {
void pc_baselevelchanged(struct map_session_data *sd) {
int i;
+ nullpo_retv(sd);
for( i = 0; i < EQI_MAX; i++ ) {
if( sd->equip_index[i] >= 0 ) {
if( sd->inventory_data[ sd->equip_index[i] ]->elvmax && sd->status.base_level > (unsigned int)sd->inventory_data[ sd->equip_index[i] ]->elvmax )
@@ -6613,34 +6663,72 @@ int pc_checkjoblevelup(struct map_session_data *sd)
* Alters EXP based on self bonuses that do not get shared with the party
**/
void pc_calcexp(struct map_session_data *sd, unsigned int *base_exp, unsigned int *job_exp, struct block_list *src) {
- int bonus = 0;
- struct status_data *st = status->get_status_data(src);
+ int buff_ratio = 0, buff_job_ratio = 0, race_ratio = 0, pk_ratio = 0;
+ int64 jexp, bexp;
- if (sd->expaddrace[st->race])
- bonus += sd->expaddrace[st->race];
- bonus += sd->expaddrace[(st->mode&MD_BOSS) ? RC_BOSS : RC_NONBOSS];
+ nullpo_retv(sd);
+ nullpo_retv(base_exp);
+ nullpo_retv(job_exp);
- if (battle_config.pk_mode
- && (int)(status->get_lv(src) - sd->status.base_level) >= 20)
- bonus += 15; // pk_mode additional exp if monster >20 levels [Valaris]
+ jexp = *job_exp;
+ bexp = *base_exp;
- if (sd->sc.data[SC_CASH_PLUSEXP])
- bonus += sd->sc.data[SC_CASH_PLUSEXP]->val1;
- if (sd->sc.data[SC_OVERLAPEXPUP])
- bonus += sd->sc.data[SC_OVERLAPEXPUP]->val1;
+ if (src != NULL) {
+ const struct status_data *st = status->get_status_data(src);
+
+#ifdef RENEWAL_EXP //should happen first before we caluclate any modifiers
+ if (src->type == BL_MOB) {
+ const struct mob_data *md = BL_UCAST(BL_MOB, src);
+ int re_mod;
+ re_mod = pc->level_penalty_mod(md->level - sd->status.base_level, md->status.race, md->status.mode, 1);
+ jexp = apply_percentrate64(jexp, re_mod, 100);
+ bexp = apply_percentrate64(bexp, re_mod, 100);
+ }
+#endif
+
+ //Race modifier
+ if (sd->expaddrace[st->race])
+ race_ratio += sd->expaddrace[st->race];
+ race_ratio += sd->expaddrace[(st->mode&MD_BOSS) ? RC_BOSS : RC_NONBOSS];
+ }
- *base_exp = (unsigned int) cap_value(*base_exp + apply_percentrate64(*base_exp, bonus, 100), 1, UINT_MAX);
+ //PK modifier
+ /* this doesn't exist in Aegis, instead there's a CrazyKiller check which double all EXP from this point */
+ if (battle_config.pk_mode && (int)(status->get_lv(src) - sd->status.base_level) >= 20)
+ pk_ratio += 15; // pk_mode additional exp if monster >20 levels [Valaris]
+
+
+ //Buffs modifier
+ if (sd->sc.data[SC_CASH_PLUSEXP]) {
+ buff_job_ratio += sd->sc.data[SC_CASH_PLUSEXP]->val1;
+ buff_ratio += sd->sc.data[SC_CASH_PLUSEXP]->val1;
+ }
+ if (sd->sc.data[SC_OVERLAPEXPUP]) {
+ buff_job_ratio += sd->sc.data[SC_OVERLAPEXPUP]->val1;
+ buff_ratio += sd->sc.data[SC_OVERLAPEXPUP]->val1;
+ }
if (sd->sc.data[SC_CASH_PLUSONLYJOBEXP])
- bonus += sd->sc.data[SC_CASH_PLUSONLYJOBEXP]->val1;
+ buff_job_ratio += sd->sc.data[SC_CASH_PLUSONLYJOBEXP]->val1;
- *job_exp = (unsigned int) cap_value(*job_exp + apply_percentrate64(*job_exp, bonus, 100), 1, UINT_MAX);
+ //Applying Race and PK modifier First then Premium (Perment modifier) and finally buff modifier
+ jexp += apply_percentrate64(jexp, race_ratio, 100);
+ jexp += apply_percentrate64(jexp, pk_ratio, 100);
+
+ bexp += apply_percentrate64(bexp, race_ratio, 100);
+ bexp += apply_percentrate64(bexp, pk_ratio, 100);
- if (sd->status.mod_exp != 100) {
- *base_exp = (unsigned int) cap_value(apply_percentrate64(*base_exp, sd->status.mod_exp, 100), 1, UINT_MAX);
- *job_exp = (unsigned int) cap_value(apply_percentrate64(*job_exp, sd->status.mod_exp, 100), 1, UINT_MAX);
+ if (sd->status.mod_exp != 100) {
+ jexp = apply_percentrate64(jexp, sd->status.mod_exp, 100);
+ bexp = apply_percentrate64(bexp, sd->status.mod_exp, 100);
}
+
+ bexp += apply_percentrate64(bexp, buff_ratio, 100);
+ jexp += apply_percentrate64(jexp, buff_ratio + buff_job_ratio, 100);
+
+ *job_exp = (unsigned int)cap_value(jexp, 1, UINT_MAX);
+ *base_exp = (unsigned int)cap_value(bexp, 1, UINT_MAX);
}
/**
@@ -6654,24 +6742,25 @@ bool pc_gainexp(struct map_session_data *sd, struct block_list *src, unsigned in
unsigned int nextb=0, nextj=0;
nullpo_ret(sd);
- if(sd->bl.prev == NULL || pc_isdead(sd))
+ if (sd->bl.prev == NULL || pc_isdead(sd))
return false;
- if(!battle_config.pvp_exp && map->list[sd->bl.m].flag.pvp) // [MouseJstr]
+ if (!battle_config.pvp_exp && map->list[sd->bl.m].flag.pvp) // [MouseJstr]
return false; // no exp on pvp maps
- if( pc_has_permission(sd,PC_PERM_DISABLE_EXP) )
+ if (pc_has_permission(sd,PC_PERM_DISABLE_EXP))
return false;
- if(sd->status.guild_id>0)
- base_exp-=guild->payexp(sd,base_exp);
+ if (src)
+ pc->calcexp(sd, &base_exp, &job_exp, src);
- if(src) pc->calcexp(sd, &base_exp, &job_exp, src);
+ if (sd->status.guild_id > 0)
+ base_exp -= guild->payexp(sd,base_exp);
nextb = pc->nextbaseexp(sd);
nextj = pc->nextjobexp(sd);
- if(sd->state.showexp || battle_config.max_exp_gain_rate){
+ if (sd->state.showexp || battle_config.max_exp_gain_rate) {
if (nextb > 0)
nextbp = (float) base_exp / (float) nextb;
if (nextj > 0)
@@ -6726,7 +6815,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;
@@ -7875,6 +7964,7 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) {
}
void pc_revive(struct map_session_data *sd,unsigned int hp, unsigned int sp) {
+ nullpo_retv(sd);
if(hp) clif->updatestatus(sd,SP_HP);
if(sp) clif->updatestatus(sd,SP_SP);
@@ -8210,6 +8300,7 @@ int pc_setparam(struct map_session_data *sd,int type,int val)
*------------------------------------------*/
void pc_heal(struct map_session_data *sd,unsigned int hp,unsigned int sp, int type)
{
+ nullpo_retv(sd);
if (type) {
if (hp)
clif->heal(sd->fd,SP_HP,hp);
@@ -8233,6 +8324,7 @@ int pc_itemheal(struct map_session_data *sd,int itemid, int hp,int sp)
{
int bonus, tmp;
+ nullpo_ret(sd);
if(hp) {
int i;
bonus = 100 + (sd->battle_status.vit<<1)
@@ -8803,6 +8895,7 @@ int pc_setcart(struct map_session_data *sd,int type) {
**/
void pc_setfalcon(struct map_session_data *sd, bool flag)
{
+ nullpo_retv(sd);
if (flag) {
if (pc->checkskill(sd,HT_FALCON) > 0) // add falcon if he have the skill
pc->setoption(sd,sd->sc.option|OPTION_FALCON);
@@ -8821,6 +8914,7 @@ void pc_setfalcon(struct map_session_data *sd, bool flag)
**/
void pc_setridingpeco(struct map_session_data *sd, bool flag)
{
+ nullpo_retv(sd);
if (flag) {
if (pc->checkskill(sd, KN_RIDING))
pc->setoption(sd, sd->sc.option|OPTION_RIDING);
@@ -8839,6 +8933,7 @@ void pc_setridingpeco(struct map_session_data *sd, bool flag)
**/
void pc_setmadogear(struct map_session_data *sd, bool flag)
{
+ nullpo_retv(sd);
if (flag) {
if ((sd->class_&MAPID_THIRDMASK) == MAPID_MECHANIC)
pc->setoption(sd, sd->sc.option|OPTION_MADOGEAR);
@@ -8857,6 +8952,7 @@ void pc_setmadogear(struct map_session_data *sd, bool flag)
**/
void pc_setridingdragon(struct map_session_data *sd, unsigned int type)
{
+ nullpo_retv(sd);
if (type&OPTION_DRAGON) {
// Ensure only one dragon is set at a time.
if (type&OPTION_DRAGON1)
@@ -8889,6 +8985,7 @@ void pc_setridingdragon(struct map_session_data *sd, unsigned int type)
**/
void pc_setridingwug(struct map_session_data *sd, bool flag)
{
+ nullpo_retv(sd);
if (flag) {
if (pc->checkskill(sd, RA_WUGRIDER) > 0)
pc->setoption(sd,sd->sc.option|OPTION_WUGRIDER);
@@ -8956,6 +9053,7 @@ int pc_candrop(struct map_session_data *sd, struct item *item)
* For '@type' variables (temporary numeric char reg)
**/
int pc_readreg(struct map_session_data* sd, int64 reg) {
+ nullpo_ret(sd);
return i64db_iget(sd->regs.vars, reg);
}
/**
@@ -8964,6 +9062,7 @@ int pc_readreg(struct map_session_data* sd, int64 reg) {
void pc_setreg(struct map_session_data* sd, int64 reg, int val) {
unsigned int index = script_getvaridx(reg);
+ nullpo_retv(sd);
if( val ) {
i64db_iput(sd->regs.vars, reg, val);
if( index )
@@ -8981,6 +9080,7 @@ void pc_setreg(struct map_session_data* sd, int64 reg, int val) {
char* pc_readregstr(struct map_session_data* sd, int64 reg) {
struct script_reg_str *p = NULL;
+ nullpo_retr(NULL, sd);
p = i64db_get(sd->regs.vars, reg);
return p ? p->value : NULL;
@@ -8993,6 +9093,8 @@ void pc_setregstr(struct map_session_data* sd, int64 reg, const char* str) {
unsigned int index = script_getvaridx(reg);
struct DBData prev;
+ nullpo_retv(sd);
+ nullpo_retv(str);
if( str[0] ) {
p = ers_alloc(pc->str_reg_ers, struct script_reg_str);
@@ -9028,6 +9130,7 @@ void pc_setregstr(struct map_session_data* sd, int64 reg, const char* str) {
int pc_readregistry(struct map_session_data *sd, int64 reg) {
struct script_reg_num *p = NULL;
+ nullpo_ret(sd);
if (!sd->vars_ok) {
ShowError("pc_readregistry: Trying to read reg %s before it's been loaded!\n", script->get_str(script_getvarid(reg)));
//This really shouldn't happen, so it's possible the data was lost somewhere, we should request it again.
@@ -9049,6 +9152,7 @@ int pc_readregistry(struct map_session_data *sd, int64 reg) {
char* pc_readregistry_str(struct map_session_data *sd, int64 reg) {
struct script_reg_str *p = NULL;
+ nullpo_retr(NULL, sd);
if (!sd->vars_ok) {
ShowError("pc_readregistry_str: Trying to read reg %s before it's been loaded!\n", script->get_str(script_getvarid(reg)));
//This really shouldn't happen, so it's possible the data was lost somewhere, we should request it again.
@@ -9072,6 +9176,7 @@ int pc_setregistry(struct map_session_data *sd, int64 reg, int val) {
const char *regname = script->get_str( script_getvarid(reg) );
unsigned int index = script_getvaridx(reg);
+ nullpo_ret(sd);
/* SAAD! those things should be stored elsewhere e.g. char ones in char table, the cash ones in account_data table! */
switch( regname[0] ) {
default: //Char reg
@@ -9147,6 +9252,8 @@ int pc_setregistry_str(struct map_session_data *sd, int64 reg, const char *val)
const char *regname = script->get_str( script_getvarid(reg) );
unsigned int index = script_getvaridx(reg);
+ nullpo_ret(sd);
+ nullpo_ret(val);
if ( !pc->reg_load && !sd->vars_ok ) {
ShowError("pc_setregistry_str : refusing to set %s until vars are received.\n", regname);
return 0;
@@ -9224,6 +9331,7 @@ int pc_addeventtimer(struct map_session_data *sd,int tick,const char *name)
{
int i;
nullpo_ret(sd);
+ nullpo_ret(name);
ARR_FIND( 0, MAX_EVENTTIMER, i, sd->eventtimer[i] == INVALID_TIMER );
if( i == MAX_EVENTTIMER )
@@ -9244,6 +9352,7 @@ int pc_deleventtimer(struct map_session_data *sd,const char *name)
int i;
nullpo_ret(sd);
+ nullpo_ret(name);
if (sd->eventcount <= 0)
return 0;
@@ -9312,6 +9421,8 @@ int pc_checkcombo(struct map_session_data *sd, struct item_data *data ) {
int index, success = 0;
struct pc_combos *combo;
+ nullpo_ret(sd);
+ nullpo_ret(data);
for( i = 0; i < data->combos_count; i++ ) {
/* ensure this isn't a duplicate combo */
@@ -9387,6 +9498,8 @@ int pc_checkcombo(struct map_session_data *sd, struct item_data *data ) {
int pc_removecombo(struct map_session_data *sd, struct item_data *data ) {
int i, retval = 0;
+ nullpo_ret(sd);
+ nullpo_ret(data);
if( !sd->combos )
return 0;/* nothing to do here, player has no combos */
@@ -9431,6 +9544,7 @@ int pc_removecombo(struct map_session_data *sd, struct item_data *data ) {
}
int pc_load_combo(struct map_session_data *sd) {
int i, ret = 0;
+ nullpo_ret(sd);
for( i = 0; i < EQI_MAX; i++ ) {
struct item_data *id = NULL;
int idx = sd->equip_index[i];
@@ -9463,6 +9577,7 @@ int pc_load_combo(struct map_session_data *sd) {
**/
void pc_equipitem_pos(struct map_session_data *sd, struct item_data *id, int n, int pos)
{
+ nullpo_retv(sd);
if ((!map_no_view(sd->bl.m,EQP_SHADOW_WEAPON) && pos & EQP_SHADOW_WEAPON) ||
(pos & EQP_HAND_R)) {
if(id)
@@ -9574,7 +9689,7 @@ int pc_equipitem(struct map_session_data *sd,int n,int req_pos)
if(battle_config.battle_log)
ShowInfo("equip %d(%d) %x:%x\n", sd->status.inventory[n].nameid, n, (unsigned int)(id ? id->equip : 0), (unsigned int)req_pos);
- if(!pc->isequip(sd,n) || !(pos&req_pos) || sd->status.inventory[n].equip != 0 || sd->status.inventory[n].attribute==1 ) { // [Valaris]
+ if(!pc->isequip(sd,n) || !(pos&req_pos) || sd->status.inventory[n].equip != 0 || (sd->status.inventory[n].attribute & ATTR_BROKEN) != 0 ) { // [Valaris]
// FIXME: pc->isequip: equip level failure uses 2 instead of 0
clif->equipitemack(sd,n,0,EIA_FAIL); // fail
return 0;
@@ -9693,6 +9808,7 @@ int pc_equipitem(struct map_session_data *sd,int n,int req_pos)
**/
void pc_unequipitem_pos(struct map_session_data *sd, int n, int pos)
{
+ nullpo_retv(sd);
if (pos & EQP_HAND_R) {
sd->weapontype1 = 0;
sd->status.weapon = sd->weapontype2;
@@ -10048,6 +10164,7 @@ int pc_calc_pvprank_sub(struct block_list *bl, va_list ap)
int pc_calc_pvprank(struct map_session_data *sd) {
int old;
struct map_data *m;
+ nullpo_ret(sd);
m=&map->list[sd->bl.m];
old=sd->pvp_rank;
sd->pvp_rank=1;
@@ -10202,6 +10319,7 @@ void pc_bleeding (struct map_session_data *sd, unsigned int diff_tick)
{
int hp = 0, sp = 0;
+ nullpo_retv(sd);
if( pc_isdead(sd) )
return;
@@ -10235,6 +10353,7 @@ void pc_bleeding (struct map_session_data *sd, unsigned int diff_tick)
void pc_regen (struct map_session_data *sd, unsigned int diff_tick) {
int hp = 0, sp = 0;
+ nullpo_retv(sd);
if (sd->hp_regen.value) {
sd->hp_regen.tick += diff_tick;
while (sd->hp_regen.tick >= sd->hp_regen.rate) {
@@ -10312,6 +10431,7 @@ int pc_autosave(int tid, int64 tick, int id, intptr_t data) {
}
int pc_daynight_timer_sub(struct map_session_data *sd,va_list ap) {
+ nullpo_ret(sd);
if (sd->state.night != map->night_flag && map->list[sd->bl.m].flag.nightenabled) { //Night/day state does not match.
clif->status_change(&sd->bl, SI_SKE, map->night_flag, 0, 0, 0, 0); //New night effect by dynamix [Skotlex]
sd->state.night = map->night_flag;
@@ -10335,7 +10455,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;
}
@@ -10355,7 +10475,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;
}
@@ -10376,6 +10496,7 @@ void pc_overheat(struct map_session_data *sd, int val) {
int heat = val, skill_lv,
limit[] = { 10, 20, 28, 46, 66 };
+ nullpo_retv(sd);
if( !pc_ismadogear(sd) || sd->sc.data[SC_OVERHEAT] )
return; // already burning
@@ -10401,6 +10522,7 @@ bool pc_isautolooting(struct map_session_data *sd, int nameid)
{
int i = 0;
+ nullpo_ret(sd);
if (sd->state.autoloottype && sd->state.autoloottype&(1<<itemdb_type(nameid)))
return true;
@@ -10589,6 +10711,7 @@ int pc_split_str(char *str,char **val,int num)
{
int i;
+ nullpo_ret(val);
for (i=0; i<num && str; i++){
val[i] = str;
str = strchr(str,',');
@@ -10601,6 +10724,7 @@ int pc_split_str(char *str,char **val,int num)
int pc_split_atoi(char* str, int* val, char sep, int max)
{
int i,j;
+ nullpo_ret(val);
for (i=0; i<max; i++) {
if (!str) break;
val[i] = atoi(str);
@@ -10618,6 +10742,7 @@ int pc_split_atoui(char* str, unsigned int* val, char sep, int max)
{
static int warning=0;
int i,j;
+ nullpo_ret(val);
for (i=0; i<max; i++) {
double f;
if (!str) break;
@@ -10870,6 +10995,7 @@ bool pc_readdb_levelpenalty(char* fields[], int columns, int current) {
#if defined(RENEWAL_DROP) || defined(RENEWAL_EXP)
int type, race, diff;
+ nullpo_retr(false, fields);
type = atoi(fields[0]);
race = atoi(fields[1]);
diff = atoi(fields[2]);
@@ -11014,18 +11140,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]);
@@ -11037,8 +11163,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
@@ -11046,7 +11172,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++;
@@ -11112,6 +11239,7 @@ void pc_itemcd_do(struct map_session_data *sd, bool load) {
int i,cursor = 0;
struct item_cd* cd = NULL;
+ nullpo_retv(sd);
if( load ) {
if( !(cd = idb_get(pc->itemcd_db, sd->status.char_id)) ) {
// no skill cooldown is associated with this character
@@ -11143,7 +11271,10 @@ void pc_itemcd_do(struct map_session_data *sd, bool load) {
}
void pc_bank_deposit(struct map_session_data *sd, int money) {
- unsigned int limit_check = money+sd->status.bank_vault;
+ unsigned int limit_check;
+
+ nullpo_retv(sd);
+ limit_check = money + sd->status.bank_vault;
if( money <= 0 || limit_check > MAX_BANK_ZENY ) {
clif->bank_deposit(sd,BDA_OVERFLOW);
@@ -11163,8 +11294,10 @@ void pc_bank_deposit(struct map_session_data *sd, int money) {
}
}
void pc_bank_withdraw(struct map_session_data *sd, int money) {
- unsigned int limit_check = money+sd->status.zeny;
+ unsigned int limit_check;
+ nullpo_retv(sd);
+ limit_check = money + sd->status.zeny;
if (money <= 0) {
clif->bank_withdraw(sd,BWA_UNKNOWN_ERROR);
return;
@@ -11188,6 +11321,7 @@ void pc_bank_withdraw(struct map_session_data *sd, int money) {
}
/* status change data arrived from char-server */
void pc_scdata_received(struct map_session_data *sd) {
+ nullpo_retv(sd);
pc->inventory_rentals(sd);
clif->show_modifiers(sd);
@@ -11195,7 +11329,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);
}
@@ -11236,6 +11370,7 @@ int pc_global_expiration_timer(int tid, int64 tick, int id, intptr_t data) {
return 0;
}
void pc_expire_check(struct map_session_data *sd) {
+ nullpo_retv(sd);
/* ongoing timer */
if( sd->expiration_tid != INVALID_TIMER )
return;
@@ -11293,6 +11428,7 @@ void pc_autotrade_start(struct map_session_data *sd) {
int i;
char *data;
+ nullpo_retv(sd);
if (SQL_ERROR == SQL->Query(map->mysql_handle, "SELECT `itemkey`,`amount`,`price` FROM `%s` WHERE `char_id` = '%d'",map->autotrade_data_db,sd->status.char_id))
Sql_ShowDebug(map->mysql_handle);
@@ -11337,6 +11473,7 @@ void pc_autotrade_start(struct map_session_data *sd) {
void pc_autotrade_update(struct map_session_data *sd, enum e_pc_autotrade_update_action action) {
int i;
+ nullpo_retv(sd);
/* either way, this goes down */
if( action != PAUC_START ) {
if (SQL_ERROR == SQL->Query(map->mysql_handle, "DELETE FROM `%s` WHERE `char_id` = '%d'",map->autotrade_data_db,sd->status.char_id))
@@ -11390,6 +11527,7 @@ void pc_autotrade_prepare(struct map_session_data *sd) {
char title[MESSAGE_SIZE];
unsigned char sex;
+ nullpo_retv(sd);
CREATE(data, struct autotrade_vending, 1);
memcpy(data->vending, sd->vending, sizeof(sd->vending));
@@ -11436,6 +11574,7 @@ void pc_autotrade_populate(struct map_session_data *sd) {
struct autotrade_vending *data;
int i, j, k, cursor = 0;
+ nullpo_retv(sd);
if( !(data = idb_get(pc->at_db,sd->status.char_id)) )
return;
@@ -11478,6 +11617,7 @@ void pc_autotrade_populate(struct map_session_data *sd) {
int pc_autotrade_final(union DBKey key, struct DBData *data, va_list ap)
{
struct autotrade_vending* at_v = DB->data2ptr(data);
+ nullpo_ret(at_v);
HPM->data_store_destroy(&at_v->hdata);
return 0;
}
@@ -11516,6 +11656,90 @@ 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)
+{
+ nullpo_retr(false, sd);
+ 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;
+
+ nullpo_retv(sd);
+ nullpo_retv(message);
+ 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);
@@ -11871,6 +12095,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]
**/
@@ -11883,6 +12110,6 @@ void pc_defaults(void) {
pc->check_job_name = pc_check_job_name;
pc->update_idle_time = pc_update_idle_time;
-
+
pc->have_magnifier = pc_have_magnifier;
}
diff --git a/src/map/pc.h b/src/map/pc.h
index b648b7113..58f7a2266 100644
--- a/src/map/pc.h
+++ b/src/map/pc.h
@@ -258,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;
@@ -610,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 )
@@ -1089,8 +1089,11 @@ END_ZEROED_BLOCK; /* End */
int (*check_job_name) (const char *name);
void (*update_idle_time) (struct map_session_data* sd, enum e_battle_config_idletime type);
-
+
int (*have_magnifier) (struct map_session_data *sd);
+
+ 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/script.c b/src/map/script.c
index 007c6e0e1..ed38ed1c5 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -83,36 +83,18 @@
struct script_interface script_s;
struct script_interface *script;
-static inline int GETVALUE(const unsigned char* buf, int i) {
- return (int)MakeDWord(MakeWord(buf[i], buf[i+1]), MakeWord(buf[i+2], 0));
-}
-static inline void SETVALUE(unsigned char* buf, int i, int n) {
- buf[i] = GetByte(n, 0);
- buf[i+1] = GetByte(n, 1);
- buf[i+2] = GetByte(n, 2);
-}
-
-static inline void script_string_buf_ensure(struct script_string_buf *buf, size_t ensure) {
- if( buf->pos+ensure >= buf->size ) {
- do {
- buf->size += 512;
- } while ( buf->pos+ensure >= buf->size );
- RECREATE(buf->ptr, char, buf->size);
- }
-}
-
-static inline void script_string_buf_addb(struct script_string_buf *buf,uint8 b) {
- if( buf->pos+1 >= buf->size ) {
- buf->size += 512;
- RECREATE(buf->ptr, char, buf->size);
- }
- buf->ptr[buf->pos++] = b;
+static inline int GETVALUE(const struct script_buf *buf, int i)
+{
+ Assert_ret(VECTOR_LENGTH(*buf) > i + 2);
+ return (int)MakeDWord(MakeWord(VECTOR_INDEX(*buf, i), VECTOR_INDEX(*buf, i+1)),
+ MakeWord(VECTOR_INDEX(*buf, i+2), 0));
}
-
-static inline void script_string_buf_destroy(struct script_string_buf *buf) {
- if( buf->ptr )
- aFree(buf->ptr);
- memset(buf,0,sizeof(struct script_string_buf));
+static inline void SETVALUE(struct script_buf *buf, int i, int n)
+{
+ Assert_retv(VECTOR_LENGTH(*buf) > i + 2);
+ VECTOR_INDEX(*buf, i) = GetByte(n, 0);
+ VECTOR_INDEX(*buf, i+1) = GetByte(n, 1);
+ VECTOR_INDEX(*buf, i+2) = GetByte(n, 2);
}
const char* script_op2name(int op) {
@@ -606,21 +588,26 @@ int script_add_str(const char* p)
return script->str_num++;
}
-/// Appends 1 byte to the script buffer.
+/**
+ * Appends 1 byte to the script buffer.
+ *
+ * @param a The byte to append.
+ */
void add_scriptb(int a)
{
- if( script->pos+1 >= script->size )
- {
- script->size += SCRIPT_BLOCK_SIZE;
- RECREATE(script->buf,unsigned char,script->size);
- }
- script->buf[script->pos++] = (uint8)(a);
+ VECTOR_ENSURE(script->buf, 1, SCRIPT_BLOCK_SIZE);
+ VECTOR_PUSH(script->buf, (uint8)a);
}
-/// Appends a c_op value to the script buffer.
-/// The value is variable-length encoded into 8-bit blocks.
-/// The encoding scheme is ( 01?????? )* 00??????, LSB first.
-/// All blocks but the last hold 7 bits of data, topmost bit is always 1 (carries).
+/**
+ * Appends a c_op value to the script buffer.
+ *
+ * The value is variable-length encoded into 8-bit blocks.
+ * The encoding scheme is ( 01?????? )* 00??????, LSB first.
+ * All blocks but the last hold 7 bits of data, topmost bit is always 1 (carries).
+ *
+ * @param a The value to append.
+ */
void add_scriptc(int a)
{
while( a >= 0x40 )
@@ -632,10 +619,15 @@ void add_scriptc(int a)
script->addb(a);
}
-/// Appends an integer value to the script buffer.
-/// The value is variable-length encoded into 8-bit blocks.
-/// The encoding scheme is ( 11?????? )* 10??????, LSB first.
-/// All blocks but the last hold 7 bits of data, topmost bit is always 1 (carries).
+/**
+ * Appends an integer value to the script buffer.
+ *
+ * The value is variable-length encoded into 8-bit blocks.
+ * The encoding scheme is ( 11?????? )* 10??????, LSB first.
+ * All blocks but the last hold 7 bits of data, topmost bit is always 1 (carries).
+ *
+ * @param a The value to append.
+ */
void add_scripti(int a)
{
while( a >= 0x40 )
@@ -646,11 +638,11 @@ void add_scripti(int a)
script->addb(a|0x80);
}
-/// Appends a script->str_data object (label/function/variable/integer) to the script buffer.
-
-///
-/// @param l The id of the script->str_data entry
-// Maximum up to 16M
+/**
+ * Appends a script->str_data object (label/function/variable/integer) to the script buffer.
+ *
+ * @param l The id of the script->str_data entry (Maximum up to 16M)
+ */
void add_scriptl(int l)
{
int backpatch = script->str_data[l].backpatch;
@@ -667,7 +659,7 @@ void add_scriptl(int l)
case C_USERFUNC:
// Embedded data backpatch there is a possibility of label
script->addc(C_NAME);
- script->str_data[l].backpatch = script->pos;
+ script->str_data[l].backpatch = VECTOR_LENGTH(script->buf);
script->addb(backpatch);
script->addb(backpatch>>8);
script->addb(backpatch>>16);
@@ -705,9 +697,9 @@ void set_label(int l,int pos, const char* script_pos)
script->str_data[l].type=(script->str_data[l].type == C_USERFUNC ? C_USERFUNC_POS : C_POS);
script->str_data[l].label=pos;
for (i = script->str_data[l].backpatch; i >= 0 && i != 0x00ffffff; ) {
- int next = GETVALUE(script->buf,i);
- script->buf[i-1]=(script->str_data[l].type == C_USERFUNC ? C_USERFUNC_POS : C_POS);
- SETVALUE(script->buf,i,pos);
+ int next = GETVALUE(&script->buf, i);
+ VECTOR_INDEX(script->buf, i-1) = (script->str_data[l].type == C_USERFUNC ? C_USERFUNC_POS : C_POS);
+ SETVALUE(&script->buf, i, pos);
i = next;
}
}
@@ -811,26 +803,25 @@ const char* parse_callfunc(const char* p, int require_paren, int is_custom)
char *arg = NULL;
char null_arg = '\0';
int func;
- bool nested_call = false, macro = false;
+ bool macro = false;
// is need add check for arg null pointer below?
func = script->add_word(p);
- if( script->str_data[func].type == C_FUNC ) {
- /** only when unset (-1), valid values are >= 0 **/
- if( script->syntax.last_func == -1 )
- script->syntax.last_func = script->str_data[func].val;
- else { //Nested function call
- script->syntax.nested_call++;
- nested_call = true;
-
- if( script->str_data[func].val == script->buildin_lang_macro_offset ) {
+ if (script->str_data[func].type == C_FUNC) {
+ script->syntax.nested_call++;
+ if (script->syntax.last_func != -1) {
+ if (script->str_data[func].val == script->buildin_lang_macro_offset) {
script->syntax.lang_macro_active = true;
macro = true;
+ } else if (script->str_data[func].val == script->buildin_lang_macro_fmtstring_offset) {
+ script->syntax.lang_macro_fmtstring_active = true;
+ macro = true;
}
}
if( !macro ) {
// buildin function
+ script->syntax.last_func = script->str_data[func].val;
script->addl(func);
script->addc(C_ARG);
}
@@ -919,18 +910,17 @@ const char* parse_callfunc(const char* p, int require_paren, int is_custom)
disp_error_message("parse_callfunc: expected ')' to close argument list",p);
++p;
- if( script->str_data[func].val == script->buildin_lang_macro_offset )
+ if (script->str_data[func].val == script->buildin_lang_macro_offset)
script->syntax.lang_macro_active = false;
+ else if (script->str_data[func].val == script->buildin_lang_macro_fmtstring_offset)
+ script->syntax.lang_macro_fmtstring_active = false;
}
- if( nested_call )
- script->syntax.nested_call--;
-
- if( !script->syntax.nested_call )
- script->syntax.last_func = -1;
-
- if( !macro )
+ if (!macro) {
+ if (0 == --script->syntax.nested_call)
+ script->syntax.last_func = -1;
script->addc(C_FUNC);
+ }
return p;
}
@@ -942,7 +932,7 @@ void parse_nextline(bool first, const char* p)
if( !first )
{
script->addc(C_EOL); // mark end of line for stack cleanup
- script->set_label(LABEL_NEXTLINE, script->pos, p); // fix up '-' labels
+ script->set_label(LABEL_NEXTLINE, VECTOR_LENGTH(script->buf), p); // fix up '-' labels
}
// initialize data for new '-' label fix up scheduling
@@ -1066,6 +1056,8 @@ const char* parse_variable(const char* p)
}
// push the set function onto the stack
+ script->syntax.nested_call++;
+ script->syntax.last_func = script->str_data[script->buildin_set_ref].val;
script->addl(script->buildin_set_ref);
script->addc(C_ARG);
@@ -1117,6 +1109,8 @@ const char* parse_variable(const char* p)
// close the script by appending the function operator
script->addc(C_FUNC);
+ if (--script->syntax.nested_call == 0)
+ script->syntax.last_func = -1;
// push the buffer from the method
return p;
@@ -1159,13 +1153,19 @@ bool is_number(const char *p) {
}
/**
+ * Duplicates a script string into the script string list.
*
- **/
-int script_string_dup(char *str) {
- size_t len = strlen(str);
+ * Grows the script string list as needed.
+ *
+ * @param str The string to insert.
+ * @return the string position in the script string list.
+ */
+int script_string_dup(char *str)
+{
+ int len = (int)strlen(str);
int pos = script->string_list_pos;
- while( pos+len+1 >= script->string_list_size ) {
+ while (pos+len+1 >= script->string_list_size) {
script->string_list_size += (1024*1024)/2;
RECREATE(script->string_list,char,script->string_list_size);
}
@@ -1179,231 +1179,194 @@ int script_string_dup(char *str) {
/*==========================================
* Analysis section
*------------------------------------------*/
-const char* parse_simpleexpr(const char *p)
+const char *parse_simpleexpr(const char *p)
{
p=script->skip_space(p);
- if(*p==';' || *p==',')
+ if (*p == ';' || *p == ',')
disp_error_message("parse_simpleexpr: unexpected end of expression",p);
- if(*p=='(') {
- int i = script->syntax.curly_count-1;
- if (i >= 0 && script->syntax.curly[i].type == TYPE_ARGLIST)
- ++script->syntax.curly[i].count;
- p=script->parse_subexpr(p+1,-1);
- p=script->skip_space(p);
- if( (i=script->syntax.curly_count-1) >= 0 && script->syntax.curly[i].type == TYPE_ARGLIST
- && script->syntax.curly[i].flag == ARGLIST_UNDEFINED && --script->syntax.curly[i].count == 0
- ) {
- if( *p == ',' ) {
- script->syntax.curly[i].flag = ARGLIST_PAREN;
- return p;
- } else {
- script->syntax.curly[i].flag = ARGLIST_NO_PAREN;
- }
- }
- if( *p != ')' )
- disp_error_message("parse_simpleexpr: unmatched ')'",p);
- ++p;
- } else if(is_number(p)) {
- char *np;
- long long lli;
- while(*p == '0' && ISDIGIT(p[1])) p++; // Skip leading zeros, we don't support octal literals
- lli=strtoll(p,&np,0);
- if( lli < INT_MIN ) {
- lli = INT_MIN;
- script->disp_warning_message("parse_simpleexpr: underflow detected, capping value to INT_MIN",p);
- } else if( lli > INT_MAX ) {
- lli = INT_MAX;
- script->disp_warning_message("parse_simpleexpr: overflow detected, capping value to INT_MAX",p);
- }
- script->addi((int)lli); // Cast is safe, as it's already been checked for overflows
- p=np;
- } else if(*p=='"') {
- struct string_translation *st = NULL;
- const char *start_point = p;
- bool duplicate = true;
- struct script_string_buf *sbuf = &script->parse_simpleexpr_str;
-
- do {
- p++;
- while( *p && *p != '"' ) {
- if( (unsigned char)p[-1] <= 0x7e && *p == '\\' ) {
- char buf[8];
- size_t len = sv->skip_escaped_c(p) - p;
- size_t n = sv->unescape_c(buf, p, len);
- if( n != 1 )
- ShowDebug("parse_simpleexpr: unexpected length %d after unescape (\"%.*s\" -> %.*s)\n", (int)n, (int)len, p, (int)n, buf);
- p += len;
- script_string_buf_addb(sbuf, *buf);
- continue;
- } else if( *p == '\n' ) {
- disp_error_message("parse_simpleexpr: unexpected newline @ string",p);
- }
- script_string_buf_addb(sbuf, *p++);
- }
- if(!*p)
- disp_error_message("parse_simpleexpr: unexpected end of file @ string",p);
- p++; //'"'
- p = script->skip_space(p);
- } while( *p && *p == '"' );
-
- script_string_buf_addb(sbuf, 0);
-
- if (!(script->syntax.translation_db && (st = strdb_get(script->syntax.translation_db, sbuf->ptr)) != NULL)) {
- script->addc(C_STR);
-
- if( script->pos+sbuf->pos >= script->size ) {
- do {
- script->size += SCRIPT_BLOCK_SIZE;
- } while( script->pos+sbuf->pos >= script->size );
- RECREATE(script->buf,unsigned char,script->size);
- }
+ if (*p == '(') {
+ return script->parse_simpleexpr_paren(p);
+ } else if (is_number(p)) {
+ return script->parse_simpleexpr_number(p);
+ } else if(*p == '"') {
+ return script->parse_simpleexpr_string(p);
+ } else {
+ return script->parse_simpleexpr_name(p);
+ }
+}
- memcpy(script->buf+script->pos, sbuf->ptr, sbuf->pos);
- script->pos += sbuf->pos;
+const char *parse_simpleexpr_paren(const char *p)
+{
+ int i = script->syntax.curly_count - 1;
+ if (i >= 0 && script->syntax.curly[i].type == TYPE_ARGLIST)
+ ++script->syntax.curly[i].count;
+ p = script->parse_subexpr(p + 1, -1);
+ p = script->skip_space(p);
+ if ((i = script->syntax.curly_count - 1) >= 0
+ && script->syntax.curly[i].type == TYPE_ARGLIST
+ && script->syntax.curly[i].flag == ARGLIST_UNDEFINED
+ && --script->syntax.curly[i].count == 0
+ ) {
+ if (*p == ',') {
+ script->syntax.curly[i].flag = ARGLIST_PAREN;
+ return p;
} else {
- int expand = sizeof(int) + sizeof(uint8);
- unsigned char j;
- unsigned int st_cursor = 0;
+ script->syntax.curly[i].flag = ARGLIST_NO_PAREN;
+ }
+ }
+ if (*p != ')')
+ disp_error_message("parse_simpleexpr: unmatched ')'", p);
- script->addc(C_LSTR);
+ return p + 1;
+}
- expand += (sizeof(char*) + sizeof(uint8)) * st->translations;
+const char *parse_simpleexpr_number(const char *p)
+{
+ char *np = NULL;
+ long long lli;
- while( script->pos+expand >= script->size ) {
- script->size += SCRIPT_BLOCK_SIZE;
- RECREATE(script->buf,unsigned char,script->size);
- }
+ while (*p == '0' && ISDIGIT(p[1]))
+ p++; // Skip leading zeros, we don't support octal literals
- *((int *)(&script->buf[script->pos])) = st->string_id;
- *((uint8 *)(&script->buf[script->pos + sizeof(int)])) = st->translations;
+ lli = strtoll(p, &np, 0);
+ if (lli < INT_MIN) {
+ lli = INT_MIN;
+ script->disp_warning_message("parse_simpleexpr: underflow detected, capping value to INT_MIN", p);
+ } else if (lli > INT_MAX) {
+ lli = INT_MAX;
+ script->disp_warning_message("parse_simpleexpr: overflow detected, capping value to INT_MAX", p);
+ }
+ script->addi((int)lli); // Cast is safe, as it's already been checked for overflows
- script->pos += sizeof(int) + sizeof(uint8);
+ return np;
+}
- for(j = 0; j < st->translations; j++) {
- *((uint8 *)(&script->buf[script->pos])) = RBUFB(st->buf, st_cursor);
- *((char **)(&script->buf[script->pos+sizeof(uint8)])) = &st->buf[st_cursor + sizeof(uint8)];
- script->pos += sizeof(char*) + sizeof(uint8);
- st_cursor += sizeof(uint8);
- while(st->buf[st_cursor++]);
- st_cursor += sizeof(uint8);
- }
- }
+const char *parse_simpleexpr_string(const char *p)
+{
+ const char *start_point = p;
- /* When exporting we don't know what is a translation and what isn't */
- if( script->lang_export_fp && sbuf->pos > 1 ) {//sbuf->pos will always be at least 1 because of the '\0'
- if( !script->syntax.strings ) {
- script->syntax.strings = strdb_alloc(DB_OPT_DUP_KEY|DB_OPT_ALLOW_NULL_DATA, 0);
+ do {
+ p++;
+ while (*p != '\0' && *p != '"') {
+ if ((unsigned char)p[-1] <= 0x7e && *p == '\\') {
+ char buf[8];
+ size_t len = sv->skip_escaped_c(p) - p;
+ size_t n = sv->unescape_c(buf, p, len);
+ if (n != 1)
+ ShowDebug("parse_simpleexpr: unexpected length %d after unescape (\"%.*s\" -> %.*s)\n", (int)n, (int)len, p, (int)n, buf);
+ p += len;
+ VECTOR_ENSURE(script->parse_simpleexpr_strbuf, 1, 512);
+ VECTOR_PUSH(script->parse_simpleexpr_strbuf, buf[0]);
+ continue;
}
-
- if( !strdb_exists(script->syntax.strings,sbuf->ptr) ) {
- strdb_put(script->syntax.strings, sbuf->ptr, NULL);
- duplicate = false;
+ if (*p == '\n') {
+ disp_error_message("parse_simpleexpr: unexpected newline @ string", p);
}
+ VECTOR_ENSURE(script->parse_simpleexpr_strbuf, 1, 512);
+ VECTOR_PUSH(script->parse_simpleexpr_strbuf, *p++);
}
+ if (*p == '\0')
+ disp_error_message("parse_simpleexpr: unexpected end of file @ string", p);
+ p++; //'"'
+ p = script->skip_space(p);
+ } while (*p != '\0' && *p == '"');
- if( script->lang_export_fp && !duplicate &&
- ( ( ( script->syntax.last_func == script->buildin_mes_offset ||
- script->syntax.last_func == script->buildin_select_offset ) && !script->syntax.nested_call
- ) || script->syntax.lang_macro_active ) ) {
- const char *line_start = start_point;
- const char *line_end = start_point;
- struct script_string_buf *lbuf = &script->lang_export_line_buf;
- struct script_string_buf *ubuf = &script->lang_export_unescaped_buf;
- size_t line_length, cursor;
+ VECTOR_ENSURE(script->parse_simpleexpr_strbuf, 1, 512);
+ VECTOR_PUSH(script->parse_simpleexpr_strbuf, '\0');
- while( line_start > script->parser_current_src ) {
- if( *line_start != '\n' )
- line_start--;
- else
- break;
- }
+ script->add_translatable_string(&script->parse_simpleexpr_strbuf, start_point);
- while( *line_end != '\n' && *line_end != '\0' )
- line_end++;
+ VECTOR_TRUNCATE(script->parse_simpleexpr_strbuf);
- line_length = (size_t)(line_end - line_start);
- if( line_length > 0 ) {
- script_string_buf_ensure(lbuf,line_length + 1);
+ return p;
+}
- memcpy(lbuf->ptr, line_start, line_length);
- lbuf->pos = line_length;
- script_string_buf_addb(lbuf, 0);
+const char *parse_simpleexpr_name(const char *p)
+{
+ int l;
+ const char *pv = NULL;
- normalize_name(lbuf->ptr, "\r\n\t ");
- }
+ // label , register , function etc
+ if (script->skip_word(p) == p)
+ disp_error_message("parse_simpleexpr: unexpected character", p);
- for(cursor = 0; cursor < sbuf->pos; cursor++) {
- if( sbuf->ptr[cursor] == '"' )
- script_string_buf_addb(ubuf, '\\');
- script_string_buf_addb(ubuf, sbuf->ptr[cursor]);
- }
- script_string_buf_addb(ubuf, 0);
-
- fprintf(script->lang_export_fp, "#: %s\n"
- "# %s\n"
- "msgctxt \"%s\"\n"
- "msgid \"%s\"\n"
- "msgstr \"\"\n",
- script->parser_current_file ? script->parser_current_file : "Unknown File",
- lbuf->ptr,
- script->parser_current_npc_name ? script->parser_current_npc_name : "Unknown NPC",
- ubuf->ptr
- );
- lbuf->pos = 0;
- ubuf->pos = 0;
+ l = script->add_word(p);
+ if (script->str_data[l].type == C_FUNC || script->str_data[l].type == C_USERFUNC || script->str_data[l].type == C_USERFUNC_POS) {
+ return script->parse_callfunc(p,1,0);
+#ifdef SCRIPT_CALLFUNC_CHECK
+ } else {
+ const char *name = script->get_str(l);
+ if (strdb_get(script->userfunc_db,name) != NULL) {
+ return script->parse_callfunc(p, 1, 1);
}
- sbuf->pos = 0;
+#endif
+ }
+
+ if ((pv = script->parse_variable(p)) != NULL) {
+ // successfully processed a variable assignment
+ return pv;
+ }
+
+ if (script->str_data[l].type == C_INT && script->str_data[l].deprecated) {
+ disp_warning_message("This constant is deprecated and it will be removed in a future version. Please see the script documentation and constants.conf for an alternative.\n", p);
+ }
+
+ p = script->skip_word(p);
+ if (*p == '[') {
+ // array(name[i] => getelementofarray(name,i) )
+ script->addl(script->buildin_getelementofarray_ref);
+ script->addc(C_ARG);
+ script->addl(l);
+
+ p = script->parse_subexpr(p + 1, -1);
+ p = script->skip_space(p);
+ if (*p != ']')
+ disp_error_message("parse_simpleexpr: unmatched ']'", p);
+ ++p;
+ script->addc(C_FUNC);
} else {
- int l;
- const char* pv;
+ script->addl(l);
+ }
- // label , register , function etc
- if(script->skip_word(p)==p)
- disp_error_message("parse_simpleexpr: unexpected character",p);
+ return p;
+}
- l=script->add_word(p);
- if( script->str_data[l].type == C_FUNC || script->str_data[l].type == C_USERFUNC || script->str_data[l].type == C_USERFUNC_POS) {
- return script->parse_callfunc(p,1,0);
-#ifdef SCRIPT_CALLFUNC_CHECK
- } else {
- const char* name = script->get_str(l);
- if( strdb_get(script->userfunc_db,name) != NULL ) {
- return script->parse_callfunc(p,1,1);
- }
-#endif
- }
+void script_add_translatable_string(const struct script_string_buf *string, const char *start_point)
+{
+ struct string_translation *st = NULL;
- if( (pv = script->parse_variable(p)) ) {
- // successfully processed a variable assignment
- return pv;
- }
+ if (script->syntax.translation_db == NULL
+ || (st = strdb_get(script->syntax.translation_db, VECTOR_DATA(*string))) == NULL) {
+ script->addc(C_STR);
- if (script->str_data[l].type == C_INT && script->str_data[l].deprecated) {
- disp_warning_message("This constant is deprecated and it will be removed in a future version. Please see the script documentation and constants.conf for an alternative.\n", p);
- }
+ VECTOR_ENSURE(script->buf, VECTOR_LENGTH(*string), SCRIPT_BLOCK_SIZE);
- p=script->skip_word(p);
- if( *p == '[' ) {
- // array(name[i] => getelementofarray(name,i) )
- script->addl(script->buildin_getelementofarray_ref);
- script->addc(C_ARG);
- script->addl(l);
+ VECTOR_PUSHARRAY(script->buf, VECTOR_DATA(*string), VECTOR_LENGTH(*string));
+ } else {
+ unsigned char u;
+ int st_cursor = 0;
- p=script->parse_subexpr(p+1,-1);
- p=script->skip_space(p);
- if( *p != ']' )
- disp_error_message("parse_simpleexpr: unmatched ']'",p);
- ++p;
- script->addc(C_FUNC);
- } else {
- script->addl(l);
- }
+ script->addc(C_LSTR);
- }
+ VECTOR_ENSURE(script->buf, (int)(sizeof(st->string_id) + sizeof(st->translations)), SCRIPT_BLOCK_SIZE);
+ VECTOR_PUSHARRAY(script->buf, (void *)&st->string_id, sizeof(st->string_id));
+ VECTOR_PUSHARRAY(script->buf, (void *)&st->translations, sizeof(st->translations));
- return p;
+ for (u = 0; u != st->translations; u++) {
+ struct string_translation_entry *entry = (void *)(st->buf+st_cursor);
+ char *stringptr = &entry->string[0];
+ st_cursor += sizeof(*entry);
+ VECTOR_ENSURE(script->buf, (int)(sizeof(entry->lang_id) + sizeof(char *)), SCRIPT_BLOCK_SIZE);
+ VECTOR_PUSHARRAY(script->buf, (void *)&entry->lang_id, sizeof(entry->lang_id));
+ VECTOR_PUSHARRAY(script->buf, (void *)&stringptr, sizeof(stringptr));
+ st_cursor += sizeof(uint8); // FIXME: What are we skipping here?
+ while (st->buf[st_cursor++] != 0)
+ (void)0; // Skip string
+ st_cursor += sizeof(uint8); // FIXME: What are we skipping here?
+ }
+ }
}
/*==========================================
@@ -1582,7 +1545,7 @@ const char* parse_curly_close(const char* p)
// You are here labeled
sprintf(label,"__SW%x_%x", (unsigned int)script->syntax.curly[pos].index, (unsigned int)script->syntax.curly[pos].count);
l=script->add_str(label);
- script->set_label(l,script->pos, p);
+ script->set_label(l, VECTOR_LENGTH(script->buf), p);
if(script->syntax.curly[pos].flag) {
//Exists default
@@ -1595,7 +1558,7 @@ const char* parse_curly_close(const char* p)
// Label end
sprintf(label,"__SW%x_FIN", (unsigned int)script->syntax.curly[pos].index);
l=script->add_str(label);
- script->set_label(l,script->pos, p);
+ script->set_label(l, VECTOR_LENGTH(script->buf), p);
linkdb_final(&script->syntax.curly[pos].case_label); // free the list of case label
script->syntax.curly_count--;
//Closing decision if, for , while
@@ -1674,7 +1637,7 @@ const char* parse_syntax(const char* p)
// You are here labeled
sprintf(label,"__SW%x_%x", (unsigned int)script->syntax.curly[pos].index, (unsigned int)script->syntax.curly[pos].count);
l=script->add_str(label);
- script->set_label(l,script->pos, p);
+ script->set_label(l, VECTOR_LENGTH(script->buf), p);
}
//Decision statement switch
p = script->skip_space(p2);
@@ -1714,7 +1677,7 @@ const char* parse_syntax(const char* p)
// Label after the completion of FALLTHRU
sprintf(label, "__SW%x_%xJ", (unsigned int)script->syntax.curly[pos].index, (unsigned int)script->syntax.curly[pos].count);
l=script->add_str(label);
- script->set_label(l,script->pos,p);
+ script->set_label(l, VECTOR_LENGTH(script->buf), p);
}
// check duplication of case label [Rayce]
if(linkdb_search(&script->syntax.curly[pos].case_label, (void*)h64BPTRSIZE(v)) != NULL)
@@ -1781,7 +1744,7 @@ const char* parse_syntax(const char* p)
}
sprintf(label, "__SW%x_%x", (unsigned int)script->syntax.curly[pos].index, (unsigned int)script->syntax.curly[pos].count);
l=script->add_str(label);
- script->set_label(l,script->pos,p);
+ script->set_label(l, VECTOR_LENGTH(script->buf), p);
// Skip to the next link w/o condition
sprintf(label, "goto __SW%x_%x;", (unsigned int)script->syntax.curly[pos].index, (unsigned int)script->syntax.curly[pos].count + 1);
@@ -1792,7 +1755,7 @@ const char* parse_syntax(const char* p)
// The default label
sprintf(label, "__SW%x_DEF", (unsigned int)script->syntax.curly[pos].index);
l=script->add_str(label);
- script->set_label(l,script->pos,p);
+ script->set_label(l, VECTOR_LENGTH(script->buf), p);
script->syntax.curly[script->syntax.curly_count - 1].flag = 1;
script->syntax.curly[pos].count++;
@@ -1810,7 +1773,7 @@ const char* parse_syntax(const char* p)
// Label of the (do) form here
sprintf(label, "__DO%x_BGN", (unsigned int)script->syntax.curly[script->syntax.curly_count].index);
l=script->add_str(label);
- script->set_label(l,script->pos,p);
+ script->set_label(l, VECTOR_LENGTH(script->buf), p);
script->syntax.curly_count++;
return p;
}
@@ -1841,7 +1804,7 @@ const char* parse_syntax(const char* p)
// Form the start of label decision
sprintf(label, "__FR%x_J", (unsigned int)script->syntax.curly[pos].index);
l=script->add_str(label);
- script->set_label(l,script->pos,p);
+ script->set_label(l, VECTOR_LENGTH(script->buf), p);
p=script->skip_space(p);
if(*p == ';') {
@@ -1870,7 +1833,7 @@ const char* parse_syntax(const char* p)
// Labels to form the next loop
sprintf(label, "__FR%x_NXT", (unsigned int)script->syntax.curly[pos].index);
l=script->add_str(label);
- script->set_label(l,script->pos,p);
+ script->set_label(l, VECTOR_LENGTH(script->buf), p);
// Process the next time you enter the loop
// A ')' last for; flag to be treated as'
@@ -1889,7 +1852,7 @@ const char* parse_syntax(const char* p)
// Loop start labeling
sprintf(label, "__FR%x_BGN", (unsigned int)script->syntax.curly[pos].index);
l=script->add_str(label);
- script->set_label(l,script->pos,p);
+ script->set_label(l, VECTOR_LENGTH(script->buf), p);
return p;
} else if( p2 - p == 8 && strncmp(p, "function", 8) == 0 ) {
// internal script function
@@ -1939,9 +1902,9 @@ const char* parse_syntax(const char* p)
if( script->str_data[l].type == C_NOP || script->str_data[l].type == C_USERFUNC )// register only, if the name was not used by something else
{
script->str_data[l].type = C_USERFUNC;
- script->set_label(l, script->pos, p);
+ script->set_label(l, VECTOR_LENGTH(script->buf), p);
if( script->parse_options&SCRIPT_USE_LABEL_DB )
- script->label_add(l,script->pos);
+ script->label_add(l, VECTOR_LENGTH(script->buf));
}
else
disp_error_message("parse_syntax:function: function name is invalid", func_name);
@@ -2021,7 +1984,7 @@ const char* parse_syntax(const char* p)
// Form the start of label decision
sprintf(label, "__WL%x_NXT", (unsigned int)script->syntax.curly[script->syntax.curly_count].index);
l=script->add_str(label);
- script->set_label(l,script->pos,p);
+ script->set_label(l, VECTOR_LENGTH(script->buf), p);
// Skip to the end point if the condition is false
sprintf(label, "__WL%x_FIN", (unsigned int)script->syntax.curly[script->syntax.curly_count].index);
@@ -2078,7 +2041,7 @@ const char* parse_syntax_close_sub(const char* p,int* flag)
// Put the label of the location
sprintf(label, "__IF%x_%x", (unsigned int)script->syntax.curly[pos].index, (unsigned int)script->syntax.curly[pos].count);
l=script->add_str(label);
- script->set_label(l,script->pos,p);
+ script->set_label(l, VECTOR_LENGTH(script->buf), p);
script->syntax.curly[pos].count++;
p = script->skip_space(p);
@@ -2116,7 +2079,7 @@ const char* parse_syntax_close_sub(const char* p,int* flag)
// Put the label of the final location
sprintf(label, "__IF%x_FIN", (unsigned int)script->syntax.curly[pos].index);
l=script->add_str(label);
- script->set_label(l,script->pos,p);
+ script->set_label(l, VECTOR_LENGTH(script->buf), p);
if(script->syntax.curly[pos].flag == 1) {
// Because the position of the pointer is the same if not else for this
return bp;
@@ -2129,7 +2092,7 @@ const char* parse_syntax_close_sub(const char* p,int* flag)
// (Come here continue) to form the label here
sprintf(label, "__DO%x_NXT", (unsigned int)script->syntax.curly[pos].index);
l=script->add_str(label);
- script->set_label(l,script->pos,p);
+ script->set_label(l, VECTOR_LENGTH(script->buf), p);
}
// Skip to the end point if the condition is false
@@ -2164,7 +2127,7 @@ const char* parse_syntax_close_sub(const char* p,int* flag)
// Form label of the end point conditions
sprintf(label, "__DO%x_FIN", (unsigned int)script->syntax.curly[pos].index);
l=script->add_str(label);
- script->set_label(l,script->pos,p);
+ script->set_label(l, VECTOR_LENGTH(script->buf), p);
p = script->skip_space(p);
if(*p != ';') {
disp_error_message("parse_syntax: need ';'",p);
@@ -2186,7 +2149,7 @@ const char* parse_syntax_close_sub(const char* p,int* flag)
// End for labeling
sprintf(label, "__FR%x_FIN", (unsigned int)script->syntax.curly[pos].index);
l=script->add_str(label);
- script->set_label(l,script->pos,p);
+ script->set_label(l, VECTOR_LENGTH(script->buf), p);
script->syntax.curly_count--;
return p;
} else if(script->syntax.curly[pos].type == TYPE_WHILE) {
@@ -2202,7 +2165,7 @@ const char* parse_syntax_close_sub(const char* p,int* flag)
// End while labeling
sprintf(label, "__WL%x_FIN", (unsigned int)script->syntax.curly[pos].index);
l=script->add_str(label);
- script->set_label(l,script->pos,p);
+ script->set_label(l, VECTOR_LENGTH(script->buf), p);
script->syntax.curly_count--;
return p;
} else if(script->syntax.curly[pos].type == TYPE_USERFUNC) {
@@ -2215,7 +2178,7 @@ const char* parse_syntax_close_sub(const char* p,int* flag)
// Put the label of the location
sprintf(label, "__FN%x_FIN", (unsigned int)script->syntax.curly[pos].index);
l=script->add_str(label);
- script->set_label(l,script->pos,p);
+ script->set_label(l, VECTOR_LENGTH(script->buf), p);
script->syntax.curly_count--;
return p;
} else {
@@ -2544,9 +2507,6 @@ struct script_code* parse_script(const char *src,const char *file,int line,int o
script->parse_cleanup_timer_id = timer->add(timer->gettick() + 10, script->parse_cleanup_timer, 0, 0);
}
- if( script->syntax.strings ) /* used only when generating translation file */
- db_destroy(script->syntax.strings);
-
memset(&script->syntax,0,sizeof(script->syntax));
script->syntax.last_func = -1;/* as valid values are >= 0 */
if( script->parser_current_npc_name ) {
@@ -2556,11 +2516,7 @@ struct script_code* parse_script(const char *src,const char *file,int line,int o
script->syntax.translation_db = strdb_get(script->translation_db, script->parser_current_npc_name);
}
- if( !script->buf ) {
- script->buf = (unsigned char *)aMalloc(SCRIPT_BLOCK_SIZE*sizeof(unsigned char));
- script->size = SCRIPT_BLOCK_SIZE;
- }
- script->pos=0;
+ VECTOR_TRUNCATE(script->buf);
script->parse_nextline(true, NULL);
// who called parse_script is responsible for clearing the database after using it, but just in case... lets clear it here
@@ -2574,7 +2530,7 @@ struct script_code* parse_script(const char *src,const char *file,int line,int o
if( script->error_report )
script->error(src,file,line,script->error_msg,script->error_pos);
aFree( script->error_msg );
- script->pos = 0;
+ VECTOR_TRUNCATE(script->buf);
for(i=LABEL_START;i<script->str_num;i++)
if(script->str_data[i].type == C_NOP) script->str_data[i].type = C_NAME;
for(i=0; i<size; i++)
@@ -2594,9 +2550,9 @@ struct script_code* parse_script(const char *src,const char *file,int line,int o
p=script->skip_space(p);
if( options&SCRIPT_IGNORE_EXTERNAL_BRACKETS )
{// does not require brackets around the script
- if( *p == '\0' && !(options&SCRIPT_RETURN_EMPTY_SCRIPT) )
- {// empty script and can return NULL
- script->pos = 0;
+ if (*p == '\0' && !(options&SCRIPT_RETURN_EMPTY_SCRIPT)) {
+ // empty script and can return NULL
+ VECTOR_TRUNCATE(script->buf);
#ifdef ENABLE_CASE_CHECK
script->local_casecheck.clear();
script->parser_current_src = NULL;
@@ -2614,9 +2570,9 @@ struct script_code* parse_script(const char *src,const char *file,int line,int o
if (retval) *retval = EXIT_FAILURE;
}
p = script->skip_space(p+1);
- if( *p == '}' && !(options&SCRIPT_RETURN_EMPTY_SCRIPT) )
- {// empty script and can return NULL
- script->pos = 0;
+ if (*p == '}' && !(options&SCRIPT_RETURN_EMPTY_SCRIPT)) {
+ // empty script and can return NULL
+ VECTOR_TRUNCATE(script->buf);
#ifdef ENABLE_CASE_CHECK
script->local_casecheck.clear();
script->parser_current_src = NULL;
@@ -2648,9 +2604,9 @@ struct script_code* parse_script(const char *src,const char *file,int line,int o
tmpp=script->skip_space(script->skip_word(p));
if(*tmpp==':' && !(strncmp(p,"default:",8) == 0 && p + 7 == tmpp)) {
i=script->add_word(p);
- script->set_label(i,script->pos,p);
+ script->set_label(i, VECTOR_LENGTH(script->buf), p);
if( script->parse_options&SCRIPT_USE_LABEL_DB )
- script->label_add(i,script->pos);
+ script->label_add(i, VECTOR_LENGTH(script->buf));
p=tmpp+1;
p=script->skip_space(p);
continue;
@@ -2672,8 +2628,8 @@ struct script_code* parse_script(const char *src,const char *file,int line,int o
script->str_data[i].type=C_NAME;
script->str_data[i].label=i;
for (j = script->str_data[i].backpatch; j >= 0 && j != 0x00ffffff; ) {
- int next = GETVALUE(script->buf,j);
- SETVALUE(script->buf,j,i);
+ int next = GETVALUE(&script->buf, j);
+ SETVALUE(&script->buf, j, i);
j = next;
}
} else if(script->str_data[i].type == C_USERFUNC) {
@@ -2690,37 +2646,39 @@ struct script_code* parse_script(const char *src,const char *file,int line,int o
}
#ifdef SCRIPT_DEBUG_DISP
- for(i=0;i<script->pos;i++) {
- if((i&15)==0) ShowMessage("%04x : ",i);
- ShowMessage("%02x ",script->buf[i]);
- if((i&15)==15) ShowMessage("\n");
+ for (i = 0; i < VECTOR_LENGTH(script->buf); i++) {
+ if ((i&15) == 0)
+ ShowMessage("%04x : ",i);
+ ShowMessage("%02x ", VECTOR_INDEX(script->buf, i));
+ if ((i&15) == 15)
+ ShowMessage("\n");
}
ShowMessage("\n");
#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 < VECTOR_LENGTH(script->buf)) {
+ 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));
+ ShowMessage(" %d", script->get_num(&script->buf, &i));
break;
case C_POS:
- ShowMessage(" 0x%06x", *(int*)(script->buf+i)&0xffffff);
+ ShowMessage(" 0x%06x", *(int*)(&VECTOR_INDEX(script->buf, i))&0xffffff);
i += 3;
break;
case C_NAME:
- j = (*(int*)(script->buf+i)&0xffffff);
+ j = (*(int*)(&VECTOR_INDEX(script->buf, i))&0xffffff);
ShowMessage(" %s", ( j == 0xffffff ) ? "?? unknown ??" : script->get_str(j));
i += 3;
break;
case C_STR:
- j = (int)strlen((char*)script->buf + i);
- ShowMessage(" %s", script->buf + i);
+ j = (int)strlen((char*)&VECTOR_INDEX(script->buf, i));
+ ShowMessage(" %s", &VECTOR_INDEX(script->buf, i));
i += j+1;
break;
}
@@ -2729,9 +2687,9 @@ struct script_code* parse_script(const char *src,const char *file,int line,int o
#endif
CREATE(code,struct script_code,1);
- code->script_buf = (unsigned char *)aMalloc(script->pos*sizeof(unsigned char));
- memcpy(code->script_buf, script->buf, script->pos);
- code->script_size = script->pos;
+ VECTOR_INIT(code->script_buf);
+ VECTOR_ENSURE(code->script_buf, VECTOR_LENGTH(script->buf), 1);
+ VECTOR_PUSHARRAY(code->script_buf, VECTOR_DATA(script->buf), VECTOR_LENGTH(script->buf));
code->local.vars = NULL;
code->local.arrays = NULL;
#ifdef ENABLE_CASE_CHECK
@@ -3624,7 +3582,7 @@ void script_free_code(struct script_code* code)
script->free_vars(code->local.vars);
if (code->local.arrays)
code->local.arrays->destroy(code->local.arrays,script->array_free_db);
- aFree(code->script_buf);
+ VECTOR_CLEAR(code->script_buf);
aFree(code);
}
@@ -3749,32 +3707,32 @@ void script_add_pending_ref(struct script_state *st, struct reg_db *ref) {
/*==========================================
* Read command
*------------------------------------------*/
-c_op get_com(unsigned char *scriptbuf,int *pos)
+c_op get_com(const struct script_buf *scriptbuf, int *pos)
{
int i = 0, j = 0;
- if(scriptbuf[*pos]>=0x80) {
+ if (VECTOR_INDEX(*scriptbuf, *pos) >= 0x80) {
return C_INT;
}
- while(scriptbuf[*pos]>=0x40) {
- i=scriptbuf[(*pos)++]<<j;
+ while (VECTOR_INDEX(*scriptbuf, *pos) >= 0x40) {
+ i = VECTOR_INDEX(*scriptbuf, (*pos)++) << j;
j+=6;
}
- return (c_op)(i+(scriptbuf[(*pos)++]<<j));
+ return (c_op)(i+(VECTOR_INDEX(*scriptbuf, (*pos)++)<<j));
}
/*==========================================
* Income figures
*------------------------------------------*/
-int get_num(unsigned char *scriptbuf,int *pos)
+int get_num(const struct script_buf *scriptbuf, int *pos)
{
int i,j;
i=0; j=0;
- while(scriptbuf[*pos]>=0xc0) {
- i+=(scriptbuf[(*pos)++]&0x7f)<<j;
+ while (VECTOR_INDEX(*scriptbuf, *pos) >= 0xc0) {
+ i+= (VECTOR_INDEX(*scriptbuf, (*pos)++)&0x7f)<<j;
j+=6;
}
- return i+((scriptbuf[(*pos)++]&0x7f)<<j);
+ return i+((VECTOR_INDEX(*scriptbuf, (*pos)++)&0x7f)<<j);
}
/// Ternary operators
@@ -3834,7 +3792,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);
@@ -3875,8 +3833,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);
@@ -4083,10 +4042,17 @@ void op_1(struct script_state* st, int op)
///
/// @param st Script state whose stack arguments should be inspected.
/// @param func Built-in function for which the arguments are intended.
-void script_check_buildin_argtype(struct script_state* st, int func)
+bool script_check_buildin_argtype(struct script_state* st, int func)
{
int idx, invalid = 0;
- char* sf = script->buildin[script->str_data[func].val];
+ char* sf;
+ if (script->str_data[func].val < 0 || script->str_data[func].val >= script->buildin_count) {
+ ShowDebug("Function: %s\n", script->get_str(func));
+ ShowError("Script data corruption detected!\n");
+ script->reportsrc(st);
+ return false;
+ }
+ sf = script->buildin[script->str_data[func].val];
for (idx = 2; script_hasdata(st, idx); idx++) {
struct script_data* data = script_getdata(st, idx);
@@ -4157,6 +4123,7 @@ void script_check_buildin_argtype(struct script_state* st, int func)
ShowDebug("Function: %s\n", script->get_str(func));
script->reportsrc(st);
}
+ return true;
}
/// Executes a buildin command.
@@ -4194,7 +4161,11 @@ int run_func(struct script_state *st)
}
if( script->config.warn_func_mismatch_argtypes ) {
- script->check_buildin_argtype(st, func);
+ if (script->check_buildin_argtype(st, func) == false)
+ {
+ st->state = END;
+ return 1;
+ }
}
if(script->str_data[func].func) {
@@ -4393,7 +4364,7 @@ void run_script_main(struct script_state *st) {
st->state = RUN;
while( st->state == RUN ) {
- enum c_op c = script->get_com(st->script->script_buf,&st->pos);
+ enum c_op c = script->get_com(&st->script->script_buf, &st->pos);
switch(c) {
case C_EOL:
if( stack->defsp > stack->sp )
@@ -4402,27 +4373,29 @@ void run_script_main(struct script_state *st) {
script->pop_stack(st, stack->defsp, stack->sp);// pop unused stack data. (unused return value)
break;
case C_INT:
- script->push_val(stack,C_INT,script->get_num(st->script->script_buf,&st->pos),NULL);
+ script->push_val(stack,C_INT,script->get_num(&st->script->script_buf, &st->pos), NULL);
break;
case C_POS:
case C_NAME:
- script->push_val(stack,c,GETVALUE(st->script->script_buf,st->pos),NULL);
+ script->push_val(stack,c,GETVALUE(&st->script->script_buf, st->pos), NULL);
st->pos+=3;
break;
case C_ARG:
script->push_val(stack,c,0,NULL);
break;
case C_STR:
- script->push_conststr(stack, (const char *)(st->script->script_buf+st->pos));
- while(st->script->script_buf[st->pos++]);
+ script->push_conststr(stack, (const char *)&VECTOR_INDEX(st->script->script_buf, st->pos));
+ while (VECTOR_INDEX(st->script->script_buf, st->pos++) != 0)
+ (void)0; // Skip string
break;
case C_LSTR:
{
- int string_id = *((int *)(&st->script->script_buf[st->pos]));
- uint8 translations = *((uint8 *)(&st->script->script_buf[st->pos+sizeof(int)]));
struct map_session_data *lsd = NULL;
-
- st->pos += sizeof(int) + sizeof(uint8);
+ uint8 translations = 0;
+ int string_id = *((int *)(&VECTOR_INDEX(st->script->script_buf, st->pos)));
+ st->pos += sizeof(string_id);
+ translations = *((uint8 *)(&VECTOR_INDEX(st->script->script_buf, st->pos)));
+ st->pos += sizeof(translations);
if( (!st->rid || !(lsd = map->id2sd(st->rid)) || !lsd->lang_id) && !map->default_lang_id )
script->push_conststr(stack, script->string_list+string_id);
@@ -4431,7 +4404,7 @@ void run_script_main(struct script_state *st) {
int offset = st->pos;
for(k = 0; k < translations; k++) {
- uint8 lang_id = *(uint8 *)(&st->script->script_buf[offset]);
+ uint8 lang_id = *(uint8 *)(&VECTOR_INDEX(st->script->script_buf, offset));
offset += sizeof(uint8);
if( lang_id == wlang_id )
break;
@@ -4440,7 +4413,7 @@ void run_script_main(struct script_state *st) {
if (k == translations)
script->push_conststr(stack, script->string_list+string_id);
else
- script->push_conststr(stack, *(const char**)(&st->script->script_buf[offset]) );
+ script->push_conststr(stack, *(const char**)(&VECTOR_INDEX(st->script->script_buf, offset)));
}
st->pos += ( ( sizeof(char*) + sizeof(uint8) ) * translations );
}
@@ -4854,9 +4827,6 @@ void do_final_script(void)
script->clear_translations(false);
script->parser_clean_leftovers();
-
- if( script->lang_export_file )
- aFree(script->lang_export_file);
}
/**
@@ -4878,7 +4848,7 @@ void script_load_translations(void) {
const char *config_filename = "db/translations.conf"; // FIXME hardcoded name
struct config_setting_t *translations = NULL;
int i, size;
- uint32 total = 0;
+ int total = 0;
uint8 lang_id = 0, k;
if (map->minimal) // No translations in minimal mode
@@ -4915,24 +4885,22 @@ void script_load_translations(void) {
for(i = 0; i < size; i++) {
const char *translation_file = libconfig->setting_get_string_elem(translations, i);
- script->load_translation(translation_file, ++lang_id, &total);
+ total += script->load_translation(translation_file, ++lang_id);
}
libconfig->destroy(&translations_conf);
- if( total ) {
- struct DBIterator *main_iter, *sub_iter;
+ if (total != 0) {
+ struct DBIterator *main_iter;
struct DBMap *string_db;
struct string_translation *st = NULL;
- uint32 j = 0;
- CREATE(script->translation_buf, char *, total);
- script->translation_buf_size = total;
+ VECTOR_ENSURE(script->translation_buf, total, 1);
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) ) {
- script->translation_buf[j++] = st->buf;
+ 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)) {
+ VECTOR_PUSH(script->translation_buf, st->buf);
}
dbi_destroy(sub_iter);
}
@@ -4954,52 +4922,75 @@ void script_load_translations(void) {
}
/**
+ * Generates a language name from a translation filename.
*
- **/
-const char * script_get_translation_file_name(const char *file) {
- static char file_name[200];
- int i, len = (int)strlen(file), last_bar = -1, last_dot = -1;
+ * @param file The filename.
+ * @return The corresponding translation name.
+ */
+const char *script_get_translation_file_name(const char *file)
+{
+ const char *basename = NULL, *last_dot = NULL;
- for(i = 0; i < len; i++) {
- if( file[i] == '/' || file[i] == '\\' )
- last_bar = i;
- else if ( file[i] == '.' )
- last_dot = i;
+ nullpo_retr("Unknown", file);
+
+ basename = strrchr(file, '/');;
+#ifdef WIN32
+ {
+ const char *basename_windows = strrchr(file, '\\');
+ if (basename_windows > basename)
+ basename = basename_windows;
}
+#endif // WIN32
+ if (basename == NULL)
+ basename = file;
+ else
+ basename++; // Skip slash
+ Assert_retr("Unknown", *basename != '\0');
- if( last_bar != -1 || last_dot != -1 ) {
- 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) ));
+ last_dot = strrchr(basename, '.');
+ if (last_dot != NULL) {
+ static char file_name[200];
+ if (last_dot == basename)
+ return basename + 1;
+
+ safestrncpy(file_name, basename, last_dot - basename + 1);
return file_name;
}
- return file;
+ return basename;
}
/**
- * Parses a individual translation file
- **/
-void script_load_translation(const char *file, uint8 lang_id, uint32 *total) {
- uint32 translations = 0;
+ * Parses an individual translation file.
+ *
+ * @param file The filename to parse.
+ * @param lang_id The language identifier.
+ * @return The amount of strings loaded.
+ */
+int script_load_translation(const char *file, uint8 lang_id)
+{
+ int translations = 0;
char line[1024];
char msgctxt[NAME_LENGTH*2+1] = { 0 };
struct DBMap *string_db;
size_t i;
FILE *fp;
- struct script_string_buf msgid = { 0 }, msgstr = { 0 };
+ struct script_string_buf msgid, msgstr;
if( !(fp = fopen(file,"rb")) ) {
ShowError("load_translation: failed to open '%s' for reading\n",file);
- return;
+ return 0;
}
+ VECTOR_INIT(msgid);
+ VECTOR_INIT(msgstr);
+
script->add_language(script->get_translation_file_name(file));
if( lang_id >= atcommand->max_message_table )
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;
@@ -5008,6 +4999,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] == '"' ) {
@@ -5015,44 +5007,50 @@ 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';
} else if ( strncasecmp(line, "msgid \"", 7) == 0 ) {
- msgid.pos = 0;
+ VECTOR_TRUNCATE(msgid);
for(i = 7; i < len - 2; i++) {
+ VECTOR_ENSURE(msgid, 1, 512);
if( line[i] == '\\' && line[i+1] == '"' ) {
- script_string_buf_addb(&msgid, '"');
+ VECTOR_PUSH(msgid, '"');
i++;
- } else
- script_string_buf_addb(&msgid, line[i]);
+ } else {
+ VECTOR_PUSH(msgid, line[i]);
+ }
}
- script_string_buf_addb(&msgid,0);
+ VECTOR_ENSURE(msgid, 1, 512);
+ VECTOR_PUSH(msgid, '\0');
} else if ( len > 9 && line[9] != '"' && strncasecmp(line, "msgstr \"",8) == 0 ) {
- msgstr.pos = 0;
+ VECTOR_TRUNCATE(msgstr);
for(i = 8; i < len - 2; i++) {
+ VECTOR_ENSURE(msgstr, 1, 512);
if( line[i] == '\\' && line[i+1] == '"' ) {
- script_string_buf_addb(&msgstr, '"');
+ VECTOR_PUSH(msgstr, '"');
i++;
- } else
- script_string_buf_addb(&msgstr, line[i]);
+ } else {
+ VECTOR_PUSH(msgstr, line[i]);
+ }
}
- script_string_buf_addb(&msgstr,0);
+ VECTOR_ENSURE(msgstr, 1, 512);
+ VECTOR_PUSH(msgstr, '\0');
}
- if( msgctxt[0] && msgid.pos > 1 && msgstr.pos > 1 ) {
- size_t msgstr_len = msgstr.pos;
+ if( msgctxt[0] && VECTOR_LENGTH(msgid) > 1 && VECTOR_LENGTH(msgstr) > 1 ) {
+ int msgstr_len = VECTOR_LENGTH(msgstr);
unsigned int inner_len = 1 + (uint32)msgstr_len + 1; //uint8 lang_id + msgstr_len + '\0'
if( strcasecmp(msgctxt, "messages.conf") == 0 ) {
int k;
for(k = 0; k < MAX_MSG; k++) {
- if( atcommand->msg_table[0][k] && strcmpi(atcommand->msg_table[0][k],msgid.ptr) == 0 ) {
+ if( atcommand->msg_table[0][k] && strcmpi(atcommand->msg_table[0][k], VECTOR_DATA(msgid)) == 0 ) {
if( atcommand->msg_table[lang_id][k] )
aFree(atcommand->msg_table[lang_id][k]);
- atcommand->msg_table[lang_id][k] = aStrdup(msgstr.ptr);
+ atcommand->msg_table[lang_id][k] = aStrdup(VECTOR_DATA(msgstr));
break;
}
}
@@ -5064,33 +5062,33 @@ void script_load_translation(const char *file, uint8 lang_id, uint32 *total) {
strdb_put(script->translation_db, msgctxt, string_db);
}
- if( !(st = strdb_get(string_db, msgid.ptr) ) ) {
+ if ((st = strdb_get(string_db, VECTOR_DATA(msgid))) == NULL) {
CREATE(st, struct string_translation, 1);
- st->string_id = script->string_dup(msgid.ptr);
- strdb_put(string_db, msgid.ptr, st);
+ st->string_id = script->string_dup(VECTOR_DATA(msgid));
+ strdb_put(string_db, VECTOR_DATA(msgid), st);
}
- RECREATE(st->buf, char, st->len + inner_len);
+ RECREATE(st->buf, uint8, st->len + inner_len);
WBUFB(st->buf, st->len) = lang_id;
- safestrncpy(WBUFP(st->buf, st->len + 1), msgstr.ptr, msgstr_len + 1);
+ safestrncpy(WBUFP(st->buf, st->len + 1), VECTOR_DATA(msgstr), msgstr_len + 1);
st->translations++;
st->len += inner_len;
}
msgctxt[0] = '\0';
- msgid.pos = msgstr.pos = 0;
+ VECTOR_TRUNCATE(msgid);
+ VECTOR_TRUNCATE(msgstr);
translations++;
}
}
- *total += translations;
-
fclose(fp);
- script_string_buf_destroy(&msgid);
- script_string_buf_destroy(&msgstr);
+ VECTOR_CLEAR(msgid);
+ VECTOR_CLEAR(msgstr);
- ShowStatus("Done reading '"CL_WHITE"%u"CL_RESET"' translations in '"CL_WHITE"%s"CL_RESET"'.\n", translations, file);
+ ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' translations in '"CL_WHITE"%s"CL_RESET"'.\n", translations, file);
+ return translations;
}
/**
@@ -5106,15 +5104,10 @@ void script_clear_translations(bool reload) {
script->string_list_pos = 0;
script->string_list_size = 0;
- if( script->translation_buf ) {
- for(i = 0; i < script->translation_buf_size; i++) {
- aFree(script->translation_buf[i]);
- }
- aFree(script->translation_buf);
+ while (VECTOR_LENGTH(script->translation_buf) > 0) {
+ aFree(VECTOR_POP(script->translation_buf));
}
-
- script->translation_buf = NULL;
- script->translation_buf_size = 0;
+ VECTOR_CLEAR(script->translation_buf);
if( script->languages ) {
for(i = 0; i < script->max_lang_id; i++)
@@ -5156,26 +5149,16 @@ int script_translation_db_destroyer(union DBKey key, struct DBData *data, va_lis
/**
*
**/
-void script_parser_clean_leftovers(void) {
- if( script->buf )
- aFree(script->buf);
-
- script->buf = NULL;
- script->size = 0;
+void script_parser_clean_leftovers(void)
+{
+ VECTOR_CLEAR(script->buf);
if( script->translation_db ) {
script->translation_db->destroy(script->translation_db,script->translation_db_destroyer);
script->translation_db = NULL;
}
- if( script->syntax.strings ) { /* used only when generating translation file */
- db_destroy(script->syntax.strings);
- script->syntax.strings = NULL;
- }
-
- script_string_buf_destroy(&script->parse_simpleexpr_str);
- script_string_buf_destroy(&script->lang_export_line_buf);
- script_string_buf_destroy(&script->lang_export_unescaped_buf);
+ VECTOR_CLEAR(script->parse_simpleexpr_strbuf);
}
/**
@@ -5194,6 +5177,7 @@ int script_parse_cleanup_timer(int tid, int64 tick, int id, intptr_t data) {
*------------------------------------------*/
void do_init_script(bool minimal) {
script->parse_cleanup_timer_id = INVALID_TIMER;
+ VECTOR_INIT(script->parse_simpleexpr_strbuf);
script->st_db = idb_alloc(DB_OPT_BASE);
script->userfunc_db = strdb_alloc(DB_OPT_DUP_KEY,0);
@@ -5280,6 +5264,232 @@ const char *script_getfuncname(struct script_state *st) {
return NULL;
}
+/**
+ * Writes a string to a StringBuf by combining a format string and a set of
+ * arguments taken from the current script state (caller script function
+ * arguments).
+ *
+ * @param[in] st Script state (must have at least a string at index
+ * 'start').
+ * @param[in] start Index of the format string argument.
+ * @param[out] out Output string buffer (managed by the caller, must be
+ * already initialized)
+ * @retval false if an error occurs.
+ */
+bool script_sprintf(struct script_state *st, int start, struct StringBuf *out)
+{
+ const char *format = NULL;
+ const char *p = NULL, *np = NULL;
+ char *buf = NULL;
+ int buf_len = 0;
+ int lastarg = start;
+ int argc = script_lastdata(st) + 1;
+
+ Assert_retr(-1, start >= 2 && start <= argc);
+ Assert_retr(-1, script_hasdata(st, start));
+
+ p = format = script_getstr(st, start);
+
+ /*
+ * format-string = "" / *(text / placeholder)
+ * placeholder = "%%" / "%n" / std-placeholder
+ * std-placeholder = "%" [pos-parameter] [flags] [width] [precision] [length] type
+ * pos-parameter = number "$"
+ * flags = *("-" / "+" / "0" / SP)
+ * width = number / ("*" [pos-parameter])
+ * precision = "." (number / ("*" [pos-parameter]))
+ * length = "hh" / "h" / "l" / "ll" / "L" / "z" / "j" / "t"
+ * type = "d" / "i" / "u" / "f" / "F" / "e" / "E" / "g" / "G" / "x" / "X" / "o" / "s" / "c" / "p" / "a" / "A"
+ * number = digit-nonzero *DIGIT
+ * digit-nonzero = "1" / "2" / "3" / "4" / "5" / "6" / "7" / "8" / "9"
+ */
+
+ while ((np = strchr(p, '%')) != NULL) {
+ bool flag_plus = false, flag_minus = false, flag_zero = false, flag_space = false;
+ bool positional_arg = false;
+ int width = 0, nextarg = lastarg + 1, thisarg = nextarg;
+
+ if (p != np) {
+ int len = (int)(np - p + 1);
+ if (buf_len < len) {
+ RECREATE(buf, char, len);
+ buf_len = len;
+ }
+ safestrncpy(buf, p, len);
+ StrBuf->AppendStr(out, buf);
+ }
+
+ p = np;
+ np++;
+
+ // placeholder = "%%" ; (special case)
+ if (*np == '%') {
+ StrBuf->AppendStr(out, "%");
+ p = np + 1;
+ continue;
+ }
+ // placeholder = "%n" ; (ignored)
+ if (*np == 'n') {
+ ShowWarning("script_sprintf: Format %%n not supported! Skipping...\n");
+ script->reportsrc(st);
+ lastarg = nextarg;
+ p = np + 1;
+ continue;
+ }
+
+ // std-placeholder = "%" [pos-parameter] [flags] [width] [precision] [length] type
+
+ // pos-parameter = number "$"
+ if (ISDIGIT(*np) && *np != '0') {
+ const char *pp = np;
+ while (ISDIGIT(*pp))
+ pp++;
+ if (*pp == '$') {
+ thisarg = atoi(np) + start;
+ positional_arg = true;
+ np = pp + 1;
+ }
+ }
+
+ if (thisarg >= argc) {
+ ShowError("buildin_sprintf: Not enough arguments passed!\n");
+ if (buf != NULL)
+ aFree(buf);
+ return false;
+ }
+
+ // flags = *("-" / "+" / "0" / SP)
+ while (true) {
+ if (*np == '-') {
+ flag_minus = true;
+ } else if (*np == '+') {
+ flag_plus = true;
+ } else if (*np == ' ') {
+ flag_space = true;
+ } else if (*np == '0') {
+ flag_zero = true;
+ } else {
+ break;
+ }
+ np++;
+ }
+
+ // width = number / ("*" [pos-parameter])
+ if (ISDIGIT(*np)) {
+ width = atoi(np);
+ while (ISDIGIT(*np))
+ np++;
+ } else if (*np == '*') {
+ bool positional_widtharg = false;
+ int width_arg;
+ np++;
+ // pos-parameter = number "$"
+ if (ISDIGIT(*np) && *np != '0') {
+ const char *pp = np;
+ while (ISDIGIT(*pp))
+ pp++;
+ if (*pp == '$') {
+ width_arg = atoi(np) + start;
+ positional_widtharg = true;
+ np = pp + 1;
+ }
+ }
+ if (!positional_widtharg) {
+ width_arg = nextarg;
+ nextarg++;
+ if (!positional_arg)
+ thisarg++;
+ }
+
+ if (width_arg >= argc || thisarg >= argc) {
+ ShowError("buildin_sprintf: Not enough arguments passed!\n");
+ if (buf != NULL)
+ aFree(buf);
+ return false;
+ }
+ width = script_getnum(st, width_arg);
+ }
+
+ // precision = "." (number / ("*" [pos-parameter])) ; (not needed/implemented)
+
+ // length = "hh" / "h" / "l" / "ll" / "L" / "z" / "j" / "t" ; (not needed/implemented)
+
+ // type = "d" / "i" / "u" / "f" / "F" / "e" / "E" / "g" / "G" / "x" / "X" / "o" / "s" / "c" / "p" / "a" / "A"
+ if (buf_len < 16) {
+ RECREATE(buf, char, 16);
+ buf_len = 16;
+ }
+ {
+ int i = 0;
+ memset(buf, '\0', buf_len);
+ buf[i++] = '%';
+ if (flag_minus)
+ buf[i++] = '-';
+ if (flag_plus)
+ buf[i++] = '+';
+ else if (flag_space) // ignored if '+' is specified
+ buf[i++] = ' ';
+ if (flag_zero)
+ buf[i++] = '0';
+ if (width > 0)
+ safesnprintf(buf + i, buf_len - i - 1, "%d", width);
+ }
+ buf[(int)strlen(buf)] = *np;
+ switch (*np) {
+ case 'd':
+ case 'i':
+ case 'u':
+ case 'x':
+ case 'X':
+ case 'o':
+ // Piggyback printf
+ StrBuf->Printf(out, buf, script_getnum(st, thisarg));
+ break;
+ case 's':
+ // Piggyback printf
+ StrBuf->Printf(out, buf, script_getstr(st, thisarg));
+ break;
+ case 'c':
+ {
+ const char *str = script_getstr(st, thisarg);
+ // Piggyback printf
+ StrBuf->Printf(out, buf, str[0]);
+ }
+ break;
+ case 'f':
+ case 'F':
+ case 'e':
+ case 'E':
+ case 'g':
+ case 'G':
+ case 'p':
+ case 'a':
+ case 'A':
+ ShowWarning("buildin_sprintf: Format %%%c not supported! Skipping...\n", *np);
+ script->reportsrc(st);
+ lastarg = nextarg;
+ p = np + 1;
+ continue;
+ default:
+ ShowError("buildin_sprintf: Invalid format string.\n");
+ if (buf != NULL)
+ aFree(buf);
+ return false;
+ }
+ lastarg = nextarg;
+ p = np + 1;
+ }
+
+ // Append the remaining part
+ if (p != NULL)
+ StrBuf->AppendStr(out, p);
+
+ if (buf != NULL)
+ aFree(buf);
+
+ return true;
+}
+
//-----------------------------------------------------------------------------
// buildin functions
//
@@ -5295,20 +5505,42 @@ const char *script_getfuncname(struct script_state *st) {
BUILDIN(mes)
{
struct map_session_data *sd = script->rid2sd(st);
- if( sd == NULL )
+ if (sd == NULL)
return true;
- if( !script_hasdata(st, 3) ) {// only a single line detected in the script
- clif->scriptmes(sd, st->oid, script_getstr(st, 2));
- } else {// parse multiple lines as they exist
- int i;
+ clif->scriptmes(sd, st->oid, script_getstr(st, 2));
- for( i = 2; script_hasdata(st, i); i++ ) {
- // send the message to the client
- clif->scriptmes(sd, st->oid, script_getstr(st, i));
- }
+ return true;
+}
+
+/**
+ * Appends a message to the npc dialog, applying format string conversions (see
+ * sprintf).
+ *
+ * If a dialog doesn't exist yet, one is created.
+ *
+ * @code
+ * mes "<message>";
+ * @endcode
+ */
+BUILDIN(mesf)
+{
+ struct map_session_data *sd = script->rid2sd(st);
+ struct StringBuf buf;
+
+ if (sd == NULL)
+ return true;
+
+ StrBuf->Init(&buf);
+
+ if (!script_sprintf(st, 2, &buf)) {
+ StrBuf->Destroy(&buf);
+ return false;
}
+ clif->scriptmes(sd, st->oid, StrBuf->Value(&buf));
+ StrBuf->Destroy(&buf);
+
return true;
}
@@ -8384,7 +8616,7 @@ BUILDIN(getbrokenid)
num=script_getnum(st,2);
for(i=0; i<MAX_INVENTORY; i++) {
- if(sd->status.inventory[i].attribute) {
+ if ((sd->status.inventory[i].attribute & ATTR_BROKEN) != 0) {
brokencounter++;
if(num==brokencounter) {
id=sd->status.inventory[i].nameid;
@@ -8409,7 +8641,7 @@ BUILDIN(getbrokencount)
return true;
for (i = 0; i < MAX_INVENTORY; i++) {
- if (sd->status.inventory[i].attribute)
+ if ((sd->status.inventory[i].attribute & ATTR_BROKEN) != 0)
counter++;
}
@@ -8431,10 +8663,11 @@ BUILDIN(repair)
num=script_getnum(st,2);
for(i=0; i<MAX_INVENTORY; i++) {
- if(sd->status.inventory[i].attribute) {
+ if ((sd->status.inventory[i].attribute & ATTR_BROKEN) != 0) {
repaircounter++;
if(num==repaircounter) {
- sd->status.inventory[i].attribute=0;
+ sd->status.inventory[i].attribute |= ATTR_BROKEN;
+ sd->status.inventory[i].attribute ^= ATTR_BROKEN;
clif->equiplist(sd);
clif->produce_effect(sd, 0, sd->status.inventory[i].nameid);
clif->misceffect(&sd->bl, 3);
@@ -8458,9 +8691,10 @@ BUILDIN(repairall)
for(i = 0; i < MAX_INVENTORY; i++)
{
- if(sd->status.inventory[i].nameid && sd->status.inventory[i].attribute)
+ if (sd->status.inventory[i].nameid && (sd->status.inventory[i].attribute & ATTR_BROKEN) != 0)
{
- sd->status.inventory[i].attribute = 0;
+ sd->status.inventory[i].attribute |= ATTR_BROKEN;
+ sd->status.inventory[i].attribute ^= ATTR_BROKEN;
clif->produce_effect(sd,0,sd->status.inventory[i].nameid);
repaircounter++;
}
@@ -10085,6 +10319,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;
@@ -10507,7 +10742,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;
@@ -10515,6 +10751,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
@@ -10539,14 +10777,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;
}
@@ -10554,10 +10792,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);
@@ -10604,7 +10842,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);
@@ -10614,17 +10853,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);
@@ -10638,12 +10880,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;
}
@@ -13782,7 +14026,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;
@@ -15229,130 +15473,19 @@ BUILDIN(implode)
// Implements C sprintf, except format %n. The resulting string is
// returned, instead of being saved in variable by reference.
//-------------------------------------------------------
-BUILDIN(sprintf) {
- unsigned int argc = 0, arg = 0;
- const char* format;
- char* p;
- char* q;
- char* buf = NULL;
- char* buf2 = NULL;
- struct script_data* data;
- size_t len, buf2_len = 0;
- StringBuf final_buf;
-
- // Fetch init data
- format = script_getstr(st, 2);
- argc = script_lastdata(st)-2;
- len = strlen(format);
-
- // Skip parsing, where no parsing is required.
- if(len==0) {
- script_pushconststr(st,"");
- return true;
- }
-
- // Pessimistic alloc
- CREATE(buf, char, len+1);
-
- // Need not be parsed, just solve stuff like %%.
- if(argc==0) {
- memcpy(buf,format,len+1);
- script_pushstrcopy(st, buf);
- aFree(buf);
- return true;
- }
-
- safestrncpy(buf, format, len+1);
-
- // Issue sprintf for each parameter
- StrBuf->Init(&final_buf);
- q = buf;
- while((p = strchr(q, '%'))!=NULL) {
- if(p!=q) {
- len = p-q+1;
- if(buf2_len<len) {
- RECREATE(buf2, char, len);
- buf2_len = len;
- }
- safestrncpy(buf2, q, len);
- StrBuf->AppendStr(&final_buf, buf2);
- q = p;
- }
- p = q+1;
- if(*p=='%') { // %%
- StrBuf->AppendStr(&final_buf, "%");
- q+=2;
- continue;
- }
- if(*p=='n') { // %n
- ShowWarning("buildin_sprintf: Format %%n not supported! Skipping...\n");
- script->reportsrc(st);
- q+=2;
- continue;
- }
- if(arg>=argc) {
- ShowError("buildin_sprintf: Not enough arguments passed!\n");
- aFree(buf);
- if(buf2) aFree(buf2);
- StrBuf->Destroy(&final_buf);
- script_pushconststr(st,"");
- return false;
- }
- if((p = strchr(q+1, '%'))==NULL) {
- p = strchr(q, 0); // EOS
- }
- len = p-q+1;
- if(buf2_len<len) {
- RECREATE(buf2, char, len);
- buf2_len = len;
- }
- safestrncpy(buf2, q, len);
- q = p;
-
- // Note: This assumes the passed value being the correct
- // type to the current format specifier. If not, the server
- // probably crashes or returns anything else, than expected,
- // but it would behave in normal code the same way so it's
- // the scripter's responsibility.
- data = script_getdata(st, arg+3);
- if(data_isstring(data)) { // String
- StrBuf->Printf(&final_buf, buf2, script_getstr(st, arg+3));
- } else if(data_isint(data)) { // Number
- StrBuf->Printf(&final_buf, buf2, script_getnum(st, arg+3));
- } else if(data_isreference(data)) { // Variable
- char* name = reference_getname(data);
- if(name[strlen(name)-1]=='$') { // var Str
- StrBuf->Printf(&final_buf, buf2, script_getstr(st, arg+3));
- } else { // var Int
- StrBuf->Printf(&final_buf, buf2, script_getnum(st, arg+3));
- }
- } else { // Unsupported type
- ShowError("buildin_sprintf: Unknown argument type!\n");
- aFree(buf);
- if(buf2) aFree(buf2);
- StrBuf->Destroy(&final_buf);
- script_pushconststr(st,"");
- return false;
- }
- arg++;
- }
-
- // Append anything left
- if(*q) {
- StrBuf->AppendStr(&final_buf, q);
- }
+BUILDIN(sprintf)
+{
+ struct StringBuf buf;
+ StrBuf->Init(&buf);
- // Passed more, than needed
- if(arg<argc) {
- ShowWarning("buildin_sprintf: Unused arguments passed.\n");
- script->reportsrc(st);
+ if (!script_sprintf(st, 2, &buf)) {
+ StrBuf->Destroy(&buf);
+ script_pushconststr(st, "");
+ return false;
}
- script_pushstrcopy(st, StrBuf->Value(&final_buf));
-
- aFree(buf);
- if(buf2) aFree(buf2);
- StrBuf->Destroy(&final_buf);
+ script_pushstrcopy(st, StrBuf->Value(&buf));
+ StrBuf->Destroy(&buf);
return true;
}
@@ -16479,7 +16612,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);
@@ -18017,7 +18150,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);
@@ -18026,8 +18160,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 )
@@ -18041,7 +18176,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;
}
@@ -18631,22 +18766,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);
}
@@ -18869,68 +18993,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;
@@ -20272,8 +20334,10 @@ bool script_add_builtin(const struct script_function *buildin, bool override) {
else if( strcmp(buildin->name, "callfunc") == 0 ) script->buildin_callfunc_ref = n;
else if( strcmp(buildin->name, "getelementofarray") == 0 ) script->buildin_getelementofarray_ref = n;
else if( strcmp(buildin->name, "mes") == 0 ) script->buildin_mes_offset = script->buildin_count;
+ else if( strcmp(buildin->name, "mesf") == 0 ) script->buildin_mesf_offset = script->buildin_count;
else if( strcmp(buildin->name, "select") == 0 ) script->buildin_select_offset = script->buildin_count;
else if( strcmp(buildin->name, "_") == 0 ) script->buildin_lang_macro_offset = script->buildin_count;
+ else if( strcmp(buildin->name, "_$") == 0 ) script->buildin_lang_macro_fmtstring_offset = script->buildin_count;
offset = script->buildin_count;
@@ -20367,7 +20431,8 @@ void script_parse_builtin(void) {
BUILDIN_DEF(__setr,"rv?"),
// NPC interaction
- BUILDIN_DEF(mes,"s*"),
+ BUILDIN_DEF(mes,"s"),
+ BUILDIN_DEF(mesf,"s*"),
BUILDIN_DEF(next,""),
BUILDIN_DEF(close,""),
BUILDIN_DEF(close2,""),
@@ -20879,6 +20944,7 @@ void script_parse_builtin(void) {
BUILDIN_DEF(showscript, "s?"),
BUILDIN_DEF(mergeitem,""),
BUILDIN_DEF(_,"s"),
+ BUILDIN_DEF2(_, "_$", "s"),
};
int i, len = ARRAYLENGTH(BUILDIN);
RECREATE(script->buildin, char *, script->buildin_count + len); // Pre-alloc to speed up
@@ -21112,8 +21178,8 @@ void script_defaults(void) {
script->label_count = 0;
script->labels_size = 0;
- script->buf = NULL;
- script->pos = 0, script->size = 0;
+ VECTOR_INIT(script->buf);
+ VECTOR_INIT(script->translation_buf);
script->parse_options = 0;
script->buildin_set_ref = 0;
@@ -21239,6 +21305,11 @@ void script_defaults(void) {
script->parse_nextline = parse_nextline;
script->parse_variable = parse_variable;
script->parse_simpleexpr = parse_simpleexpr;
+ script->parse_simpleexpr_paren = parse_simpleexpr_paren;
+ script->parse_simpleexpr_number = parse_simpleexpr_number;
+ script->parse_simpleexpr_string = parse_simpleexpr_string;
+ script->parse_simpleexpr_name = parse_simpleexpr_name;
+ script->add_translatable_string = script_add_translatable_string;
script->parse_expr = parse_expr;
script->parse_line = parse_line;
script->read_constdb = read_constdb;
diff --git a/src/map/script.h b/src/map/script.h
index a1fbe31f0..4df8941b7 100644
--- a/src/map/script.h
+++ b/src/map/script.h
@@ -394,11 +394,20 @@ struct script_data {
struct reg_db *ref; ///< Reference to the scope's variables
};
+/**
+ * A script string buffer, used to hold strings used by the script engine.
+ */
+VECTOR_STRUCT_DECL(script_string_buf, char);
+
+/**
+ * Script buffer, used to hold parsed script data.
+ */
+VECTOR_STRUCT_DECL(script_buf, unsigned char);
+
// Moved defsp from script_state to script_stack since
// it must be saved when script state is RERUNLINE. [Eoe / jA 1094]
struct script_code {
- int script_size;
- unsigned char *script_buf;
+ struct script_buf script_buf;
struct reg_db local; ///< Local (npc) vars
unsigned short instances;
};
@@ -493,8 +502,8 @@ struct script_syntax_data {
int index; // Number of the syntax used in the script
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;
- struct DBMap *strings; // string map parsed (used when exporting strings only)
+ bool lang_macro_active; // Used to generate translation strings
+ bool lang_macro_fmtstring_active; // Used to generate translation strings
struct DBMap *translation_db; //non-null if this npc has any translated strings to be linked
};
@@ -517,16 +526,16 @@ struct script_array {
unsigned int *members;/* member list */
};
-struct script_string_buf {
- char *ptr;
- size_t pos,size;
+struct string_translation_entry {
+ uint8 lang_id;
+ char string[];
};
struct string_translation {
int string_id;
uint8 translations;
- unsigned int len;
- char *buf;
+ int len;
+ uint8 *buf; // Array of struct string_translation_entry
};
/**
@@ -576,8 +585,7 @@ struct script_interface {
/* */
/// temporary buffer for passing around compiled bytecode
/// @see add_scriptb, set_label, parse_script
- unsigned char* buf;
- int pos, size;
+ struct script_buf buf;
/* */
struct script_syntax_data syntax;
/* */
@@ -611,26 +619,22 @@ struct script_interface {
/* */
unsigned int *generic_ui_array;
unsigned int generic_ui_array_size;
- /* Set during startup when attempting to export the lang, unset after server initialization is over */
- FILE *lang_export_fp;
- char *lang_export_file;/* for lang_export_fp */
/* set and unset on npc_parse_script */
const char *parser_current_npc_name;
/* */
int buildin_mes_offset;
+ int buildin_mesf_offset;
int buildin_select_offset;
int buildin_lang_macro_offset;
+ int buildin_lang_macro_fmtstring_offset;
/* */
struct DBMap *translation_db;/* npc_name => DBMap (strings) */
- char **translation_buf;/* */
- uint32 translation_buf_size;
+ VECTOR_DECL(uint8 *) translation_buf;
/* */
char **languages;
uint8 max_lang_id;
/* */
- struct script_string_buf parse_simpleexpr_str;
- struct script_string_buf lang_export_line_buf;
- struct script_string_buf lang_export_unescaped_buf;
+ struct script_string_buf parse_simpleexpr_strbuf;
/* */
int parse_cleanup_timer_id;
/* */
@@ -706,8 +710,8 @@ struct script_interface {
const char * (*parse_syntax_close) (const char *p);
const char * (*parse_syntax_close_sub) (const char *p, int *flag);
const char * (*parse_syntax) (const char *p);
- c_op (*get_com) (unsigned char *scriptbuf, int *pos);
- int (*get_num) (unsigned char *scriptbuf, int *pos);
+ c_op (*get_com) (const struct script_buf *scriptbuf, int *pos);
+ int (*get_num) (const struct script_buf *scriptbuf, int *pos);
const char* (*op2name) (int op);
void (*reportsrc) (struct script_state *st);
void (*reportdata) (struct script_data *data);
@@ -724,10 +728,15 @@ struct script_interface {
int (*add_word) (const char *p);
const char* (*parse_callfunc) (const char *p, int require_paren, int is_custom);
void (*parse_nextline) (bool first, const char *p);
- const char* (*parse_variable) (const char *p);
- const char* (*parse_simpleexpr) (const char *p);
- const char* (*parse_expr) (const char *p);
- const char* (*parse_line) (const char *p);
+ const char *(*parse_variable) (const char *p);
+ const char *(*parse_simpleexpr) (const char *p);
+ const char *(*parse_simpleexpr_paren) (const char *p);
+ const char *(*parse_simpleexpr_number) (const char *p);
+ const char *(*parse_simpleexpr_string) (const char *p);
+ const char *(*parse_simpleexpr_name) (const char *p);
+ void (*add_translatable_string) (const struct script_string_buf *string, const char *start_point);
+ const char *(*parse_expr) (const char *p);
+ const char *(*parse_line) (const char *p);
void (*read_constdb) (void);
void (*constdb_comment) (const char *comment);
void (*load_parameters) (void);
@@ -749,7 +758,7 @@ struct script_interface {
void (*op_2num) (struct script_state *st, int op, int i1, int i2);
void (*op_2) (struct script_state *st, int op);
void (*op_1) (struct script_state *st, int op);
- void (*check_buildin_argtype) (struct script_state *st, int func);
+ bool (*check_buildin_argtype) (struct script_state *st, int func);
void (*detach_state) (struct script_state *st, bool dequeue_event);
int (*db_free_code_sub) (union DBKey key, struct DBData *data, va_list ap);
void (*add_autobonus) (const char *autobonus);
@@ -807,7 +816,7 @@ struct script_interface {
unsigned short (*mapindexname2id) (struct script_state *st, const char* name);
int (*string_dup) (char *str);
void (*load_translations) (void);
- void (*load_translation) (const char *file, uint8 lang_id, uint32 *total);
+ int (*load_translation) (const char *file, uint8 lang_id);
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);
diff --git a/src/map/skill.c b/src/map/skill.c
index fb0d54e23..dceebb5b2 100644
--- a/src/map/skill.c
+++ b/src/map/skill.c
@@ -84,7 +84,8 @@ struct s_skill_dbs skilldbs;
struct skill_interface *skill;
//Since only mob-casted splash skills can hit ice-walls
-static inline int splash_target(struct block_list* bl) {
+int skill_splash_target(struct block_list* bl)
+{
#ifndef RENEWAL
return ( bl->type == BL_MOB ) ? BL_SKILL|BL_CHAR : BL_CHAR;
#else // Some skills can now hit ground skills(traps, ice wall & etc.)
@@ -2006,7 +2007,7 @@ int skill_break_equip (struct block_list *bl, unsigned short where, int rate, in
if (sd) {
for (i = 0; i < EQI_MAX; i++) {
int j = sd->equip_index[i];
- if (j < 0 || sd->status.inventory[j].attribute == 1 || !sd->inventory_data[j])
+ if (j < 0 || (sd->status.inventory[j].attribute & ATTR_BROKEN) != 0 || !sd->inventory_data[j])
continue;
switch(i) {
@@ -2032,7 +2033,7 @@ int skill_break_equip (struct block_list *bl, unsigned short where, int rate, in
continue;
}
if (flag) {
- sd->status.inventory[j].attribute = 1;
+ sd->status.inventory[j].attribute |= ATTR_BROKEN;
pc->unequipitem(sd, j, PCUNEQUIPITEM_RECALC|PCUNEQUIPITEM_FORCE);
}
}
@@ -2069,12 +2070,12 @@ int skill_strip_equip(struct block_list *bl, unsigned short where, int rate, int
return where?1:0;
}
/*=========================================================================
- Used to knock back players, monsters, traps, etc
- - 'count' is the number of squares to knock back
- - 'direction' indicates the way OPPOSITE to the knockback direction (or -1 for default behavior)
- - if 'flag&0x1', position update packets must not be sent.
- - if 'flag&0x2', skill blown ignores players' special_state.no_knockback
- -------------------------------------------------------------------------*/
+ * Used to knock back players, monsters, traps, etc
+ * 'count' is the number of squares to knock back
+ * 'direction' indicates the way OPPOSITE to the knockback direction (or -1 for default behavior)
+ * if 'flag&0x1', position update packets must not be sent.
+ * if 'flag&0x2', skill blown ignores players' special_state.no_knockback
+ */
int skill_blown(struct block_list* src, struct block_list* target, int count, int8 dir, int flag)
{
int dx = 0, dy = 0;
@@ -2891,11 +2892,11 @@ void skill_attack_display_unknown(int *attack_type, struct block_list* src, stru
}
int skill_attack_copy_unknown(int *attack_type, struct block_list* src, struct block_list *dsrc, struct block_list *bl, uint16 *skill_id, uint16 *skill_lv, int64 *tick, int *flag) {
- return *skill_id;
+ return *skill_id;
}
int skill_attack_dir_unknown(int *attack_type, struct block_list* src, struct block_list *dsrc, struct block_list *bl, uint16 *skill_id, uint16 *skill_lv, int64 *tick, int *flag) {
- return -1;
+ return -1;
}
void skill_attack_blow_unknown(int *attack_type, struct block_list* src, struct block_list *dsrc, struct block_list *bl, uint16 *skill_id, uint16 *skill_lv, int64 *tick, int *flag, int *type, struct Damage *dmg, int64 *damage, int8 *dir) {
@@ -3745,7 +3746,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
if (!(flag&1) && sc && sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_MONK) {
//Becomes a splash attack when Soul Linked.
map->foreachinrange(skill->area_sub, bl,
- skill->get_splash(skill_id, skill_lv),splash_target(src),
+ skill->get_splash(skill_id, skill_lv),skill->splash_target(src),
src,skill_id,skill_lv,tick, flag|BCT_ENEMY|1,
skill->castend_damage_id);
} else
@@ -3756,7 +3757,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
skill->area_temp[1] = 0;
map->foreachinrange(skill->attack_area, src,
- skill->get_splash(skill_id, skill_lv), splash_target(src),
+ skill->get_splash(skill_id, skill_lv), skill->splash_target(src),
BF_WEAPON, src, src, skill_id, skill_lv, tick, flag, BCT_ENEMY);
break;
@@ -3792,7 +3793,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
//line of sight between caster and target.
skill->area_temp[1] = bl->id;
map->foreachinpath(skill->attack_area,src->m,src->x,src->y,bl->x,bl->y,
- skill->get_splash(skill_id, skill_lv),skill->get_maxcount(skill_id,skill_lv), splash_target(src),
+ skill->get_splash(skill_id, skill_lv),skill->get_maxcount(skill_id,skill_lv), skill->splash_target(src),
skill->get_type(skill_id),src,src,skill_id,skill_lv,tick,flag,BCT_ENEMY);
break;
@@ -3803,7 +3804,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
case NPC_THUNDERBREATH:
skill->area_temp[1] = bl->id;
map->foreachinpath(skill->attack_area,src->m,src->x,src->y,bl->x,bl->y,
- skill->get_splash(skill_id, skill_lv),skill->get_maxcount(skill_id,skill_lv), splash_target(src),
+ skill->get_splash(skill_id, skill_lv),skill->get_maxcount(skill_id,skill_lv), skill->splash_target(src),
skill->get_type(skill_id),src,src,skill_id,skill_lv,tick,flag,BCT_ENEMY);
break;
@@ -4006,7 +4007,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
skill->area_temp[0] = map->foreachinrange(skill->area_sub, bl, (skill_id == AS_SPLASHER)?1:skill->get_splash(skill_id, skill_lv), BL_CHAR, src, skill_id, skill_lv, tick, BCT_ENEMY, skill->area_sub_count);
// recursive invocation of skill->castend_damage_id() with flag|1
- map->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill->castend_damage_id);
+ map->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), skill->splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill->castend_damage_id);
}
break;
@@ -4087,9 +4088,9 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
// Splash around target cell, but only cells inside area; we first have to check the area is not negative
if((max(min_x,tx-1) <= min(max_x,tx+1)) &&
(max(min_y,ty-1) <= min(max_y,ty+1)) &&
- (map->foreachinarea(skill->area_sub, bl->m, max(min_x,tx-1), max(min_y,ty-1), min(max_x,tx+1), min(max_y,ty+1), splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY, skill->area_sub_count))) {
+ (map->foreachinarea(skill->area_sub, bl->m, max(min_x,tx-1), max(min_y,ty-1), min(max_x,tx+1), min(max_y,ty+1), skill->splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY, skill->area_sub_count))) {
// Recursive call
- map->foreachinarea(skill->area_sub, bl->m, max(min_x,tx-1), max(min_y,ty-1), min(max_x,tx+1), min(max_y,ty+1), splash_target(src), src, skill_id, skill_lv, tick, (flag|BCT_ENEMY)+1, skill->castend_damage_id);
+ map->foreachinarea(skill->area_sub, bl->m, max(min_x,tx-1), max(min_y,ty-1), min(max_x,tx+1), min(max_y,ty+1), skill->splash_target(src), src, skill_id, skill_lv, tick, (flag|BCT_ENEMY)+1, skill->castend_damage_id);
// Self-collision
if(bl->x >= min_x && bl->x <= max_x && bl->y >= min_y && bl->y <= max_y)
skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,(flag&0xFFF)>0?SD_ANIMATION:0);
@@ -4590,7 +4591,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
status_change_end(bl, SC_CLOAKING, INVALID_TIMER);
status_change_end(bl, SC_CLOAKINGEXCEED, INVALID_TIMER); // Need confirm it.
} else {
- map->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill->castend_damage_id);
+ map->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), skill->splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill->castend_damage_id);
clif->skill_damage(src,src,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL);
if( sd ) pc->overheat(sd,1);
}
@@ -4608,7 +4609,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
// Destination area
skill->area_temp[4] = x;
skill->area_temp[5] = y;
- map->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_damage_id);
+ map->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), skill->splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_damage_id);
skill->addtimerskill(src,tick + 800,src->id,x,y,skill_id,skill_lv,0,flag); // To teleport Self
clif->skill_damage(src,src,tick,status_get_amotion(src),0,-30000,1,skill_id,skill_lv,BDT_SKILL);
}
@@ -4667,7 +4668,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
status_change_end(bl, SC_HIDING, INVALID_TIMER);
status_change_end(bl, SC_CLOAKINGEXCEED, INVALID_TIMER);
} else{
- map->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill->castend_damage_id);
+ map->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), skill->splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill->castend_damage_id);
clif->skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL);
}
break;
@@ -4804,7 +4805,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
if(flag & 1)
skill->attack(skill->get_type(skill_id), src, src, bl, skill_id, skill_lv, tick, flag);
else {
- map->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), splash_target(src), src, skill_id, skill_lv, tick, flag | BCT_ENEMY | SD_SPLASH | 1, skill->castend_damage_id);
+ map->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), skill->splash_target(src), src, skill_id, skill_lv, tick, flag | BCT_ENEMY | SD_SPLASH | 1, skill->castend_damage_id);
}
break;
@@ -5220,7 +5221,7 @@ int skill_castend_id(int tid, int64 tick, int id, intptr_t data) {
bool skill_castend_id_unknown(struct unit_data *ud, struct block_list *src, struct block_list *target)
{
- return false;
+ return false;
}
/*==========================================
@@ -5456,7 +5457,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
heal_get_jobexp = heal_get_jobexp * battle_config.heal_exp / 100;
if (heal_get_jobexp <= 0)
heal_get_jobexp = 1;
- pc->gainexp (sd, bl, 0, heal_get_jobexp, false);
+ pc->gainexp(sd, bl, 0, heal_get_jobexp, false);
}
}
break;
@@ -5532,7 +5533,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
if (jexp < 1) jexp = 1;
}
if(exp > 0 || jexp > 0)
- pc->gainexp (sd, bl, exp, jexp, false);
+ pc->gainexp(sd, bl, exp, jexp, false);
}
}
}
@@ -6260,7 +6261,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
skill->area_temp[1] = 0;
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
map->foreachinrange(skill->area_sub, bl,
- skill->get_splash(skill_id, skill_lv), splash_target(src),
+ skill->get_splash(skill_id, skill_lv), skill->splash_target(src),
src,skill_id,skill_lv,tick, flag|BCT_ENEMY|1,
skill->castend_damage_id);
status_change_end(src, SC_HIDING, INVALID_TIMER);
@@ -6279,7 +6280,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
int count = 0;
skill->area_temp[1] = 0;
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
- count = map->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), splash_target(src),
+ count = map->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), skill->splash_target(src),
src, skill_id, skill_lv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill->castend_damage_id);
if( !count && ( skill_id == NC_AXETORNADO || skill_id == SR_SKYNETBLOW || skill_id == KO_HAPPOKUNAI ) )
clif->skill_damage(src,src,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL);
@@ -6325,7 +6326,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
skill->area_temp[1] = 0;
map->foreachinrange(skill->attack_area, src,
- skill->get_splash(skill_id, skill_lv), splash_target(src),
+ skill->get_splash(skill_id, skill_lv), skill->splash_target(src),
BF_MAGIC, src, src, skill_id, skill_lv, tick, flag, BCT_ENEMY);
break;
@@ -6339,7 +6340,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
clif->skill_nodamage(src, src, skill_id, -1, 1);
map->delblock(src); //Required to prevent chain-self-destructions hitting back.
map->foreachinrange(skill->area_sub, bl,
- skill->get_splash(skill_id, skill_lv), splash_target(src),
+ skill->get_splash(skill_id, skill_lv), skill->splash_target(src),
src, skill_id, skill_lv, tick, flag|targetmask,
skill->castend_damage_id);
map->addblock(src);
@@ -8736,7 +8737,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
int failure;
if( (failure = sc_start2(src,bl,type,100,skill_lv,src->id,skill->get_time(skill_id,skill_lv))) )
{
- map->foreachinrange(skill->area_sub,src,skill->get_splash(skill_id,skill_lv),splash_target(src),src,skill_id,skill_lv,tick,flag|BCT_ENEMY|SD_SPLASH|1,skill->castend_damage_id);;
+ map->foreachinrange(skill->area_sub,src,skill->get_splash(skill_id,skill_lv),skill->splash_target(src),src,skill_id,skill_lv,tick,flag|BCT_ENEMY|SD_SPLASH|1,skill->castend_damage_id);;
clif->skill_damage(src,src,tick,status_get_amotion(src),0,-30000,1,skill_id,skill_lv,BDT_SKILL);
if (sd) pc->overheat(sd,1);
}
@@ -9077,7 +9078,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
clif->skill_nodamage(src, bl, skill_id, skill_lv, sp ? 1:0);
} else {
clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, BDT_SKILL);
- map->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|BCT_SELF|SD_SPLASH|1, skill->castend_nodamage_id);
+ map->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), skill->splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|BCT_SELF|SD_SPLASH|1, skill->castend_nodamage_id);
}
break;
@@ -9281,7 +9282,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;
@@ -9769,7 +9770,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
}
} else {
skill->area_temp[2] = 0;
- map->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill->castend_nodamage_id);
+ map->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), skill->splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill->castend_nodamage_id);
}
break;
@@ -9900,17 +9901,17 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
bool skill_castend_nodamage_id_dead_unknown(struct block_list *src, struct block_list *bl, uint16 *skill_id, uint16 *skill_lv, int64 *tick, int *flag)
{
- return true;
+ return true;
}
bool skill_castend_nodamage_id_undead_unknown(struct block_list *src, struct block_list *bl, uint16 *skill_id, uint16 *skill_lv, int64 *tick, int *flag)
{
- return true;
+ return true;
}
bool skill_castend_nodamage_id_mado_unknown(struct block_list *src, struct block_list *bl, uint16 *skill_id, uint16 *skill_lv, int64 *tick, int *flag)
{
- return false;
+ return false;
}
bool skill_castend_nodamage_id_unknown(struct block_list *src, struct block_list *bl, uint16 *skill_id, uint16 *skill_lv, int64 *tick, int *flag)
@@ -10084,7 +10085,7 @@ int skill_castend_pos(int tid, int64 tick, int id, intptr_t data)
}
-static int check_npc_chaospanic(struct block_list *bl, va_list args)
+int skill_check_npc_chaospanic(struct block_list *bl, va_list args)
{
const struct npc_data *nd = NULL;
@@ -10098,7 +10099,8 @@ static int check_npc_chaospanic(struct block_list *bl, va_list args)
return 1;
}
/* skill count without self */
-static int skill_count_wos(struct block_list *bl,va_list ap) {
+int skill_count_wos(struct block_list *bl, va_list ap)
+{
struct block_list* src = va_arg(ap, struct block_list*);
if( src->id != bl->id ) {
return 1;
@@ -10340,7 +10342,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
case SC_CHAOSPANIC:
case SC_MAELSTROM:
- if (sd && map->foreachinarea(&check_npc_chaospanic,src->m, x-3, y-3, x+3, y+3, BL_NPC) > 0 ) {
+ if (sd && map->foreachinarea(skill->check_npc_chaospanic, src->m, x-3, y-3, x+3, y+3, BL_NPC) > 0 ) {
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
break;
}
@@ -10482,7 +10484,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
if( sc && sc->data[SC_BASILICA] )
status_change_end(src, SC_BASILICA, INVALID_TIMER); // Cancel Basilica
else { // Create Basilica. Start SC on caster. Unit timer start SC on others.
- if( map->foreachinrange(skill_count_wos, src, 2, BL_MOB|BL_PC, src) ) {
+ if( map->foreachinrange(skill->count_wos, src, 2, BL_MOB|BL_PC, src) ) {
if( sd )
clif->skill_fail(sd,skill_id,USESKILL_FAIL,0);
return 1;
@@ -10747,7 +10749,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
case RK_DRAGONBREATH:
case RK_DRAGONBREATH_WATER:
r = skill->get_splash(skill_id,skill_lv);
- map->foreachinarea(skill->area_sub,src->m,x-r,y-r,x+r,y+r,splash_target(src),
+ map->foreachinarea(skill->area_sub,src->m,x-r,y-r,x+r,y+r,skill->splash_target(src),
src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_damage_id);
break;
case WM_GREAT_ECHO:
@@ -10769,7 +10771,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
break;
case SO_ARRULLO:
r = skill->get_splash(skill_id,skill_lv);
- map->foreachinarea(skill->area_sub,src->m,x-r,y-r,x+r,y+r,splash_target(src),
+ map->foreachinarea(skill->area_sub,src->m,x-r,y-r,x+r,y+r,skill->splash_target(src),
src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_nodamage_id);
break;
/**
@@ -10884,7 +10886,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
case LG_RAYOFGENESIS:
if( status->charge(src,status_get_max_hp(src)*3*skill_lv / 100,0) ) {
r = skill->get_splash(skill_id,skill_lv);
- map->foreachinarea(skill->area_sub,src->m,x-r,y-r,x+r,y+r,splash_target(src),
+ map->foreachinarea(skill->area_sub,src->m,x-r,y-r,x+r,y+r,skill->splash_target(src),
src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_damage_id);
} else if( sd )
clif->skill_fail(sd,skill_id,USESKILL_FAIL,0);
@@ -11717,7 +11719,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;
@@ -13123,7 +13125,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]
@@ -14063,22 +14066,22 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
int skill_check_condition_castbegin_off_unknown(struct status_change *sc, uint16 *skill_id)
{
- return -1;
+ return -1;
}
int skill_check_condition_castbegin_mount_unknown(struct status_change *sc, uint16 *skill_id)
{
- return 0;
+ return 0;
}
int skill_check_condition_castbegin_madogear_unknown(struct status_change *sc, uint16 *skill_id)
{
- return 0;
+ return 0;
}
int skill_check_condition_castbegin_unknown(struct status_change *sc, uint16 *skill_id)
{
- return -1;
+ return -1;
}
int skill_check_condition_castend(struct map_session_data* sd, uint16 skill_id, uint16 skill_lv) {
@@ -14089,7 +14092,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 ) {
@@ -14701,12 +14704,12 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, uint16
bool skill_get_requirement_off_unknown(struct status_change *sc, uint16 *skill_id)
{
- return false;
+ return false;
}
bool skill_get_requirement_item_unknown(struct status_change *sc, struct map_session_data* sd, uint16 *skill_id, uint16 *skill_lv, uint16 *idx, int *i)
{
- return false;
+ return false;
}
void skill_get_requirement_unknown(struct status_change *sc, struct map_session_data* sd, uint16 *skill_id, uint16 *skill_lv, struct skill_condition *req)
@@ -15222,7 +15225,7 @@ void skill_repairweapon (struct map_session_data *sd, int idx) {
return; //Invalid index??
item = &target_sd->status.inventory[idx];
- if( item->nameid <= 0 || item->attribute == 0 )
+ if( item->nameid <= 0 || (item->attribute & ATTR_BROKEN) == 0 )
return; //Again invalid item....
if( sd != target_sd && !battle->check_range(&sd->bl,&target_sd->bl, skill->get_range2(&sd->bl, sd->menuskill_id,sd->menuskill_val2) ) ){
@@ -15241,7 +15244,8 @@ void skill_repairweapon (struct map_session_data *sd, int idx) {
clif->skill_nodamage(&sd->bl,&target_sd->bl,sd->menuskill_id,1,1);
- item->attribute = 0;/* clear broken state */
+ item->attribute |= ATTR_BROKEN;
+ item->attribute ^= ATTR_BROKEN; /* clear broken state */
clif->equiplist(target_sd);
@@ -15995,14 +15999,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 )
@@ -16060,11 +16064,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 )
@@ -16671,7 +16675,7 @@ int skill_unit_timer_sub(union DBKey key, struct DBData *data, va_list ap)
case UNT_FEINTBOMB: {
struct block_list *src = map->id2bl(group->src_id);
if( src ) {
- map->foreachinrange(skill->area_sub, &su->bl, su->range, splash_target(src), src, SC_FEINTBOMB, group->skill_lv, tick, BCT_ENEMY|SD_ANIMATION|1, skill->castend_damage_id);
+ map->foreachinrange(skill->area_sub, &su->bl, su->range, skill->splash_target(src), src, SC_FEINTBOMB, group->skill_lv, tick, BCT_ENEMY|SD_ANIMATION|1, skill->castend_damage_id);
status_change_end(src, SC__FEINTBOMB_MASTER, INVALID_TIMER);
}
skill->delunit(su);
@@ -20634,4 +20638,7 @@ void skill_defaults(void) {
skill->get_requirement_off_unknown = skill_get_requirement_off_unknown;
skill->get_requirement_item_unknown = skill_get_requirement_item_unknown;
skill->get_requirement_unknown = skill_get_requirement_unknown;
+ skill->splash_target = skill_splash_target;
+ skill->check_npc_chaospanic = skill_check_npc_chaospanic;
+ skill->count_wos = skill_count_wos;
}
diff --git a/src/map/skill.h b/src/map/skill.h
index 9bb3eae13..45f025e74 100644
--- a/src/map/skill.h
+++ b/src/map/skill.h
@@ -2113,6 +2113,9 @@ struct skill_interface {
bool (*get_requirement_off_unknown) (struct status_change *sc, uint16 *skill_id);
bool (*get_requirement_item_unknown) (struct status_change *sc, struct map_session_data* sd, uint16 *skill_id, uint16 *skill_lv, uint16 *idx, int *i);
void (*get_requirement_unknown) (struct status_change *sc, struct map_session_data* sd, uint16 *skill_id, uint16 *skill_lv, struct skill_condition *req);
+ int (*splash_target) (struct block_list* bl);
+ int (*check_npc_chaospanic) (struct block_list *bl, va_list args);
+ int (*count_wos) (struct block_list *bl, va_list ap);
};
#ifdef HERCULES_CORE
diff --git a/src/map/status.c b/src/map/status.c
index a8771c0a5..83d8943c9 100644
--- a/src/map/status.c
+++ b/src/map/status.c
@@ -125,7 +125,8 @@ int status_type2relevant_bl_types(int type)
return status->dbs->RelevantBLTypes[type];
}
-static void set_sc(uint16 skill_id, sc_type sc, int icon, unsigned int flag) {
+void status_set_sc(uint16 skill_id, sc_type sc, int icon, unsigned int flag)
+{
uint16 idx;
if( (idx = skill->get_index(skill_id)) == 0 ) {
ShowError("set_sc: Unsupported skill id %d\n", skill_id);
@@ -147,9 +148,9 @@ static void set_sc(uint16 skill_id, sc_type sc, int icon, unsigned int flag) {
}
void initChangeTables(void) {
-#define add_sc(skill,sc) set_sc((skill),(sc),SI_BLANK,SCB_NONE)
+#define add_sc(skill,sc) status->set_sc((skill),(sc),SI_BLANK,SCB_NONE)
// indicates that the status displays a visual effect for the affected unit, and should be sent to the client for all supported units
-#define set_sc_with_vfx(skill, sc, icon, flag) do { set_sc((skill), (sc), (icon), (flag)); if((icon) < SI_MAX) status->dbs->RelevantBLTypes[(icon)] |= BL_SCEFFECT; } while(0)
+#define set_sc_with_vfx(skill, sc, icon, flag) do { status->set_sc((skill), (sc), (icon), (flag)); if((icon) < SI_MAX) status->dbs->RelevantBLTypes[(icon)] |= BL_SCEFFECT; } while(0)
int i;
@@ -167,83 +168,83 @@ void initChangeTables(void) {
memset(status->dbs->DisplayType, 0, sizeof(status->dbs->DisplayType));
//First we define the skill for common ailments. These are used in skill_additional_effect through sc cards. [Skotlex]
- set_sc( NPC_PETRIFYATTACK , SC_STONE , SI_BLANK , SCB_DEF_ELE|SCB_DEF|SCB_MDEF );
- set_sc( NPC_WIDEFREEZE , SC_FREEZE , SI_BLANK , SCB_DEF_ELE|SCB_DEF|SCB_MDEF );
- set_sc( NPC_STUNATTACK , SC_STUN , SI_BLANK , SCB_NONE );
- set_sc( NPC_SLEEPATTACK , SC_SLEEP , SI_BLANK , SCB_NONE );
- set_sc( NPC_POISON , SC_POISON , SI_BLANK , SCB_DEF2|SCB_REGEN );
- set_sc( NPC_CURSEATTACK , SC_CURSE , SI_BLANK , SCB_LUK|SCB_BATK|SCB_WATK|SCB_SPEED );
- set_sc( NPC_SILENCEATTACK , SC_SILENCE , SI_BLANK , SCB_NONE );
- set_sc( NPC_WIDECONFUSE , SC_CONFUSION , SI_BLANK , SCB_NONE );
- set_sc( NPC_BLINDATTACK , SC_BLIND , SI_BLANK , SCB_HIT|SCB_FLEE );
- set_sc( NPC_BLEEDING , SC_BLOODING , SI_BLOODING , SCB_REGEN );
- set_sc( NPC_POISON , SC_DPOISON , SI_BLANK , SCB_DEF2|SCB_REGEN );
+ status->set_sc( NPC_PETRIFYATTACK , SC_STONE , SI_BLANK , SCB_DEF_ELE|SCB_DEF|SCB_MDEF );
+ status->set_sc( NPC_WIDEFREEZE , SC_FREEZE , SI_BLANK , SCB_DEF_ELE|SCB_DEF|SCB_MDEF );
+ status->set_sc( NPC_STUNATTACK , SC_STUN , SI_BLANK , SCB_NONE );
+ status->set_sc( NPC_SLEEPATTACK , SC_SLEEP , SI_BLANK , SCB_NONE );
+ status->set_sc( NPC_POISON , SC_POISON , SI_BLANK , SCB_DEF2|SCB_REGEN );
+ status->set_sc( NPC_CURSEATTACK , SC_CURSE , SI_BLANK , SCB_LUK|SCB_BATK|SCB_WATK|SCB_SPEED );
+ status->set_sc( NPC_SILENCEATTACK , SC_SILENCE , SI_BLANK , SCB_NONE );
+ status->set_sc( NPC_WIDECONFUSE , SC_CONFUSION , SI_BLANK , SCB_NONE );
+ status->set_sc( NPC_BLINDATTACK , SC_BLIND , SI_BLANK , SCB_HIT|SCB_FLEE );
+ status->set_sc( NPC_BLEEDING , SC_BLOODING , SI_BLOODING , SCB_REGEN );
+ status->set_sc( NPC_POISON , SC_DPOISON , SI_BLANK , SCB_DEF2|SCB_REGEN );
//The main status definitions
add_sc( SM_BASH , SC_STUN );
- set_sc( SM_PROVOKE , SC_PROVOKE , SI_PROVOKE , SCB_DEF|SCB_DEF2|SCB_BATK|SCB_WATK );
+ status->set_sc( SM_PROVOKE , SC_PROVOKE , SI_PROVOKE , SCB_DEF|SCB_DEF2|SCB_BATK|SCB_WATK );
add_sc( SM_MAGNUM , SC_SUB_WEAPONPROPERTY );
- set_sc( SM_ENDURE , SC_ENDURE , SI_ENDURE , SCB_MDEF|SCB_DSPD );
+ status->set_sc( SM_ENDURE , SC_ENDURE , SI_ENDURE , SCB_MDEF|SCB_DSPD );
add_sc( MG_SIGHT , SC_SIGHT );
add_sc( MG_SAFETYWALL , SC_SAFETYWALL );
add_sc( MG_FROSTDIVER , SC_FREEZE );
add_sc( MG_STONECURSE , SC_STONE );
add_sc( AL_RUWACH , SC_RUWACH );
add_sc( AL_PNEUMA , SC_PNEUMA );
- set_sc( AL_INCAGI , SC_INC_AGI , SI_INC_AGI , SCB_AGI|SCB_SPEED );
- set_sc( AL_DECAGI , SC_DEC_AGI , SI_DEC_AGI , SCB_AGI|SCB_SPEED );
- set_sc( AL_CRUCIS , SC_CRUCIS , SI_CRUCIS , SCB_DEF );
- set_sc( AL_ANGELUS , SC_ANGELUS , SI_ANGELUS , SCB_DEF2 );
- set_sc( AL_BLESSING , SC_BLESSING , SI_BLESSING , SCB_STR|SCB_INT|SCB_DEX );
- set_sc( AC_CONCENTRATION , SC_CONCENTRATION , SI_CONCENTRATION , SCB_AGI|SCB_DEX );
- set_sc( TF_HIDING , SC_HIDING , SI_HIDING , SCB_SPEED );
+ status->set_sc( AL_INCAGI , SC_INC_AGI , SI_INC_AGI , SCB_AGI|SCB_SPEED );
+ status->set_sc( AL_DECAGI , SC_DEC_AGI , SI_DEC_AGI , SCB_AGI|SCB_SPEED );
+ status->set_sc( AL_CRUCIS , SC_CRUCIS , SI_CRUCIS , SCB_DEF );
+ status->set_sc( AL_ANGELUS , SC_ANGELUS , SI_ANGELUS , SCB_DEF2 );
+ status->set_sc( AL_BLESSING , SC_BLESSING , SI_BLESSING , SCB_STR|SCB_INT|SCB_DEX );
+ status->set_sc( AC_CONCENTRATION , SC_CONCENTRATION , SI_CONCENTRATION , SCB_AGI|SCB_DEX );
+ status->set_sc( TF_HIDING , SC_HIDING , SI_HIDING , SCB_SPEED );
add_sc( TF_POISON , SC_POISON );
- set_sc( KN_TWOHANDQUICKEN , SC_TWOHANDQUICKEN , SI_TWOHANDQUICKEN , SCB_ASPD );
+ status->set_sc( KN_TWOHANDQUICKEN , SC_TWOHANDQUICKEN , SI_TWOHANDQUICKEN , SCB_ASPD );
add_sc( KN_AUTOCOUNTER , SC_AUTOCOUNTER );
- set_sc( PR_IMPOSITIO , SC_IMPOSITIO , SI_IMPOSITIO ,
+ status->set_sc( PR_IMPOSITIO , SC_IMPOSITIO , SI_IMPOSITIO ,
#ifdef RENEWAL
SCB_NONE );
#else
SCB_WATK );
#endif
- set_sc( PR_SUFFRAGIUM , SC_SUFFRAGIUM , SI_SUFFRAGIUM , SCB_NONE );
- set_sc( PR_ASPERSIO , SC_ASPERSIO , SI_ASPERSIO , SCB_ATK_ELE );
- set_sc( PR_BENEDICTIO , SC_BENEDICTIO , SI_BENEDICTIO , SCB_DEF_ELE );
- set_sc( PR_SLOWPOISON , SC_SLOWPOISON , SI_SLOWPOISON , SCB_REGEN );
- set_sc( PR_KYRIE , SC_KYRIE , SI_KYRIE , SCB_NONE );
- set_sc( PR_MAGNIFICAT , SC_MAGNIFICAT , SI_MAGNIFICAT , SCB_REGEN );
- set_sc( PR_GLORIA , SC_GLORIA , SI_GLORIA , SCB_LUK );
+ status->set_sc( PR_SUFFRAGIUM , SC_SUFFRAGIUM , SI_SUFFRAGIUM , SCB_NONE );
+ status->set_sc( PR_ASPERSIO , SC_ASPERSIO , SI_ASPERSIO , SCB_ATK_ELE );
+ status->set_sc( PR_BENEDICTIO , SC_BENEDICTIO , SI_BENEDICTIO , SCB_DEF_ELE );
+ status->set_sc( PR_SLOWPOISON , SC_SLOWPOISON , SI_SLOWPOISON , SCB_REGEN );
+ status->set_sc( PR_KYRIE , SC_KYRIE , SI_KYRIE , SCB_NONE );
+ status->set_sc( PR_MAGNIFICAT , SC_MAGNIFICAT , SI_MAGNIFICAT , SCB_REGEN );
+ status->set_sc( PR_GLORIA , SC_GLORIA , SI_GLORIA , SCB_LUK );
add_sc( PR_LEXDIVINA , SC_SILENCE );
- set_sc( PR_LEXAETERNA , SC_LEXAETERNA , SI_LEXAETERNA , SCB_NONE );
+ status->set_sc( PR_LEXAETERNA , SC_LEXAETERNA , SI_LEXAETERNA , SCB_NONE );
add_sc( WZ_METEOR , SC_STUN );
add_sc( WZ_VERMILION , SC_BLIND );
add_sc( WZ_FROSTNOVA , SC_FREEZE );
add_sc( WZ_STORMGUST , SC_FREEZE );
- set_sc( WZ_QUAGMIRE , SC_QUAGMIRE , SI_QUAGMIRE , SCB_AGI|SCB_DEX|SCB_ASPD|SCB_SPEED );
- set_sc( BS_ADRENALINE , SC_ADRENALINE , SI_ADRENALINE , SCB_ASPD );
- set_sc( BS_WEAPONPERFECT , SC_WEAPONPERFECT , SI_WEAPONPERFECT, SCB_NONE );
- set_sc( BS_OVERTHRUST , SC_OVERTHRUST , SI_OVERTHRUST , SCB_NONE );
- set_sc( BS_MAXIMIZE , SC_MAXIMIZEPOWER , SI_MAXIMIZE , SCB_REGEN );
+ status->set_sc( WZ_QUAGMIRE , SC_QUAGMIRE , SI_QUAGMIRE , SCB_AGI|SCB_DEX|SCB_ASPD|SCB_SPEED );
+ status->set_sc( BS_ADRENALINE , SC_ADRENALINE , SI_ADRENALINE , SCB_ASPD );
+ status->set_sc( BS_WEAPONPERFECT , SC_WEAPONPERFECT , SI_WEAPONPERFECT, SCB_NONE );
+ status->set_sc( BS_OVERTHRUST , SC_OVERTHRUST , SI_OVERTHRUST , SCB_NONE );
+ status->set_sc( BS_MAXIMIZE , SC_MAXIMIZEPOWER , SI_MAXIMIZE , SCB_REGEN );
add_sc( HT_LANDMINE , SC_STUN );
- set_sc( HT_ANKLESNARE , SC_ANKLESNARE , SI_ANKLESNARE , SCB_NONE );
+ status->set_sc( HT_ANKLESNARE , SC_ANKLESNARE , SI_ANKLESNARE , SCB_NONE );
add_sc( HT_SANDMAN , SC_SLEEP );
add_sc( HT_FLASHER , SC_BLIND );
add_sc( HT_FREEZINGTRAP , SC_FREEZE );
- set_sc( AS_CLOAKING , SC_CLOAKING , SI_CLOAKING , SCB_CRI|SCB_SPEED );
+ status->set_sc( AS_CLOAKING , SC_CLOAKING , SI_CLOAKING , SCB_CRI|SCB_SPEED );
add_sc( AS_SONICBLOW , SC_STUN );
- set_sc( AS_ENCHANTPOISON , SC_ENCHANTPOISON , SI_ENCHANTPOISON, SCB_ATK_ELE );
- set_sc( AS_POISONREACT , SC_POISONREACT , SI_POISONREACT , SCB_NONE );
+ status->set_sc( AS_ENCHANTPOISON , SC_ENCHANTPOISON , SI_ENCHANTPOISON, SCB_ATK_ELE );
+ status->set_sc( AS_POISONREACT , SC_POISONREACT , SI_POISONREACT , SCB_NONE );
add_sc( AS_VENOMDUST , SC_POISON );
add_sc( AS_SPLASHER , SC_SPLASHER );
- set_sc( NV_TRICKDEAD , SC_TRICKDEAD , SI_TRICKDEAD , SCB_REGEN );
- set_sc( SM_AUTOBERSERK , SC_AUTOBERSERK , SI_AUTOBERSERK , SCB_NONE );
+ status->set_sc( NV_TRICKDEAD , SC_TRICKDEAD , SI_TRICKDEAD , SCB_REGEN );
+ status->set_sc( SM_AUTOBERSERK , SC_AUTOBERSERK , SI_AUTOBERSERK , SCB_NONE );
add_sc( TF_SPRINKLESAND , SC_BLIND );
add_sc( TF_THROWSTONE , SC_STUN );
- set_sc( MC_LOUD , SC_SHOUT , SI_SHOUT , SCB_STR );
- set_sc( MG_ENERGYCOAT , SC_ENERGYCOAT , SI_ENERGYCOAT , SCB_NONE );
- set_sc( NPC_EMOTION , SC_MODECHANGE , SI_BLANK , SCB_MODE );
+ status->set_sc( MC_LOUD , SC_SHOUT , SI_SHOUT , SCB_STR );
+ status->set_sc( MG_ENERGYCOAT , SC_ENERGYCOAT , SI_ENERGYCOAT , SCB_NONE );
+ status->set_sc( NPC_EMOTION , SC_MODECHANGE , SI_BLANK , SCB_MODE );
add_sc( NPC_EMOTION_ON , SC_MODECHANGE );
- set_sc( NPC_ATTRICHANGE , SC_ARMOR_PROPERTY , SI_ARMOR_PROPERTY , SCB_DEF_ELE );
+ status->set_sc( NPC_ATTRICHANGE , SC_ARMOR_PROPERTY , SI_ARMOR_PROPERTY , SCB_DEF_ELE );
add_sc( NPC_CHANGEWATER , SC_ARMOR_PROPERTY );
add_sc( NPC_CHANGEGROUND , SC_ARMOR_PROPERTY );
add_sc( NPC_CHANGEFIRE , SC_ARMOR_PROPERTY );
@@ -260,184 +261,184 @@ void initChangeTables(void) {
add_sc( NPC_CURSEATTACK , SC_CURSE );
add_sc( NPC_SLEEPATTACK , SC_SLEEP );
add_sc( NPC_MAGICALATTACK , SC_MAGICALATTACK );
- set_sc( NPC_KEEPING , SC_KEEPING , SI_BLANK , SCB_DEF );
+ status->set_sc( NPC_KEEPING , SC_KEEPING , SI_BLANK , SCB_DEF );
add_sc( NPC_DARKBLESSING , SC_COMA );
- set_sc( NPC_BARRIER , SC_BARRIER , SI_BLANK , SCB_MDEF|SCB_DEF );
+ status->set_sc( NPC_BARRIER , SC_BARRIER , SI_BLANK , SCB_MDEF|SCB_DEF );
add_sc( NPC_DEFENDER , SC_ARMOR );
add_sc( NPC_LICK , SC_STUN );
- set_sc( NPC_HALLUCINATION , SC_ILLUSION , SI_ILLUSION , SCB_NONE );
+ status->set_sc( NPC_HALLUCINATION , SC_ILLUSION , SI_ILLUSION , SCB_NONE );
add_sc( NPC_REBIRTH , SC_REBIRTH );
add_sc( RG_RAID , SC_STUN );
#ifdef RENEWAL
add_sc( RG_RAID , SC_RAID );
add_sc( RG_BACKSTAP , SC_STUN );
#endif
- set_sc( RG_STRIPWEAPON , SC_NOEQUIPWEAPON , SI_NOEQUIPWEAPON , SCB_WATK );
- set_sc( RG_STRIPSHIELD , SC_NOEQUIPSHIELD , SI_NOEQUIPSHIELD , SCB_DEF );
- set_sc( RG_STRIPARMOR , SC_NOEQUIPARMOR , SI_NOEQUIPARMOR , SCB_VIT );
- set_sc( RG_STRIPHELM , SC_NOEQUIPHELM , SI_NOEQUIPHELM , SCB_INT );
+ status->set_sc( RG_STRIPWEAPON , SC_NOEQUIPWEAPON , SI_NOEQUIPWEAPON , SCB_WATK );
+ status->set_sc( RG_STRIPSHIELD , SC_NOEQUIPSHIELD , SI_NOEQUIPSHIELD , SCB_DEF );
+ status->set_sc( RG_STRIPARMOR , SC_NOEQUIPARMOR , SI_NOEQUIPARMOR , SCB_VIT );
+ status->set_sc( RG_STRIPHELM , SC_NOEQUIPHELM , SI_NOEQUIPHELM , SCB_INT );
add_sc( AM_ACIDTERROR , SC_BLOODING );
- set_sc( AM_CP_WEAPON , SC_PROTECTWEAPON , SI_PROTECTWEAPON , SCB_NONE );
- set_sc( AM_CP_SHIELD , SC_PROTECTSHIELD , SI_PROTECTSHIELD , SCB_NONE );
- set_sc( AM_CP_ARMOR , SC_PROTECTARMOR , SI_PROTECTARMOR , SCB_NONE );
- set_sc( AM_CP_HELM , SC_PROTECTHELM , SI_PROTECTHELM , SCB_NONE );
- set_sc( CR_AUTOGUARD , SC_AUTOGUARD , SI_AUTOGUARD , SCB_NONE );
+ status->set_sc( AM_CP_WEAPON , SC_PROTECTWEAPON , SI_PROTECTWEAPON , SCB_NONE );
+ status->set_sc( AM_CP_SHIELD , SC_PROTECTSHIELD , SI_PROTECTSHIELD , SCB_NONE );
+ status->set_sc( AM_CP_ARMOR , SC_PROTECTARMOR , SI_PROTECTARMOR , SCB_NONE );
+ status->set_sc( AM_CP_HELM , SC_PROTECTHELM , SI_PROTECTHELM , SCB_NONE );
+ status->set_sc( CR_AUTOGUARD , SC_AUTOGUARD , SI_AUTOGUARD , SCB_NONE );
add_sc( CR_SHIELDCHARGE , SC_STUN );
- set_sc( CR_REFLECTSHIELD , SC_REFLECTSHIELD , SI_REFLECTSHIELD , SCB_NONE );
+ status->set_sc( CR_REFLECTSHIELD , SC_REFLECTSHIELD , SI_REFLECTSHIELD , SCB_NONE );
add_sc( CR_HOLYCROSS , SC_BLIND );
add_sc( CR_GRANDCROSS , SC_BLIND );
add_sc( CR_DEVOTION , SC_DEVOTION );
- set_sc( CR_PROVIDENCE , SC_PROVIDENCE , SI_PROVIDENCE , SCB_ALL );
- set_sc( CR_DEFENDER , SC_DEFENDER , SI_DEFENDER , SCB_SPEED|SCB_ASPD );
- set_sc( CR_SPEARQUICKEN , SC_SPEARQUICKEN , SI_SPEARQUICKEN , SCB_ASPD|SCB_CRI|SCB_FLEE );
- set_sc( MO_STEELBODY , SC_STEELBODY , SI_STEELBODY , SCB_DEF|SCB_MDEF|SCB_ASPD|SCB_SPEED );
+ status->set_sc( CR_PROVIDENCE , SC_PROVIDENCE , SI_PROVIDENCE , SCB_ALL );
+ status->set_sc( CR_DEFENDER , SC_DEFENDER , SI_DEFENDER , SCB_SPEED|SCB_ASPD );
+ status->set_sc( CR_SPEARQUICKEN , SC_SPEARQUICKEN , SI_SPEARQUICKEN , SCB_ASPD|SCB_CRI|SCB_FLEE );
+ status->set_sc( MO_STEELBODY , SC_STEELBODY , SI_STEELBODY , SCB_DEF|SCB_MDEF|SCB_ASPD|SCB_SPEED );
add_sc( MO_BLADESTOP , SC_BLADESTOP_WAIT );
add_sc( MO_BLADESTOP , SC_BLADESTOP );
- set_sc( MO_EXPLOSIONSPIRITS , SC_EXPLOSIONSPIRITS, SI_EXPLOSIONSPIRITS, SCB_CRI|SCB_REGEN );
- set_sc( MO_EXTREMITYFIST , SC_EXTREMITYFIST , SI_BLANK , SCB_REGEN );
+ status->set_sc( MO_EXPLOSIONSPIRITS , SC_EXPLOSIONSPIRITS, SI_EXPLOSIONSPIRITS, SCB_CRI|SCB_REGEN );
+ status->set_sc( MO_EXTREMITYFIST , SC_EXTREMITYFIST , SI_BLANK , SCB_REGEN );
#ifdef RENEWAL
- set_sc( MO_EXTREMITYFIST , SC_EXTREMITYFIST2 , SI_EXTREMITYFIST , SCB_NONE );
+ status->set_sc( MO_EXTREMITYFIST , SC_EXTREMITYFIST2 , SI_EXTREMITYFIST , SCB_NONE );
#endif
add_sc( SA_MAGICROD , SC_MAGICROD );
- set_sc( SA_AUTOSPELL , SC_AUTOSPELL , SI_AUTOSPELL , SCB_NONE );
- set_sc( SA_FLAMELAUNCHER , SC_PROPERTYFIRE , SI_PROPERTYFIRE , SCB_ATK_ELE );
- set_sc( SA_FROSTWEAPON , SC_PROPERTYWATER , SI_PROPERTYWATER , SCB_ATK_ELE );
- set_sc( SA_LIGHTNINGLOADER , SC_PROPERTYWIND , SI_PROPERTYWIND , SCB_ATK_ELE );
- set_sc( SA_SEISMICWEAPON , SC_PROPERTYGROUND , SI_PROPERTYGROUND , SCB_ATK_ELE );
- set_sc( SA_VOLCANO , SC_VOLCANO , SI_GROUNDMAGIC , SCB_WATK );
- set_sc( SA_DELUGE , SC_DELUGE , SI_GROUNDMAGIC , SCB_MAXHP );
- set_sc( SA_VIOLENTGALE , SC_VIOLENTGALE , SI_GROUNDMAGIC , SCB_FLEE );
+ status->set_sc( SA_AUTOSPELL , SC_AUTOSPELL , SI_AUTOSPELL , SCB_NONE );
+ status->set_sc( SA_FLAMELAUNCHER , SC_PROPERTYFIRE , SI_PROPERTYFIRE , SCB_ATK_ELE );
+ status->set_sc( SA_FROSTWEAPON , SC_PROPERTYWATER , SI_PROPERTYWATER , SCB_ATK_ELE );
+ status->set_sc( SA_LIGHTNINGLOADER , SC_PROPERTYWIND , SI_PROPERTYWIND , SCB_ATK_ELE );
+ status->set_sc( SA_SEISMICWEAPON , SC_PROPERTYGROUND , SI_PROPERTYGROUND , SCB_ATK_ELE );
+ status->set_sc( SA_VOLCANO , SC_VOLCANO , SI_GROUNDMAGIC , SCB_WATK );
+ status->set_sc( SA_DELUGE , SC_DELUGE , SI_GROUNDMAGIC , SCB_MAXHP );
+ status->set_sc( SA_VIOLENTGALE , SC_VIOLENTGALE , SI_GROUNDMAGIC , SCB_FLEE );
add_sc( SA_REVERSEORCISH , SC_ORCISH );
add_sc( SA_COMA , SC_COMA );
- set_sc( BD_ENCORE , SC_DANCING , SI_BLANK , SCB_SPEED|SCB_REGEN );
+ status->set_sc( BD_ENCORE , SC_DANCING , SI_BLANK , SCB_SPEED|SCB_REGEN );
add_sc( BD_RICHMANKIM , SC_RICHMANKIM );
- set_sc( BD_ETERNALCHAOS , SC_ETERNALCHAOS , SI_BLANK , SCB_DEF2 );
- set_sc( BD_DRUMBATTLEFIELD , SC_DRUMBATTLE , SI_BLANK , SCB_WATK|SCB_DEF );
- set_sc( BD_RINGNIBELUNGEN , SC_NIBELUNGEN , SI_BLANK , SCB_WATK );
+ status->set_sc( BD_ETERNALCHAOS , SC_ETERNALCHAOS , SI_BLANK , SCB_DEF2 );
+ status->set_sc( BD_DRUMBATTLEFIELD , SC_DRUMBATTLE , SI_BLANK , SCB_WATK|SCB_DEF );
+ status->set_sc( BD_RINGNIBELUNGEN , SC_NIBELUNGEN , SI_BLANK , SCB_WATK );
add_sc( BD_ROKISWEIL , SC_ROKISWEIL );
add_sc( BD_INTOABYSS , SC_INTOABYSS );
- set_sc( BD_SIEGFRIED , SC_SIEGFRIED , SI_BLANK , SCB_ALL );
+ status->set_sc( BD_SIEGFRIED , SC_SIEGFRIED , SI_BLANK , SCB_ALL );
add_sc( BA_FROSTJOKER , SC_FREEZE );
- set_sc( BA_WHISTLE , SC_WHISTLE , SI_BLANK , SCB_FLEE|SCB_FLEE2 );
- set_sc( BA_ASSASSINCROSS , SC_ASSNCROS , SI_BLANK , SCB_ASPD );
+ status->set_sc( BA_WHISTLE , SC_WHISTLE , SI_BLANK , SCB_FLEE|SCB_FLEE2 );
+ status->set_sc( BA_ASSASSINCROSS , SC_ASSNCROS , SI_BLANK , SCB_ASPD );
add_sc( BA_POEMBRAGI , SC_POEMBRAGI );
- set_sc( BA_APPLEIDUN , SC_APPLEIDUN , SI_BLANK , SCB_MAXHP );
+ status->set_sc( BA_APPLEIDUN , SC_APPLEIDUN , SI_BLANK , SCB_MAXHP );
add_sc( DC_SCREAM , SC_STUN );
- set_sc( DC_HUMMING , SC_HUMMING , SI_BLANK , SCB_HIT );
- set_sc( DC_DONTFORGETME , SC_DONTFORGETME , SI_BLANK , SCB_SPEED|SCB_ASPD );
- set_sc( DC_FORTUNEKISS , SC_FORTUNE , SI_BLANK , SCB_CRI );
- set_sc( DC_SERVICEFORYOU , SC_SERVICEFORYOU , SI_BLANK , SCB_ALL );
+ status->set_sc( DC_HUMMING , SC_HUMMING , SI_BLANK , SCB_HIT );
+ status->set_sc( DC_DONTFORGETME , SC_DONTFORGETME , SI_BLANK , SCB_SPEED|SCB_ASPD );
+ status->set_sc( DC_FORTUNEKISS , SC_FORTUNE , SI_BLANK , SCB_CRI );
+ status->set_sc( DC_SERVICEFORYOU , SC_SERVICEFORYOU , SI_BLANK , SCB_ALL );
add_sc( NPC_DARKCROSS , SC_BLIND );
add_sc( NPC_GRANDDARKNESS , SC_BLIND );
- set_sc( NPC_STOP , SC_STOP , SI_STOP , SCB_NONE );
- set_sc( NPC_WEAPONBRAKER , SC_BROKENWEAPON , SI_BROKENWEAPON , SCB_NONE );
- set_sc( NPC_ARMORBRAKE , SC_BROKENARMOR , SI_BROKENARMOR , SCB_NONE );
- set_sc( NPC_CHANGEUNDEAD , SC_PROPERTYUNDEAD , SI_PROPERTYUNDEAD , SCB_DEF_ELE );
- set_sc( NPC_POWERUP , SC_INCHITRATE , SI_BLANK , SCB_HIT );
- set_sc( NPC_AGIUP , SC_INCFLEERATE , SI_BLANK , SCB_FLEE );
+ status->set_sc( NPC_STOP , SC_STOP , SI_STOP , SCB_NONE );
+ status->set_sc( NPC_WEAPONBRAKER , SC_BROKENWEAPON , SI_BROKENWEAPON , SCB_NONE );
+ status->set_sc( NPC_ARMORBRAKE , SC_BROKENARMOR , SI_BROKENARMOR , SCB_NONE );
+ status->set_sc( NPC_CHANGEUNDEAD , SC_PROPERTYUNDEAD , SI_PROPERTYUNDEAD , SCB_DEF_ELE );
+ status->set_sc( NPC_POWERUP , SC_INCHITRATE , SI_BLANK , SCB_HIT );
+ status->set_sc( NPC_AGIUP , SC_INCFLEERATE , SI_BLANK , SCB_FLEE );
add_sc( NPC_INVISIBLE , SC_CLOAKING );
- set_sc( LK_AURABLADE , SC_AURABLADE , SI_AURABLADE , SCB_NONE );
- set_sc( LK_PARRYING , SC_PARRYING , SI_PARRYING , SCB_NONE );
+ status->set_sc( LK_AURABLADE , SC_AURABLADE , SI_AURABLADE , SCB_NONE );
+ status->set_sc( LK_PARRYING , SC_PARRYING , SI_PARRYING , SCB_NONE );
#ifndef RENEWAL
- set_sc( LK_CONCENTRATION , SC_LKCONCENTRATION , SI_LKCONCENTRATION , SCB_BATK|SCB_WATK|SCB_HIT|SCB_DEF|SCB_DEF2);
+ status->set_sc( LK_CONCENTRATION , SC_LKCONCENTRATION , SI_LKCONCENTRATION , SCB_BATK|SCB_WATK|SCB_HIT|SCB_DEF|SCB_DEF2);
#else
- set_sc( LK_CONCENTRATION , SC_LKCONCENTRATION , SI_LKCONCENTRATION , SCB_HIT|SCB_DEF);
+ status->set_sc( LK_CONCENTRATION , SC_LKCONCENTRATION , SI_LKCONCENTRATION , SCB_HIT|SCB_DEF);
#endif
- set_sc( LK_TENSIONRELAX , SC_TENSIONRELAX , SI_TENSIONRELAX , SCB_REGEN );
- set_sc( LK_BERSERK , SC_BERSERK , SI_BERSERK , SCB_DEF|SCB_DEF2|SCB_MDEF|SCB_MDEF2|SCB_FLEE|SCB_SPEED|SCB_ASPD|SCB_MAXHP|SCB_REGEN );
- set_sc( HP_ASSUMPTIO , SC_ASSUMPTIO , SI_ASSUMPTIO , SCB_NONE );
+ status->set_sc( LK_TENSIONRELAX , SC_TENSIONRELAX , SI_TENSIONRELAX , SCB_REGEN );
+ status->set_sc( LK_BERSERK , SC_BERSERK , SI_BERSERK , SCB_DEF|SCB_DEF2|SCB_MDEF|SCB_MDEF2|SCB_FLEE|SCB_SPEED|SCB_ASPD|SCB_MAXHP|SCB_REGEN );
+ status->set_sc( HP_ASSUMPTIO , SC_ASSUMPTIO , SI_ASSUMPTIO , SCB_NONE );
add_sc( HP_BASILICA , SC_BASILICA );
- set_sc( HW_MAGICPOWER , SC_MAGICPOWER , SI_MAGICPOWER , SCB_MATK );
+ status->set_sc( HW_MAGICPOWER , SC_MAGICPOWER , SI_MAGICPOWER , SCB_MATK );
add_sc( PA_SACRIFICE , SC_SACRIFICE );
- set_sc( PA_GOSPEL , SC_GOSPEL , SI_BLANK , SCB_SPEED|SCB_ASPD );
+ status->set_sc( PA_GOSPEL , SC_GOSPEL , SI_BLANK , SCB_SPEED|SCB_ASPD );
add_sc( PA_GOSPEL , SC_SCRESIST );
add_sc( CH_TIGERFIST , SC_STOP );
- set_sc( ASC_EDP , SC_EDP , SI_EDP , SCB_NONE );
- set_sc( SN_SIGHT , SC_TRUESIGHT , SI_TRUESIGHT , SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK|SCB_CRI|SCB_HIT );
- set_sc( SN_WINDWALK , SC_WINDWALK , SI_WINDWALK , SCB_FLEE|SCB_SPEED );
- set_sc( WS_MELTDOWN , SC_MELTDOWN , SI_MELTDOWN , SCB_NONE );
- set_sc( WS_CARTBOOST , SC_CARTBOOST , SI_CARTBOOST , SCB_SPEED );
- set_sc( ST_CHASEWALK , SC_CHASEWALK , SI_BLANK , SCB_SPEED );
- set_sc( ST_REJECTSWORD , SC_SWORDREJECT , SI_SWORDREJECT , SCB_NONE );
+ status->set_sc( ASC_EDP , SC_EDP , SI_EDP , SCB_NONE );
+ status->set_sc( SN_SIGHT , SC_TRUESIGHT , SI_TRUESIGHT , SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK|SCB_CRI|SCB_HIT );
+ status->set_sc( SN_WINDWALK , SC_WINDWALK , SI_WINDWALK , SCB_FLEE|SCB_SPEED );
+ status->set_sc( WS_MELTDOWN , SC_MELTDOWN , SI_MELTDOWN , SCB_NONE );
+ status->set_sc( WS_CARTBOOST , SC_CARTBOOST , SI_CARTBOOST , SCB_SPEED );
+ status->set_sc( ST_CHASEWALK , SC_CHASEWALK , SI_BLANK , SCB_SPEED );
+ status->set_sc( ST_REJECTSWORD , SC_SWORDREJECT , SI_SWORDREJECT , SCB_NONE );
add_sc( ST_REJECTSWORD , SC_AUTOCOUNTER );
- set_sc( CG_MARIONETTE , SC_MARIONETTE_MASTER , SI_MARIONETTE_MASTER , SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK );
- set_sc( CG_MARIONETTE , SC_MARIONETTE , SI_MARIONETTE , SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK );
+ status->set_sc( CG_MARIONETTE , SC_MARIONETTE_MASTER , SI_MARIONETTE_MASTER , SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK );
+ status->set_sc( CG_MARIONETTE , SC_MARIONETTE , SI_MARIONETTE , SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK );
add_sc( LK_SPIRALPIERCE , SC_STOP );
add_sc( LK_HEADCRUSH , SC_BLOODING );
- set_sc( LK_JOINTBEAT , SC_JOINTBEAT , SI_JOINTBEAT , SCB_BATK|SCB_DEF2|SCB_SPEED|SCB_ASPD );
+ status->set_sc( LK_JOINTBEAT , SC_JOINTBEAT , SI_JOINTBEAT , SCB_BATK|SCB_DEF2|SCB_SPEED|SCB_ASPD );
add_sc( HW_NAPALMVULCAN , SC_CURSE );
- set_sc( PF_MINDBREAKER , SC_MINDBREAKER , SI_BLANK , SCB_MATK|SCB_MDEF2 );
+ status->set_sc( PF_MINDBREAKER , SC_MINDBREAKER , SI_BLANK , SCB_MATK|SCB_MDEF2 );
add_sc( PF_MEMORIZE , SC_MEMORIZE );
add_sc( PF_FOGWALL , SC_FOGWALL );
- set_sc( PF_SPIDERWEB , SC_SPIDERWEB , SI_BLANK , SCB_FLEE );
- set_sc( WE_BABY , SC_BABY , SI_PROTECTEXP , SCB_NONE );
- set_sc( TK_RUN , SC_RUN , SI_RUN , SCB_SPEED|SCB_DSPD );
- set_sc( TK_RUN , SC_STRUP , SI_STRUP , SCB_STR );
- set_sc( TK_READYSTORM , SC_STORMKICK_READY , SI_STORMKICK_ON , SCB_NONE );
- set_sc( TK_READYDOWN , SC_DOWNKICK_READY , SI_DOWNKICK_ON , SCB_NONE );
+ status->set_sc( PF_SPIDERWEB , SC_SPIDERWEB , SI_BLANK , SCB_FLEE );
+ status->set_sc( WE_BABY , SC_BABY , SI_PROTECTEXP , SCB_NONE );
+ status->set_sc( TK_RUN , SC_RUN , SI_RUN , SCB_SPEED|SCB_DSPD );
+ status->set_sc( TK_RUN , SC_STRUP , SI_STRUP , SCB_STR );
+ status->set_sc( TK_READYSTORM , SC_STORMKICK_READY , SI_STORMKICK_ON , SCB_NONE );
+ status->set_sc( TK_READYDOWN , SC_DOWNKICK_READY , SI_DOWNKICK_ON , SCB_NONE );
add_sc( TK_DOWNKICK , SC_STUN );
- set_sc( TK_READYTURN , SC_TURNKICK_READY , SI_TURNKICK_ON , SCB_NONE );
- set_sc( TK_READYCOUNTER , SC_COUNTERKICK_READY , SI_COUNTER_ON , SCB_NONE );
- set_sc( TK_DODGE , SC_DODGE_READY , SI_DODGE_ON , SCB_NONE );
- set_sc( TK_SPTIME , SC_EARTHSCROLL , SI_EARTHSCROLL , SCB_NONE );
+ status->set_sc( TK_READYTURN , SC_TURNKICK_READY , SI_TURNKICK_ON , SCB_NONE );
+ status->set_sc( TK_READYCOUNTER , SC_COUNTERKICK_READY , SI_COUNTER_ON , SCB_NONE );
+ status->set_sc( TK_DODGE , SC_DODGE_READY , SI_DODGE_ON , SCB_NONE );
+ status->set_sc( TK_SPTIME , SC_EARTHSCROLL , SI_EARTHSCROLL , SCB_NONE );
add_sc( TK_SEVENWIND , SC_TK_SEVENWIND );
- set_sc( TK_SEVENWIND , SC_PROPERTYTELEKINESIS , SI_PROPERTYTELEKINESIS , SCB_ATK_ELE );
- set_sc( TK_SEVENWIND , SC_PROPERTYDARK , SI_PROPERTYDARK , SCB_ATK_ELE );
- set_sc( SG_SUN_WARM , SC_WARM , SI_SG_SUN_WARM , SCB_NONE );
+ status->set_sc( TK_SEVENWIND , SC_PROPERTYTELEKINESIS , SI_PROPERTYTELEKINESIS , SCB_ATK_ELE );
+ status->set_sc( TK_SEVENWIND , SC_PROPERTYDARK , SI_PROPERTYDARK , SCB_ATK_ELE );
+ status->set_sc( SG_SUN_WARM , SC_WARM , SI_SG_SUN_WARM , SCB_NONE );
add_sc( SG_MOON_WARM , SC_WARM );
add_sc( SG_STAR_WARM , SC_WARM );
- set_sc( SG_SUN_COMFORT , SC_SUN_COMFORT , SI_SUN_COMFORT , SCB_DEF2 );
- set_sc( SG_MOON_COMFORT , SC_MOON_COMFORT , SI_MOON_COMFORT , SCB_FLEE );
- set_sc( SG_STAR_COMFORT , SC_STAR_COMFORT , SI_STAR_COMFORT , SCB_ASPD );
+ status->set_sc( SG_SUN_COMFORT , SC_SUN_COMFORT , SI_SUN_COMFORT , SCB_DEF2 );
+ status->set_sc( SG_MOON_COMFORT , SC_MOON_COMFORT , SI_MOON_COMFORT , SCB_FLEE );
+ status->set_sc( SG_STAR_COMFORT , SC_STAR_COMFORT , SI_STAR_COMFORT , SCB_ASPD );
add_sc( SG_FRIEND , SC_SKILLRATE_UP );
- set_sc( SG_KNOWLEDGE , SC_KNOWLEDGE , SI_BLANK , SCB_ALL );
- set_sc( SG_FUSION , SC_FUSION , SI_BLANK , SCB_SPEED );
- set_sc( BS_ADRENALINE2 , SC_ADRENALINE2 , SI_ADRENALINE2 , SCB_ASPD );
- set_sc( SL_KAIZEL , SC_KAIZEL , SI_KAIZEL , SCB_NONE );
- set_sc( SL_KAAHI , SC_KAAHI , SI_KAAHI , SCB_NONE );
- set_sc( SL_KAUPE , SC_KAUPE , SI_KAUPE , SCB_NONE );
- set_sc( SL_KAITE , SC_KAITE , SI_KAITE , SCB_NONE );
+ status->set_sc( SG_KNOWLEDGE , SC_KNOWLEDGE , SI_BLANK , SCB_ALL );
+ status->set_sc( SG_FUSION , SC_FUSION , SI_BLANK , SCB_SPEED );
+ status->set_sc( BS_ADRENALINE2 , SC_ADRENALINE2 , SI_ADRENALINE2 , SCB_ASPD );
+ status->set_sc( SL_KAIZEL , SC_KAIZEL , SI_KAIZEL , SCB_NONE );
+ status->set_sc( SL_KAAHI , SC_KAAHI , SI_KAAHI , SCB_NONE );
+ status->set_sc( SL_KAUPE , SC_KAUPE , SI_KAUPE , SCB_NONE );
+ status->set_sc( SL_KAITE , SC_KAITE , SI_KAITE , SCB_NONE );
add_sc( SL_STUN , SC_STUN );
- set_sc( SL_SWOO , SC_SWOO , SI_BLANK , SCB_SPEED );
- set_sc( SL_SKE , SC_SKE , SI_BLANK , SCB_BATK|SCB_WATK|SCB_DEF|SCB_DEF2 );
- set_sc( SL_SKA , SC_SKA , SI_BLANK , SCB_DEF|SCB_MDEF|SCB_ASPD );
- set_sc( SL_SMA , SC_SMA_READY , SI_SMA_READY , SCB_NONE );
- set_sc( SM_SELFPROVOKE , SC_PROVOKE , SI_PROVOKE , SCB_DEF|SCB_DEF2|SCB_BATK|SCB_WATK );
- set_sc( ST_PRESERVE , SC_PRESERVE , SI_PRESERVE , SCB_NONE );
- set_sc( PF_DOUBLECASTING , SC_DOUBLECASTING , SI_DOUBLECASTING , SCB_NONE );
- set_sc( HW_GRAVITATION , SC_GRAVITATION , SI_BLANK , SCB_ASPD );
+ status->set_sc( SL_SWOO , SC_SWOO , SI_BLANK , SCB_SPEED );
+ status->set_sc( SL_SKE , SC_SKE , SI_BLANK , SCB_BATK|SCB_WATK|SCB_DEF|SCB_DEF2 );
+ status->set_sc( SL_SKA , SC_SKA , SI_BLANK , SCB_DEF|SCB_MDEF|SCB_ASPD );
+ status->set_sc( SL_SMA , SC_SMA_READY , SI_SMA_READY , SCB_NONE );
+ status->set_sc( SM_SELFPROVOKE , SC_PROVOKE , SI_PROVOKE , SCB_DEF|SCB_DEF2|SCB_BATK|SCB_WATK );
+ status->set_sc( ST_PRESERVE , SC_PRESERVE , SI_PRESERVE , SCB_NONE );
+ status->set_sc( PF_DOUBLECASTING , SC_DOUBLECASTING , SI_DOUBLECASTING , SCB_NONE );
+ status->set_sc( HW_GRAVITATION , SC_GRAVITATION , SI_BLANK , SCB_ASPD );
add_sc( WS_CARTTERMINATION , SC_STUN );
- set_sc( WS_OVERTHRUSTMAX , SC_OVERTHRUSTMAX , SI_OVERTHRUSTMAX , SCB_NONE );
- set_sc( CG_LONGINGFREEDOM , SC_LONGING , SI_BLANK , SCB_SPEED|SCB_ASPD );
+ status->set_sc( WS_OVERTHRUSTMAX , SC_OVERTHRUSTMAX , SI_OVERTHRUSTMAX , SCB_NONE );
+ status->set_sc( CG_LONGINGFREEDOM , SC_LONGING , SI_BLANK , SCB_SPEED|SCB_ASPD );
add_sc( CG_HERMODE , SC_HERMODE );
- set_sc( CG_TAROTCARD , SC_TAROTCARD , SI_TAROTCARD , SCB_NONE );
- set_sc( ITEM_ENCHANTARMS , SC_ENCHANTARMS , SI_BLANK , SCB_ATK_ELE );
- set_sc( SL_HIGH , SC_SOULLINK , SI_SOULLINK , SCB_ALL );
- set_sc( KN_ONEHAND , SC_ONEHANDQUICKEN , SI_ONEHANDQUICKEN , SCB_ASPD );
- set_sc( GS_FLING , SC_FLING , SI_BLANK , SCB_DEF|SCB_DEF2 );
+ status->set_sc( CG_TAROTCARD , SC_TAROTCARD , SI_TAROTCARD , SCB_NONE );
+ status->set_sc( ITEM_ENCHANTARMS , SC_ENCHANTARMS , SI_BLANK , SCB_ATK_ELE );
+ status->set_sc( SL_HIGH , SC_SOULLINK , SI_SOULLINK , SCB_ALL );
+ status->set_sc( KN_ONEHAND , SC_ONEHANDQUICKEN , SI_ONEHANDQUICKEN , SCB_ASPD );
+ status->set_sc( GS_FLING , SC_FLING , SI_BLANK , SCB_DEF|SCB_DEF2 );
add_sc( GS_CRACKER , SC_STUN );
add_sc( GS_DISARM , SC_NOEQUIPWEAPON );
add_sc( GS_PIERCINGSHOT , SC_BLOODING );
- set_sc( GS_MADNESSCANCEL , SC_GS_MADNESSCANCEL , SI_GS_MADNESSCANCEL , SCB_ASPD
+ status->set_sc( GS_MADNESSCANCEL , SC_GS_MADNESSCANCEL , SI_GS_MADNESSCANCEL , SCB_ASPD
#ifndef RENEWAL
|SCB_BATK );
#else
);
#endif
- set_sc( GS_ADJUSTMENT , SC_GS_ADJUSTMENT , SI_GS_ADJUSTMENT , SCB_HIT|SCB_FLEE );
- set_sc( GS_INCREASING , SC_GS_ACCURACY , SI_GS_ACCURACY , SCB_AGI|SCB_DEX|SCB_HIT );
- set_sc( GS_GATLINGFEVER , SC_GS_GATLINGFEVER , SI_GS_GATLINGFEVER , SCB_FLEE|SCB_SPEED|SCB_ASPD
+ status->set_sc( GS_ADJUSTMENT , SC_GS_ADJUSTMENT , SI_GS_ADJUSTMENT , SCB_HIT|SCB_FLEE );
+ status->set_sc( GS_INCREASING , SC_GS_ACCURACY , SI_GS_ACCURACY , SCB_AGI|SCB_DEX|SCB_HIT );
+ status->set_sc( GS_GATLINGFEVER , SC_GS_GATLINGFEVER , SI_GS_GATLINGFEVER , SCB_FLEE|SCB_SPEED|SCB_ASPD
#ifndef RENEWAL
|SCB_BATK );
#else
);
#endif
- set_sc( NJ_TATAMIGAESHI , SC_NJ_TATAMIGAESHI , SI_BLANK , SCB_NONE );
- set_sc( NJ_SUITON , SC_NJ_SUITON , SI_NJ_SUITON , SCB_AGI|SCB_SPEED );
+ status->set_sc( NJ_TATAMIGAESHI , SC_NJ_TATAMIGAESHI , SI_BLANK , SCB_NONE );
+ status->set_sc( NJ_SUITON , SC_NJ_SUITON , SI_NJ_SUITON , SCB_AGI|SCB_SPEED );
add_sc( NJ_HYOUSYOURAKU , SC_FREEZE );
- set_sc( NJ_NEN , SC_NJ_NEN , SI_NJ_NEN , SCB_STR|SCB_INT );
- set_sc( NJ_UTSUSEMI , SC_NJ_UTSUSEMI , SI_NJ_UTSUSEMI , SCB_NONE );
- set_sc( NJ_BUNSINJYUTSU , SC_NJ_BUNSINJYUTSU , SI_NJ_BUNSINJYUTSU , SCB_DYE );
+ status->set_sc( NJ_NEN , SC_NJ_NEN , SI_NJ_NEN , SCB_STR|SCB_INT );
+ status->set_sc( NJ_UTSUSEMI , SC_NJ_UTSUSEMI , SI_NJ_UTSUSEMI , SCB_NONE );
+ status->set_sc( NJ_BUNSINJYUTSU , SC_NJ_BUNSINJYUTSU , SI_NJ_BUNSINJYUTSU , SCB_DYE );
add_sc( NPC_ICEBREATH , SC_FREEZE );
add_sc( NPC_ACIDBREATH , SC_POISON );
@@ -451,201 +452,201 @@ void initChangeTables(void) {
add_sc( NPC_WIDESIGHT , SC_SIGHT );
add_sc( NPC_EVILLAND , SC_BLIND );
add_sc( NPC_MAGICMIRROR , SC_MAGICMIRROR );
- set_sc( NPC_SLOWCAST , SC_SLOWCAST , SI_SLOWCAST , SCB_NONE );
- set_sc( NPC_CRITICALWOUND , SC_CRITICALWOUND , SI_CRITICALWOUND , SCB_NONE );
- set_sc( NPC_STONESKIN , SC_STONESKIN , SI_BLANK , SCB_DEF|SCB_MDEF );
+ status->set_sc( NPC_SLOWCAST , SC_SLOWCAST , SI_SLOWCAST , SCB_NONE );
+ status->set_sc( NPC_CRITICALWOUND , SC_CRITICALWOUND , SI_CRITICALWOUND , SCB_NONE );
+ status->set_sc( NPC_STONESKIN , SC_STONESKIN , SI_BLANK , SCB_DEF|SCB_MDEF );
add_sc( NPC_ANTIMAGIC , SC_STONESKIN );
add_sc( NPC_WIDECURSE , SC_CURSE );
add_sc( NPC_WIDESTUN , SC_STUN );
- set_sc( NPC_HELLPOWER , SC_HELLPOWER , SI_HELLPOWER , SCB_NONE );
- set_sc( NPC_WIDEHELLDIGNITY , SC_HELLPOWER , SI_HELLPOWER , SCB_NONE );
- set_sc( NPC_INVINCIBLE , SC_INVINCIBLE , SI_INVINCIBLE , SCB_SPEED );
- set_sc( NPC_INVINCIBLEOFF , SC_INVINCIBLEOFF , SI_BLANK , SCB_SPEED );
+ status->set_sc( NPC_HELLPOWER , SC_HELLPOWER , SI_HELLPOWER , SCB_NONE );
+ status->set_sc( NPC_WIDEHELLDIGNITY , SC_HELLPOWER , SI_HELLPOWER , SCB_NONE );
+ status->set_sc( NPC_INVINCIBLE , SC_INVINCIBLE , SI_INVINCIBLE , SCB_SPEED );
+ status->set_sc( NPC_INVINCIBLEOFF , SC_INVINCIBLEOFF , SI_BLANK , SCB_SPEED );
- set_sc( CASH_BLESSING , SC_BLESSING , SI_BLESSING , SCB_STR|SCB_INT|SCB_DEX );
- set_sc( CASH_INCAGI , SC_INC_AGI , SI_INC_AGI , SCB_AGI|SCB_SPEED );
- set_sc( CASH_ASSUMPTIO , SC_ASSUMPTIO , SI_ASSUMPTIO , SCB_NONE );
+ status->set_sc( CASH_BLESSING , SC_BLESSING , SI_BLESSING , SCB_STR|SCB_INT|SCB_DEX );
+ status->set_sc( CASH_INCAGI , SC_INC_AGI , SI_INC_AGI , SCB_AGI|SCB_SPEED );
+ status->set_sc( CASH_ASSUMPTIO , SC_ASSUMPTIO , SI_ASSUMPTIO , SCB_NONE );
- set_sc( ALL_PARTYFLEE , SC_PARTYFLEE , SI_PARTYFLEE , SCB_NONE );
- set_sc( ALL_ODINS_POWER , SC_ODINS_POWER , SI_ODINS_POWER , SCB_WATK | SCB_MATK | SCB_MDEF | SCB_DEF);
+ status->set_sc( ALL_PARTYFLEE , SC_PARTYFLEE , SI_PARTYFLEE , SCB_NONE );
+ status->set_sc( ALL_ODINS_POWER , SC_ODINS_POWER , SI_ODINS_POWER , SCB_WATK | SCB_MATK | SCB_MDEF | SCB_DEF);
- set_sc( CR_SHRINK , SC_CR_SHRINK , SI_CR_SHRINK , SCB_NONE );
- set_sc( RG_CLOSECONFINE , SC_RG_CCONFINE_S , SI_RG_CCONFINE_S , SCB_NONE );
- set_sc( RG_CLOSECONFINE , SC_RG_CCONFINE_M , SI_RG_CCONFINE_M , SCB_FLEE );
- set_sc( WZ_SIGHTBLASTER , SC_WZ_SIGHTBLASTER , SI_WZ_SIGHTBLASTER , SCB_NONE );
- set_sc( DC_WINKCHARM , SC_DC_WINKCHARM , SI_DC_WINKCHARM , SCB_NONE );
+ status->set_sc( CR_SHRINK , SC_CR_SHRINK , SI_CR_SHRINK , SCB_NONE );
+ status->set_sc( RG_CLOSECONFINE , SC_RG_CCONFINE_S , SI_RG_CCONFINE_S , SCB_NONE );
+ status->set_sc( RG_CLOSECONFINE , SC_RG_CCONFINE_M , SI_RG_CCONFINE_M , SCB_FLEE );
+ status->set_sc( WZ_SIGHTBLASTER , SC_WZ_SIGHTBLASTER , SI_WZ_SIGHTBLASTER , SCB_NONE );
+ status->set_sc( DC_WINKCHARM , SC_DC_WINKCHARM , SI_DC_WINKCHARM , SCB_NONE );
add_sc( MO_BALKYOUNG , SC_STUN );
add_sc( SA_ELEMENTWATER , SC_ARMOR_PROPERTY );
add_sc( SA_ELEMENTFIRE , SC_ARMOR_PROPERTY );
add_sc( SA_ELEMENTGROUND , SC_ARMOR_PROPERTY );
add_sc( SA_ELEMENTWIND , SC_ARMOR_PROPERTY );
- set_sc( HLIF_AVOID , SC_HLIF_AVOID , SI_BLANK , SCB_SPEED );
- set_sc( HLIF_CHANGE , SC_HLIF_CHANGE , SI_BLANK , SCB_VIT|SCB_INT );
- set_sc( HFLI_FLEET , SC_HLIF_FLEET , SI_BLANK , SCB_ASPD|SCB_BATK|SCB_WATK );
- set_sc( HFLI_SPEED , SC_HLIF_SPEED , SI_BLANK , SCB_FLEE );
- set_sc( HAMI_DEFENCE , SC_HAMI_DEFENCE , SI_BLANK , SCB_DEF );
- set_sc( HAMI_BLOODLUST , SC_HAMI_BLOODLUST , SI_BLANK , SCB_BATK|SCB_WATK );
+ status->set_sc( HLIF_AVOID , SC_HLIF_AVOID , SI_BLANK , SCB_SPEED );
+ status->set_sc( HLIF_CHANGE , SC_HLIF_CHANGE , SI_BLANK , SCB_VIT|SCB_INT );
+ status->set_sc( HFLI_FLEET , SC_HLIF_FLEET , SI_BLANK , SCB_ASPD|SCB_BATK|SCB_WATK );
+ status->set_sc( HFLI_SPEED , SC_HLIF_SPEED , SI_BLANK , SCB_FLEE );
+ status->set_sc( HAMI_DEFENCE , SC_HAMI_DEFENCE , SI_BLANK , SCB_DEF );
+ status->set_sc( HAMI_BLOODLUST , SC_HAMI_BLOODLUST , SI_BLANK , SCB_BATK|SCB_WATK );
// Homunculus S
- set_sc( MH_LIGHT_OF_REGENE , SC_LIGHT_OF_REGENE , SI_LIGHT_OF_REGENE , SCB_NONE );
- set_sc( MH_OVERED_BOOST , SC_OVERED_BOOST , SI_OVERED_BOOST , SCB_FLEE|SCB_ASPD|SCB_DEF );
+ status->set_sc( MH_LIGHT_OF_REGENE , SC_LIGHT_OF_REGENE , SI_LIGHT_OF_REGENE , SCB_NONE );
+ status->set_sc( MH_OVERED_BOOST , SC_OVERED_BOOST , SI_OVERED_BOOST , SCB_FLEE|SCB_ASPD|SCB_DEF );
add_sc(MH_STAHL_HORN, SC_STUN);
- set_sc(MH_ANGRIFFS_MODUS, SC_ANGRIFFS_MODUS, SI_ANGRIFFS_MODUS, SCB_BATK | SCB_DEF | SCB_FLEE | SCB_MAXHP);
- set_sc(MH_GOLDENE_FERSE, SC_GOLDENE_FERSE, SI_GOLDENE_FERSE, SCB_ASPD|SCB_MAXHP);
+ status->set_sc(MH_ANGRIFFS_MODUS, SC_ANGRIFFS_MODUS, SI_ANGRIFFS_MODUS, SCB_BATK | SCB_DEF | SCB_FLEE | SCB_MAXHP);
+ status->set_sc(MH_GOLDENE_FERSE, SC_GOLDENE_FERSE, SI_GOLDENE_FERSE, SCB_ASPD|SCB_MAXHP);
add_sc( MH_STEINWAND, SC_SAFETYWALL );
- set_sc(MH_VOLCANIC_ASH, SC_VOLCANIC_ASH, SI_VOLCANIC_ASH, SCB_DEF|SCB_DEF2|SCB_HIT|SCB_BATK|SCB_FLEE);
- set_sc(MH_GRANITIC_ARMOR, SC_GRANITIC_ARMOR, SI_GRANITIC_ARMOR, SCB_NONE);
- set_sc(MH_MAGMA_FLOW, SC_MAGMA_FLOW, SI_MAGMA_FLOW, SCB_NONE);
- set_sc(MH_PYROCLASTIC, SC_PYROCLASTIC, SI_PYROCLASTIC, SCB_BATK|SCB_ATK_ELE);
+ status->set_sc(MH_VOLCANIC_ASH, SC_VOLCANIC_ASH, SI_VOLCANIC_ASH, SCB_DEF|SCB_DEF2|SCB_HIT|SCB_BATK|SCB_FLEE);
+ status->set_sc(MH_GRANITIC_ARMOR, SC_GRANITIC_ARMOR, SI_GRANITIC_ARMOR, SCB_NONE);
+ status->set_sc(MH_MAGMA_FLOW, SC_MAGMA_FLOW, SI_MAGMA_FLOW, SCB_NONE);
+ status->set_sc(MH_PYROCLASTIC, SC_PYROCLASTIC, SI_PYROCLASTIC, SCB_BATK|SCB_ATK_ELE);
add_sc(MH_LAVA_SLIDE, SC_BURNING);
- set_sc(MH_NEEDLE_OF_PARALYZE, SC_NEEDLE_OF_PARALYZE, SI_NEEDLE_OF_PARALYZE, SCB_DEF2);
+ status->set_sc(MH_NEEDLE_OF_PARALYZE, SC_NEEDLE_OF_PARALYZE, SI_NEEDLE_OF_PARALYZE, SCB_DEF2);
add_sc(MH_POISON_MIST, SC_BLIND);
- set_sc(MH_PAIN_KILLER, SC_PAIN_KILLER, SI_PAIN_KILLER, SCB_ASPD);
+ status->set_sc(MH_PAIN_KILLER, SC_PAIN_KILLER, SI_PAIN_KILLER, SCB_ASPD);
- set_sc( MH_SILENT_BREEZE , SC_SILENCE , SI_SILENT_BREEZE , SCB_NONE );
+ status->set_sc( MH_SILENT_BREEZE , SC_SILENCE , SI_SILENT_BREEZE , SCB_NONE );
add_sc( MH_STYLE_CHANGE , SC_STYLE_CHANGE);
- set_sc( MH_TINDER_BREAKER , SC_RG_CCONFINE_S , SI_RG_CCONFINE_S , SCB_NONE );
- set_sc( MH_TINDER_BREAKER , SC_RG_CCONFINE_M , SI_RG_CCONFINE_M , SCB_FLEE );
+ status->set_sc( MH_TINDER_BREAKER , SC_RG_CCONFINE_S , SI_RG_CCONFINE_S , SCB_NONE );
+ status->set_sc( MH_TINDER_BREAKER , SC_RG_CCONFINE_M , SI_RG_CCONFINE_M , SCB_FLEE );
add_sc( MER_CRASH , SC_STUN );
- set_sc( MER_PROVOKE , SC_PROVOKE , SI_PROVOKE , SCB_DEF|SCB_DEF2|SCB_BATK|SCB_WATK );
+ status->set_sc( MER_PROVOKE , SC_PROVOKE , SI_PROVOKE , SCB_DEF|SCB_DEF2|SCB_BATK|SCB_WATK );
add_sc( MS_MAGNUM , SC_SUB_WEAPONPROPERTY );
add_sc( MER_SIGHT , SC_SIGHT );
- set_sc( MER_DECAGI , SC_DEC_AGI , SI_DEC_AGI , SCB_AGI|SCB_SPEED );
- set_sc( MER_MAGNIFICAT , SC_MAGNIFICAT , SI_MAGNIFICAT , SCB_REGEN );
+ status->set_sc( MER_DECAGI , SC_DEC_AGI , SI_DEC_AGI , SCB_AGI|SCB_SPEED );
+ status->set_sc( MER_MAGNIFICAT , SC_MAGNIFICAT , SI_MAGNIFICAT , SCB_REGEN );
add_sc( MER_LEXDIVINA , SC_SILENCE );
add_sc( MA_LANDMINE , SC_STUN );
add_sc( MA_SANDMAN , SC_SLEEP );
add_sc( MA_FREEZINGTRAP , SC_FREEZE );
- set_sc( MER_AUTOBERSERK , SC_AUTOBERSERK , SI_AUTOBERSERK , SCB_NONE );
- set_sc( ML_AUTOGUARD , SC_AUTOGUARD , SI_AUTOGUARD , SCB_NONE );
- set_sc( MS_REFLECTSHIELD , SC_REFLECTSHIELD , SI_REFLECTSHIELD , SCB_NONE );
- set_sc( ML_DEFENDER , SC_DEFENDER , SI_DEFENDER , SCB_SPEED|SCB_ASPD );
- set_sc( MS_PARRYING , SC_PARRYING , SI_PARRYING , SCB_NONE );
- set_sc( MS_BERSERK , SC_BERSERK , SI_BERSERK , SCB_DEF|SCB_DEF2|SCB_MDEF|SCB_MDEF2|SCB_FLEE|SCB_SPEED|SCB_ASPD|SCB_MAXHP|SCB_REGEN );
+ status->set_sc( MER_AUTOBERSERK , SC_AUTOBERSERK , SI_AUTOBERSERK , SCB_NONE );
+ status->set_sc( ML_AUTOGUARD , SC_AUTOGUARD , SI_AUTOGUARD , SCB_NONE );
+ status->set_sc( MS_REFLECTSHIELD , SC_REFLECTSHIELD , SI_REFLECTSHIELD , SCB_NONE );
+ status->set_sc( ML_DEFENDER , SC_DEFENDER , SI_DEFENDER , SCB_SPEED|SCB_ASPD );
+ status->set_sc( MS_PARRYING , SC_PARRYING , SI_PARRYING , SCB_NONE );
+ status->set_sc( MS_BERSERK , SC_BERSERK , SI_BERSERK , SCB_DEF|SCB_DEF2|SCB_MDEF|SCB_MDEF2|SCB_FLEE|SCB_SPEED|SCB_ASPD|SCB_MAXHP|SCB_REGEN );
add_sc( ML_SPIRALPIERCE , SC_STOP );
- set_sc( MER_QUICKEN , SC_MER_QUICKEN , SI_BLANK , SCB_ASPD );
+ status->set_sc( MER_QUICKEN , SC_MER_QUICKEN , SI_BLANK , SCB_ASPD );
add_sc( ML_DEVOTION , SC_DEVOTION );
- set_sc( MER_KYRIE , SC_KYRIE , SI_KYRIE , SCB_NONE );
- set_sc( MER_BLESSING , SC_BLESSING , SI_BLESSING , SCB_STR|SCB_INT|SCB_DEX );
- set_sc( MER_INCAGI , SC_INC_AGI , SI_INC_AGI , SCB_AGI|SCB_SPEED );
+ status->set_sc( MER_KYRIE , SC_KYRIE , SI_KYRIE , SCB_NONE );
+ status->set_sc( MER_BLESSING , SC_BLESSING , SI_BLESSING , SCB_STR|SCB_INT|SCB_DEX );
+ status->set_sc( MER_INCAGI , SC_INC_AGI , SI_INC_AGI , SCB_AGI|SCB_SPEED );
- set_sc( GD_LEADERSHIP , SC_LEADERSHIP , SI_BLANK , SCB_STR );
- set_sc( GD_GLORYWOUNDS , SC_GLORYWOUNDS , SI_BLANK , SCB_VIT );
- set_sc( GD_SOULCOLD , SC_SOULCOLD , SI_BLANK , SCB_AGI );
- set_sc( GD_HAWKEYES , SC_HAWKEYES , SI_BLANK , SCB_DEX );
+ status->set_sc( GD_LEADERSHIP , SC_LEADERSHIP , SI_BLANK , SCB_STR );
+ status->set_sc( GD_GLORYWOUNDS , SC_GLORYWOUNDS , SI_BLANK , SCB_VIT );
+ status->set_sc( GD_SOULCOLD , SC_SOULCOLD , SI_BLANK , SCB_AGI );
+ status->set_sc( GD_HAWKEYES , SC_HAWKEYES , SI_BLANK , SCB_DEX );
- set_sc( GD_BATTLEORDER , SC_GDSKILL_BATTLEORDER , SI_BLANK , SCB_STR|SCB_INT|SCB_DEX );
- set_sc( GD_REGENERATION , SC_GDSKILL_REGENERATION , SI_BLANK , SCB_REGEN );
+ status->set_sc( GD_BATTLEORDER , SC_GDSKILL_BATTLEORDER , SI_BLANK , SCB_STR|SCB_INT|SCB_DEX );
+ status->set_sc( GD_REGENERATION , SC_GDSKILL_REGENERATION , SI_BLANK , SCB_REGEN );
/**
* Rune Knight
**/
- set_sc( RK_ENCHANTBLADE , SC_ENCHANTBLADE , SI_ENCHANTBLADE , SCB_NONE );
- set_sc( RK_DRAGONHOWLING , SC_FEAR , SI_BLANK , SCB_FLEE|SCB_HIT );
- set_sc( RK_DEATHBOUND , SC_DEATHBOUND , SI_DEATHBOUND , SCB_NONE );
- set_sc( RK_WINDCUTTER , SC_FEAR , SI_BLANK , SCB_FLEE|SCB_HIT );
+ status->set_sc( RK_ENCHANTBLADE , SC_ENCHANTBLADE , SI_ENCHANTBLADE , SCB_NONE );
+ status->set_sc( RK_DRAGONHOWLING , SC_FEAR , SI_BLANK , SCB_FLEE|SCB_HIT );
+ status->set_sc( RK_DEATHBOUND , SC_DEATHBOUND , SI_DEATHBOUND , SCB_NONE );
+ status->set_sc( RK_WINDCUTTER , SC_FEAR , SI_BLANK , SCB_FLEE|SCB_HIT );
add_sc( RK_DRAGONBREATH , SC_BURNING );
- set_sc( RK_MILLENNIUMSHIELD , SC_MILLENNIUMSHIELD , SI_BLANK , SCB_NONE );
- set_sc( RK_REFRESH , SC_REFRESH , SI_REFRESH , SCB_NONE );
- set_sc( RK_GIANTGROWTH , SC_GIANTGROWTH , SI_GIANTGROWTH , SCB_STR );
- set_sc( RK_STONEHARDSKIN , SC_STONEHARDSKIN , SI_STONEHARDSKIN , SCB_NONE );
- set_sc( RK_VITALITYACTIVATION, SC_VITALITYACTIVATION, SI_VITALITYACTIVATION, SCB_REGEN );
- set_sc( RK_FIGHTINGSPIRIT , SC_FIGHTINGSPIRIT , SI_FIGHTINGSPIRIT , SCB_WATK|SCB_ASPD );
- set_sc( RK_ABUNDANCE , SC_ABUNDANCE , SI_ABUNDANCE , SCB_NONE );
- set_sc( RK_CRUSHSTRIKE , SC_CRUSHSTRIKE , SI_CRUSHSTRIKE , SCB_NONE );
+ status->set_sc( RK_MILLENNIUMSHIELD , SC_MILLENNIUMSHIELD , SI_BLANK , SCB_NONE );
+ status->set_sc( RK_REFRESH , SC_REFRESH , SI_REFRESH , SCB_NONE );
+ status->set_sc( RK_GIANTGROWTH , SC_GIANTGROWTH , SI_GIANTGROWTH , SCB_STR );
+ status->set_sc( RK_STONEHARDSKIN , SC_STONEHARDSKIN , SI_STONEHARDSKIN , SCB_NONE );
+ status->set_sc( RK_VITALITYACTIVATION, SC_VITALITYACTIVATION, SI_VITALITYACTIVATION, SCB_REGEN );
+ status->set_sc( RK_FIGHTINGSPIRIT , SC_FIGHTINGSPIRIT , SI_FIGHTINGSPIRIT , SCB_WATK|SCB_ASPD );
+ status->set_sc( RK_ABUNDANCE , SC_ABUNDANCE , SI_ABUNDANCE , SCB_NONE );
+ status->set_sc( RK_CRUSHSTRIKE , SC_CRUSHSTRIKE , SI_CRUSHSTRIKE , SCB_NONE );
add_sc( RK_DRAGONBREATH_WATER, SC_FROSTMISTY );
/**
* GC Guillotine Cross
**/
set_sc_with_vfx( GC_VENOMIMPRESS , SC_VENOMIMPRESS , SI_VENOMIMPRESS , SCB_NONE );
- set_sc( GC_POISONINGWEAPON , SC_POISONINGWEAPON , SI_POISONINGWEAPON , SCB_NONE );
- set_sc( GC_WEAPONBLOCKING , SC_WEAPONBLOCKING , SI_WEAPONBLOCKING , SCB_NONE );
- set_sc( GC_CLOAKINGEXCEED , SC_CLOAKINGEXCEED , SI_CLOAKINGEXCEED , SCB_SPEED );
- set_sc( GC_HALLUCINATIONWALK , SC_HALLUCINATIONWALK, SI_HALLUCINATIONWALK, SCB_FLEE );
- set_sc( GC_ROLLINGCUTTER , SC_ROLLINGCUTTER , SI_ROLLINGCUTTER , SCB_NONE );
+ status->set_sc( GC_POISONINGWEAPON , SC_POISONINGWEAPON , SI_POISONINGWEAPON , SCB_NONE );
+ status->set_sc( GC_WEAPONBLOCKING , SC_WEAPONBLOCKING , SI_WEAPONBLOCKING , SCB_NONE );
+ status->set_sc( GC_CLOAKINGEXCEED , SC_CLOAKINGEXCEED , SI_CLOAKINGEXCEED , SCB_SPEED );
+ status->set_sc( GC_HALLUCINATIONWALK , SC_HALLUCINATIONWALK, SI_HALLUCINATIONWALK, SCB_FLEE );
+ status->set_sc( GC_ROLLINGCUTTER , SC_ROLLINGCUTTER , SI_ROLLINGCUTTER , SCB_NONE );
set_sc_with_vfx( GC_DARKCROW , SC_DARKCROW , SI_DARKCROW , SCB_NONE );
/**
* Arch Bishop
**/
- set_sc( AB_ADORAMUS , SC_ADORAMUS , SI_ADORAMUS , SCB_AGI|SCB_SPEED );
+ status->set_sc( AB_ADORAMUS , SC_ADORAMUS , SI_ADORAMUS , SCB_AGI|SCB_SPEED );
add_sc( AB_CLEMENTIA , SC_BLESSING );
add_sc( AB_CANTO , SC_INC_AGI );
- set_sc( AB_EPICLESIS , SC_EPICLESIS , SI_EPICLESIS , SCB_MAXHP );
+ status->set_sc( AB_EPICLESIS , SC_EPICLESIS , SI_EPICLESIS , SCB_MAXHP );
add_sc( AB_PRAEFATIO , SC_KYRIE );
set_sc_with_vfx( AB_ORATIO , SC_ORATIO , SI_ORATIO , SCB_NONE );
- set_sc( AB_LAUDAAGNUS , SC_LAUDAAGNUS , SI_LAUDAAGNUS , SCB_VIT );
- set_sc( AB_LAUDARAMUS , SC_LAUDARAMUS , SI_LAUDARAMUS , SCB_LUK );
- set_sc( AB_RENOVATIO , SC_RENOVATIO , SI_RENOVATIO , SCB_REGEN );
- set_sc( AB_EXPIATIO , SC_EXPIATIO , SI_EXPIATIO , SCB_ATK_ELE );
- set_sc( AB_DUPLELIGHT , SC_DUPLELIGHT , SI_DUPLELIGHT , SCB_NONE );
- set_sc( AB_SECRAMENT , SC_SECRAMENT , SI_SECRAMENT , SCB_NONE );
- set_sc( AB_OFFERTORIUM , SC_OFFERTORIUM , SI_OFFERTORIUM , SCB_NONE );
+ status->set_sc( AB_LAUDAAGNUS , SC_LAUDAAGNUS , SI_LAUDAAGNUS , SCB_VIT );
+ status->set_sc( AB_LAUDARAMUS , SC_LAUDARAMUS , SI_LAUDARAMUS , SCB_LUK );
+ status->set_sc( AB_RENOVATIO , SC_RENOVATIO , SI_RENOVATIO , SCB_REGEN );
+ status->set_sc( AB_EXPIATIO , SC_EXPIATIO , SI_EXPIATIO , SCB_ATK_ELE );
+ status->set_sc( AB_DUPLELIGHT , SC_DUPLELIGHT , SI_DUPLELIGHT , SCB_NONE );
+ status->set_sc( AB_SECRAMENT , SC_SECRAMENT , SI_SECRAMENT , SCB_NONE );
+ status->set_sc( AB_OFFERTORIUM , SC_OFFERTORIUM , SI_OFFERTORIUM , SCB_NONE );
/**
* Warlock
**/
add_sc( WL_WHITEIMPRISON , SC_WHITEIMPRISON );
set_sc_with_vfx( WL_FROSTMISTY , SC_FROSTMISTY , SI_FROSTMISTY , SCB_ASPD|SCB_SPEED|SCB_DEF );
- set_sc( WL_MARSHOFABYSS , SC_MARSHOFABYSS , SI_MARSHOFABYSS , SCB_SPEED|SCB_FLEE|SCB_AGI|SCB_DEX );
- set_sc(WL_RECOGNIZEDSPELL , SC_RECOGNIZEDSPELL , SI_RECOGNIZEDSPELL , SCB_MATK);
- set_sc( WL_STASIS , SC_STASIS , SI_STASIS , SCB_NONE );
- set_sc( WL_TELEKINESIS_INTENSE, SC_TELEKINESIS_INTENSE , SI_TELEKINESIS_INTENSE , SCB_MATK );
+ status->set_sc( WL_MARSHOFABYSS , SC_MARSHOFABYSS , SI_MARSHOFABYSS , SCB_SPEED|SCB_FLEE|SCB_AGI|SCB_DEX );
+ status->set_sc(WL_RECOGNIZEDSPELL , SC_RECOGNIZEDSPELL , SI_RECOGNIZEDSPELL , SCB_MATK);
+ status->set_sc( WL_STASIS , SC_STASIS , SI_STASIS , SCB_NONE );
+ status->set_sc( WL_TELEKINESIS_INTENSE, SC_TELEKINESIS_INTENSE , SI_TELEKINESIS_INTENSE , SCB_MATK );
/**
* Ranger
**/
- set_sc( RA_FEARBREEZE , SC_FEARBREEZE , SI_FEARBREEZE , SCB_NONE );
- set_sc( RA_ELECTRICSHOCKER , SC_ELECTRICSHOCKER , SI_ELECTRICSHOCKER , SCB_NONE );
- set_sc( RA_WUGDASH , SC_WUGDASH , SI_WUGDASH , SCB_SPEED );
- set_sc( RA_CAMOUFLAGE , SC_CAMOUFLAGE , SI_CAMOUFLAGE , SCB_SPEED );
+ status->set_sc( RA_FEARBREEZE , SC_FEARBREEZE , SI_FEARBREEZE , SCB_NONE );
+ status->set_sc( RA_ELECTRICSHOCKER , SC_ELECTRICSHOCKER , SI_ELECTRICSHOCKER , SCB_NONE );
+ status->set_sc( RA_WUGDASH , SC_WUGDASH , SI_WUGDASH , SCB_SPEED );
+ status->set_sc( RA_CAMOUFLAGE , SC_CAMOUFLAGE , SI_CAMOUFLAGE , SCB_SPEED );
add_sc( RA_MAGENTATRAP , SC_ARMOR_PROPERTY );
add_sc( RA_COBALTTRAP , SC_ARMOR_PROPERTY );
add_sc( RA_MAIZETRAP , SC_ARMOR_PROPERTY );
add_sc( RA_VERDURETRAP , SC_ARMOR_PROPERTY );
add_sc( RA_FIRINGTRAP , SC_BURNING );
add_sc( RA_ICEBOUNDTRAP , SC_FROSTMISTY );
- set_sc( RA_UNLIMIT , SC_UNLIMIT , SI_UNLIMIT , SCB_DEF|SCB_DEF2|SCB_MDEF|SCB_MDEF2 );
+ status->set_sc( RA_UNLIMIT , SC_UNLIMIT , SI_UNLIMIT , SCB_DEF|SCB_DEF2|SCB_MDEF|SCB_MDEF2 );
/**
* Mechanic
**/
- set_sc( NC_ACCELERATION , SC_ACCELERATION , SI_ACCELERATION , SCB_SPEED );
- set_sc( NC_HOVERING , SC_HOVERING , SI_HOVERING , SCB_SPEED );
- set_sc( NC_SHAPESHIFT , SC_SHAPESHIFT , SI_SHAPESHIFT , SCB_DEF_ELE );
- set_sc( NC_INFRAREDSCAN , SC_INFRAREDSCAN , SI_INFRAREDSCAN , SCB_FLEE );
- set_sc( NC_ANALYZE , SC_ANALYZE , SI_ANALYZE , SCB_DEF|SCB_DEF2|SCB_MDEF|SCB_MDEF2 );
- set_sc( NC_MAGNETICFIELD , SC_MAGNETICFIELD , SI_MAGNETICFIELD , SCB_NONE );
- set_sc( NC_NEUTRALBARRIER , SC_NEUTRALBARRIER , SI_NEUTRALBARRIER , SCB_DEF|SCB_MDEF );
- set_sc( NC_STEALTHFIELD , SC_STEALTHFIELD , SI_STEALTHFIELD , SCB_NONE );
+ status->set_sc( NC_ACCELERATION , SC_ACCELERATION , SI_ACCELERATION , SCB_SPEED );
+ status->set_sc( NC_HOVERING , SC_HOVERING , SI_HOVERING , SCB_SPEED );
+ status->set_sc( NC_SHAPESHIFT , SC_SHAPESHIFT , SI_SHAPESHIFT , SCB_DEF_ELE );
+ status->set_sc( NC_INFRAREDSCAN , SC_INFRAREDSCAN , SI_INFRAREDSCAN , SCB_FLEE );
+ status->set_sc( NC_ANALYZE , SC_ANALYZE , SI_ANALYZE , SCB_DEF|SCB_DEF2|SCB_MDEF|SCB_MDEF2 );
+ status->set_sc( NC_MAGNETICFIELD , SC_MAGNETICFIELD , SI_MAGNETICFIELD , SCB_NONE );
+ status->set_sc( NC_NEUTRALBARRIER , SC_NEUTRALBARRIER , SI_NEUTRALBARRIER , SCB_DEF|SCB_MDEF );
+ status->set_sc( NC_STEALTHFIELD , SC_STEALTHFIELD , SI_STEALTHFIELD , SCB_NONE );
/**
* Royal Guard
**/
- set_sc( LG_REFLECTDAMAGE , SC_LG_REFLECTDAMAGE , SI_LG_REFLECTDAMAGE, SCB_NONE );
- set_sc( LG_FORCEOFVANGUARD , SC_FORCEOFVANGUARD , SI_FORCEOFVANGUARD , SCB_MAXHP );
- set_sc( LG_EXEEDBREAK , SC_EXEEDBREAK , SI_EXEEDBREAK , SCB_NONE );
- set_sc( LG_PRESTIGE , SC_PRESTIGE , SI_PRESTIGE , SCB_DEF );
- set_sc( LG_BANDING , SC_BANDING , SI_BANDING , SCB_DEF2|SCB_WATK );// Renewal: atk2 & def2
- set_sc( LG_PIETY , SC_BENEDICTIO , SI_BENEDICTIO , SCB_DEF_ELE );
- set_sc( LG_EARTHDRIVE , SC_EARTHDRIVE , SI_EARTHDRIVE , SCB_DEF|SCB_ASPD );
- set_sc( LG_INSPIRATION , SC_INSPIRATION , SI_INSPIRATION , SCB_MAXHP|SCB_WATK|SCB_HIT|SCB_VIT|SCB_AGI|SCB_STR|SCB_DEX|SCB_INT|SCB_LUK);
- set_sc( LG_KINGS_GRACE , SC_KINGS_GRACE , SI_KINGS_GRACE , SCB_NONE );
+ status->set_sc( LG_REFLECTDAMAGE , SC_LG_REFLECTDAMAGE , SI_LG_REFLECTDAMAGE, SCB_NONE );
+ status->set_sc( LG_FORCEOFVANGUARD , SC_FORCEOFVANGUARD , SI_FORCEOFVANGUARD , SCB_MAXHP );
+ status->set_sc( LG_EXEEDBREAK , SC_EXEEDBREAK , SI_EXEEDBREAK , SCB_NONE );
+ status->set_sc( LG_PRESTIGE , SC_PRESTIGE , SI_PRESTIGE , SCB_DEF );
+ status->set_sc( LG_BANDING , SC_BANDING , SI_BANDING , SCB_DEF2|SCB_WATK );// Renewal: atk2 & def2
+ status->set_sc( LG_PIETY , SC_BENEDICTIO , SI_BENEDICTIO , SCB_DEF_ELE );
+ status->set_sc( LG_EARTHDRIVE , SC_EARTHDRIVE , SI_EARTHDRIVE , SCB_DEF|SCB_ASPD );
+ status->set_sc( LG_INSPIRATION , SC_INSPIRATION , SI_INSPIRATION , SCB_MAXHP|SCB_WATK|SCB_HIT|SCB_VIT|SCB_AGI|SCB_STR|SCB_DEX|SCB_INT|SCB_LUK);
+ status->set_sc( LG_KINGS_GRACE , SC_KINGS_GRACE , SI_KINGS_GRACE , SCB_NONE );
/**
* Shadow Chaser
**/
- set_sc( SC_REPRODUCE , SC__REPRODUCE , SI_REPRODUCE , SCB_NONE );
- set_sc( SC_AUTOSHADOWSPELL , SC__AUTOSHADOWSPELL, SI_AUTOSHADOWSPELL , SCB_NONE );
- set_sc( SC_SHADOWFORM , SC__SHADOWFORM , SI_SHADOWFORM , SCB_NONE );
- set_sc( SC_BODYPAINT , SC__BODYPAINT , SI_BODYPAINT , SCB_ASPD );
- set_sc( SC_INVISIBILITY , SC__INVISIBILITY , SI_INVISIBILITY , SCB_ASPD|SCB_CRI|SCB_ATK_ELE );
- set_sc( SC_DEADLYINFECT , SC__DEADLYINFECT , SI_DEADLYINFECT , SCB_NONE );
- set_sc( SC_ENERVATION , SC__ENERVATION , SI_ENERVATION , SCB_BATK );
- set_sc( SC_GROOMY , SC__GROOMY , SI_GROOMY , SCB_ASPD|SCB_HIT|SCB_SPEED );
- set_sc( SC_IGNORANCE , SC__IGNORANCE , SI_IGNORANCE , SCB_NONE );
- set_sc( SC_LAZINESS , SC__LAZINESS , SI_LAZINESS , SCB_FLEE );
- set_sc( SC_UNLUCKY , SC__UNLUCKY , SI_UNLUCKY , SCB_CRI|SCB_FLEE2 );
- set_sc( SC_WEAKNESS , SC__WEAKNESS , SI_WEAKNESS , SCB_FLEE2|SCB_MAXHP );
- set_sc( SC_STRIPACCESSARY , SC__STRIPACCESSARY , SI_STRIPACCESSARY , SCB_DEX|SCB_INT|SCB_LUK );
+ status->set_sc( SC_REPRODUCE , SC__REPRODUCE , SI_REPRODUCE , SCB_NONE );
+ status->set_sc( SC_AUTOSHADOWSPELL , SC__AUTOSHADOWSPELL, SI_AUTOSHADOWSPELL , SCB_NONE );
+ status->set_sc( SC_SHADOWFORM , SC__SHADOWFORM , SI_SHADOWFORM , SCB_NONE );
+ status->set_sc( SC_BODYPAINT , SC__BODYPAINT , SI_BODYPAINT , SCB_ASPD );
+ status->set_sc( SC_INVISIBILITY , SC__INVISIBILITY , SI_INVISIBILITY , SCB_ASPD|SCB_CRI|SCB_ATK_ELE );
+ status->set_sc( SC_DEADLYINFECT , SC__DEADLYINFECT , SI_DEADLYINFECT , SCB_NONE );
+ status->set_sc( SC_ENERVATION , SC__ENERVATION , SI_ENERVATION , SCB_BATK );
+ status->set_sc( SC_GROOMY , SC__GROOMY , SI_GROOMY , SCB_ASPD|SCB_HIT|SCB_SPEED );
+ status->set_sc( SC_IGNORANCE , SC__IGNORANCE , SI_IGNORANCE , SCB_NONE );
+ status->set_sc( SC_LAZINESS , SC__LAZINESS , SI_LAZINESS , SCB_FLEE );
+ status->set_sc( SC_UNLUCKY , SC__UNLUCKY , SI_UNLUCKY , SCB_CRI|SCB_FLEE2 );
+ status->set_sc( SC_WEAKNESS , SC__WEAKNESS , SI_WEAKNESS , SCB_FLEE2|SCB_MAXHP );
+ status->set_sc( SC_STRIPACCESSARY , SC__STRIPACCESSARY , SI_STRIPACCESSARY , SCB_DEX|SCB_INT|SCB_LUK );
set_sc_with_vfx( SC_MANHOLE , SC__MANHOLE , SI_MANHOLE , SCB_NONE );
add_sc( SC_CHAOSPANIC , SC__CHAOS );
add_sc( SC_MAELSTROM , SC__MAELSTROM );
@@ -656,113 +657,113 @@ void initChangeTables(void) {
**/
add_sc( SR_DRAGONCOMBO , SC_STUN );
add_sc( SR_EARTHSHAKER , SC_STUN );
- set_sc( SR_FALLENEMPIRE , SC_FALLENEMPIRE , SI_FALLENEMPIRE , SCB_NONE );
- set_sc( SR_CRESCENTELBOW , SC_CRESCENTELBOW , SI_CRESCENTELBOW , SCB_NONE );
+ status->set_sc( SR_FALLENEMPIRE , SC_FALLENEMPIRE , SI_FALLENEMPIRE , SCB_NONE );
+ status->set_sc( SR_CRESCENTELBOW , SC_CRESCENTELBOW , SI_CRESCENTELBOW , SCB_NONE );
set_sc_with_vfx( SR_CURSEDCIRCLE , SC_CURSEDCIRCLE_TARGET, SI_CURSEDCIRCLE_TARGET , SCB_NONE );
- set_sc( SR_LIGHTNINGWALK , SC_LIGHTNINGWALK , SI_LIGHTNINGWALK , SCB_NONE );
- set_sc( SR_RAISINGDRAGON , SC_RAISINGDRAGON , SI_RAISINGDRAGON , SCB_REGEN|SCB_MAXHP|SCB_MAXSP );
- set_sc( SR_GENTLETOUCH_ENERGYGAIN, SC_GENTLETOUCH_ENERGYGAIN , SI_GENTLETOUCH_ENERGYGAIN, SCB_NONE );
- set_sc( SR_GENTLETOUCH_CHANGE , SC_GENTLETOUCH_CHANGE , SI_GENTLETOUCH_CHANGE , SCB_ASPD|SCB_MDEF|SCB_MAXHP );
- set_sc( SR_GENTLETOUCH_REVITALIZE, SC_GENTLETOUCH_REVITALIZE , SI_GENTLETOUCH_REVITALIZE, SCB_MAXHP|SCB_DEF2|SCB_REGEN );
- set_sc( SR_FLASHCOMBO , SC_FLASHCOMBO , SI_FLASHCOMBO , SCB_WATK );
+ status->set_sc( SR_LIGHTNINGWALK , SC_LIGHTNINGWALK , SI_LIGHTNINGWALK , SCB_NONE );
+ status->set_sc( SR_RAISINGDRAGON , SC_RAISINGDRAGON , SI_RAISINGDRAGON , SCB_REGEN|SCB_MAXHP|SCB_MAXSP );
+ status->set_sc( SR_GENTLETOUCH_ENERGYGAIN, SC_GENTLETOUCH_ENERGYGAIN , SI_GENTLETOUCH_ENERGYGAIN, SCB_NONE );
+ status->set_sc( SR_GENTLETOUCH_CHANGE , SC_GENTLETOUCH_CHANGE , SI_GENTLETOUCH_CHANGE , SCB_ASPD|SCB_MDEF|SCB_MAXHP );
+ status->set_sc( SR_GENTLETOUCH_REVITALIZE, SC_GENTLETOUCH_REVITALIZE , SI_GENTLETOUCH_REVITALIZE, SCB_MAXHP|SCB_DEF2|SCB_REGEN );
+ status->set_sc( SR_FLASHCOMBO , SC_FLASHCOMBO , SI_FLASHCOMBO , SCB_WATK );
/**
* Wanderer / Minstrel
**/
- set_sc( WA_SWING_DANCE , SC_SWING , SI_SWINGDANCE , SCB_SPEED|SCB_ASPD );
- set_sc( WA_SYMPHONY_OF_LOVER , SC_SYMPHONY_LOVE , SI_SYMPHONYOFLOVERS , SCB_MDEF );
- set_sc( WA_MOONLIT_SERENADE , SC_MOONLIT_SERENADE , SI_MOONLITSERENADE , SCB_MATK );
- set_sc( MI_RUSH_WINDMILL , SC_RUSH_WINDMILL , SI_RUSHWINDMILL , SCB_WATK );
- set_sc( MI_ECHOSONG , SC_ECHOSONG , SI_ECHOSONG , SCB_DEF2 );
- set_sc( MI_HARMONIZE , SC_HARMONIZE , SI_HARMONIZE , SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK );
+ status->set_sc( WA_SWING_DANCE , SC_SWING , SI_SWINGDANCE , SCB_SPEED|SCB_ASPD );
+ status->set_sc( WA_SYMPHONY_OF_LOVER , SC_SYMPHONY_LOVE , SI_SYMPHONYOFLOVERS , SCB_MDEF );
+ status->set_sc( WA_MOONLIT_SERENADE , SC_MOONLIT_SERENADE , SI_MOONLITSERENADE , SCB_MATK );
+ status->set_sc( MI_RUSH_WINDMILL , SC_RUSH_WINDMILL , SI_RUSHWINDMILL , SCB_WATK );
+ status->set_sc( MI_ECHOSONG , SC_ECHOSONG , SI_ECHOSONG , SCB_DEF2 );
+ status->set_sc( MI_HARMONIZE , SC_HARMONIZE , SI_HARMONIZE , SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK );
set_sc_with_vfx(WM_POEMOFNETHERWORLD, SC_NETHERWORLD , SI_NETHERWORLD , SCB_NONE);
set_sc_with_vfx( WM_VOICEOFSIREN , SC_SIREN , SI_SIREN , SCB_NONE );
set_sc_with_vfx( WM_LULLABY_DEEPSLEEP , SC_DEEP_SLEEP , SI_DEEPSLEEP , SCB_NONE );
- set_sc( WM_SIRCLEOFNATURE , SC_SIRCLEOFNATURE , SI_SIRCLEOFNATURE , SCB_NONE );
- set_sc( WM_GLOOMYDAY , SC_GLOOMYDAY , SI_GLOOMYDAY , SCB_FLEE|SCB_ASPD );
- set_sc( WM_SONG_OF_MANA , SC_SONG_OF_MANA , SI_SONG_OF_MANA , SCB_NONE );
- set_sc( WM_DANCE_WITH_WUG , SC_DANCE_WITH_WUG , SI_DANCEWITHWUG , SCB_ASPD );
- set_sc( WM_SATURDAY_NIGHT_FEVER , SC_SATURDAY_NIGHT_FEVER , SI_SATURDAYNIGHTFEVER , SCB_BATK|SCB_DEF|SCB_FLEE|SCB_REGEN );
- set_sc( WM_LERADS_DEW , SC_LERADS_DEW , SI_LERADSDEW , SCB_MAXHP );
- set_sc( WM_MELODYOFSINK , SC_MELODYOFSINK , SI_MELODYOFSINK , SCB_INT );
- set_sc( WM_BEYOND_OF_WARCRY , SC_BEYOND_OF_WARCRY , SI_WARCRYOFBEYOND , SCB_STR|SCB_CRI|SCB_MAXHP );
- set_sc( WM_UNLIMITED_HUMMING_VOICE, SC_UNLIMITED_HUMMING_VOICE, SI_UNLIMITEDHUMMINGVOICE, SCB_NONE );
- set_sc( WM_FRIGG_SONG , SC_FRIGG_SONG , SI_FRIGG_SONG , SCB_MAXHP );
+ status->set_sc( WM_SIRCLEOFNATURE , SC_SIRCLEOFNATURE , SI_SIRCLEOFNATURE , SCB_NONE );
+ status->set_sc( WM_GLOOMYDAY , SC_GLOOMYDAY , SI_GLOOMYDAY , SCB_FLEE|SCB_ASPD );
+ status->set_sc( WM_SONG_OF_MANA , SC_SONG_OF_MANA , SI_SONG_OF_MANA , SCB_NONE );
+ status->set_sc( WM_DANCE_WITH_WUG , SC_DANCE_WITH_WUG , SI_DANCEWITHWUG , SCB_ASPD );
+ status->set_sc( WM_SATURDAY_NIGHT_FEVER , SC_SATURDAY_NIGHT_FEVER , SI_SATURDAYNIGHTFEVER , SCB_BATK|SCB_DEF|SCB_FLEE|SCB_REGEN );
+ status->set_sc( WM_LERADS_DEW , SC_LERADS_DEW , SI_LERADSDEW , SCB_MAXHP );
+ status->set_sc( WM_MELODYOFSINK , SC_MELODYOFSINK , SI_MELODYOFSINK , SCB_INT );
+ status->set_sc( WM_BEYOND_OF_WARCRY , SC_BEYOND_OF_WARCRY , SI_WARCRYOFBEYOND , SCB_STR|SCB_CRI|SCB_MAXHP );
+ status->set_sc( WM_UNLIMITED_HUMMING_VOICE, SC_UNLIMITED_HUMMING_VOICE, SI_UNLIMITEDHUMMINGVOICE, SCB_NONE );
+ status->set_sc( WM_FRIGG_SONG , SC_FRIGG_SONG , SI_FRIGG_SONG , SCB_MAXHP );
/**
* Sorcerer
**/
- set_sc( SO_FIREWALK , SC_PROPERTYWALK , SI_PROPERTYWALK , SCB_NONE );
- set_sc( SO_ELECTRICWALK , SC_PROPERTYWALK , SI_PROPERTYWALK , SCB_NONE );
- set_sc( SO_SPELLFIST , SC_SPELLFIST , SI_SPELLFIST , SCB_NONE );
+ status->set_sc( SO_FIREWALK , SC_PROPERTYWALK , SI_PROPERTYWALK , SCB_NONE );
+ status->set_sc( SO_ELECTRICWALK , SC_PROPERTYWALK , SI_PROPERTYWALK , SCB_NONE );
+ status->set_sc( SO_SPELLFIST , SC_SPELLFIST , SI_SPELLFIST , SCB_NONE );
set_sc_with_vfx( SO_DIAMONDDUST , SC_COLD , SI_COLD , SCB_NONE ); // it does show the snow icon on mobs but doesn't affect it.
- set_sc( SO_CLOUD_KILL , SC_POISON , SI_CLOUDKILL , SCB_NONE );
- set_sc( SO_STRIKING , SC_STRIKING , SI_STRIKING , SCB_WATK|SCB_CRI );
+ status->set_sc( SO_CLOUD_KILL , SC_POISON , SI_CLOUDKILL , SCB_NONE );
+ status->set_sc( SO_STRIKING , SC_STRIKING , SI_STRIKING , SCB_WATK|SCB_CRI );
add_sc( SO_WARMER , SC_WARMER ); // At the moment, no icon on officials
- set_sc( SO_VACUUM_EXTREME , SC_VACUUM_EXTREME , SI_VACUUM_EXTREME , SCB_NONE );
- set_sc( SO_ARRULLO , SC_DEEP_SLEEP , SI_DEEPSLEEP , SCB_NONE );
- set_sc( SO_FIRE_INSIGNIA , SC_FIRE_INSIGNIA , SI_FIRE_INSIGNIA , SCB_MATK | SCB_BATK | SCB_WATK | SCB_ATK_ELE | SCB_REGEN );
- set_sc( SO_WATER_INSIGNIA , SC_WATER_INSIGNIA , SI_WATER_INSIGNIA , SCB_WATK | SCB_ATK_ELE | SCB_REGEN );
- set_sc( SO_WIND_INSIGNIA , SC_WIND_INSIGNIA , SI_WIND_INSIGNIA , SCB_WATK | SCB_ATK_ELE | SCB_REGEN );
- set_sc( SO_EARTH_INSIGNIA , SC_EARTH_INSIGNIA , SI_EARTH_INSIGNIA , SCB_MDEF|SCB_DEF|SCB_MAXHP|SCB_MAXSP|SCB_WATK | SCB_ATK_ELE | SCB_REGEN );
+ status->set_sc( SO_VACUUM_EXTREME , SC_VACUUM_EXTREME , SI_VACUUM_EXTREME , SCB_NONE );
+ status->set_sc( SO_ARRULLO , SC_DEEP_SLEEP , SI_DEEPSLEEP , SCB_NONE );
+ status->set_sc( SO_FIRE_INSIGNIA , SC_FIRE_INSIGNIA , SI_FIRE_INSIGNIA , SCB_MATK | SCB_BATK | SCB_WATK | SCB_ATK_ELE | SCB_REGEN );
+ status->set_sc( SO_WATER_INSIGNIA , SC_WATER_INSIGNIA , SI_WATER_INSIGNIA , SCB_WATK | SCB_ATK_ELE | SCB_REGEN );
+ status->set_sc( SO_WIND_INSIGNIA , SC_WIND_INSIGNIA , SI_WIND_INSIGNIA , SCB_WATK | SCB_ATK_ELE | SCB_REGEN );
+ status->set_sc( SO_EARTH_INSIGNIA , SC_EARTH_INSIGNIA , SI_EARTH_INSIGNIA , SCB_MDEF|SCB_DEF|SCB_MAXHP|SCB_MAXSP|SCB_WATK | SCB_ATK_ELE | SCB_REGEN );
add_sc( SO_ELEMENTAL_SHIELD , SC_SAFETYWALL );
/**
* Genetic
**/
- set_sc( GN_CARTBOOST , SC_GN_CARTBOOST, SI_CARTSBOOST , SCB_SPEED );
- set_sc( GN_THORNS_TRAP , SC_THORNS_TRAP , SI_THORNTRAP , SCB_NONE );
+ status->set_sc( GN_CARTBOOST , SC_GN_CARTBOOST, SI_CARTSBOOST , SCB_SPEED );
+ status->set_sc( GN_THORNS_TRAP , SC_THORNS_TRAP , SI_THORNTRAP , SCB_NONE );
set_sc_with_vfx( GN_BLOOD_SUCKER , SC_BLOOD_SUCKER , SI_BLOODSUCKER , SCB_NONE );
- set_sc( GN_WALLOFTHORN , SC_STOP , SI_BLANK , SCB_NONE );
- set_sc( GN_FIRE_EXPANSION_SMOKE_POWDER, SC_FIRE_EXPANSION_SMOKE_POWDER , SI_FIRE_EXPANSION_SMOKE_POWDER, SCB_NONE );
- set_sc( GN_FIRE_EXPANSION_TEAR_GAS , SC_FIRE_EXPANSION_TEAR_GAS , SI_FIRE_EXPANSION_TEAR_GAS , SCB_NONE );
- set_sc( GN_MANDRAGORA , SC_MANDRAGORA , SI_MANDRAGORA , SCB_INT );
+ status->set_sc( GN_WALLOFTHORN , SC_STOP , SI_BLANK , SCB_NONE );
+ status->set_sc( GN_FIRE_EXPANSION_SMOKE_POWDER, SC_FIRE_EXPANSION_SMOKE_POWDER , SI_FIRE_EXPANSION_SMOKE_POWDER, SCB_NONE );
+ status->set_sc( GN_FIRE_EXPANSION_TEAR_GAS , SC_FIRE_EXPANSION_TEAR_GAS , SI_FIRE_EXPANSION_TEAR_GAS , SCB_NONE );
+ status->set_sc( GN_MANDRAGORA , SC_MANDRAGORA , SI_MANDRAGORA , SCB_INT );
// Elemental Spirit summoner's 'side' status changes.
- set_sc( EL_CIRCLE_OF_FIRE , SC_CIRCLE_OF_FIRE_OPTION, SI_CIRCLE_OF_FIRE_OPTION, SCB_NONE );
- set_sc( EL_FIRE_CLOAK , SC_FIRE_CLOAK_OPTION , SI_FIRE_CLOAK_OPTION , SCB_ALL );
- set_sc( EL_WATER_SCREEN , SC_WATER_SCREEN_OPTION , SI_WATER_SCREEN_OPTION , SCB_NONE );
- set_sc( EL_WATER_DROP , SC_WATER_DROP_OPTION , SI_WATER_DROP_OPTION , SCB_ALL );
- set_sc( EL_WATER_BARRIER , SC_WATER_BARRIER , SI_WATER_BARRIER , SCB_WATK|SCB_FLEE );
- set_sc( EL_WIND_STEP , SC_WIND_STEP_OPTION , SI_WIND_STEP_OPTION , SCB_SPEED|SCB_FLEE );
- set_sc( EL_WIND_CURTAIN , SC_WIND_CURTAIN_OPTION , SI_WIND_CURTAIN_OPTION , SCB_ALL );
- set_sc( EL_ZEPHYR , SC_ZEPHYR , SI_ZEPHYR , SCB_FLEE );
- set_sc( EL_SOLID_SKIN , SC_SOLID_SKIN_OPTION , SI_SOLID_SKIN_OPTION , SCB_DEF|SCB_MAXHP );
- set_sc( EL_STONE_SHIELD , SC_STONE_SHIELD_OPTION , SI_STONE_SHIELD_OPTION , SCB_ALL );
- set_sc( EL_POWER_OF_GAIA , SC_POWER_OF_GAIA , SI_POWER_OF_GAIA , SCB_MAXHP|SCB_DEF|SCB_SPEED );
- set_sc( EL_PYROTECHNIC , SC_PYROTECHNIC_OPTION , SI_PYROTECHNIC_OPTION , SCB_WATK );
- set_sc( EL_HEATER , SC_HEATER_OPTION , SI_HEATER_OPTION , SCB_WATK );
- set_sc( EL_TROPIC , SC_TROPIC_OPTION , SI_TROPIC_OPTION , SCB_WATK );
- set_sc( EL_AQUAPLAY , SC_AQUAPLAY_OPTION , SI_AQUAPLAY_OPTION , SCB_MATK );
- set_sc( EL_COOLER , SC_COOLER_OPTION , SI_COOLER_OPTION , SCB_MATK );
- set_sc( EL_CHILLY_AIR , SC_CHILLY_AIR_OPTION , SI_CHILLY_AIR_OPTION , SCB_MATK );
- set_sc( EL_GUST , SC_GUST_OPTION , SI_GUST_OPTION , SCB_ASPD );
- set_sc( EL_BLAST , SC_BLAST_OPTION , SI_BLAST_OPTION , SCB_ASPD );
- set_sc( EL_WILD_STORM , SC_WILD_STORM_OPTION , SI_WILD_STORM_OPTION , SCB_ASPD );
- set_sc( EL_PETROLOGY , SC_PETROLOGY_OPTION , SI_PETROLOGY_OPTION , SCB_MAXHP );
- set_sc( EL_CURSED_SOIL , SC_CURSED_SOIL_OPTION , SI_CURSED_SOIL_OPTION , SCB_MAXHP );
- set_sc( EL_UPHEAVAL , SC_UPHEAVAL_OPTION , SI_UPHEAVAL_OPTION , SCB_MAXHP );
- set_sc( EL_TIDAL_WEAPON , SC_TIDAL_WEAPON_OPTION , SI_TIDAL_WEAPON_OPTION , SCB_ALL );
- set_sc( EL_ROCK_CRUSHER , SC_ROCK_CRUSHER , SI_ROCK_CRUSHER , SCB_DEF );
- set_sc( EL_ROCK_CRUSHER_ATK, SC_ROCK_CRUSHER_ATK , SI_ROCK_CRUSHER_ATK , SCB_SPEED );
+ status->set_sc( EL_CIRCLE_OF_FIRE , SC_CIRCLE_OF_FIRE_OPTION, SI_CIRCLE_OF_FIRE_OPTION, SCB_NONE );
+ status->set_sc( EL_FIRE_CLOAK , SC_FIRE_CLOAK_OPTION , SI_FIRE_CLOAK_OPTION , SCB_ALL );
+ status->set_sc( EL_WATER_SCREEN , SC_WATER_SCREEN_OPTION , SI_WATER_SCREEN_OPTION , SCB_NONE );
+ status->set_sc( EL_WATER_DROP , SC_WATER_DROP_OPTION , SI_WATER_DROP_OPTION , SCB_ALL );
+ status->set_sc( EL_WATER_BARRIER , SC_WATER_BARRIER , SI_WATER_BARRIER , SCB_WATK|SCB_FLEE );
+ status->set_sc( EL_WIND_STEP , SC_WIND_STEP_OPTION , SI_WIND_STEP_OPTION , SCB_SPEED|SCB_FLEE );
+ status->set_sc( EL_WIND_CURTAIN , SC_WIND_CURTAIN_OPTION , SI_WIND_CURTAIN_OPTION , SCB_ALL );
+ status->set_sc( EL_ZEPHYR , SC_ZEPHYR , SI_ZEPHYR , SCB_FLEE );
+ status->set_sc( EL_SOLID_SKIN , SC_SOLID_SKIN_OPTION , SI_SOLID_SKIN_OPTION , SCB_DEF|SCB_MAXHP );
+ status->set_sc( EL_STONE_SHIELD , SC_STONE_SHIELD_OPTION , SI_STONE_SHIELD_OPTION , SCB_ALL );
+ status->set_sc( EL_POWER_OF_GAIA , SC_POWER_OF_GAIA , SI_POWER_OF_GAIA , SCB_MAXHP|SCB_DEF|SCB_SPEED );
+ status->set_sc( EL_PYROTECHNIC , SC_PYROTECHNIC_OPTION , SI_PYROTECHNIC_OPTION , SCB_WATK );
+ status->set_sc( EL_HEATER , SC_HEATER_OPTION , SI_HEATER_OPTION , SCB_WATK );
+ status->set_sc( EL_TROPIC , SC_TROPIC_OPTION , SI_TROPIC_OPTION , SCB_WATK );
+ status->set_sc( EL_AQUAPLAY , SC_AQUAPLAY_OPTION , SI_AQUAPLAY_OPTION , SCB_MATK );
+ status->set_sc( EL_COOLER , SC_COOLER_OPTION , SI_COOLER_OPTION , SCB_MATK );
+ status->set_sc( EL_CHILLY_AIR , SC_CHILLY_AIR_OPTION , SI_CHILLY_AIR_OPTION , SCB_MATK );
+ status->set_sc( EL_GUST , SC_GUST_OPTION , SI_GUST_OPTION , SCB_ASPD );
+ status->set_sc( EL_BLAST , SC_BLAST_OPTION , SI_BLAST_OPTION , SCB_ASPD );
+ status->set_sc( EL_WILD_STORM , SC_WILD_STORM_OPTION , SI_WILD_STORM_OPTION , SCB_ASPD );
+ status->set_sc( EL_PETROLOGY , SC_PETROLOGY_OPTION , SI_PETROLOGY_OPTION , SCB_MAXHP );
+ status->set_sc( EL_CURSED_SOIL , SC_CURSED_SOIL_OPTION , SI_CURSED_SOIL_OPTION , SCB_MAXHP );
+ status->set_sc( EL_UPHEAVAL , SC_UPHEAVAL_OPTION , SI_UPHEAVAL_OPTION , SCB_MAXHP );
+ status->set_sc( EL_TIDAL_WEAPON , SC_TIDAL_WEAPON_OPTION , SI_TIDAL_WEAPON_OPTION , SCB_ALL );
+ status->set_sc( EL_ROCK_CRUSHER , SC_ROCK_CRUSHER , SI_ROCK_CRUSHER , SCB_DEF );
+ status->set_sc( EL_ROCK_CRUSHER_ATK, SC_ROCK_CRUSHER_ATK , SI_ROCK_CRUSHER_ATK , SCB_SPEED );
add_sc( KO_YAMIKUMO , SC_HIDING );
set_sc_with_vfx( KO_JYUMONJIKIRI , SC_KO_JYUMONJIKIRI , SI_KO_JYUMONJIKIRI , SCB_NONE );
add_sc( KO_MAKIBISHI , SC_STUN );
- set_sc( KO_MEIKYOUSISUI , SC_MEIKYOUSISUI , SI_MEIKYOUSISUI , SCB_NONE );
- set_sc( KO_KYOUGAKU , SC_KYOUGAKU , SI_KYOUGAKU , SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK );
+ status->set_sc( KO_MEIKYOUSISUI , SC_MEIKYOUSISUI , SI_MEIKYOUSISUI , SCB_NONE );
+ status->set_sc( KO_KYOUGAKU , SC_KYOUGAKU , SI_KYOUGAKU , SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK );
add_sc( KO_JYUSATSU , SC_CURSE );
- set_sc( KO_ZENKAI , SC_ZENKAI , SI_ZENKAI , SCB_NONE );
- set_sc( KO_IZAYOI , SC_IZAYOI , SI_IZAYOI , SCB_MATK );
- set_sc( KG_KYOMU , SC_KYOMU , SI_KYOMU , SCB_NONE );
- set_sc( KG_KAGEMUSYA , SC_KAGEMUSYA , SI_KAGEMUSYA , SCB_NONE );
- set_sc( KG_KAGEHUMI , SC_KG_KAGEHUMI , SI_KG_KAGEHUMI , SCB_NONE );
- set_sc( OB_ZANGETSU , SC_ZANGETSU , SI_ZANGETSU , SCB_MATK|SCB_BATK );
+ status->set_sc( KO_ZENKAI , SC_ZENKAI , SI_ZENKAI , SCB_NONE );
+ status->set_sc( KO_IZAYOI , SC_IZAYOI , SI_IZAYOI , SCB_MATK );
+ status->set_sc( KG_KYOMU , SC_KYOMU , SI_KYOMU , SCB_NONE );
+ status->set_sc( KG_KAGEMUSYA , SC_KAGEMUSYA , SI_KAGEMUSYA , SCB_NONE );
+ status->set_sc( KG_KAGEHUMI , SC_KG_KAGEHUMI , SI_KG_KAGEHUMI , SCB_NONE );
+ status->set_sc( OB_ZANGETSU , SC_ZANGETSU , SI_ZANGETSU , SCB_MATK|SCB_BATK );
set_sc_with_vfx( OB_AKAITSUKI, SC_AKAITSUKI , SI_AKAITSUKI , SCB_NONE );
- set_sc( OB_OBOROGENSOU , SC_GENSOU , SI_GENSOU , SCB_NONE );
+ status->set_sc( OB_OBOROGENSOU , SC_GENSOU , SI_GENSOU , SCB_NONE );
- set_sc( ALL_FULL_THROTTLE , SC_FULL_THROTTLE , SI_FULL_THROTTLE , SCB_SPEED|SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK );
+ status->set_sc( ALL_FULL_THROTTLE , SC_FULL_THROTTLE , SI_FULL_THROTTLE , SCB_SPEED|SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK );
add_sc( ALL_REVERSEORCISH , SC_ORCISH );
- set_sc( ALL_ANGEL_PROTECT , SC_ANGEL_PROTECT , SI_ANGEL_PROTECT , SCB_REGEN );
+ status->set_sc( ALL_ANGEL_PROTECT , SC_ANGEL_PROTECT , SI_ANGEL_PROTECT , SCB_REGEN );
add_sc( NPC_WIDEHEALTHFEAR , SC_FEAR );
add_sc( NPC_WIDEBODYBURNNING , SC_BURNING );
@@ -1237,7 +1238,7 @@ void initDummyData(void)
}
//For copying a status_data structure from b to a, without overwriting current Hp and Sp
-static inline void status_cpy(struct status_data* a, const struct status_data* b)
+void status_copy(struct status_data *a, const struct status_data *b)
{
memcpy((void*)&a->max_hp, (const void*)&b->max_hp, sizeof(struct status_data)-(sizeof(a->hp)+sizeof(a->sp)));
}
@@ -3160,7 +3161,7 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) {
sd->left_weapon.addrace[RC_DEMON] += sc->data[SC_PHI_DEMON]->val1;
}
}
- status_cpy(&sd->battle_status, bstatus);
+ status->copy(&sd->battle_status, bstatus);
// ----- CLIENT-SIDE REFRESH -----
if(!sd->bl.prev) {
@@ -3199,7 +3200,7 @@ int status_calc_mercenary_(struct mercenary_data *md, enum e_status_calc_opt opt
}
status->calc_misc(&md->bl, mstatus, md->db->lv);
- status_cpy(&md->battle_status, mstatus);
+ status->copy(&md->battle_status, mstatus);
return 0;
}
@@ -3237,7 +3238,7 @@ int status_calc_elemental_(struct elemental_data *ed, enum e_status_calc_opt opt
memcpy(&ed->battle_status, estatus, sizeof(struct status_data));
} else {
status->calc_misc(&ed->bl, estatus, 0);
- status_cpy(&ed->battle_status, estatus);
+ status->copy(&ed->battle_status, estatus);
}
return 0;
@@ -3274,7 +3275,7 @@ int status_calc_npc_(struct npc_data *nd, enum e_status_calc_opt opt) {
nstatus->luk = nd->stat_point;
status->calc_misc(&nd->bl, nstatus, nd->level);
- status_cpy(&nd->status, nstatus);
+ status->copy(&nd->status, nstatus);
return 0;
}
@@ -3360,7 +3361,7 @@ int status_calc_homunculus_(struct homun_data *hd, enum e_status_calc_opt opt) {
status->calc_misc(&hd->bl, hstatus, hom->level);
- status_cpy(&hd->battle_status, hstatus);
+ status->copy(&hd->battle_status, hstatus);
return 1;
}
@@ -3540,7 +3541,7 @@ void status_calc_regen_rate(struct block_list *bl, struct regen_data *regen, str
#endif
regen->rate.sp += 1;
}
-
+
if (sc->data[SC_GDSKILL_REGENERATION]) {
const struct status_change_entry *sce = sc->data[SC_GDSKILL_REGENERATION];
if (!sce->val4) {
@@ -3610,7 +3611,7 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) {
}
if((!(bl->type&BL_REGEN)) && (!sc || !sc->count)) { //No difference.
- status_cpy(st, bst);
+ status->copy(st, bst);
return;
}
@@ -4300,10 +4301,15 @@ unsigned short status_base_atk(const struct block_list *bl, const struct status_
return cap_value(str, 0, USHRT_MAX);
}
-#ifndef RENEWAL
-static inline unsigned short status_base_matk_min(const struct status_data *st) { return st->int_ + (st->int_ / 7)*(st->int_ / 7); }
-#endif // not RENEWAL
-static inline unsigned short status_base_matk_max(const struct status_data *st) { return st->int_ + (st->int_ / 5)*(st->int_ / 5); }
+unsigned short status_base_matk_min(const struct status_data *st)
+{
+ return st->int_ + (st->int_ / 7) * (st->int_ / 7);
+}
+
+unsigned short status_base_matk_max(const struct status_data *st)
+{
+ return st->int_ + (st->int_ / 5)*(st->int_ / 5);
+}
unsigned short status_base_matk(struct block_list *bl, const struct status_data *st, int level) {
#ifdef RENEWAL
@@ -4350,8 +4356,8 @@ void status_calc_misc(struct block_list *bl, struct status_data *st, int level)
st->mdef2 += (int)(bl->type == BL_PC ? (st->int_ + ((float)level / 4) + ((float)(st->dex + st->vit) / 5)) : ((float)(st->int_ + level) / 4)); //(every 4 base level = +1 mdef) + (every 1 int = +1 mdef) + (every 5 dex = +1 mdef) + (every 5 vit = +1 mdef)
}
#else // not RENEWAL
- st->matk_min = status_base_matk_min(st);
- st->matk_max = status_base_matk_max(st);
+ st->matk_min = status->base_matk_min(st);
+ st->matk_max = status->base_matk_max(st);
st->hit += level + st->dex;
st->flee += level + st->agi;
st->def2 += st->vit;
@@ -4386,7 +4392,7 @@ void status_calc_misc(struct block_list *bl, struct status_data *st, int level)
break;
case BL_MER:
#ifdef RENEWAL
- st->matk_min = st->matk_max = status_base_matk_max(st);
+ st->matk_min = st->matk_max = status->base_matk_max(st);
st->def2 = st->vit + level / 10 + st->vit / 5;
st->mdef2 = level / 10 + st->int_ / 5;
#endif
@@ -5576,9 +5582,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
@@ -5648,8 +5654,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()
@@ -7495,8 +7501,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)
@@ -7506,8 +7513,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;
@@ -11610,7 +11619,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;
@@ -12107,8 +12116,8 @@ void status_get_matk_sub(struct block_list *bl, int flag, unsigned short *matk_m
}
#else // not RENEWAL
- *matk_min = status_base_matk_min(st) + (sd ? sd->bonus.ematk : 0);
- *matk_max = status_base_matk_max(st) + (sd ? sd->bonus.ematk : 0);
+ *matk_min = status->base_matk_min(st) + (sd ? sd->bonus.ematk : 0);
+ *matk_max = status->base_matk_max(st) + (sd ? sd->bonus.ematk : 0);
#endif
if ( sd && sd->matk_rate != 100 ) {
@@ -12961,7 +12970,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))
@@ -12971,10 +12980,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++;
}
}
@@ -13224,4 +13236,10 @@ void status_defaults(void) {
status->readdb_scconfig = status_readdb_scconfig;
status->read_job_db = status_read_job_db;
status->read_job_db_sub = status_read_job_db_sub;
+ status->set_sc = status_set_sc;
+ status->copy = status_copy;
+#ifndef RENEWAL
+ status->base_matk_min = status_base_matk_min;
+#endif // RENEWAL
+ status->base_matk_max = status_base_matk_max;
}
diff --git a/src/map/status.h b/src/map/status.h
index 2b932b149..dbb507bd1 100644
--- a/src/map/status.h
+++ b/src/map/status.h
@@ -64,7 +64,9 @@ enum refine_type {
REFINE_TYPE_WEAPON2 = 2,
REFINE_TYPE_WEAPON3 = 3,
REFINE_TYPE_WEAPON4 = 4,
+#ifndef REFINE_TYPE_MAX
REFINE_TYPE_MAX = 5
+#endif
};
/**
@@ -825,8 +827,9 @@ typedef enum sc_type {
SC_M_LIFEPOTION,
SC_G_LIFEPOTION, // 640
SC_MYSTICPOWDER,
-
+#ifndef SC_MAX
SC_MAX, //Automatically updated max, used in for's to check we are within bounds.
+#endif
} sc_type;
/// Official status change ids, used to display status icons in the client.
@@ -1792,8 +1795,9 @@ enum si_type {
//SI_EP16_2_BUFF_SS = 963,
//SI_EP16_2_BUFF_SC = 964,
//SI_EP16_2_BUFF_AC = 965,
-
+#ifndef SI_MAX
SI_MAX,
+#endif
};
// JOINTBEAT stackable ailments
@@ -2313,6 +2317,10 @@ struct status_interface {
bool (*readdb_scconfig) (char *fields[], int columns, int current);
void (*read_job_db) (void);
void (*read_job_db_sub) (int idx, const char *name, struct config_setting_t *jdb);
+ void (*set_sc) (uint16 skill_id, sc_type sc, int icon, unsigned int flag);
+ void (*copy) (struct status_data *a, const struct status_data *b);
+ unsigned short (*base_matk_min) (const struct status_data *st);
+ unsigned short (*base_matk_max) (const struct status_data *st);
};
#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 d9001f6f5..3ae1017f8 100644
--- a/src/map/vending.c
+++ b/src/map/vending.c
@@ -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);
}
}
@@ -276,7 +276,7 @@ void vending_openvending(struct map_session_data* sd, const char* message, const
|| pc->cartitem_amount(sd, index, amount) < 0 // invalid item or insufficient quantity
//NOTE: official server does not do any of the following checks!
|| !sd->status.cart[index].identify // unidentified item
- || sd->status.cart[index].attribute == 1 // broken item
+ || (sd->status.cart[index].attribute & ATTR_BROKEN) != 0 // broken item
|| sd->status.cart[index].expire_time // It should not be in the cart but just in case
|| (sd->status.cart[index].bound && !pc_can_give_bound_items(sd)) // can't trade bound items w/o permission
|| !itemdb_cantrade(&sd->status.cart[index], pc_get_group_level(sd), pc_get_group_level(sd)) ) // untradeable item