Core/Spells: fixed several special damage calculations for class spells and fixed a duplicate application of mastery

This commit is contained in:
Ovahlord committed 2025-06-09 11:08:43 +02:00
1 parent 6f39a57ad3
commit 4ccfe1ebed
6 files changed
+168 -145

No files matched your search

@@ -0,0 +1,7 @@
DELETE FROM `spell_script_names` WHERE `ScriptName` IN ('spell_hun_aimed_shot', 'spell_hun_explosive_shot');
INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
(19434, 'spell_hun_aimed_shot'),
(82928, 'spell_hun_aimed_shot'),
(53301, 'spell_hun_explosive_shot');
-- dk strike dmg bonus
@@ -482,12 +482,7 @@ void AuraEffect::GetApplicationList(Container& applicationContainer) const
int32 AuraEffect::CalculateAmount(Unit* caster)
{
// default amount calculation
int32 amount = 0;
if (!m_spellInfo->HasAttribute(SPELL_ATTR8_MASTERY_AFFECTS_POINTS) || G3D::fuzzyEq(m_spellInfo->Effects[m_effIndex].BonusMultiplier, 0.0f))
amount = m_spellInfo->Effects[m_effIndex].CalcValue(caster, &m_baseAmount, GetBase()->GetOwner()->ToUnit());
else if (caster && caster->GetTypeId() == TYPEID_PLAYER)
amount = int32(caster->GetFloatValue(PLAYER_MASTERY) * m_spellInfo->Effects[m_effIndex].BonusMultiplier);
int32 amount = amount = m_spellInfo->Effects[m_effIndex].CalcValue(caster, &m_baseAmount, GetBase()->GetOwner()->ToUnit());;
// check item enchant aura cast
if (!amount && caster)
+48 -117
View File
@@ -2760,24 +2760,39 @@ void Spell::EffectWeaponDmg(SpellEffIndex effIndex)
if (!unitTarget || !unitTarget->IsAlive())
return;
uint32 effectType = m_spellInfo->Effects[effIndex].Effect;
bool useWeaponDamage = true;
/*
Multiple weapon damage effect case. SPELL_EFFECT_WEAPON_PERCENT_DAMAGE is being prioritized for calculating weapon damage values.
The other effects only add their fixed bonus to the damage sum.
*/
if (m_spellInfo->HasEffect(SPELL_EFFECT_WEAPON_PERCENT_DAMAGE) && effectType != SPELL_EFFECT_WEAPON_PERCENT_DAMAGE)
useWeaponDamage = false;
for(uint8 j = effIndex + 1; j < MAX_SPELL_EFFECTS; ++j)
{
switch (m_spellInfo->Effects[j].Effect)
{
case SPELL_EFFECT_WEAPON_DAMAGE:
case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL:
case SPELL_EFFECT_NORMALIZED_WEAPON_DMG:
case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE:
return;
default:
break;
}
}
// some spell specific modifiers
float totalDamagePercentMod = 1.0f; // applied to final bonus+weapon damage
int32 fixed_bonus = 0;
switch (m_spellInfo->SpellFamilyName)
{
case SPELLFAMILY_SHAMAN:
{
// Skyshatter Harness item set bonus
// Stormstrike
if (AuraEffect* aurEff = unitCaster->IsScriptOverriden(m_spellInfo, 5634))
unitCaster->CastSpell(nullptr, 38430, aurEff);
break;
}
}
bool normalized = false;
float weaponDamagePercentMod = 1.0f;
Mechanics mechanic = MECHANIC_NONE;
for (uint8 j = 0; j < MAX_SPELL_EFFECTS; ++j)
{
switch (m_spellInfo->Effects[j].Effect)
@@ -2794,101 +2809,7 @@ void Spell::EffectWeaponDmg(SpellEffIndex effIndex)
ApplyPct(weaponDamagePercentMod, CalculateDamage(j, unitTarget));
break;
default:
continue; // not weapon damage effect, just skip
}
if (m_spellInfo->Effects[j].Mechanic != MECHANIC_NONE && mechanic == MECHANIC_NONE)
mechanic = m_spellInfo->Effects[j].Mechanic;
}
if (useWeaponDamage)
{
switch (m_spellInfo->SpellFamilyName)
{
case SPELLFAMILY_SHAMAN:
{
// Skyshatter Harness item set bonus
// Stormstrike
if (AuraEffect* aurEff = unitCaster->IsScriptOverriden(m_spellInfo, 5634))
unitCaster->CastSpell(unitCaster, 38430, aurEff);
break;
}
case SPELLFAMILY_DRUID:
{
// Mangle (Cat): CP
if (m_spellInfo->SpellFamilyFlags[1] & 0x400)
unitCaster->CastSpell(unitTarget, 34071, true);
// Shred, Maul - Rend and Tear
else if (m_spellInfo->SpellFamilyFlags[0] & 0x00008800 && unitTarget->HasAuraState(AURA_STATE_BLEEDING))
{
if (AuraEffect const* rendAndTear = unitCaster->GetDummyAuraEffect(SPELLFAMILY_DRUID, 2859, 0))
AddPct(totalDamagePercentMod, rendAndTear->GetAmount());
}
break;
}
case SPELLFAMILY_DEATHKNIGHT:
{
// Death Strike
if (m_spellInfo->SpellFamilyFlags[0] & 0x10)
{
// Glyph of Death Strike
// 2% more damage per 5 runic power, up to a maximum of 40%
if (AuraEffect const* aurEff = unitCaster->GetAuraEffect(59336, EFFECT_0))
if (uint32 runic = std::min<uint32>(uint32(unitCaster->GetPower(POWER_RUNIC_POWER) / 2.5f), aurEff->GetSpellInfo()->Effects[EFFECT_1].CalcValue(unitCaster)))
AddPct(totalDamagePercentMod, runic);
}
// Obliterate / Blood Strike / Blood-Caked Strike (12.5% more damage per disease) / Heart Strike (15% more damage per disease)
if (m_spellInfo->SpellFamilyFlags[1] & 0x20000 || m_spellInfo->SpellFamilyFlags[0] & 0x400000
|| m_spellInfo->SpellFamilyFlags[0] & 0x1000000 || m_spellInfo->Id == 50463)
{
float bonusPct = m_spellInfo->Effects[EFFECT_2].CalcValue(m_caster);
uint8 diseaseCount = unitTarget->GetDiseasesByCaster(m_caster->GetGUID(), false);
if (m_spellInfo->SpellFamilyFlags[1] & 0x20000) // Obliterate - 50% of Basepoints as bonus
bonusPct *= 0.5f;
else if (m_spellInfo->SpellFamilyFlags[0] & 0x400000) // Blood Strike - 10% of Basepoints as bonus
bonusPct *= 0.1f;
float bonusAmount = bonusPct * diseaseCount;
// Death Knight T8 Melee 4P Bonus
if (AuraEffect const* aurEff = unitCaster->GetAuraEffect(64736, EFFECT_0))
AddPct(bonusAmount, aurEff->GetAmount());
AddPct(totalDamagePercentMod, bonusAmount);
}
// Blood-Caked Strike - Blood-Caked Blade
if (m_spellInfo->SpellIconID == 1736)
AddPct(totalDamagePercentMod, unitTarget->GetDiseasesByCaster(unitCaster->GetGUID()) * 50.0f);
// Merciless Combat (Obliterate and Frost Strike)
if (m_spellInfo->SpellFamilyFlags[1] & 0x20000 || m_spellInfo->SpellFamilyFlags[1] & 0x4)
if (unitTarget->GetHealthPct() < 35.0f)
if (AuraEffect const* mercilessCombat = unitCaster->GetDummyAuraEffect(SPELLFAMILY_DEATHKNIGHT, 2656, 0))
AddPct(totalDamagePercentMod, mercilessCombat->GetAmount());
break;
}
case SPELLFAMILY_WARLOCK:
{
if (useWeaponDamage)
{
// Felstorm and Legion Strike
if (m_spellInfo->Id == 89753)
{
if (unitCaster->IsPet())
if (Unit* owner = unitCaster->GetOwner())
m_damage += ((owner->SpellBaseDamageBonusDone(SPELL_SCHOOL_MASK_SHADOW) * 0.5f) * 2) * 0.231f;
}
else if (m_spellInfo->Id == 30213)
{
if (unitCaster->IsPet())
if (Unit* owner = unitCaster->GetOwner())
m_damage += ((owner->SpellBaseDamageBonusDone(SPELL_SCHOOL_MASK_SHADOW) * 0.5f) * 2) * 0.264f;
}
}
break;
}
break; // not weapon damage effect, just skip
}
}
@@ -2911,20 +2832,30 @@ void Spell::EffectWeaponDmg(SpellEffIndex effIndex)
fixed_bonus = int32(fixed_bonus * weapon_total_pct);
}
int32 weaponDamage = useWeaponDamage ? unitCaster->CalculateDamage(m_attackType, normalized, addPctMods) : 0;
int32 weaponDamage = unitCaster->CalculateDamage(m_attackType, normalized, addPctMods);
Mechanics mechanic = MECHANIC_NONE;
switch (effectType)
// Sequence is important
for (uint8 j = 0; j < MAX_SPELL_EFFECTS; ++j)
{
case SPELL_EFFECT_WEAPON_DAMAGE:
case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL:
case SPELL_EFFECT_NORMALIZED_WEAPON_DMG:
weaponDamage += fixed_bonus;
break;
case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE:
weaponDamage = int32(weaponDamage * weaponDamagePercentMod);
break;
default:
break;
// We assume that a spell have at most one fixed_bonus
// and at most one weaponDamagePercentMod
switch (m_spellInfo->Effects[j].Effect)
{
case SPELL_EFFECT_WEAPON_DAMAGE:
case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL:
case SPELL_EFFECT_NORMALIZED_WEAPON_DMG:
weaponDamage += fixed_bonus;
break;
case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE:
weaponDamage = int32(weaponDamage * weaponDamagePercentMod);
break;
default:
break;
}
if (m_spellInfo->Effects[j].Mechanic != MECHANIC_NONE && mechanic == MECHANIC_NONE)
mechanic = m_spellInfo->Effects[j].Mechanic;
}
weaponDamage = int32(weaponDamage * totalDamagePercentMod);
+5 -2
View File
@@ -1456,9 +1456,12 @@ class spell_dk_disease : public AuraScript
}
// According to tooltip: ($m1*1.15+$AP*0.055*1.15)
void CalculateDamage(AuraEffect const* /*aurEff*/, Unit* /*victim*/, int32& damage, int32& /*flatMod*/, float& /*pctMod*/)
void CalculateDamage(AuraEffect const* /*aurEff*/, Unit* /*victim*/, int32& damage, int32& flatMod, float& /*pctMod*/)
{
damage = damage * 1.15f + GetCaster()->GetTotalAttackPowerValue(BASE_ATTACK) * 0.055f * 1.15f;
damage *= 1.15f;
if (Unit* caster = GetCaster())
flatMod = caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.055f * 1.15f;
}
void HandleResilientInfection(DispelInfo* /*dispelInfo*/)
+26 -15
View File
@@ -1594,33 +1594,44 @@ class spell_dru_pulverize : public SpellScript
});
}
void ChangeDamage(SpellEffIndex /*effIndex*/)
void CalculateDamage(Unit* victim, int32& damage, int32& flatMod, float& /*pctMod*/)
{
Unit* caster = GetCaster();
Unit* target = GetHitUnit();
if (!caster || !target)
return;
// Formular: $m3 * $m1 / 100
int32 bp = CalculatePct(GetEffectValue() * GetSpellInfo()->Effects[EFFECT_0].CalcValue(caster), 1);
int32 normalizedWeaponDamage = GetSpellInfo()->Effects[EFFECT_2].CalcValue(caster);
if (Aura* aura = target->GetAura(SPELL_DRUID_LACERATE, caster->GetGUID()))
// Subtract the normalized weapon damage bonus because it's not supposed to be used in the regular way
damage -= normalizedWeaponDamage;
if (Aura* aura = victim->GetAura(SPELL_DRUID_LACERATE, caster->GetGUID()))
{
uint8 stacks = aura->GetStackAmount();
bp *= stacks;
SetEffectValue(bp);
// Damage bonus per application of Lacerate:
// ${$m3*$m1/100}
int32 weaponPctDamage = GetSpellInfo()->Effects[EFFECT_0].CalcValue(caster);
int32 lacerateBonus = CalculatePct(normalizedWeaponDamage, weaponPctDamage);
flatMod += lacerateBonus * aura->GetStackAmount();
}
}
void HandleLacerateRemoval(SpellEffIndex /*effIndex*/)
{
Unit* caster = GetCaster();
if (Aura* aura = GetHitUnit()->GetAura(SPELL_DRUID_LACERATE, caster->GetGUID()))
{
// Crit chance bonus per Lacerate stack consumed
int32 critPerStack = sSpellMgr->GetSpellInfo(SPELL_DRUID_PULVERIZE_TRIGGERED)->Effects[EFFECT_0].CalcValue(caster);
caster->CastSpell(caster, SPELL_DRUID_PULVERIZE_TRIGGERED, CastSpellExtraArgs(TRIGGERED_FULL_MASK).AddSpellBP0(critPerStack * aura->GetStackAmount()));
uint32 critPerStack = sSpellMgr->GetSpellInfo(SPELL_DRUID_PULVERIZE_TRIGGERED)->Effects[EFFECT_0].BasePoints;
caster->CastSpell(caster, SPELL_DRUID_PULVERIZE_TRIGGERED, CastSpellExtraArgs(true).AddSpellBP0(int32(critPerStack * stacks)));
aura->Remove();
}
else
SetEffectValue(0);
}
void Register() override
{
OnEffectLaunchTarget.Register(&spell_dru_pulverize::ChangeDamage, EFFECT_2, SPELL_EFFECT_NORMALIZED_WEAPON_DMG);
CalcDamage.Register(&spell_dru_pulverize::CalculateDamage);
OnEffectHitTarget.Register(&spell_dru_pulverize::HandleLacerateRemoval, EFFECT_0, SPELL_EFFECT_WEAPON_PERCENT_DAMAGE);
}
};
+81 -5
View File
@@ -34,7 +34,6 @@ namespace Spells::Hunter
{
enum HunterSpells
{
SPELL_HUNTER_AIMED_SHOT = 19434,
SPELL_HUNTER_BESTIAL_WRATH = 19574,
SPELL_HUNTER_CALL_PET_1 = 883,
SPELL_HUNTER_CALL_PET_2 = 83242,
@@ -140,9 +139,15 @@ class spell_hun_ancient_hysteria : public SpellScript
// 3044 - Arcane Shot
class spell_hun_arcane_shot : public SpellScript
{
void CalculateDamage(Unit* /*victim*/, int32& /*damage*/, int32& flatMod, float& /*pctMod*/)
void CalculateDamage(Unit* /*victim*/, int32& damage, int32& /*flatMod*/, float& /*pctMod*/)
{
flatMod += GetCaster()->GetTotalAttackPowerValue(RANGED_ATTACK) * 0.0493f;
Unit* caster = GetCaster();
// Due to limited control over weapon damage effects, we have to override the default damage calculation
// Arcane shot has a very special calculation pattern
damage = CalculatePct(caster->CalculateDamage(RANGED_ATTACK, true, true), GetSpellInfo()->Effects[EFFECT_1].CalcValue(caster));
damage += GetCaster()->GetTotalAttackPowerValue(RANGED_ATTACK) * 0.0493f;
damage += GetSpellInfo()->Effects[EFFECT_0].CalcValue(caster);
}
void Register() override
@@ -173,6 +178,11 @@ class spell_hun_chimera_shot : public SpellScript
return ValidateSpellInfo({ SPELL_HUNTER_CHIMERA_SHOT_HEAL });
}
void CalculateDamage(Unit* /*victim*/, int32& /*damage*/, int32& flatMod, float& /*pctMod*/)
{
flatMod += GetCaster()->GetTotalAttackPowerValue(RANGED_ATTACK) * 0.732f;
}
void HandleScriptEffect(SpellEffIndex /*effIndex*/)
{
Unit* caster = GetCaster();
@@ -187,6 +197,7 @@ class spell_hun_chimera_shot : public SpellScript
void Register() override
{
CalcDamage.Register(&spell_hun_chimera_shot::CalculateDamage);
OnEffectHitTarget.Register(&spell_hun_chimera_shot::HandleScriptEffect, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
}
};
@@ -204,6 +215,11 @@ class spell_hun_cobra_shot : public SpellScript
return ValidateSpellInfo({ SPELL_HUNTER_GENERIC_ENERGIZE_FOCUS });
}
void CalculateDamage(Unit* /*victim*/, int32& /*damage*/, int32& flatMod, float& /*pctMod*/)
{
flatMod += GetCaster()->GetTotalAttackPowerValue(RANGED_ATTACK) * 0.017f;
}
void HandleLaunch(SpellEffIndex /*effIndex*/)
{
Unit* caster = GetCaster();
@@ -234,6 +250,7 @@ class spell_hun_cobra_shot : public SpellScript
void Register() override
{
CalcDamage.Register(&spell_hun_cobra_shot::CalculateDamage);
OnEffectLaunch.Register(&spell_hun_cobra_shot::HandleLaunch, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT);
OnEffectHitTarget.Register(&spell_hun_cobra_shot::HandleScriptEffect, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT);
}
@@ -669,9 +686,14 @@ class spell_hun_steady_shot : public SpellScript
return ValidateSpellInfo({ SPELL_HUNTER_STEADY_SHOT_FOCUS });
}
void CalculateDamage(Unit* /*victim*/, int32& /*damage*/, int32& flatMod, float& /*pctMod*/)
void CalculateDamage(Unit* /*victim*/, int32& damage, int32& /*flatMod*/, float& /*pctMod*/)
{
flatMod += GetCaster()->GetTotalAttackPowerValue(RANGED_ATTACK) * 0.021f;
Unit* caster = GetCaster();
// Due to limited control over weapon damage effects, we have to override the default damage calculation
// Steady shot has a very special calculation pattern
damage = CalculatePct(caster->CalculateDamage(RANGED_ATTACK, true, true), GetSpellInfo()->Effects[EFFECT_1].CalcValue(caster));
damage += caster->GetTotalAttackPowerValue(RANGED_ATTACK) * 0.021f;
damage += GetSpellInfo()->Effects[EFFECT_0].CalcValue(caster);
}
void HandleLaunch(SpellEffIndex /*effIndex*/)
@@ -904,6 +926,12 @@ class spell_hun_serpent_sting : public AuraScript
return ValidateSpellInfo({ SPELL_HUNTER_IMPROVED_SERPENT_STING_DAMAGE });
}
void CalculateDamage(AuraEffect const* /*aurEff*/, Unit* /*victim*/, int32& /*damage*/, int32& flatMod, float& /*pctMod*/)
{
if (Unit* caster = GetCaster())
flatMod += caster->GetTotalAttackPowerValue(RANGED_ATTACK) * 0.4f / 5;
}
void HandleImprovedSerpentSting(AuraEffect const* aurEff, AuraEffectHandleModes /*mode*/)
{
Unit* caster = GetCaster();
@@ -919,6 +947,7 @@ class spell_hun_serpent_sting : public AuraScript
void Register() override
{
DoEffectCalcDamageAndHealing.Register(&spell_hun_serpent_sting::CalculateDamage, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE);
AfterEffectApply.Register(&spell_hun_serpent_sting::HandleImprovedSerpentSting, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE, AURA_EFFECT_HANDLE_REAL_OR_REAPPLY_MASK);
}
};
@@ -1458,11 +1487,57 @@ class spell_hun_serpent_spread : public AuraScript
OnEffectProc.Register(&spell_hun_serpent_spread::HandleProc, EFFECT_0, SPELL_AURA_DUMMY);
}
};
// 19434 - Aimed Shot
// 82928 - Aimed Shot! (Master Marksman)
class spell_hun_aimed_shot : public SpellScript
{
bool Load() override
{
return GetCaster()->IsPlayer();
}
bool Validate(SpellInfo const* /*spellInfo*/) override
{
return ValidateSpellInfo({ SPELL_HUNTER_STEADY_SHOT_FOCUS });
}
void CalculateDamage(Unit* /*victim*/, int32& damage, int32& /*flatMod*/, float& /*pctMod*/)
{
Unit* caster = GetCaster();
// Due to limited control over weapon damage effects, we have to override the default damage calculation
// Aimed Shot has a very special calculation pattern
damage = CalculatePct(caster->CalculateDamage(RANGED_ATTACK, true, true), GetSpellInfo()->Effects[EFFECT_1].CalcValue(caster));
damage += caster->GetTotalAttackPowerValue(RANGED_ATTACK) * 0.724f;
damage += GetSpellInfo()->Effects[EFFECT_0].CalcValue(caster);
}
void Register() override
{
CalcDamage.Register(&spell_hun_aimed_shot::CalculateDamage);
}
};
// 53301 - Explosive Shot
class spell_hun_explosive_shot : public AuraScript
{
void CalculateDamage(AuraEffect const* /*aurEff*/, Unit* /*victim*/, int32& /*damage*/, int32& flatMod, float& /*pctMod*/)
{
if (Unit* caster = GetCaster())
flatMod += caster->GetTotalAttackPowerValue(RANGED_ATTACK) * 0.273f;
}
void Register() override
{
DoEffectCalcDamageAndHealing.Register(&spell_hun_explosive_shot::CalculateDamage, EFFECT_0, SPELL_AURA_PERIODIC_DAMAGE);
}
};
}
void AddSC_hunter_spell_scripts()
{
using namespace Spells::Hunter;
RegisterSpellScript(spell_hun_aimed_shot);
RegisterSpellScript(spell_hun_ancient_hysteria);
RegisterSpellScript(spell_hun_arcane_shot);
RegisterSpellScript(spell_hun_camouflage);
@@ -1472,6 +1547,7 @@ void AddSC_hunter_spell_scripts()
RegisterSpellScript(spell_hun_cobra_shot);
RegisterSpellScript(spell_hun_crouching_tiger_hidden_chimera);
RegisterSpellScript(spell_hun_disengage);
RegisterSpellScript(spell_hun_explosive_shot);
RegisterSpellScript(spell_hun_fervor);
RegisterSpellAndAuraScriptPair(spell_hun_focus_fire, spell_hun_focus_fire_AuraScript);
RegisterSpellScript(spell_hun_frenzy_effect);