From 33a99b59931346097c684c305c58a4eae97088e7 Mon Sep 17 00:00:00 2001 From: Aleos Date: Thu, 19 May 2022 12:24:34 -0400 Subject: [PATCH] Fixes reflected damage from overflowing (#6717) * Fixes #6693. * Reflected damage should never be negative. * Reflect Damage no longer has a 'reflect counter'. * Reflect Damage is removed on log out. * Reflect Damage Reduction should only reduce in normal cases (outside of WoE/BG). * Adjusts the variable names to better match their use. * General cleanups to speed up certain scenarios. Thanks to @kaninhot004 and @Lemongrass3110's review! --- db/re/status.yml | 1 + src/map/battle.cpp | 114 ++++++++++++++++++++++----------------------- src/map/status.cpp | 1 - 3 files changed, 56 insertions(+), 60 deletions(-) diff --git a/db/re/status.yml b/db/re/status.yml index 26dae58dbf..18dacfea8f 100644 --- a/db/re/status.yml +++ b/db/re/status.yml @@ -3727,6 +3727,7 @@ Body: NoDispell: true NoBanishingBuster: true RequireShield: true + NoSave: true End: Reflectshield: true - Status: Forceofvanguard diff --git a/src/map/battle.cpp b/src/map/battle.cpp index fd8fb68e41..843e1e7c16 100644 --- a/src/map/battle.cpp +++ b/src/map/battle.cpp @@ -8266,100 +8266,96 @@ struct Damage battle_calc_attack(int attack_type,struct block_list *bl,struct bl * Initial refactoring by Baalberith * Refined and optimized by helvetica */ -int64 battle_calc_return_damage(struct block_list* bl, struct block_list *src, int64 *dmg, int flag, uint16 skill_id, bool status_reflect){ - struct map_session_data* sd; +int64 battle_calc_return_damage(struct block_list* tbl, struct block_list *src, int64 *dmg, int flag, uint16 skill_id, bool status_reflect){ + status_change *tsc = status_get_sc(tbl); + + if (tsc) { // These statuses do not reflect any damage (off the target) + if (tsc->data[SC_WHITEIMPRISON] || tsc->data[SC_DARKCROW] || tsc->data[SC_KYOMU]) + return 0; + } + + status_change *sc = status_get_sc(src); + + if (sc) { + if (sc->data[SC_HELLS_PLANT]) + return 0; + if (sc->data[SC_REF_T_POTION]) + return 1; // Returns 1 damage + } + + map_session_data *tsd = BL_CAST(BL_PC, tbl); int64 rdamage = 0, damage = *dmg; - int max_damage = status_get_max_hp(bl); - struct status_change *sc, *ssc; - - sd = BL_CAST(BL_PC, bl); - sc = status_get_sc(bl); - ssc = status_get_sc(src); - - if (sc) { // These statuses do not reflect any damage (off the target) - if (sc->data[SC_WHITEIMPRISON] || sc->data[SC_DARKCROW] || sc->data[SC_KYOMU]) - return 0; - } - - if (ssc) { - if (ssc->data[SC_HELLS_PLANT]) - return 0; - } if (flag & BF_SHORT) {//Bounces back part of the damage. - if ( (skill_get_inf2(skill_id, INF2_ISTRAP) || !status_reflect) && sd && sd->bonus.short_weapon_damage_return ) { - rdamage += damage * sd->bonus.short_weapon_damage_return / 100; + if ( (skill_get_inf2(skill_id, INF2_ISTRAP) || !status_reflect) && tsd && tsd->bonus.short_weapon_damage_return ) { + rdamage += damage * tsd->bonus.short_weapon_damage_return / 100; rdamage = i64max(rdamage, 1); - } else if( status_reflect && sc && sc->count ) { - if( sc->data[SC_REFLECTSHIELD] ) { - struct status_change_entry *sce_d; - struct block_list *d_bl = NULL; + } else if( status_reflect && tsc && tsc->count ) { + if( tsc->data[SC_REFLECTSHIELD] ) { + status_change_entry *sce_d; + block_list *d_bl; - if( (sce_d = sc->data[SC_DEVOTION]) && (d_bl = map_id2bl(sce_d->val1)) && - ((d_bl->type == BL_MER && ((TBL_MER*)d_bl)->master && ((TBL_MER*)d_bl)->master->bl.id == bl->id) || - (d_bl->type == BL_PC && ((TBL_PC*)d_bl)->devotion[sce_d->val2] == bl->id)) ) + if( (sce_d = tsc->data[SC_DEVOTION]) && (d_bl = map_id2bl(sce_d->val1)) && + ((d_bl->type == BL_MER && ((TBL_MER*)d_bl)->master && ((TBL_MER*)d_bl)->master->bl.id == tbl->id) || + (d_bl->type == BL_PC && ((TBL_PC*)d_bl)->devotion[sce_d->val2] == tbl->id)) ) { //Don't reflect non-skill attack if has SC_REFLECTSHIELD from Devotion bonus inheritance - if( (!skill_id && battle_config.devotion_rdamage_skill_only && sc->data[SC_REFLECTSHIELD]->val4) || - !check_distance_bl(bl,d_bl,sce_d->val3) ) + if( (!skill_id && battle_config.devotion_rdamage_skill_only && tsc->data[SC_REFLECTSHIELD]->val4) || + !check_distance_bl(tbl,d_bl,sce_d->val3) ) return 0; } } - if ( sc->data[SC_REFLECTSHIELD] && skill_id != WS_CARTTERMINATION ) { + if ( tsc->data[SC_REFLECTSHIELD] && skill_id != WS_CARTTERMINATION ) { // Don't reflect non-skill attack if has SC_REFLECTSHIELD from Devotion bonus inheritance - if (!skill_id && battle_config.devotion_rdamage_skill_only && sc->data[SC_REFLECTSHIELD]->val4) + if (!skill_id && battle_config.devotion_rdamage_skill_only && tsc->data[SC_REFLECTSHIELD]->val4) rdamage = 0; else { - rdamage += damage * sc->data[SC_REFLECTSHIELD]->val2 / 100; + rdamage += damage * tsc->data[SC_REFLECTSHIELD]->val2 / 100; rdamage = i64max(rdamage, 1); } } - if (sc->data[SC_DEATHBOUND] && skill_id != WS_CARTTERMINATION && skill_id != GN_HELLS_PLANT_ATK && !status_bl_has_mode(src,MD_STATUSIMMUNE)) { - if (distance_bl(src,bl) <= 0 || !map_check_dir(map_calc_dir(bl,src->x,src->y), unit_getdir(bl))) { - int64 rd1 = i64min(damage, status_get_max_hp(bl)) * sc->data[SC_DEATHBOUND]->val2 / 100; // Amplify damage. + if (tsc->data[SC_DEATHBOUND] && skill_id != WS_CARTTERMINATION && skill_id != GN_HELLS_PLANT_ATK && !status_bl_has_mode(src,MD_STATUSIMMUNE)) { + if (distance_bl(src,tbl) <= 0 || !map_check_dir(map_calc_dir(tbl,src->x,src->y), unit_getdir(tbl))) { + int64 rd1 = i64min(damage, status_get_max_hp(tbl)) * tsc->data[SC_DEATHBOUND]->val2 / 100; // Amplify damage. *dmg = rd1 * 30 / 100; // Received damage = 30% of amplified damage. - clif_skill_damage(src, bl, gettick(), status_get_amotion(src), 0, -30000, 1, RK_DEATHBOUND, sc->data[SC_DEATHBOUND]->val1, DMG_SINGLE); - skill_blown(bl, src, skill_get_blewcount(RK_DEATHBOUND, 1), unit_getdir(src), BLOWN_NONE); - status_change_end(bl, SC_DEATHBOUND, INVALID_TIMER); + clif_skill_damage(src, tbl, gettick(), status_get_amotion(src), 0, -30000, 1, RK_DEATHBOUND, tsc->data[SC_DEATHBOUND]->val1, DMG_SINGLE); + skill_blown(tbl, src, skill_get_blewcount(RK_DEATHBOUND, tsc->data[SC_DEATHBOUND]->val1), unit_getdir(src), BLOWN_NONE); + status_change_end(tbl, SC_DEATHBOUND, INVALID_TIMER); rdamage += rd1 * 70 / 100; // Target receives 70% of the amplified damage. [Rytech] } } } } else { - if (!status_reflect && sd && sd->bonus.long_weapon_damage_return) { - rdamage += damage * sd->bonus.long_weapon_damage_return / 100; + if (!status_reflect && tsd && tsd->bonus.long_weapon_damage_return) { + rdamage += damage * tsd->bonus.long_weapon_damage_return / 100; rdamage = i64max(rdamage, 1); } } if (rdamage > 0) { - map_session_data* ssd = BL_CAST(BL_PC, src); - if (ssd && ssd->bonus.reduce_damage_return != 0) { - rdamage -= rdamage * ssd->bonus.reduce_damage_return / 100; + map_session_data* sd = BL_CAST(BL_PC, src); + if (sd && sd->bonus.reduce_damage_return != 0) { + rdamage -= rdamage * sd->bonus.reduce_damage_return / 100; rdamage = i64max(rdamage, 1); } } - if (ssc) { - if (ssc->data[SC_REFLECTDAMAGE]) { - rdamage -= damage * ssc->data[SC_REFLECTDAMAGE]->val2 / 100; - if (--(ssc->data[SC_REFLECTDAMAGE]->val3) < 1) // TODO: Confirm if reflect count still exists - status_change_end(bl, SC_REFLECTDAMAGE, INVALID_TIMER); - } - if (ssc->data[SC_VENOMBLEED] && ssc->data[SC_VENOMBLEED]->val3 == 0) - rdamage -= damage * ssc->data[SC_VENOMBLEED]->val2 / 100; - - if (rdamage > 0 && ssc->data[SC_REF_T_POTION]) - return 1; // Returns 1 damage - } - if (sc) { - if (sc->data[SC_MAXPAIN]) - rdamage = damage * sc->data[SC_MAXPAIN]->val1 * 10 / 100; + if (status_reflect && sc->data[SC_REFLECTDAMAGE]) + rdamage -= damage * sc->data[SC_REFLECTDAMAGE]->val2 / 100; + if (sc->data[SC_VENOMBLEED] && sc->data[SC_VENOMBLEED]->val3 == 0) + rdamage -= damage * sc->data[SC_VENOMBLEED]->val2 / 100; + + rdamage = i64max(rdamage, 1); } - return cap_value(i64min(rdamage,max_damage),INT_MIN,INT_MAX); + if (tsc) { + if (tsc->data[SC_MAXPAIN]) + rdamage = damage * tsc->data[SC_MAXPAIN]->val1 * 10 / 100; + } + + return cap_value(rdamage, 1, status_get_max_hp(tbl)); } /** diff --git a/src/map/status.cpp b/src/map/status.cpp index 73aa606158..d8410246f5 100644 --- a/src/map/status.cpp +++ b/src/map/status.cpp @@ -11079,7 +11079,6 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty break; case SC_REFLECTDAMAGE: val2 = 10 * val1; // Reflect reduction amount - val3 = val1*5 + 25; // Number of reflects val4 = tick/1000; // Number of SP cycles (duration) tick_time = 1000; // [GodLesZ] tick time break;