summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHaru <haru@dotalux.com>2017-07-27 10:39:40 +0200
committerGitHub <noreply@github.com>2017-07-27 10:39:40 +0200
commitb04ce31b952c75d5206fbfec68f2a2712da833c3 (patch)
tree9031210c2158e437dec26b26f1135934fe692dbf
parent45d2d465591d89d927aadf398cdb6166afe9cd9a (diff)
parent08121dbcef6b6a70e39ba6c5391d605d1f3e3944 (diff)
downloadhercules-b04ce31b952c75d5206fbfec68f2a2712da833c3.tar.gz
hercules-b04ce31b952c75d5206fbfec68f2a2712da833c3.tar.bz2
hercules-b04ce31b952c75d5206fbfec68f2a2712da833c3.tar.xz
hercules-b04ce31b952c75d5206fbfec68f2a2712da833c3.zip
Merge pull request #1811 from 4144/refactor
Refactor status_change_start and fix some issues in other code
-rw-r--r--configure.ac2
-rw-r--r--src/char/int_mail.c2
-rw-r--r--src/map/clif.c2
-rw-r--r--src/map/homunculus.c2
-rw-r--r--src/map/itemdb.c4
-rw-r--r--src/map/map.c4
-rw-r--r--src/map/mob.c8
-rw-r--r--src/map/npc.c4
-rw-r--r--src/map/quest.c2
-rw-r--r--src/map/script.c2
-rw-r--r--src/map/status.c1399
-rw-r--r--src/map/status.h8
12 files changed, 792 insertions, 647 deletions
diff --git a/configure.ac b/configure.ac
index 6fef4ee4e..7539b0890 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1313,6 +1313,8 @@ case $enable_renewal in
;;
esac
+AC_CHECK_FLAG(-fno-var-tracking)
+
#
# Host specific stuff
#
diff --git a/src/char/int_mail.c b/src/char/int_mail.c
index 1d00b0fdf..7f054eda1 100644
--- a/src/char/int_mail.c
+++ b/src/char/int_mail.c
@@ -426,7 +426,7 @@ void mapif_parse_mail_return(int fd)
safestrncpy(msg.dest_name, temp_, NAME_LENGTH);
// set reply message title
- snprintf(temp_, MAIL_TITLE_LENGTH, "RE:%s", msg.title);
+ safesnprintf(temp_, MAIL_TITLE_LENGTH, "RE:%s", msg.title);
safestrncpy(msg.title, temp_, MAIL_TITLE_LENGTH);
msg.status = MAIL_NEW;
diff --git a/src/map/clif.c b/src/map/clif.c
index 905b6a3ce..bb4d53a99 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -17726,7 +17726,7 @@ void clif_cashshop_db(void) {
if( cashshop != NULL && (cats = libconfig->setting_get_elem(cashshop, 0)) != NULL ) {
for(i = 0; i < CASHSHOP_TAB_MAX; i++) {
struct config_setting_t *cat;
- char entry_name[10];
+ char entry_name[15];
sprintf(entry_name,"cat_%d",i);
diff --git a/src/map/homunculus.c b/src/map/homunculus.c
index 91a455416..ddaf3443a 100644
--- a/src/map/homunculus.c
+++ b/src/map/homunculus.c
@@ -1215,7 +1215,7 @@ void homunculus_read_db(void) {
if( i > 0 ) {
char filepath[256];
- snprintf(filepath, 256, "%s/%s", map->db_path, filename[i]);
+ safesnprintf(filepath, 256, "%s/%s", map->db_path, filename[i]);
if( !exists(filepath) ) {
continue;
diff --git a/src/map/itemdb.c b/src/map/itemdb.c
index 9a43bae14..2b0847e1a 100644
--- a/src/map/itemdb.c
+++ b/src/map/itemdb.c
@@ -1527,7 +1527,7 @@ void itemdb_read_combos(void)
char filepath[256];
FILE* fp;
- snprintf(filepath, 256, "%s/%s", map->db_path, DBPATH"item_combo_db.txt");
+ safesnprintf(filepath, 256, "%s/%s", map->db_path, DBPATH"item_combo_db.txt");
if ((fp = fopen(filepath, "r")) == NULL) {
ShowError("itemdb_read_combos: File not found \"%s\".\n", filepath);
@@ -2231,7 +2231,7 @@ int itemdb_readdb_libconfig(const char *filename) {
nullpo_ret(filename);
- sprintf(filepath, "%s/%s", map->db_path, filename);
+ safesnprintf(filepath, sizeof(filepath), "%s/%s", map->db_path, filename);
if (!libconfig->load_file(&item_db_conf, filepath))
return 0;
diff --git a/src/map/map.c b/src/map/map.c
index 16d5e645d..17156f631 100644
--- a/src/map/map.c
+++ b/src/map/map.c
@@ -3741,7 +3741,7 @@ int map_readallmaps (void) {
ShowStatus("Loading maps (using GRF files)...\n");
else {
char mapcachefilepath[256];
- snprintf(mapcachefilepath, 256, "%s/%s%s", map->db_path, DBPATH, "map_cache.dat");
+ safesnprintf(mapcachefilepath, 256, "%s/%s%s", map->db_path, DBPATH, "map_cache.dat");
ShowStatus("Loading maps (using %s as map cache)...\n", mapcachefilepath);
if( (fp = fopen(mapcachefilepath, "rb")) == NULL ) {
ShowFatalError("Unable to open map cache file "CL_WHITE"%s"CL_RESET"\n", mapcachefilepath);
@@ -4396,7 +4396,7 @@ struct map_zone_data *map_merge_zone(struct map_zone_data *main, struct map_zone
nullpo_retr(NULL, main);
nullpo_retr(NULL, other);
- snprintf(newzone, MAP_ZONE_NAME_LENGTH, "%s+%s", main->name, other->name);
+ safesnprintf(newzone, MAP_ZONE_NAME_LENGTH, "%s+%s", main->name, other->name);
if( (zone = strdb_get(map->zone_db, newzone)) )
return zone;/* this zone has already been merged */
diff --git a/src/map/mob.c b/src/map/mob.c
index 52705cf4d..98f8865a9 100644
--- a/src/map/mob.c
+++ b/src/map/mob.c
@@ -3350,7 +3350,7 @@ int mobskill_use(struct mob_data *md, int64 tick, int event) {
char name[NAME_LENGTH];
snprintf(name, sizeof name,"%s", md->name);
strtok(name, "#"); // discard extra name identifier if present [Daegaladh]
- snprintf(temp, sizeof temp,"%s : %s", name, mc->msg);
+ safesnprintf(temp, sizeof temp,"%s : %s", name, mc->msg);
clif->messagecolor(&md->bl, mc->color, temp);
}
if(!(battle_config.mob_ai&0x200)) { //pass on delay to same skill.
@@ -4494,7 +4494,7 @@ int mob_read_libconfig(const char *filename, bool ignore_missing)
int i = 0, count = 0;
nullpo_ret(filename);
- sprintf(filepath, "%s/%s", map->db_path, filename);
+ safesnprintf(filepath, sizeof(filepath), "%s/%s", map->db_path, filename);
if (ignore_missing && !exists(filepath))
return 0;
@@ -4720,7 +4720,7 @@ void mob_readchatdb(void) {
char line[1024], filepath[256];
int i, tmp=0;
FILE *fp;
- sprintf(filepath, "%s/%s", map->db_path, arc);
+ safesnprintf(filepath, sizeof(filepath), "%s/%s", map->db_path, arc);
fp=fopen(filepath, "r");
if(fp == NULL) {
ShowWarning("mob_readchatdb: File not found \"%s\", skipping.\n", filepath);
@@ -5046,7 +5046,7 @@ void mob_readskilldb(void) {
for( fi = 0; fi < ARRAYLENGTH(filename); ++fi ) {
if(fi > 0) {
char filepath[256];
- snprintf(filepath, 256, "%s/%s", map->db_path, filename[fi]);
+ safesnprintf(filepath, 256, "%s/%s", map->db_path, filename[fi]);
if(!exists(filepath)) {
continue;
}
diff --git a/src/map/npc.c b/src/map/npc.c
index a358fd2fb..38996a0a3 100644
--- a/src/map/npc.c
+++ b/src/map/npc.c
@@ -2724,10 +2724,10 @@ struct npc_data* npc_add_warp(char* name, short from_mapid, short from_x, short
flag = 1;
if (flag == 1)
- snprintf(nd->exname, ARRAYLENGTH(nd->exname), "warp_%d_%d_%d", from_mapid, from_x, from_y);
+ safesnprintf(nd->exname, ARRAYLENGTH(nd->exname), "warp_%d_%d_%d", from_mapid, from_x, from_y);
for( i = 0; npc->name2id(nd->exname) != NULL; ++i )
- snprintf(nd->exname, ARRAYLENGTH(nd->exname), "warp%d_%d_%d_%d", i, from_mapid, from_x, from_y);
+ safesnprintf(nd->exname, ARRAYLENGTH(nd->exname), "warp%d_%d_%d_%d", i, from_mapid, from_x, from_y);
safestrncpy(nd->name, nd->exname, ARRAYLENGTH(nd->name));
nd->u.warp.mapindex = to_mapindex;
diff --git a/src/map/quest.c b/src/map/quest.c
index 4e3362adb..4c5dcb59f 100644
--- a/src/map/quest.c
+++ b/src/map/quest.c
@@ -544,7 +544,7 @@ int quest_read_db(void)
int i = 0, count = 0;
const char *filename = "quest_db.conf";
- snprintf(filepath, 256, "%s/%s", map->db_path, filename);
+ safesnprintf(filepath, 256, "%s/%s", map->db_path, filename);
if (!libconfig->load_file(&quest_db_conf, filepath))
return -1;
diff --git a/src/map/script.c b/src/map/script.c
index c23a335c3..31af59891 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -2296,7 +2296,7 @@ void read_constdb(void)
struct config_setting_t *t;
int i = 0;
- snprintf(filepath, 256, "%s/constants.conf", map->db_path);
+ safesnprintf(filepath, 256, "%s/constants.conf", map->db_path);
if (!libconfig->load_file(&constants_conf, filepath))
return;
diff --git a/src/map/status.c b/src/map/status.c
index 7982b15eb..166b33e6f 100644
--- a/src/map/status.c
+++ b/src/map/status.c
@@ -7416,6 +7416,7 @@ void status_display_remove(struct map_session_data *sd, enum sc_type type)
}
}
}
+
/**
* Starts a status change.
*
@@ -7467,73 +7468,8 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
#endif // 0
}
- if( sc->data[SC_REFRESH] ) {
- if( type >= SC_COMMON_MIN && type <= SC_COMMON_MAX) // Confirmed.
- return 0; // Immune to status ailements
- switch( type ) {
- case SC_DEEP_SLEEP:
- case SC__CHAOS:
- case SC_BURNING:
- case SC_STUN:
- case SC_SLEEP:
- case SC_CURSE:
- case SC_STONE:
- case SC_POISON:
- case SC_BLIND:
- case SC_SILENCE:
- case SC_BLOODING:
- case SC_FREEZE:
- case SC_FROSTMISTY:
- case SC_COLD:
- case SC_TOXIN:
- case SC_PARALYSE:
- case SC_VENOMBLEED:
- case SC_MAGICMUSHROOM:
- case SC_DEATHHURT:
- case SC_PYREXIA:
- case SC_OBLIVIONCURSE:
- case SC_MARSHOFABYSS:
- case SC_MANDRAGORA:
- return 0;
- }
- } else if( sc->data[SC_INSPIRATION] ) {
- if( type >= SC_COMMON_MIN && type <= SC_COMMON_MAX )
- return 0; // Immune to status ailements
- switch( type ) {
- case SC_POISON:
- case SC_BLIND:
- case SC_STUN:
- case SC_SILENCE:
- case SC__CHAOS:
- case SC_STONE:
- case SC_SLEEP:
- case SC_BLOODING:
- case SC_CURSE:
- case SC_BURNING:
- case SC_FROSTMISTY:
- case SC_FREEZE:
- case SC_COLD:
- case SC_FEAR:
- case SC_TOXIN:
- case SC_PARALYSE:
- case SC_VENOMBLEED:
- case SC_MAGICMUSHROOM:
- case SC_DEATHHURT:
- case SC_PYREXIA:
- case SC_OBLIVIONCURSE:
- case SC_LEECHESEND:
- case SC_DEEP_SLEEP:
- case SC_SATURDAY_NIGHT_FEVER:
- case SC__BODYPAINT:
- case SC__ENERVATION:
- case SC__GROOMY:
- case SC__IGNORANCE:
- case SC__LAZINESS:
- case SC__UNLUCKY:
- case SC__WEAKNESS:
- return 0;
- }
- }
+ if (status->is_immune_to_status(sc, type))
+ return 0;
sd = BL_CAST(BL_PC, bl);
@@ -7543,8 +7479,8 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
if( !tick ) return 0;
}
- undead_flag = battle->check_undead(st->race,st->def_ele);
- //Check for inmunities / sc fails
+ undead_flag = battle->check_undead(st->race, st->def_ele);
+ // Check for inmunities / sc fails
switch (type) {
case SC_DRUMBATTLE:
case SC_NIBELUNGEN:
@@ -7809,316 +7745,14 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
}
//Check for BOSS resistances
- if(st->mode&MD_BOSS && !(flag&SCFLAG_NOAVOID)) {
- if (type>=SC_COMMON_MIN && type <= SC_COMMON_MAX)
+ if (st->mode & MD_BOSS && !(flag & SCFLAG_NOAVOID)) {
+ if (status->is_boss_resist_sc(type))
return 0;
- switch (type) {
- case SC_BLESSING:
- case SC_DEC_AGI:
- case SC_PROVOKE:
- case SC_COMA:
- case SC_GRAVITATION:
- case SC_NJ_SUITON:
- case SC_RICHMANKIM:
- case SC_ROKISWEIL:
- case SC_FOGWALL:
- case SC_FROSTMISTY:
- case SC_BURNING:
- case SC_MARSHOFABYSS:
- case SC_ADORAMUS:
- case SC_NEEDLE_OF_PARALYZE:
- case SC_DEEP_SLEEP:
- case SC_COLD:
-
- // Exploit prevention - kRO Fix
- case SC_PYREXIA:
- case SC_DEATHHURT:
- case SC_TOXIN:
- case SC_PARALYSE:
- case SC_VENOMBLEED:
- case SC_MAGICMUSHROOM:
- case SC_OBLIVIONCURSE:
- case SC_LEECHESEND:
-
- // Ranger Effects
- case SC_WUGBITE:
- case SC_ELECTRICSHOCKER:
- case SC_MAGNETICFIELD:
-
- // Masquerades
- case SC__ENERVATION:
- case SC__GROOMY:
- case SC__LAZINESS:
- case SC__UNLUCKY:
- case SC__WEAKNESS:
- case SC__IGNORANCE:
-
- // Other Effects
- case SC_VACUUM_EXTREME:
- case SC_NETHERWORLD:
- case SC_FRESHSHRIMP:
- case SC_SV_ROOTTWIST:
- case SC_BITESCAR:
- return 0;
- }
}
//Before overlapping fail, one must check for status cured.
- switch (type) {
- case SC_BLESSING:
- //TO-DO Blessing and Agi up should do 1 damage against players on Undead Status, even on PvM
- //but cannot be plagiarized (this requires aegis investigation on packets and official behavior) [Brainstorm]
- if ((!undead_flag && st->race!=RC_DEMON) || bl->type == BL_PC) {
- status_change_end(bl, SC_CURSE, INVALID_TIMER);
- if (sc->data[SC_STONE] && sc->opt1 == OPT1_STONE)
- status_change_end(bl, SC_STONE, INVALID_TIMER);
- }
- if(sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_HIGH)
- status_change_end(bl, SC_SOULLINK, INVALID_TIMER);
- break;
- case SC_INC_AGI:
- status_change_end(bl, SC_DEC_AGI, INVALID_TIMER);
- if(sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_HIGH)
- status_change_end(bl, SC_SOULLINK, INVALID_TIMER);
- break;
- case SC_QUAGMIRE:
- status_change_end(bl, SC_CONCENTRATION, INVALID_TIMER);
- status_change_end(bl, SC_TRUESIGHT, INVALID_TIMER);
- status_change_end(bl, SC_WINDWALK, INVALID_TIMER);
- FALLTHROUGH
- //Also blocks the ones below...
- case SC_DEC_AGI:
- case SC_ADORAMUS:
- status_change_end(bl, SC_CARTBOOST, INVALID_TIMER);
- //Also blocks the ones below...
- FALLTHROUGH
- case SC_DONTFORGETME:
- status_change_end(bl, SC_INC_AGI, INVALID_TIMER);
- status_change_end(bl, SC_ADRENALINE, INVALID_TIMER);
- status_change_end(bl, SC_ADRENALINE2, INVALID_TIMER);
- status_change_end(bl, SC_SPEARQUICKEN, INVALID_TIMER);
- status_change_end(bl, SC_TWOHANDQUICKEN, INVALID_TIMER);
- status_change_end(bl, SC_ONEHANDQUICKEN, INVALID_TIMER);
- status_change_end(bl, SC_MER_QUICKEN, INVALID_TIMER);
- status_change_end(bl, SC_ACCELERATION, INVALID_TIMER);
- break;
- case SC_ONEHANDQUICKEN:
- //Removes the Aspd potion effect, as reported by Vicious. [Skotlex]
- status_change_end(bl, SC_ATTHASTE_POTION1, INVALID_TIMER);
- status_change_end(bl, SC_ATTHASTE_POTION2, INVALID_TIMER);
- status_change_end(bl, SC_ATTHASTE_POTION3, INVALID_TIMER);
- status_change_end(bl, SC_ATTHASTE_INFINITY, INVALID_TIMER);
- break;
- case SC_OVERTHRUSTMAX:
- //Cancels Normal Overthrust. [Skotlex]
- status_change_end(bl, SC_OVERTHRUST, INVALID_TIMER);
- break;
- case SC_KYRIE:
- //Cancels Assumptio
- status_change_end(bl, SC_ASSUMPTIO, INVALID_TIMER);
- break;
- case SC_MAGNIFICAT:
- //Cancels Offertorium
- status_change_end(bl, SC_OFFERTORIUM, INVALID_TIMER);
- break;
- case SC_OFFERTORIUM:
- //Cancels Magnificat
- status_change_end(bl, SC_MAGNIFICAT, INVALID_TIMER);
- break;
- case SC_DELUGE:
- if (sc->data[SC_FOGWALL] && sc->data[SC_BLIND])
- status_change_end(bl, SC_BLIND, INVALID_TIMER);
- break;
- case SC_SILENCE:
- if (sc->data[SC_GOSPEL] && sc->data[SC_GOSPEL]->val4 == BCT_SELF)
- status_change_end(bl, SC_GOSPEL, INVALID_TIMER);
- break;
- case SC_HIDING:
- status_change_end(bl, SC_RG_CCONFINE_M, INVALID_TIMER);
- status_change_end(bl, SC_RG_CCONFINE_S, INVALID_TIMER);
- break;
- case SC_BERSERK:
- if( val3 == SC__BLOODYLUST )
- break;
- if(battle_config.berserk_cancels_buffs) {
- status_change_end(bl, SC_ONEHANDQUICKEN, INVALID_TIMER);
- status_change_end(bl, SC_TWOHANDQUICKEN, INVALID_TIMER);
- status_change_end(bl, SC_LKCONCENTRATION, INVALID_TIMER);
- status_change_end(bl, SC_PARRYING, INVALID_TIMER);
- status_change_end(bl, SC_AURABLADE, INVALID_TIMER);
- status_change_end(bl, SC_MER_QUICKEN, INVALID_TIMER);
- }
- #ifdef RENEWAL
- else {
- status_change_end(bl, SC_TWOHANDQUICKEN, INVALID_TIMER);
- }
- #endif
- break;
- case SC_ASSUMPTIO:
- status_change_end(bl, SC_KYRIE, INVALID_TIMER);
- status_change_end(bl, SC_KAITE, INVALID_TIMER);
- break;
- case SC_KAITE:
- status_change_end(bl, SC_ASSUMPTIO, INVALID_TIMER);
- break;
- case SC_CARTBOOST:
- if (sc->data[SC_DEC_AGI] || sc->data[SC_ADORAMUS]) {
- //Cancel Decrease Agi, but take no further effect [Skotlex]
- status_change_end(bl, SC_DEC_AGI, INVALID_TIMER);
- status_change_end(bl, SC_ADORAMUS, INVALID_TIMER);
- return 0;
- }
- break;
- case SC_FUSION:
- status_change_end(bl, SC_SOULLINK, INVALID_TIMER);
- break;
- case SC_GS_ADJUSTMENT:
- status_change_end(bl, SC_GS_MADNESSCANCEL, INVALID_TIMER);
- break;
- case SC_GS_MADNESSCANCEL:
- status_change_end(bl, SC_GS_ADJUSTMENT, INVALID_TIMER);
- break;
- //NPC_CHANGEUNDEAD will debuff Blessing and Agi Up
- case SC_PROPERTYUNDEAD:
- status_change_end(bl, SC_BLESSING, INVALID_TIMER);
- status_change_end(bl, SC_INC_AGI, INVALID_TIMER);
- break;
- case SC_FOOD_STR:
- status_change_end(bl, SC_FOOD_STR, INVALID_TIMER);
- break;
- case SC_FOOD_AGI:
- status_change_end(bl, SC_FOOD_AGI, INVALID_TIMER);
- break;
- case SC_FOOD_VIT:
- status_change_end(bl, SC_FOOD_VIT, INVALID_TIMER);
- break;
- case SC_FOOD_INT:
- status_change_end(bl, SC_FOOD_INT, INVALID_TIMER);
- break;
- case SC_FOOD_DEX:
- status_change_end(bl, SC_FOOD_DEX, INVALID_TIMER);
- break;
- case SC_FOOD_LUK:
- status_change_end(bl, SC_FOOD_LUK, INVALID_TIMER);
- break;
- case SC_FOOD_STR_CASH:
- status_change_end(bl, SC_FOOD_STR, INVALID_TIMER);
- status_change_end(bl, SC_FOOD_STR_CASH, INVALID_TIMER);
- break;
- case SC_FOOD_AGI_CASH:
- status_change_end(bl, SC_FOOD_AGI, INVALID_TIMER);
- status_change_end(bl, SC_FOOD_AGI_CASH, INVALID_TIMER);
- break;
- case SC_FOOD_VIT_CASH:
- status_change_end(bl, SC_FOOD_VIT, INVALID_TIMER);
- status_change_end(bl, SC_FOOD_VIT_CASH, INVALID_TIMER);
- break;
- case SC_FOOD_INT_CASH:
- status_change_end(bl, SC_FOOD_INT, INVALID_TIMER);
- status_change_end(bl, SC_FOOD_INT_CASH, INVALID_TIMER);
- break;
- case SC_FOOD_DEX_CASH:
- status_change_end(bl, SC_FOOD_DEX, INVALID_TIMER);
- status_change_end(bl, SC_FOOD_DEX_CASH, INVALID_TIMER);
- break;
- case SC_FOOD_LUK_CASH:
- status_change_end(bl, SC_FOOD_LUK, INVALID_TIMER);
- status_change_end(bl, SC_FOOD_LUK_CASH, INVALID_TIMER);
- break;
- case SC_GM_BATTLE:
- status_change_end(bl, SC_GM_BATTLE2, INVALID_TIMER);
- break;
- case SC_GM_BATTLE2:
- status_change_end(bl, SC_GM_BATTLE, INVALID_TIMER);
- break;
- case SC_ENDURE:
- if( val4 == 1 )
- status_change_end(bl, SC_LKCONCENTRATION, INVALID_TIMER);
- break;
- case SC_FIGHTINGSPIRIT:
- case SC_OVERED_BOOST:
- status_change_end(bl, type, INVALID_TIMER); // Remove previous one.
- break;
- case SC_MARSHOFABYSS:
- status_change_end(bl, SC_INCAGI, INVALID_TIMER);
- status_change_end(bl, SC_WINDWALK, INVALID_TIMER);
- status_change_end(bl, SC_ATTHASTE_POTION1, INVALID_TIMER);
- status_change_end(bl, SC_ATTHASTE_POTION2, INVALID_TIMER);
- status_change_end(bl, SC_ATTHASTE_POTION3, INVALID_TIMER);
- status_change_end(bl, SC_ATTHASTE_INFINITY, INVALID_TIMER);
- break;
- //Group A Status (doesn't overlap)
- case SC_SWING:
- case SC_SYMPHONY_LOVE:
- case SC_MOONLIT_SERENADE:
- case SC_RUSH_WINDMILL:
- case SC_ECHOSONG:
- case SC_HARMONIZE:
- case SC_FRIGG_SONG:
- if (type != SC_SWING) status_change_end(bl, SC_SWING, INVALID_TIMER);
- if (type != SC_SYMPHONY_LOVE) status_change_end(bl, SC_SYMPHONY_LOVE, INVALID_TIMER);
- if (type != SC_MOONLIT_SERENADE) status_change_end(bl, SC_MOONLIT_SERENADE, INVALID_TIMER);
- if (type != SC_RUSH_WINDMILL) status_change_end(bl, SC_RUSH_WINDMILL, INVALID_TIMER);
- if (type != SC_ECHOSONG) status_change_end(bl, SC_ECHOSONG, INVALID_TIMER);
- if (type != SC_HARMONIZE) status_change_end(bl, SC_HARMONIZE, INVALID_TIMER);
- if (type != SC_FRIGG_SONG) status_change_end(bl, SC_FRIGG_SONG, INVALID_TIMER);
- break;
- //Group B Status
- case SC_SIREN:
- case SC_DEEP_SLEEP:
- case SC_SIRCLEOFNATURE:
- case SC_LERADS_DEW:
- case SC_MELODYOFSINK:
- case SC_BEYOND_OF_WARCRY:
- case SC_UNLIMITED_HUMMING_VOICE:
- case SC_GLOOMYDAY:
- case SC_SONG_OF_MANA:
- case SC_DANCE_WITH_WUG:
- if (type != SC_SIREN) status_change_end(bl, SC_SIREN, INVALID_TIMER);
- if (type != SC_DEEP_SLEEP) status_change_end(bl, SC_DEEP_SLEEP, INVALID_TIMER);
- if (type != SC_SIRCLEOFNATURE) status_change_end(bl, SC_SIRCLEOFNATURE, INVALID_TIMER);
- if (type != SC_LERADS_DEW) status_change_end(bl, SC_LERADS_DEW, INVALID_TIMER);
- if (type != SC_MELODYOFSINK) status_change_end(bl, SC_MELODYOFSINK, INVALID_TIMER);
- if (type != SC_BEYOND_OF_WARCRY) status_change_end(bl, SC_BEYOND_OF_WARCRY, INVALID_TIMER);
- if (type != SC_UNLIMITED_HUMMING_VOICE) status_change_end(bl, SC_UNLIMITED_HUMMING_VOICE, INVALID_TIMER);
- if (type != SC_GLOOMYDAY) status_change_end(bl, SC_GLOOMYDAY, INVALID_TIMER);
- if (type != SC_SONG_OF_MANA) status_change_end(bl, SC_SONG_OF_MANA, INVALID_TIMER);
- if (type != SC_DANCE_WITH_WUG) status_change_end(bl, SC_DANCE_WITH_WUG, INVALID_TIMER);
- break;
- case SC_REFLECTSHIELD:
- status_change_end(bl, SC_LG_REFLECTDAMAGE, INVALID_TIMER);
- break;
- case SC_LG_REFLECTDAMAGE:
- status_change_end(bl, SC_REFLECTSHIELD, INVALID_TIMER);
- break;
- case SC_SHIELDSPELL_DEF:
- case SC_SHIELDSPELL_MDEF:
- case SC_SHIELDSPELL_REF:
- status_change_end(bl, SC_MAGNIFICAT, INVALID_TIMER);
- status_change_end(bl, SC_SHIELDSPELL_DEF, INVALID_TIMER);
- status_change_end(bl, SC_SHIELDSPELL_MDEF, INVALID_TIMER);
- status_change_end(bl, SC_SHIELDSPELL_REF, INVALID_TIMER);
- break;
- case SC_GENTLETOUCH_ENERGYGAIN:
- case SC_GENTLETOUCH_CHANGE:
- case SC_GENTLETOUCH_REVITALIZE:
- if( type != SC_GENTLETOUCH_REVITALIZE )
- status_change_end(bl, SC_GENTLETOUCH_REVITALIZE, INVALID_TIMER);
- if( type != SC_GENTLETOUCH_ENERGYGAIN )
- status_change_end(bl, SC_GENTLETOUCH_ENERGYGAIN, INVALID_TIMER);
- if( type != SC_GENTLETOUCH_CHANGE )
- status_change_end(bl, SC_GENTLETOUCH_CHANGE, INVALID_TIMER);
- break;
- case SC_INVINCIBLE:
- status_change_end(bl, SC_INVINCIBLEOFF, INVALID_TIMER);
- break;
- case SC_INVINCIBLEOFF:
- status_change_end(bl, SC_INVINCIBLE, INVALID_TIMER);
- break;
- case SC_MAGICPOWER:
- status_change_end(bl, type, INVALID_TIMER);
- break;
- }
+ if (status->end_sc_before_start(bl, st, sc, type, undead_flag, val1, val2, val3, val4))
+ return 0;
//Check for overlapping fails
if( (sce = sc->data[type]) ) {
@@ -9866,9 +9500,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
val3 = 25 * val1; // Move speed reduction
break;
default:
- if (calc_flag == SCB_NONE && status->dbs->SkillChangeTable[type] == 0 && status->dbs->IconChangeTable[type] == 0) {
- //Status change with no calc, no icon, and no skill associated...?
- ShowError("UnknownStatusChange [%d]\n", type);
+ if (status->change_start_unknown_sc(src, bl, type, calc_flag, rate, val1, val2, val3, val4, tick, flag)) {
return 0;
}
}
@@ -9895,27 +9527,239 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
}
/* values that must be set regardless of SCFLAG_LOADED e.g. val_flag */
- switch(type) {
+ val_flag = status->get_val_flag(type);
+
+ /* [Ind/Hercules] */
+ status->change_start_display(sd, type, val1, val2, val3, val4);
+
+ //Those that make you stop attacking/walking....
+ status->change_start_stop_action(bl, type);
+
+ // Set option as needed.
+ opt_flag = status->change_start_set_option(bl, sc, type, val1, val2, val3, val4);
+
+ //On Aegis, when turning on a status change, first goes the option packet, then the sc packet.
+ if(opt_flag) {
+ clif->changeoption(bl);
+ if( sd && opt_flag&0x4 ) {
+ if (vd)
+ clif->changelook(bl, LOOK_BASE, vd->class);
+ clif->changelook(bl,LOOK_WEAPON,0);
+ clif->changelook(bl,LOOK_SHIELD,0);
+ if (vd)
+ clif->changelook(bl,LOOK_CLOTHES_COLOR,vd->cloth_color);
+ }
+ }
+ if (calc_flag&SCB_DYE) {
+ //Reset DYE color
+ if (vd && vd->cloth_color) {
+ val4 = vd->cloth_color;
+ clif->changelook(bl,LOOK_CLOTHES_COLOR,0);
+ }
+ calc_flag&=~SCB_DYE;
+ }
+
+#if 0 //Currently No SC's use this
+ if (calc_flag&SCB_BODY) {
+ //Reset Body Style
+ if (vd && vd->body_style) {
+ val4 = vd->body_style;
+ clif->changelook(bl,LOOK_BODY2,0);
+ }
+ calc_flag&=~SCB_BODY;
+ }
+#endif
+
+ if(!(flag&SCFLAG_NOICON) && !(flag&SCFLAG_LOADED && status->dbs->DisplayType[type]))
+ clif->status_change(bl,status->dbs->IconChangeTable[type],1,tick,(val_flag&1)?val1:1,(val_flag&2)?val2:0,(val_flag&4)?val3:0);
+
+ /**
+ * used as temporary storage for scs with interval ticks, so that the actual duration is sent to the client first.
+ **/
+ if( tick_time )
+ tick = tick_time;
+
+ //Don't trust the previous sce assignment, in case the SC ended somewhere between there and here.
+ if((sce=sc->data[type])) {// reuse old sc
+ if( sce->timer != INVALID_TIMER )
+ timer->delete(sce->timer, status->change_timer);
+ } else {// new sc
+ ++(sc->count);
+ sce = sc->data[type] = ers_alloc(status->data_ers, struct status_change_entry);
+ }
+
+ sce->val1 = val1;
+ sce->val2 = val2;
+ sce->val3 = val3;
+ sce->val4 = val4;
+
+ if (tick >= 0) {
+ sce->timer = timer->add(timer->gettick() + tick, status->change_timer, bl->id, type);
+ sce->infinite_duration = false;
+ } else {
+ sce->timer = INVALID_TIMER; //Infinite duration
+ sce->infinite_duration = true;
+ if( sd )
+ chrif->save_scdata_single(sd->status.account_id,sd->status.char_id,type,sce);
+ }
+
+ if (calc_flag)
+ status_calc_bl(bl,calc_flag);
+
+ if(sd && sd->pd)
+ pet->sc_check(sd, type); //Skotlex: Pet Status Effect Healing
+
+ switch (type) {
+ case SC_BERSERK:
+ if (!(sce->val2)) { //don't heal if already set
+ status->heal(bl, st->max_hp, 0, 1); //Do not use percent_heal as this healing must override BERSERK's block.
+ status->set_sp(bl, 0, 0); //Damage all SP
+ }
+ sce->val2 = 5 * st->max_hp / 100;
+ break;
+ case SC_HLIF_CHANGE:
+ status_percent_heal(bl, 100, 100);
+ break;
+ case SC_RUN:
+ {
+ struct unit_data *ud = unit->bl2ud(bl);
+ if( ud )
+ ud->state.running = unit->run(bl, NULL, SC_RUN);
+ }
+ break;
+ case SC_CASH_BOSS_ALARM:
+ if( sd )
+ clif->bossmapinfo(sd->fd, map->id2boss(sce->val1), 0); // First Message
+ break;
+ case SC_MER_HP:
+ status_percent_heal(bl, 100, 0); // Recover Full HP
+ break;
+ case SC_MER_SP:
+ status_percent_heal(bl, 0, 100); // Recover Full SP
+ break;
+ case SC_PROMOTE_HEALTH_RESERCH:
+ status_percent_heal(bl, sce->val4, 0);
+ break;
+ case SC_ENERGY_DRINK_RESERCH:
+ status_percent_heal(bl, 0, sce->val4);
+ break;
+ /**
+ * Ranger
+ **/
+ case SC_WUGDASH:
+ {
+ struct unit_data *ud = unit->bl2ud(bl);
+ if( ud )
+ ud->state.running = unit->run(bl, sd, SC_WUGDASH);
+ }
+ break;
+ case SC_COMBOATTACK:
+ switch (sce->val1) {
+ case TK_STORMKICK:
+ clif->skill_nodamage(bl,bl,TK_READYSTORM,1,1);
+ break;
+ case TK_DOWNKICK:
+ clif->skill_nodamage(bl,bl,TK_READYDOWN,1,1);
+ break;
+ case TK_TURNKICK:
+ clif->skill_nodamage(bl,bl,TK_READYTURN,1,1);
+ break;
+ case TK_COUNTER:
+ clif->skill_nodamage(bl,bl,TK_READYCOUNTER,1,1);
+ break;
+ case MO_COMBOFINISH:
+ case CH_TIGERFIST:
+ case CH_CHAINCRUSH:
+ if (sd)
+ clif->skillinfo(sd,MO_EXTREMITYFIST, INF_SELF_SKILL);
+ break;
+ case TK_JUMPKICK:
+ if (sd)
+ clif->skillinfo(sd,TK_JUMPKICK, INF_SELF_SKILL);
+ break;
+ case MO_TRIPLEATTACK:
+ if (sd && pc->checkskill(sd, SR_DRAGONCOMBO) > 0)
+ clif->skillinfo(sd,SR_DRAGONCOMBO, INF_SELF_SKILL);
+ break;
+ case SR_FALLENEMPIRE:
+ if (sd){
+ clif->skillinfo(sd,SR_GATEOFHELL, INF_SELF_SKILL);
+ clif->skillinfo(sd,SR_TIGERCANNON, INF_SELF_SKILL);
+ }
+ break;
+ }
+ break;
+ case SC_RAISINGDRAGON:
+ sce->val2 = st->max_hp / 100;// Officially tested its 1%hp drain. [Jobbie]
+ break;
+ }
+
+ if( opt_flag&2 && sd && sd->touching_id )
+ npc->touchnext_areanpc(sd,false); // run OnTouch_ on next char in range
+
+ return 1;
+}
+
+bool status_change_start_unknown_sc(struct block_list *src, struct block_list *bl, enum sc_type type, int calc_flag, int rate, int val1, int val2, int val3, int val4, int tick, int flag)
+{
+ Assert_retr(false, type >= SC_NONE && type < SC_MAX);
+ if (calc_flag == SCB_NONE && status->dbs->SkillChangeTable[type] == 0 && status->dbs->IconChangeTable[type] == 0) {
+ //Status change with no calc, no icon, and no skill associated...?
+ ShowError("UnknownStatusChange [%d]\n", type);
+ return true;
+ }
+ return false;
+}
+
+void status_change_start_display(struct map_session_data *sd, enum sc_type type, int val1, int val2, int val3, int val4)
+{
+ Assert_retv(type >= SC_NONE && type < SC_MAX);
+
+ if (sd && status->dbs->DisplayType[type]) {
+ int dval1 = 0, dval2 = 0, dval3 = 0;
+ switch (type) {
+ case SC_ALL_RIDING:
+ dval1 = 1;
+ break;
+ default: /* all others: just copy val1 */
+ dval1 = val1;
+ break;
+ }
+ status->display_add(sd, type, dval1, dval2, dval3);
+ }
+}
+
+/**
+ * Return val_flag based on sc type.
+ *
+ * @param type Status change type.
+ *
+ * @retval val_flag.
+ */
+int status_get_val_flag(enum sc_type type)
+{
+ int val_flag = 0;
+ switch (type) {
case SC_FIGHTINGSPIRIT:
- val_flag |= 1|2;
+ val_flag |= 1 | 2;
break;
case SC_VENOMIMPRESS:
- val_flag |= 1|2;
+ val_flag |= 1 | 2;
break;
case SC_POISONINGWEAPON:
- val_flag |= 1|2|4;
+ val_flag |= 1 | 2 | 4;
break;
case SC_WEAPONBLOCKING:
- val_flag |= 1|2;
+ val_flag |= 1 | 2;
break;
case SC_ROLLINGCUTTER:
val_flag |= 1;
break;
case SC_CLOAKINGEXCEED:
- val_flag |= 1|2|4;
+ val_flag |= 1 | 2 | 4;
break;
case SC_HALLUCINATIONWALK:
- val_flag |= 1|2|4;
+ val_flag |= 1 | 2 | 4;
break;
case SC_SUMMON1:
case SC_SUMMON2:
@@ -9925,34 +9769,34 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
val_flag |= 1;
break;
case SC__SHADOWFORM:
- val_flag |= 1|2|4;
+ val_flag |= 1 | 2 | 4;
break;
case SC__INVISIBILITY:
- val_flag |= 1|2;
+ val_flag |= 1 | 2;
break;
case SC__ENERVATION:
- val_flag |= 1|2;
+ val_flag |= 1 | 2;
break;
case SC__GROOMY:
- val_flag |= 1|2|4;
+ val_flag |= 1 | 2 | 4;
break;
case SC__LAZINESS:
- val_flag |= 1|2|4;
+ val_flag |= 1 | 2 | 4;
break;
case SC__UNLUCKY:
- val_flag |= 1|2|4;
+ val_flag |= 1 | 2 | 4;
break;
case SC__WEAKNESS:
- val_flag |= 1|2;
+ val_flag |= 1 | 2;
break;
case SC_PROPERTYWALK:
- val_flag |= 1|2;
+ val_flag |= 1 | 2;
break;
case SC_FORCEOFVANGUARD:
- val_flag |= 1|2|4;
+ val_flag |= 1 | 2 | 4;
break;
case SC_PRESTIGE:
- val_flag |= 1|2;
+ val_flag |= 1 | 2;
break;
case SC_BANDING:
val_flag |= 1;
@@ -9960,56 +9804,56 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
case SC_SHIELDSPELL_DEF:
case SC_SHIELDSPELL_MDEF:
case SC_SHIELDSPELL_REF:
- val_flag |= 1|2;
+ val_flag |= 1 | 2;
break;
case SC_SPELLFIST:
case SC_CURSEDCIRCLE_ATKER:
- val_flag |= 1|2|4;
+ val_flag |= 1 | 2 | 4;
break;
case SC_CRESCENTELBOW:
- val_flag |= 1|2;
+ val_flag |= 1 | 2;
break;
case SC_LIGHTNINGWALK:
val_flag |= 1;
break;
case SC_PYROTECHNIC_OPTION:
- val_flag |= 1|2|4;
+ val_flag |= 1 | 2 | 4;
break;
case SC_HEATER_OPTION:
- val_flag |= 1|2|4;
+ val_flag |= 1 | 2 | 4;
break;
case SC_AQUAPLAY_OPTION:
- val_flag |= 1|2|4;
+ val_flag |= 1 | 2 | 4;
break;
case SC_COOLER_OPTION:
- val_flag |= 1|2|4;
+ val_flag |= 1 | 2 | 4;
break;
case SC_CHILLY_AIR_OPTION:
- val_flag |= 1|2;
+ val_flag |= 1 | 2;
break;
case SC_GUST_OPTION:
- val_flag |= 1|2;
+ val_flag |= 1 | 2;
break;
case SC_BLAST_OPTION:
- val_flag |= 1|2|4;
+ val_flag |= 1 | 2 | 4;
break;
case SC_WILD_STORM_OPTION:
- val_flag |= 1|2;
+ val_flag |= 1 | 2;
break;
case SC_PETROLOGY_OPTION:
- val_flag |= 1|2|4;
+ val_flag |= 1 | 2 | 4;
break;
case SC_CURSED_SOIL_OPTION:
- val_flag |= 1|2|4;
+ val_flag |= 1 | 2 | 4;
break;
case SC_UPHEAVAL_OPTION:
- val_flag |= 1|2;
+ val_flag |= 1 | 2;
break;
case SC_CIRCLE_OF_FIRE_OPTION:
- val_flag |= 1|2;
+ val_flag |= 1 | 2;
break;
case SC_WATER_BARRIER:
- val_flag |= 1|2|4;
+ val_flag |= 1 | 2 | 4;
break;
case SC_KYOUGAKU:
val_flag |= 1;
@@ -10022,90 +9866,29 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
val_flag |= 1;
break;
}
+ return val_flag;
+}
- /* [Ind/Hercules] */
- if( sd && status->dbs->DisplayType[type] ) {
- int dval1 = 0, dval2 = 0, dval3 = 0;
- switch( type ) {
- case SC_ALL_RIDING:
- dval1 = 1;
- break;
- default: /* all others: just copy val1 */
- dval1 = val1;
- break;
- }
- status->display_add(sd,type,dval1,dval2,dval3);
- }
+/**
+ * Set new status values.
+ *
+ * @param bl Status change target bl.
+ * @param sc Current statuses.
+ * @param type Status change type.
+ * @param val1 Additional value (meaning depends on type).
+ * @param val2 Additional value (meaning depends on type).
+ * @param val3 Additional value (meaning depends on type).
+ * @param val4 Additional value (meaning depends on type).
+ *
+ * @retval option flag.
+ */
+int status_change_start_set_option(struct block_list *bl, struct status_change* sc, enum sc_type type, int val1, int val2, int val3, int val4)
+{
+ int opt_flag = 1;
- //Those that make you stop attacking/walking....
+ nullpo_retr(true, bl);
+ nullpo_retr(true, sc);
switch (type) {
- case SC_VACUUM_EXTREME:
- if(!map_flag_gvg(bl->m))
- unit->stop_walking(bl,1);
- break;
- case SC_FREEZE:
- case SC_STUN:
- case SC_SLEEP:
- case SC_STONE:
- case SC_DEEP_SLEEP:
- if (sd && pc_issit(sd)) //Avoid sprite sync problems.
- pc->setstand(sd);
- FALLTHROUGH
- case SC_TRICKDEAD:
- status_change_end(bl, SC_DANCING, INVALID_TIMER);
- // Cancel cast when get status [LuzZza]
- if (battle_config.sc_castcancel&bl->type)
- unit->skillcastcancel(bl, 0);
- FALLTHROUGH
- case SC_FALLENEMPIRE:
- case SC_WHITEIMPRISON:
- unit->stop_attack(bl);
- FALLTHROUGH
- case SC_STOP:
- case SC_CONFUSION:
- case SC_RG_CCONFINE_M:
- case SC_RG_CCONFINE_S:
- case SC_SPIDERWEB:
- case SC_ELECTRICSHOCKER:
- case SC_WUGBITE:
- case SC_THORNS_TRAP:
- case SC__MANHOLE:
- case SC__CHAOS:
- case SC_COLD:
- case SC_CURSEDCIRCLE_ATKER:
- case SC_CURSEDCIRCLE_TARGET:
- case SC_FEAR:
- case SC_MEIKYOUSISUI:
- case SC_NEEDLE_OF_PARALYZE:
- case SC_DEATHBOUND:
- case SC_NETHERWORLD:
- case SC_SV_ROOTTWIST:
- unit->stop_walking(bl, STOPWALKING_FLAG_FIXPOS);
- break;
- case SC_ANKLESNARE:
- if( battle_config.skill_trap_type || !map_flag_gvg(bl->m) )
- unit->stop_walking(bl, STOPWALKING_FLAG_FIXPOS);
- break;
- case SC_HIDING:
- case SC_CLOAKING:
- case SC_CLOAKINGEXCEED:
- case SC_CHASEWALK:
- case SC_WEIGHTOVER90:
- case SC_CAMOUFLAGE:
- case SC_SIREN:
- case SC_ALL_RIDING:
- case SC_SUHIDE:
- unit->stop_attack(bl);
- break;
- case SC_SILENCE:
- if (battle_config.sc_castcancel&bl->type)
- unit->skillcastcancel(bl, 0);
- break;
- }
-
- // Set option as needed.
- opt_flag = 1;
- switch(type) {
//OPT1
case SC_STONE: sc->opt1 = OPT1_STONEWAIT; break;
case SC_FREEZE: sc->opt1 = OPT1_FREEZE; break;
@@ -10183,7 +9966,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
break;
#endif // 0
case SC_DANCING:
- if ((val1&0xFFFF) == CG_MOONLIT)
+ if ((val1 & 0xFFFF) == CG_MOONLIT)
sc->opt3 |= OPT3_MOONLIT;
opt_flag = 0;
break;
@@ -10280,167 +10063,511 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
default:
opt_flag = 0;
}
+ return opt_flag;
+}
- //On Aegis, when turning on a status change, first goes the option packet, then the sc packet.
- if(opt_flag) {
- clif->changeoption(bl);
- if( sd && opt_flag&0x4 ) {
- if (vd)
- clif->changelook(bl, LOOK_BASE, vd->class);
- clif->changelook(bl,LOOK_WEAPON,0);
- clif->changelook(bl,LOOK_SHIELD,0);
- if (vd)
- clif->changelook(bl,LOOK_CLOTHES_COLOR,vd->cloth_color);
- }
- }
- if (calc_flag&SCB_DYE) {
- //Reset DYE color
- if (vd && vd->cloth_color) {
- val4 = vd->cloth_color;
- clif->changelook(bl,LOOK_CLOTHES_COLOR,0);
- }
- calc_flag&=~SCB_DYE;
- }
-
-#if 0 //Currently No SC's use this
- if (calc_flag&SCB_BODY) {
- //Reset Body Style
- if (vd && vd->body_style) {
- val4 = vd->body_style;
- clif->changelook(bl,LOOK_BODY2,0);
+/**
+ * Stop actions before start new sc.
+ *
+ * @param bl Status change target bl.
+ * @param type Status change type.
+ */
+void status_change_start_stop_action(struct block_list *bl, enum sc_type type)
+{
+ nullpo_retv(bl);
+ switch (type) {
+ case SC_VACUUM_EXTREME:
+ if (!map_flag_gvg(bl->m))
+ unit->stop_walking(bl,1);
+ break;
+ case SC_FREEZE:
+ case SC_STUN:
+ case SC_SLEEP:
+ case SC_STONE:
+ case SC_DEEP_SLEEP: {
+ struct map_session_data *sd = BL_CAST(BL_PC, bl);
+ if (sd && pc_issit(sd)) //Avoid sprite sync problems.
+ pc->setstand(sd);
+ FALLTHROUGH
}
- calc_flag&=~SCB_BODY;
- }
-#endif
-
- if(!(flag&SCFLAG_NOICON) && !(flag&SCFLAG_LOADED && status->dbs->DisplayType[type]))
- clif->status_change(bl,status->dbs->IconChangeTable[type],1,tick,(val_flag&1)?val1:1,(val_flag&2)?val2:0,(val_flag&4)?val3:0);
-
- /**
- * used as temporary storage for scs with interval ticks, so that the actual duration is sent to the client first.
- **/
- if( tick_time )
- tick = tick_time;
-
- //Don't trust the previous sce assignment, in case the SC ended somewhere between there and here.
- if((sce=sc->data[type])) {// reuse old sc
- if( sce->timer != INVALID_TIMER )
- timer->delete(sce->timer, status->change_timer);
- } else {// new sc
- ++(sc->count);
- sce = sc->data[type] = ers_alloc(status->data_ers, struct status_change_entry);
- }
-
- sce->val1 = val1;
- sce->val2 = val2;
- sce->val3 = val3;
- sce->val4 = val4;
-
- if (tick >= 0) {
- sce->timer = timer->add(timer->gettick() + tick, status->change_timer, bl->id, type);
- sce->infinite_duration = false;
- } else {
- sce->timer = INVALID_TIMER; //Infinite duration
- sce->infinite_duration = true;
- if( sd )
- chrif->save_scdata_single(sd->status.account_id,sd->status.char_id,type,sce);
+ case SC_TRICKDEAD:
+ status_change_end(bl, SC_DANCING, INVALID_TIMER);
+ // Cancel cast when get status [LuzZza]
+ if (battle_config.sc_castcancel&bl->type)
+ unit->skillcastcancel(bl, 0);
+ FALLTHROUGH
+ case SC_FALLENEMPIRE:
+ case SC_WHITEIMPRISON:
+ unit->stop_attack(bl);
+ FALLTHROUGH
+ case SC_STOP:
+ case SC_CONFUSION:
+ case SC_RG_CCONFINE_M:
+ case SC_RG_CCONFINE_S:
+ case SC_SPIDERWEB:
+ case SC_ELECTRICSHOCKER:
+ case SC_WUGBITE:
+ case SC_THORNS_TRAP:
+ case SC__MANHOLE:
+ case SC__CHAOS:
+ case SC_COLD:
+ case SC_CURSEDCIRCLE_ATKER:
+ case SC_CURSEDCIRCLE_TARGET:
+ case SC_FEAR:
+ case SC_MEIKYOUSISUI:
+ case SC_NEEDLE_OF_PARALYZE:
+ case SC_DEATHBOUND:
+ case SC_NETHERWORLD:
+ case SC_SV_ROOTTWIST:
+ unit->stop_walking(bl, STOPWALKING_FLAG_FIXPOS);
+ break;
+ case SC_ANKLESNARE:
+ if (battle_config.skill_trap_type || !map_flag_gvg(bl->m))
+ unit->stop_walking(bl, STOPWALKING_FLAG_FIXPOS);
+ break;
+ case SC_HIDING:
+ case SC_CLOAKING:
+ case SC_CLOAKINGEXCEED:
+ case SC_CHASEWALK:
+ case SC_WEIGHTOVER90:
+ case SC_CAMOUFLAGE:
+ case SC_SIREN:
+ case SC_ALL_RIDING:
+ case SC_SUHIDE:
+ unit->stop_attack(bl);
+ break;
+ case SC_SILENCE:
+ if (battle_config.sc_castcancel & bl->type)
+ unit->skillcastcancel(bl, 0);
+ break;
}
+}
- if (calc_flag)
- status_calc_bl(bl,calc_flag);
-
- if(sd && sd->pd)
- pet->sc_check(sd, type); //Skotlex: Pet Status Effect Healing
+/**
+ * End sc before starting other sc.
+ *
+ * @param bl Status change target bl.
+ * @param st Status change data.
+ * @param sc Current statuses.
+ * @param type Status change type.
+ * @param undead_flag is bl undead.
+ * @param val1 Additional value (meaning depends on type).
+ * @param val2 Additional value (meaning depends on type).
+ * @param val3 Additional value (meaning depends on type).
+ * @param val4 Additional value (meaning depends on type).
+ *
+ * @retval 0 if no status change happened.
+ * @retval 1 if the status change was successfully applied.
+ */
+bool status_end_sc_before_start(struct block_list *bl, struct status_data *st, struct status_change* sc, enum sc_type type, int undead_flag, int val1, int val2, int val3, int val4)
+{
+ nullpo_retr(true, bl);
+ nullpo_retr(true, st);
+ nullpo_retr(true, sc);
switch (type) {
- case SC_BERSERK:
- if (!(sce->val2)) { //don't heal if already set
- status->heal(bl, st->max_hp, 0, 1); //Do not use percent_heal as this healing must override BERSERK's block.
- status->set_sp(bl, 0, 0); //Damage all SP
+ case SC_BLESSING:
+ //TO-DO Blessing and Agi up should do 1 damage against players on Undead Status, even on PvM
+ //but cannot be plagiarized (this requires aegis investigation on packets and official behavior) [Brainstorm]
+ if ((!undead_flag && st->race != RC_DEMON) || bl->type == BL_PC) {
+ status_change_end(bl, SC_CURSE, INVALID_TIMER);
+ if (sc->data[SC_STONE] && sc->opt1 == OPT1_STONE)
+ status_change_end(bl, SC_STONE, INVALID_TIMER);
}
- sce->val2 = 5 * st->max_hp / 100;
+ if (sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_HIGH)
+ status_change_end(bl, SC_SOULLINK, INVALID_TIMER);
break;
- case SC_HLIF_CHANGE:
- status_percent_heal(bl, 100, 100);
+ case SC_INC_AGI:
+ status_change_end(bl, SC_DEC_AGI, INVALID_TIMER);
+ if (sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_HIGH)
+ status_change_end(bl, SC_SOULLINK, INVALID_TIMER);
break;
- case SC_RUN:
- {
- struct unit_data *ud = unit->bl2ud(bl);
- if( ud )
- ud->state.running = unit->run(bl, NULL, SC_RUN);
- }
+ case SC_QUAGMIRE:
+ status_change_end(bl, SC_CONCENTRATION, INVALID_TIMER);
+ status_change_end(bl, SC_TRUESIGHT, INVALID_TIMER);
+ status_change_end(bl, SC_WINDWALK, INVALID_TIMER);
+ FALLTHROUGH
+ //Also blocks the ones below...
+ case SC_DEC_AGI:
+ case SC_ADORAMUS:
+ status_change_end(bl, SC_CARTBOOST, INVALID_TIMER);
+ //Also blocks the ones below...
+ FALLTHROUGH
+ case SC_DONTFORGETME:
+ status_change_end(bl, SC_INC_AGI, INVALID_TIMER);
+ status_change_end(bl, SC_ADRENALINE, INVALID_TIMER);
+ status_change_end(bl, SC_ADRENALINE2, INVALID_TIMER);
+ status_change_end(bl, SC_SPEARQUICKEN, INVALID_TIMER);
+ status_change_end(bl, SC_TWOHANDQUICKEN, INVALID_TIMER);
+ status_change_end(bl, SC_ONEHANDQUICKEN, INVALID_TIMER);
+ status_change_end(bl, SC_MER_QUICKEN, INVALID_TIMER);
+ status_change_end(bl, SC_ACCELERATION, INVALID_TIMER);
break;
- case SC_CASH_BOSS_ALARM:
- if( sd )
- clif->bossmapinfo(sd->fd, map->id2boss(sce->val1), 0); // First Message
+ case SC_ONEHANDQUICKEN:
+ //Removes the Aspd potion effect, as reported by Vicious. [Skotlex]
+ status_change_end(bl, SC_ATTHASTE_POTION1, INVALID_TIMER);
+ status_change_end(bl, SC_ATTHASTE_POTION2, INVALID_TIMER);
+ status_change_end(bl, SC_ATTHASTE_POTION3, INVALID_TIMER);
+ status_change_end(bl, SC_ATTHASTE_INFINITY, INVALID_TIMER);
break;
- case SC_MER_HP:
- status_percent_heal(bl, 100, 0); // Recover Full HP
+ case SC_OVERTHRUSTMAX:
+ //Cancels Normal Overthrust. [Skotlex]
+ status_change_end(bl, SC_OVERTHRUST, INVALID_TIMER);
break;
- case SC_MER_SP:
- status_percent_heal(bl, 0, 100); // Recover Full SP
+ case SC_KYRIE:
+ //Cancels Assumptio
+ status_change_end(bl, SC_ASSUMPTIO, INVALID_TIMER);
break;
- case SC_PROMOTE_HEALTH_RESERCH:
- status_percent_heal(bl, sce->val4, 0);
+ case SC_MAGNIFICAT:
+ //Cancels Offertorium
+ status_change_end(bl, SC_OFFERTORIUM, INVALID_TIMER);
break;
- case SC_ENERGY_DRINK_RESERCH:
- status_percent_heal(bl, 0, sce->val4);
+ case SC_OFFERTORIUM:
+ //Cancels Magnificat
+ status_change_end(bl, SC_MAGNIFICAT, INVALID_TIMER);
break;
- /**
- * Ranger
- **/
- case SC_WUGDASH:
- {
- struct unit_data *ud = unit->bl2ud(bl);
- if( ud )
- ud->state.running = unit->run(bl, sd, SC_WUGDASH);
- }
+ case SC_DELUGE:
+ if (sc->data[SC_FOGWALL] && sc->data[SC_BLIND])
+ status_change_end(bl, SC_BLIND, INVALID_TIMER);
break;
- case SC_COMBOATTACK:
- switch (sce->val1) {
- case TK_STORMKICK:
- clif->skill_nodamage(bl,bl,TK_READYSTORM,1,1);
- break;
- case TK_DOWNKICK:
- clif->skill_nodamage(bl,bl,TK_READYDOWN,1,1);
- break;
- case TK_TURNKICK:
- clif->skill_nodamage(bl,bl,TK_READYTURN,1,1);
- break;
- case TK_COUNTER:
- clif->skill_nodamage(bl,bl,TK_READYCOUNTER,1,1);
- break;
- case MO_COMBOFINISH:
- case CH_TIGERFIST:
- case CH_CHAINCRUSH:
- if (sd)
- clif->skillinfo(sd,MO_EXTREMITYFIST, INF_SELF_SKILL);
- break;
- case TK_JUMPKICK:
- if (sd)
- clif->skillinfo(sd,TK_JUMPKICK, INF_SELF_SKILL);
- break;
- case MO_TRIPLEATTACK:
- if (sd && pc->checkskill(sd, SR_DRAGONCOMBO) > 0)
- clif->skillinfo(sd,SR_DRAGONCOMBO, INF_SELF_SKILL);
- break;
- case SR_FALLENEMPIRE:
- if (sd){
- clif->skillinfo(sd,SR_GATEOFHELL, INF_SELF_SKILL);
- clif->skillinfo(sd,SR_TIGERCANNON, INF_SELF_SKILL);
- }
+ case SC_SILENCE:
+ if (sc->data[SC_GOSPEL] && sc->data[SC_GOSPEL]->val4 == BCT_SELF)
+ status_change_end(bl, SC_GOSPEL, INVALID_TIMER);
+ break;
+ case SC_HIDING:
+ status_change_end(bl, SC_RG_CCONFINE_M, INVALID_TIMER);
+ status_change_end(bl, SC_RG_CCONFINE_S, INVALID_TIMER);
+ break;
+ case SC_BERSERK:
+ if (val3 == SC__BLOODYLUST)
break;
+ if (battle_config.berserk_cancels_buffs) {
+ status_change_end(bl, SC_ONEHANDQUICKEN, INVALID_TIMER);
+ status_change_end(bl, SC_TWOHANDQUICKEN, INVALID_TIMER);
+ status_change_end(bl, SC_LKCONCENTRATION, INVALID_TIMER);
+ status_change_end(bl, SC_PARRYING, INVALID_TIMER);
+ status_change_end(bl, SC_AURABLADE, INVALID_TIMER);
+ status_change_end(bl, SC_MER_QUICKEN, INVALID_TIMER);
+ }
+ #ifdef RENEWAL
+ else {
+ status_change_end(bl, SC_TWOHANDQUICKEN, INVALID_TIMER);
}
+ #endif
break;
- case SC_RAISINGDRAGON:
- sce->val2 = st->max_hp / 100;// Officially tested its 1%hp drain. [Jobbie]
+ case SC_ASSUMPTIO:
+ status_change_end(bl, SC_KYRIE, INVALID_TIMER);
+ status_change_end(bl, SC_KAITE, INVALID_TIMER);
+ break;
+ case SC_KAITE:
+ status_change_end(bl, SC_ASSUMPTIO, INVALID_TIMER);
+ break;
+ case SC_CARTBOOST:
+ if (sc->data[SC_DEC_AGI] || sc->data[SC_ADORAMUS]) {
+ //Cancel Decrease Agi, but take no further effect [Skotlex]
+ status_change_end(bl, SC_DEC_AGI, INVALID_TIMER);
+ status_change_end(bl, SC_ADORAMUS, INVALID_TIMER);
+ return true;
+ }
+ break;
+ case SC_FUSION:
+ status_change_end(bl, SC_SOULLINK, INVALID_TIMER);
+ break;
+ case SC_GS_ADJUSTMENT:
+ status_change_end(bl, SC_GS_MADNESSCANCEL, INVALID_TIMER);
+ break;
+ case SC_GS_MADNESSCANCEL:
+ status_change_end(bl, SC_GS_ADJUSTMENT, INVALID_TIMER);
+ break;
+ //NPC_CHANGEUNDEAD will debuff Blessing and Agi Up
+ case SC_PROPERTYUNDEAD:
+ status_change_end(bl, SC_BLESSING, INVALID_TIMER);
+ status_change_end(bl, SC_INC_AGI, INVALID_TIMER);
+ break;
+ case SC_FOOD_STR:
+ status_change_end(bl, SC_FOOD_STR, INVALID_TIMER);
+ break;
+ case SC_FOOD_AGI:
+ status_change_end(bl, SC_FOOD_AGI, INVALID_TIMER);
+ break;
+ case SC_FOOD_VIT:
+ status_change_end(bl, SC_FOOD_VIT, INVALID_TIMER);
+ break;
+ case SC_FOOD_INT:
+ status_change_end(bl, SC_FOOD_INT, INVALID_TIMER);
+ break;
+ case SC_FOOD_DEX:
+ status_change_end(bl, SC_FOOD_DEX, INVALID_TIMER);
+ break;
+ case SC_FOOD_LUK:
+ status_change_end(bl, SC_FOOD_LUK, INVALID_TIMER);
+ break;
+ case SC_FOOD_STR_CASH:
+ status_change_end(bl, SC_FOOD_STR, INVALID_TIMER);
+ status_change_end(bl, SC_FOOD_STR_CASH, INVALID_TIMER);
+ break;
+ case SC_FOOD_AGI_CASH:
+ status_change_end(bl, SC_FOOD_AGI, INVALID_TIMER);
+ status_change_end(bl, SC_FOOD_AGI_CASH, INVALID_TIMER);
+ break;
+ case SC_FOOD_VIT_CASH:
+ status_change_end(bl, SC_FOOD_VIT, INVALID_TIMER);
+ status_change_end(bl, SC_FOOD_VIT_CASH, INVALID_TIMER);
+ break;
+ case SC_FOOD_INT_CASH:
+ status_change_end(bl, SC_FOOD_INT, INVALID_TIMER);
+ status_change_end(bl, SC_FOOD_INT_CASH, INVALID_TIMER);
+ break;
+ case SC_FOOD_DEX_CASH:
+ status_change_end(bl, SC_FOOD_DEX, INVALID_TIMER);
+ status_change_end(bl, SC_FOOD_DEX_CASH, INVALID_TIMER);
+ break;
+ case SC_FOOD_LUK_CASH:
+ status_change_end(bl, SC_FOOD_LUK, INVALID_TIMER);
+ status_change_end(bl, SC_FOOD_LUK_CASH, INVALID_TIMER);
+ break;
+ case SC_GM_BATTLE:
+ status_change_end(bl, SC_GM_BATTLE2, INVALID_TIMER);
+ break;
+ case SC_GM_BATTLE2:
+ status_change_end(bl, SC_GM_BATTLE, INVALID_TIMER);
+ break;
+ case SC_ENDURE:
+ if (val4 == 1)
+ status_change_end(bl, SC_LKCONCENTRATION, INVALID_TIMER);
+ break;
+ case SC_FIGHTINGSPIRIT:
+ case SC_OVERED_BOOST:
+ status_change_end(bl, type, INVALID_TIMER); // Remove previous one.
+ break;
+ case SC_MARSHOFABYSS:
+ status_change_end(bl, SC_INCAGI, INVALID_TIMER);
+ status_change_end(bl, SC_WINDWALK, INVALID_TIMER);
+ status_change_end(bl, SC_ATTHASTE_POTION1, INVALID_TIMER);
+ status_change_end(bl, SC_ATTHASTE_POTION2, INVALID_TIMER);
+ status_change_end(bl, SC_ATTHASTE_POTION3, INVALID_TIMER);
+ status_change_end(bl, SC_ATTHASTE_INFINITY, INVALID_TIMER);
+ break;
+ //Group A Status (doesn't overlap)
+ case SC_SWING:
+ case SC_SYMPHONY_LOVE:
+ case SC_MOONLIT_SERENADE:
+ case SC_RUSH_WINDMILL:
+ case SC_ECHOSONG:
+ case SC_HARMONIZE:
+ case SC_FRIGG_SONG:
+ if (type != SC_SWING) status_change_end(bl, SC_SWING, INVALID_TIMER);
+ if (type != SC_SYMPHONY_LOVE) status_change_end(bl, SC_SYMPHONY_LOVE, INVALID_TIMER);
+ if (type != SC_MOONLIT_SERENADE) status_change_end(bl, SC_MOONLIT_SERENADE, INVALID_TIMER);
+ if (type != SC_RUSH_WINDMILL) status_change_end(bl, SC_RUSH_WINDMILL, INVALID_TIMER);
+ if (type != SC_ECHOSONG) status_change_end(bl, SC_ECHOSONG, INVALID_TIMER);
+ if (type != SC_HARMONIZE) status_change_end(bl, SC_HARMONIZE, INVALID_TIMER);
+ if (type != SC_FRIGG_SONG) status_change_end(bl, SC_FRIGG_SONG, INVALID_TIMER);
+ break;
+ //Group B Status
+ case SC_SIREN:
+ case SC_DEEP_SLEEP:
+ case SC_SIRCLEOFNATURE:
+ case SC_LERADS_DEW:
+ case SC_MELODYOFSINK:
+ case SC_BEYOND_OF_WARCRY:
+ case SC_UNLIMITED_HUMMING_VOICE:
+ case SC_GLOOMYDAY:
+ case SC_SONG_OF_MANA:
+ case SC_DANCE_WITH_WUG:
+ if (type != SC_SIREN) status_change_end(bl, SC_SIREN, INVALID_TIMER);
+ if (type != SC_DEEP_SLEEP) status_change_end(bl, SC_DEEP_SLEEP, INVALID_TIMER);
+ if (type != SC_SIRCLEOFNATURE) status_change_end(bl, SC_SIRCLEOFNATURE, INVALID_TIMER);
+ if (type != SC_LERADS_DEW) status_change_end(bl, SC_LERADS_DEW, INVALID_TIMER);
+ if (type != SC_MELODYOFSINK) status_change_end(bl, SC_MELODYOFSINK, INVALID_TIMER);
+ if (type != SC_BEYOND_OF_WARCRY) status_change_end(bl, SC_BEYOND_OF_WARCRY, INVALID_TIMER);
+ if (type != SC_UNLIMITED_HUMMING_VOICE) status_change_end(bl, SC_UNLIMITED_HUMMING_VOICE, INVALID_TIMER);
+ if (type != SC_GLOOMYDAY) status_change_end(bl, SC_GLOOMYDAY, INVALID_TIMER);
+ if (type != SC_SONG_OF_MANA) status_change_end(bl, SC_SONG_OF_MANA, INVALID_TIMER);
+ if (type != SC_DANCE_WITH_WUG) status_change_end(bl, SC_DANCE_WITH_WUG, INVALID_TIMER);
+ break;
+ case SC_REFLECTSHIELD:
+ status_change_end(bl, SC_LG_REFLECTDAMAGE, INVALID_TIMER);
+ break;
+ case SC_LG_REFLECTDAMAGE:
+ status_change_end(bl, SC_REFLECTSHIELD, INVALID_TIMER);
+ break;
+ case SC_SHIELDSPELL_DEF:
+ case SC_SHIELDSPELL_MDEF:
+ case SC_SHIELDSPELL_REF:
+ status_change_end(bl, SC_MAGNIFICAT, INVALID_TIMER);
+ status_change_end(bl, SC_SHIELDSPELL_DEF, INVALID_TIMER);
+ status_change_end(bl, SC_SHIELDSPELL_MDEF, INVALID_TIMER);
+ status_change_end(bl, SC_SHIELDSPELL_REF, INVALID_TIMER);
+ break;
+ case SC_GENTLETOUCH_ENERGYGAIN:
+ case SC_GENTLETOUCH_CHANGE:
+ case SC_GENTLETOUCH_REVITALIZE:
+ if (type != SC_GENTLETOUCH_REVITALIZE)
+ status_change_end(bl, SC_GENTLETOUCH_REVITALIZE, INVALID_TIMER);
+ if (type != SC_GENTLETOUCH_ENERGYGAIN)
+ status_change_end(bl, SC_GENTLETOUCH_ENERGYGAIN, INVALID_TIMER);
+ if (type != SC_GENTLETOUCH_CHANGE)
+ status_change_end(bl, SC_GENTLETOUCH_CHANGE, INVALID_TIMER);
+ break;
+ case SC_INVINCIBLE:
+ status_change_end(bl, SC_INVINCIBLEOFF, INVALID_TIMER);
+ break;
+ case SC_INVINCIBLEOFF:
+ status_change_end(bl, SC_INVINCIBLE, INVALID_TIMER);
+ break;
+ case SC_MAGICPOWER:
+ status_change_end(bl, type, INVALID_TIMER);
break;
}
- if( opt_flag&2 && sd && sd->touching_id )
- npc->touchnext_areanpc(sd,false); // run OnTouch_ on next char in range
+ return false;
+}
- return 1;
+/**
+ * Check is boss resist to given sc.
+ *
+ * @param type Status change type.
+ *
+ * @retval true if boss resist.
+ * @retval false if boss not resist.
+ */
+bool status_is_boss_resist_sc(enum sc_type type)
+{
+ if (type >= SC_COMMON_MIN && type <= SC_COMMON_MAX)
+ return true;
+ switch (type) {
+ case SC_BLESSING:
+ case SC_DEC_AGI:
+ case SC_PROVOKE:
+ case SC_COMA:
+ case SC_GRAVITATION:
+ case SC_NJ_SUITON:
+ case SC_RICHMANKIM:
+ case SC_ROKISWEIL:
+ case SC_FOGWALL:
+ case SC_FROSTMISTY:
+ case SC_BURNING:
+ case SC_MARSHOFABYSS:
+ case SC_ADORAMUS:
+ case SC_NEEDLE_OF_PARALYZE:
+ case SC_DEEP_SLEEP:
+ case SC_COLD:
+
+ // Exploit prevention - kRO Fix
+ case SC_PYREXIA:
+ case SC_DEATHHURT:
+ case SC_TOXIN:
+ case SC_PARALYSE:
+ case SC_VENOMBLEED:
+ case SC_MAGICMUSHROOM:
+ case SC_OBLIVIONCURSE:
+ case SC_LEECHESEND:
+
+ // Ranger Effects
+ case SC_WUGBITE:
+ case SC_ELECTRICSHOCKER:
+ case SC_MAGNETICFIELD:
+
+ // Masquerades
+ case SC__ENERVATION:
+ case SC__GROOMY:
+ case SC__LAZINESS:
+ case SC__UNLUCKY:
+ case SC__WEAKNESS:
+ case SC__IGNORANCE:
+
+ // Other Effects
+ case SC_VACUUM_EXTREME:
+ case SC_NETHERWORLD:
+ case SC_FRESHSHRIMP:
+ case SC_SV_ROOTTWIST:
+ case SC_BITESCAR:
+ return true;
+ }
+ return false;
+}
+
+/**
+ * Initial check for current statuses immune to given sc.
+ *
+ * @param sc Current statuses.
+ * @param type Status change type.
+ *
+ * @retval true if immune resist.
+ * @retval false if not immune resist.
+ */
+bool status_is_immune_to_status(struct status_change* sc, enum sc_type type)
+{
+ nullpo_retr(true, sc);
+ if (sc->data[SC_REFRESH]) {
+ if (type >= SC_COMMON_MIN && type <= SC_COMMON_MAX) // Confirmed.
+ return true; // Immune to status ailements
+ switch (type) {
+ case SC_DEEP_SLEEP:
+ case SC__CHAOS:
+ case SC_BURNING:
+ case SC_STUN:
+ case SC_SLEEP:
+ case SC_CURSE:
+ case SC_STONE:
+ case SC_POISON:
+ case SC_BLIND:
+ case SC_SILENCE:
+ case SC_BLOODING:
+ case SC_FREEZE:
+ case SC_FROSTMISTY:
+ case SC_COLD:
+ case SC_TOXIN:
+ case SC_PARALYSE:
+ case SC_VENOMBLEED:
+ case SC_MAGICMUSHROOM:
+ case SC_DEATHHURT:
+ case SC_PYREXIA:
+ case SC_OBLIVIONCURSE:
+ case SC_MARSHOFABYSS:
+ case SC_MANDRAGORA:
+ return true;
+ }
+ } else if (sc->data[SC_INSPIRATION]) {
+ if (type >= SC_COMMON_MIN && type <= SC_COMMON_MAX)
+ return true; // Immune to status ailements
+ switch (type) {
+ case SC_POISON:
+ case SC_BLIND:
+ case SC_STUN:
+ case SC_SILENCE:
+ case SC__CHAOS:
+ case SC_STONE:
+ case SC_SLEEP:
+ case SC_BLOODING:
+ case SC_CURSE:
+ case SC_BURNING:
+ case SC_FROSTMISTY:
+ case SC_FREEZE:
+ case SC_COLD:
+ case SC_FEAR:
+ case SC_TOXIN:
+ case SC_PARALYSE:
+ case SC_VENOMBLEED:
+ case SC_MAGICMUSHROOM:
+ case SC_DEATHHURT:
+ case SC_PYREXIA:
+ case SC_OBLIVIONCURSE:
+ case SC_LEECHESEND:
+ case SC_DEEP_SLEEP:
+ case SC_SATURDAY_NIGHT_FEVER:
+ case SC__BODYPAINT:
+ case SC__ENERVATION:
+ case SC__GROOMY:
+ case SC__IGNORANCE:
+ case SC__LAZINESS:
+ case SC__UNLUCKY:
+ case SC__WEAKNESS:
+ return true;
+ }
+ }
+ return false;
}
/*==========================================
@@ -13289,7 +13416,7 @@ int status_readdb_refine_libconfig(const char *filename)
char filepath[256];
int i = 0, count = 0;
- sprintf(filepath, "%s/%s", map->db_path, filename);
+ safesnprintf(filepath, sizeof(filepath), "%s/%s", map->db_path, filename);
if (!libconfig->load_file(&refine_db_conf, filepath))
return 0;
@@ -13477,6 +13604,12 @@ void status_defaults(void)
status->change_clear = status_change_clear;
status->change_clear_buffs = status_change_clear_buffs;
+ status->is_immune_to_status = status_is_immune_to_status;
+ status->is_boss_resist_sc = status_is_boss_resist_sc;
+ status->end_sc_before_start = status_end_sc_before_start;
+ status->change_start_stop_action = status_change_start_stop_action;
+ status->change_start_set_option = status_change_start_set_option;
+ status->get_val_flag = status_get_val_flag;
status->calc_bl_ = status_calc_bl_;
status->calc_mob_ = status_calc_mob_;
status->calc_pet_ = status_calc_pet_;
@@ -13544,6 +13677,8 @@ void status_defaults(void)
status->calc_ematk = status_calc_ematk;
status->calc_bl_main = status_calc_bl_main;
status->display_add = status_display_add;
+ status->change_start_display = status_change_start_display;
+ status->change_start_unknown_sc = status_change_start_unknown_sc;
status->display_remove = status_display_remove;
status->natural_heal = status_natural_heal;
status->natural_heal_timer = status_natural_heal_timer;
diff --git a/src/map/status.h b/src/map/status.h
index de21fa16c..3c0a87175 100644
--- a/src/map/status.h
+++ b/src/map/status.h
@@ -2331,6 +2331,14 @@ struct status_interface {
int (*get_sc_def) (struct block_list *src, struct block_list *bl, enum sc_type type, int rate, int tick, int flag);
int (*change_start) (struct block_list *src, struct block_list *bl, enum sc_type type, int rate, int val1, int val2, int val3, int val4, int tick, int flag);
int (*change_end_) (struct block_list* bl, enum sc_type type, int tid, const char* file, int line);
+ bool (*is_immune_to_status) (struct status_change* sc, enum sc_type type);
+ bool (*is_boss_resist_sc) (enum sc_type type);
+ bool (*end_sc_before_start) (struct block_list *bl, struct status_data *st, struct status_change* sc, enum sc_type type, int undead_flag, int val1, int val2, int val3, int val4);
+ void (*change_start_stop_action) (struct block_list *bl, enum sc_type type);
+ int (*change_start_set_option) (struct block_list *bl, struct status_change* sc, enum sc_type type, int val1, int val2, int val3, int val4);
+ int (*get_val_flag) (enum sc_type type);
+ void (*change_start_display) (struct map_session_data *sd, enum sc_type type, int val1, int val2, int val3, int val4);
+ bool (*change_start_unknown_sc) (struct block_list *src, struct block_list *bl, enum sc_type type, int calc_flag, int rate, int val1, int val2, int val3, int val4, int tick, int flag);
int (*kaahi_heal_timer) (int tid, int64 tick, int id, intptr_t data);
int (*change_timer) (int tid, int64 tick, int id, intptr_t data);
int (*change_timer_sub) (struct block_list* bl, va_list ap);