aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOvahlord <dreadkiller@gmx.de>2025-01-02 04:25:51 +0100
committerOvahlord <dreadkiller@gmx.de>2025-01-02 04:25:51 +0100
commit0e955e90e4e3e3566d4123a709ee0a46332f5e3c (patch)
treebfcb8167c464d982e498f2b0359e15e667f08d42
parent5001b4193e23e9e47dbb116fe66e86e80e160216 (diff)
Core/Units: restored generating rage from taking damage and increased precision for its amount calculation
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp86
-rw-r--r--src/server/game/Entities/Unit/Unit.h12
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.cpp10
3 files changed, 56 insertions, 52 deletions
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index e6b6f882709..1c2c44e5692 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -301,7 +301,7 @@ SpellSchoolMask ProcEventInfo::GetSchoolMask() const
SpellNonMeleeDamage::SpellNonMeleeDamage(Unit* _attacker, Unit* _target, SpellInfo const* _spellInfo, SpellCastVisual spellVisual, uint32 _schoolMask, ObjectGuid _castId)
: target(_target), attacker(_attacker), castId(_castId), Spell(_spellInfo), SpellVisual(spellVisual), damage(0), originalDamage(0),
- schoolMask(_schoolMask), absorb(0), resist(0), periodicLog(false), blocked(0), HitInfo(0), cleanDamage(0), fullBlock(false), preHitHealth(_target->GetHealth())
+ schoolMask(_schoolMask), absorb(0), resist(0), periodicLog(false), blocked(0), HitInfo(0), fullBlock(false), preHitHealth(_target->GetHealth())
{
}
@@ -1073,6 +1073,13 @@ bool Unit::HasBreakableByDamageCrowdControlAura(Unit* excludeCasterChannel) cons
}
}
+ // Rage from damage received
+ if (attacker != victim && victim->GetPowerType() == POWER_RAGE)
+ {
+ uint32 rageBaseReward = CalcDamageTakenRageGain(victim, std::max(damage, cleanDamage->original_damage));
+ victim->RewardRage(rageBaseReward, false);
+ }
+
if (attacker && attacker->GetTypeId() == TYPEID_PLAYER)
{
// random durability for items (HIT DONE)
@@ -1293,10 +1300,40 @@ void Unit::DealSpellDamage(SpellNonMeleeDamage const* damageInfo, bool durabilit
}
// Call default DealDamage
- CleanDamage cleanDamage(damageInfo->cleanDamage, damageInfo->absorb, BASE_ATTACK, MELEE_HIT_NORMAL);
+ CleanDamage cleanDamage(damageInfo->originalDamage, damageInfo->absorb, BASE_ATTACK, MELEE_HIT_NORMAL);
Unit::DealDamage(this, victim, damageInfo->damage, &cleanDamage, SPELL_DIRECT_DAMAGE, SpellSchoolMask(damageInfo->schoolMask), damageInfo->Spell, durabilityLoss);
}
+// Calculates the normalized rage amount per weapon swing
+/*static*/ uint32 Unit::CalcMeleeAttackRageGain(Unit const* attacker, WeaponAttackType attType)
+{
+ if (!attacker || (attType != BASE_ATTACK && attType != OFF_ATTACK))
+ return 0;
+
+ uint32 rage = uint32(attacker->GetBaseAttackTime(attType) / 1000.f * 6.5f);
+ if (attType == OFF_ATTACK)
+ rage /= 2;
+
+ // Players below level 10 start with a 50% rage gain reduction that slowly diminishes
+ if (attacker->IsPlayer() && attacker->GetLevel() < 10)
+ rage -= (rage / 2.f) * (1.0f - (attacker->GetLevel() / 10.f));
+
+ return uint32(rage * 10);
+}
+
+// Calculates the amount of rage gained from taking damage
+/*static*/ uint32 Unit::CalcDamageTakenRageGain(Unit const* victim, uint32 damage)
+{
+ if (!victim || damage == 0)
+ return 0;
+
+ float multiplier = static_cast<float>(damage) / victim->GetMaxHealth();
+
+ // This formula is based on sampling multiple sniff data at multiple level ranges
+ // There has never been any leak and the only info we have is that the amount is based on max HP and damage taken and that there is a hidden constant
+ return uint32(std::round(400 * multiplier));
+}
+
/// @todo for melee need create structure as in
void Unit::CalculateMeleeDamage(Unit* victim, CalcDamageInfo* damageInfo, WeaponAttackType attackType /*= BASE_ATTACK*/)
{
@@ -1317,7 +1354,6 @@ void Unit::CalculateMeleeDamage(Unit* victim, CalcDamageInfo* damageInfo, Weapon
damageInfo->AttackType = attackType;
damageInfo->ProcAttacker = PROC_FLAG_NONE;
damageInfo->ProcVictim = PROC_FLAG_NONE;
- damageInfo->CleanDamage = 0;
damageInfo->HitOutCome = MELEE_HIT_EVADE;
if (!victim)
@@ -1349,7 +1385,6 @@ void Unit::CalculateMeleeDamage(Unit* victim, CalcDamageInfo* damageInfo, Weapon
damageInfo->TargetState = VICTIMSTATE_IS_IMMUNE;
damageInfo->Damage = 0;
- damageInfo->CleanDamage = 0;
return;
}
@@ -1364,10 +1399,7 @@ void Unit::CalculateMeleeDamage(Unit* victim, CalcDamageInfo* damageInfo, Weapon
// Calculate armor reduction
if (Unit::IsDamageReducedByArmor(SpellSchoolMask(damageInfo->DamageSchoolMask)))
- {
damageInfo->Damage = Unit::CalcArmorReducedDamage(damageInfo->Attacker, damageInfo->Target, damage, nullptr, damageInfo->AttackType);
- damageInfo->CleanDamage += damage - damageInfo->Damage;
- }
else
damageInfo->Damage = damage;
@@ -1381,7 +1413,6 @@ void Unit::CalculateMeleeDamage(Unit* victim, CalcDamageInfo* damageInfo, Weapon
damageInfo->OriginalDamage = damageInfo->Damage;
damageInfo->Damage = 0;
- damageInfo->CleanDamage = 0;
return;
case MELEE_HIT_MISS:
damageInfo->HitInfo |= HITINFO_MISS;
@@ -1389,7 +1420,6 @@ void Unit::CalculateMeleeDamage(Unit* victim, CalcDamageInfo* damageInfo, Weapon
damageInfo->OriginalDamage = damageInfo->Damage;
damageInfo->Damage = 0;
- damageInfo->CleanDamage = 0;
break;
case MELEE_HIT_NORMAL:
damageInfo->TargetState = VICTIMSTATE_HIT;
@@ -1408,20 +1438,16 @@ void Unit::CalculateMeleeDamage(Unit* victim, CalcDamageInfo* damageInfo, Weapon
if (mod != 0)
AddPct(damageInfo->Damage, mod);
-
- damageInfo->OriginalDamage = damageInfo->Damage;
break;
}
case MELEE_HIT_PARRY:
damageInfo->TargetState = VICTIMSTATE_PARRY;
- damageInfo->CleanDamage += damageInfo->Damage;
damageInfo->OriginalDamage = damageInfo->Damage;
damageInfo->Damage = 0;
break;
case MELEE_HIT_DODGE:
damageInfo->TargetState = VICTIMSTATE_DODGE;
- damageInfo->CleanDamage += damageInfo->Damage;
damageInfo->OriginalDamage = damageInfo->Damage;
damageInfo->Damage = 0;
@@ -1436,7 +1462,6 @@ void Unit::CalculateMeleeDamage(Unit* victim, CalcDamageInfo* damageInfo, Weapon
damageInfo->OriginalDamage = damageInfo->Damage;
damageInfo->Damage -= damageInfo->Blocked;
- damageInfo->CleanDamage += damageInfo->Blocked;
break;
case MELEE_HIT_GLANCING:
{
@@ -1448,7 +1473,6 @@ void Unit::CalculateMeleeDamage(Unit* victim, CalcDamageInfo* damageInfo, Weapon
damageInfo->OriginalDamage = damageInfo->Damage;
float reducePercent = 1.f - leveldif * 0.1f;
- damageInfo->CleanDamage += damageInfo->Damage - uint32(reducePercent * damageInfo->Damage);
damageInfo->Damage = uint32(reducePercent * damageInfo->Damage);
break;
}
@@ -1472,7 +1496,6 @@ void Unit::CalculateMeleeDamage(Unit* victim, CalcDamageInfo* damageInfo, Weapon
Unit::ApplyResilience(victim, &resilienceReduction);
resilienceReduction = damageInfo->Damage - resilienceReduction;
damageInfo->Damage -= resilienceReduction;
- damageInfo->CleanDamage += resilienceReduction;
damageInfo->OriginalDamage -= resilienceReduction;
// Calculate absorb resist
@@ -1538,7 +1561,7 @@ void Unit::DealMeleeDamage(CalcDamageInfo* damageInfo, bool durabilityLoss)
}
// Call default DealDamage
- CleanDamage cleanDamage(damageInfo->CleanDamage, damageInfo->Absorb, damageInfo->AttackType, damageInfo->HitOutCome);
+ CleanDamage cleanDamage(damageInfo->OriginalDamage, damageInfo->Absorb, damageInfo->AttackType, damageInfo->HitOutCome);
Unit::DealDamage(this, victim, damageInfo->Damage, &cleanDamage, DIRECT_DAMAGE, SpellSchoolMask(damageInfo->DamageSchoolMask), nullptr, durabilityLoss);
// If this is a creature and it attacks from behind it has a probability to daze it's victim
@@ -2169,23 +2192,6 @@ void Unit::DoMeleeAttackIfReady()
}
}
-// Calculates the normalized rage amount per weapon swing
-static uint32 CalcMeleeAttackRageGain(Unit const* attacker, WeaponAttackType attType)
-{
- if (!attacker || (attType != BASE_ATTACK && attType != OFF_ATTACK))
- return 0;
-
- uint32 rage = uint32(attacker->GetBaseAttackTime(attType) / 1000.f * 6.5f);
- if (attType == OFF_ATTACK)
- rage /= 2;
-
- // Players below level 10 start with a 50% rage gain reduction that slowly diminishes
- if (attacker->IsPlayer() && attacker->GetLevel() < 10)
- rage -= (rage / 2.f) * (1.0f - (attacker->GetLevel() / 10.f));
-
- return rage;
-}
-
void Unit::AttackerStateUpdate(Unit* victim, WeaponAttackType attType, bool extra)
{
if (HasUnitFlag(UNIT_FLAG_PACIFIED))
@@ -2257,7 +2263,7 @@ void Unit::AttackerStateUpdate(Unit* victim, WeaponAttackType attType, bool extr
if (uint32 rageReward = CalcMeleeAttackRageGain(this, attType))
{
damageInfo.HitInfo |= HITINFO_RAGE_GAIN;
- damageInfo.RageGained = RewardRage(rageReward);
+ damageInfo.RageGained = RewardRage(rageReward, true);
}
}
@@ -12916,17 +12922,17 @@ void Unit::UpdateHeight(float newZ)
GetVehicleKit()->RelocatePassengers();
}
-// baseRage means damage taken when attacker = false
-int32 Unit::RewardRage(uint32 baseRage)
+// Modifies the rage amount gained by dealing or taking damage. Applies aura modifiers and power rate config settings
+int32 Unit::RewardRage(uint32 baseRage, bool asAttacker)
{
float addRage = baseRage;
- // talent who gave more rage on attack
- AddPct(addRage, GetTotalAuraModifier(SPELL_AURA_MOD_RAGE_FROM_DAMAGE_DEALT));
+ if (asAttacker)
+ AddPct(addRage, GetTotalAuraModifier(SPELL_AURA_MOD_RAGE_FROM_DAMAGE_DEALT));
addRage *= sWorld->getRate(RATE_POWER_RAGE_INCOME);
- return ModifyPower(POWER_RAGE, uint32(addRage * 10), false);
+ return ModifyPower(POWER_RAGE, static_cast<uint32>(addRage), !asAttacker);
}
void Unit::StopAttackFaction(uint32 faction_id)
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index be913cbda5b..75a85af22bc 100644
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -402,11 +402,11 @@ class DispelInfo
struct CleanDamage
{
- CleanDamage(uint32 mitigated, uint32 absorbed, WeaponAttackType _attackType, MeleeHitOutcome _hitOutCome) :
- absorbed_damage(absorbed), mitigated_damage(mitigated), attackType(_attackType), hitOutCome(_hitOutCome) { }
+ CleanDamage(uint32 original, uint32 absorbed, WeaponAttackType _attackType, MeleeHitOutcome _hitOutCome) :
+ original_damage(original), absorbed_damage(absorbed), attackType(_attackType), hitOutCome(_hitOutCome) { }
uint32 absorbed_damage;
- uint32 mitigated_damage;
+ uint32 original_damage;
WeaponAttackType attackType;
MeleeHitOutcome hitOutCome;
@@ -543,7 +543,6 @@ struct CalcDamageInfo
WeaponAttackType AttackType; //
ProcFlagsInit ProcAttacker;
ProcFlagsInit ProcVictim;
- uint32 CleanDamage; // Used only for rage calculation
MeleeHitOutcome HitOutCome; /// @todo remove this field (need use TargetState)
};
@@ -566,7 +565,6 @@ struct TC_GAME_API SpellNonMeleeDamage
uint32 blocked;
uint32 HitInfo;
// Used for help
- uint32 cleanDamage;
bool fullBlock;
uint32 preHitHealth;
};
@@ -936,6 +934,8 @@ class TC_GAME_API Unit : public WorldObject
void DoMeleeAttackIfReady();
void AttackerStateUpdate(Unit* victim, WeaponAttackType attType = BASE_ATTACK, bool extra = false);
+ static uint32 CalcMeleeAttackRageGain(Unit const* attacker, WeaponAttackType attType);
+ static uint32 CalcDamageTakenRageGain(Unit const* victim, uint32 damage);
void CalculateMeleeDamage(Unit* victim, CalcDamageInfo* damageInfo, WeaponAttackType attackType = BASE_ATTACK);
void DealMeleeDamage(CalcDamageInfo* damageInfo, bool durabilityLoss);
void HandleProcExtraAttackFor(Unit* victim, uint32 count);
@@ -1748,7 +1748,7 @@ class TC_GAME_API Unit : public WorldObject
float GetHoverOffset() const { return HasUnitMovementFlag(MOVEMENTFLAG_HOVER) ? *m_unitData->HoverHeight : 0.0f; }
- int32 RewardRage(uint32 baseRage);
+ int32 RewardRage(uint32 baseRage, bool asAttacker);
virtual float GetFollowAngle() const { return static_cast<float>(M_PI/2); }
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
index 5969e4bd37e..cd80e70f76f 100644
--- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
@@ -5610,9 +5610,8 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const
// Calculate armor mitigation
if (Unit::IsDamageReducedByArmor(GetSpellInfo()->GetSchoolMask(), GetSpellInfo()))
{
- uint32 damageReducedArmor = Unit::CalcArmorReducedDamage(caster, target, damage, GetSpellInfo(), GetSpellInfo()->GetAttackType(), GetBase()->GetCasterLevel());
- cleanDamage.mitigated_damage += damage - damageReducedArmor;
- damage = damageReducedArmor;
+ damage = Unit::CalcArmorReducedDamage(caster, target, damage, GetSpellInfo(), GetSpellInfo()->GetAttackType(), GetBase()->GetCasterLevel());
+ cleanDamage.original_damage = damage;
}
if (!GetSpellInfo()->HasAttribute(SPELL_ATTR4_IGNORE_DAMAGE_TAKEN_MODIFIERS))
@@ -5699,9 +5698,8 @@ void AuraEffect::HandlePeriodicHealthLeechAuraTick(Unit* target, Unit* caster) c
// Calculate armor mitigation
if (Unit::IsDamageReducedByArmor(GetSpellInfo()->GetSchoolMask(), GetSpellInfo()))
{
- uint32 damageReducedArmor = Unit::CalcArmorReducedDamage(caster, target, damage, GetSpellInfo(), GetSpellInfo()->GetAttackType(), GetBase()->GetCasterLevel());
- cleanDamage.mitigated_damage += damage - damageReducedArmor;
- damage = damageReducedArmor;
+ damage = Unit::CalcArmorReducedDamage(caster, target, damage, GetSpellInfo(), GetSpellInfo()->GetAttackType(), GetBase()->GetCasterLevel());
+ cleanDamage.original_damage = damage;
}
if (!GetSpellInfo()->HasAttribute(SPELL_ATTR4_IGNORE_DAMAGE_TAKEN_MODIFIERS))