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!
This commit is contained in:
@@ -3727,6 +3727,7 @@ Body:
|
||||
NoDispell: true
|
||||
NoBanishingBuster: true
|
||||
RequireShield: true
|
||||
NoSave: true
|
||||
End:
|
||||
Reflectshield: true
|
||||
- Status: Forceofvanguard
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user