Selaa lähdekoodia

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!
Aleos 3 vuotta sitten
vanhempi
commit
33a99b5993
3 muutettua tiedostoa jossa 50 lisäystä ja 54 poistoa
  1. 1 0
      db/re/status.yml
  2. 49 53
      src/map/battle.cpp
  3. 0 1
      src/map/status.cpp

+ 1 - 0
db/re/status.yml

@@ -3727,6 +3727,7 @@ Body:
       NoDispell: true
       NoBanishingBuster: true
       RequireShield: true
+      NoSave: true
     End:
       Reflectshield: true
   - Status: Forceofvanguard

+ 49 - 53
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 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);
+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 (sc) { // These statuses do not reflect any damage (off the target)
-		if (sc->data[SC_WHITEIMPRISON] || sc->data[SC_DARKCROW] || sc->data[SC_KYOMU])
+	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;
 	}
 
-	if (ssc) {
-		if (ssc->data[SC_HELLS_PLANT])
+	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;
+
 	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;
-
-				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)) )
+		} else if( status_reflect && tsc && tsc->count ) {
+			if( tsc->data[SC_REFLECTSHIELD] ) {
+				status_change_entry *sce_d;
+				block_list *d_bl;
+
+				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 (sc) {
+		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;
 
-		if (rdamage > 0 && ssc->data[SC_REF_T_POTION])
-			return 1; // Returns 1 damage
+		rdamage = i64max(rdamage, 1);
 	}
 
-	if (sc) {
-		if (sc->data[SC_MAXPAIN])
-			rdamage = damage * sc->data[SC_MAXPAIN]->val1 * 10 / 100;
+	if (tsc) {
+		if (tsc->data[SC_MAXPAIN])
+			rdamage = damage * tsc->data[SC_MAXPAIN]->val1 * 10 / 100;
 	}
 
-	return cap_value(i64min(rdamage,max_damage),INT_MIN,INT_MAX);
+	return cap_value(rdamage, 1, status_get_max_hp(tbl));
 }
 
 /**

+ 0 - 1
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;