From 5c9ecf27e98f3ad92522b394dd30a2f065949c2b Mon Sep 17 00:00:00 2001 From: Ovahlord Date: Sun, 8 Jun 2025 15:16:17 +0200 Subject: [PATCH] Core/Spells: dropped spell_bonus_data table and use the dbc internal data to calculate ap and sp bonus values * some spells have a special formula in their tooltips, which need manual scripting via the CalcDamage and CalcHealing hooks respectively --- src/server/game/Accounts/RBAC.h | 2 +- src/server/game/Entities/Unit/Unit.cpp | 98 ++++---------- src/server/game/Entities/Unit/Unit.h | 2 +- src/server/game/Spells/SpellEffects.cpp | 23 +--- src/server/game/Spells/SpellInfo.cpp | 2 +- src/server/game/Spells/SpellInfo.h | 2 +- src/server/game/Spells/SpellMgr.cpp | 57 +-------- src/server/game/Spells/SpellMgr.h | 15 --- src/server/game/World/World.cpp | 3 - src/server/scripts/Commands/cs_reload.cpp | 10 -- src/server/scripts/Spells/spell_dk.cpp | 17 ++- src/server/scripts/Spells/spell_generic.cpp | 12 +- src/server/scripts/Spells/spell_hunter.cpp | 23 +++- src/server/scripts/Spells/spell_rogue.cpp | 34 ++++- src/server/scripts/Spells/spell_warrior.cpp | 134 ++++++++++---------- 15 files changed, 182 insertions(+), 252 deletions(-) diff --git a/src/server/game/Accounts/RBAC.h b/src/server/game/Accounts/RBAC.h index 99d3a56d30..f136a24c5c 100644 --- a/src/server/game/Accounts/RBAC.h +++ b/src/server/game/Accounts/RBAC.h @@ -589,7 +589,7 @@ enum RBACPermissions RBAC_PERM_COMMAND_RELOAD_SMART_SCRIPTS = 689, RBAC_PERM_COMMAND_RELOAD_SPELL_REQUIRED = 690, RBAC_PERM_COMMAND_RELOAD_SPELL_AREA = 691, - RBAC_PERM_COMMAND_RELOAD_SPELL_BONUS_DATA = 692, + RBAC_PERM_COMMAND_RELOAD_SPELL_BONUS_DATA = 692, // unused in 4.3.4 RBAC_PERM_COMMAND_RELOAD_SPELL_GROUP = 693, RBAC_PERM_COMMAND_RELOAD_SPELL_LEARN_SPELL = 694, RBAC_PERM_COMMAND_RELOAD_SPELL_LOOT_TEMPLATE = 695, diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index df1fdad66a..e11673f241 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -1207,7 +1207,7 @@ void Unit::CalculateMeleeDamage(Unit* victim, CalcDamageInfo* damageInfo, Weapon uint32 damage = 0; damage += CalculateDamage(damageInfo->AttackType, false, true); // Add melee damage bonus - damage = MeleeDamageBonusDone(damageInfo->Target, damage, damageInfo->AttackType, DIRECT_DAMAGE, nullptr, MECHANIC_NONE, true, SpellSchoolMask(damageInfo->DamageSchoolMask)); + damage = MeleeDamageBonusDone(damageInfo->Target, damage, damageInfo->AttackType, DIRECT_DAMAGE, nullptr, MECHANIC_NONE, SpellSchoolMask(damageInfo->DamageSchoolMask)); damage = damageInfo->Target->MeleeDamageBonusTaken(this, damage, damageInfo->AttackType, nullptr, SpellSchoolMask(damageInfo->DamageSchoolMask)); // Script Hook For CalculateMeleeDamage -- Allow scripts to change the Damage pre class mitigation calculations @@ -6382,63 +6382,48 @@ int32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, int3 break; } - // Check for table values - float spellPowerCoeff = spellProto->Effects[effIndex].BonusMultiplier; - float attackPowerCoeff = spellProto->BonusCoefficient; - - WeaponAttackType const attType = [&]() + if (spellProto->BonusCoefficientFromAP > 0.0f) { - if ((spellProto->IsRangedWeaponSpell() && spellProto->DmgClass != SPELL_DAMAGE_CLASS_MELEE)) - return RANGED_ATTACK; - - if (spellProto->HasAttribute(SPELL_ATTR3_REQUIRES_OFF_HAND_WEAPON) && !spellProto->HasAttribute(SPELL_ATTR3_REQUIRES_MAIN_HAND_WEAPON)) - return OFF_ATTACK; - - return BASE_ATTACK; - }(); - - if (SpellBonusEntry const* bonus = sSpellMgr->GetSpellBonusData(spellProto->Id)) - { - if (damagetype == DOT) + float ApCoeffMod = spellProto->BonusCoefficientFromAP; + if (Player* modOwner = GetSpellModOwner()) { - spellPowerCoeff = bonus->dot_damage; - attackPowerCoeff = bonus->ap_dot_bonus; + ApCoeffMod *= 100.0f; + modOwner->ApplySpellMod(spellProto, SpellModOp::BonusCoefficient, ApCoeffMod); + ApCoeffMod /= 100.0f; } - else + + WeaponAttackType const attType = [&]() { - spellPowerCoeff = bonus->direct_damage; - attackPowerCoeff = bonus->ap_bonus; - } - } + if ((spellProto->IsRangedWeaponSpell() && spellProto->DmgClass != SPELL_DAMAGE_CLASS_MELEE)) + return RANGED_ATTACK; - if (spellPowerCoeff > 0.f) - spellPowerCoeff = spellProto->CalculateScaledCoefficient(this, spellPowerCoeff); + if (spellProto->HasAttribute(SPELL_ATTR3_REQUIRES_OFF_HAND_WEAPON) && !spellProto->HasAttribute(SPELL_ATTR3_REQUIRES_MAIN_HAND_WEAPON)) + return OFF_ATTACK; - if (attackPowerCoeff > 0.f) - { - float APbonus = float(victim->GetTotalAuraModifier(attType == BASE_ATTACK ? SPELL_AURA_MELEE_ATTACK_POWER_ATTACKER_BONUS : SPELL_AURA_RANGED_ATTACK_POWER_ATTACKER_BONUS)); + return BASE_ATTACK; + }(); + + float APbonus = float(victim->GetTotalAuraModifier(attType != RANGED_ATTACK ? SPELL_AURA_MELEE_ATTACK_POWER_ATTACKER_BONUS : SPELL_AURA_RANGED_ATTACK_POWER_ATTACKER_BONUS)); APbonus += GetTotalAttackPowerValue(attType); - DoneTotal += int32(attackPowerCoeff * stack * APbonus); + DoneTotal += int32(stack * ApCoeffMod * APbonus); } // Default calculation if (DoneAdvertisedBenefit) { - if (spellPowerCoeff < 0.f) - spellPowerCoeff = CalculateDefaultCoefficient(spellProto, damagetype); // As wowwiki says: C = (Cast Time / 3.5) - - + float coeff = spellProto->Effects[effIndex].BonusMultiplier * spellProto->GetSpellScalingMultiplier(getLevel(), false); if (Player* modOwner = GetSpellModOwner()) { - spellPowerCoeff *= 100.0f; - modOwner->ApplySpellMod(spellProto, SpellModOp::BonusCoefficient, spellPowerCoeff); - spellPowerCoeff /= 100.0f; + coeff *= 100.0f; + modOwner->ApplySpellMod(spellProto, SpellModOp::BonusCoefficient, coeff); + coeff /= 100.0f; } - DoneTotal += int32(DoneAdvertisedBenefit * spellPowerCoeff * stack); + DoneTotal += int32(DoneAdvertisedBenefit * coeff * stack); } callDamageScript(pdamage, DoneTotal, DoneTotalMod); + float tmpDamage = float(pdamage + DoneTotal) * DoneTotalMod; // apply spellmod to Done damage (flat and pct) @@ -7108,34 +7093,19 @@ int32 Unit::SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, int // Check for table values - float coeff = spellProto->Effects[effIndex].BonusMultiplier; - if (SpellBonusEntry const* bonus = sSpellMgr->GetSpellBonusData(spellProto->Id)) + if (spellProto->BonusCoefficientFromAP > 0.0f) { WeaponAttackType const attType = (spellProto->IsRangedWeaponSpell() && spellProto->DmgClass != SPELL_DAMAGE_CLASS_MELEE) ? RANGED_ATTACK : BASE_ATTACK; float APbonus = float(victim->GetTotalAuraModifier(attType == BASE_ATTACK ? SPELL_AURA_MELEE_ATTACK_POWER_ATTACKER_BONUS : SPELL_AURA_RANGED_ATTACK_POWER_ATTACKER_BONUS)); APbonus += GetTotalAttackPowerValue(attType); - if (damagetype == DOT) - { - coeff = bonus->dot_damage; - if (bonus->ap_dot_bonus > 0) - if (bonus->ap_dot_bonus > 0) - DoneTotal += int32(bonus->ap_dot_bonus * stack * APbonus); - } - else - { - coeff = bonus->direct_damage; - if (bonus->ap_bonus > 0) - DoneTotal += int32(bonus->ap_bonus * stack * APbonus); - } + DoneTotal += int32(spellProto->BonusCoefficientFromAP * stack * APbonus); } // Default calculation if (DoneAdvertisedBenefit) { - if (coeff < 0.f) - coeff = CalculateDefaultCoefficient(spellProto, damagetype) * 1.88f; // As wowwiki says: C = (Cast Time / 3.5) * 1.88 (for healing spells) - + float coeff = spellProto->Effects[effIndex].BonusMultiplier * spellProto->GetSpellScalingMultiplier(getLevel(), false); if (Player* modOwner = GetSpellModOwner()) { coeff *= 100.0f; @@ -7585,7 +7555,7 @@ bool Unit::IsImmunedToSpellEffect(SpellInfo const* spellInfo, uint32 index, Worl return false; } -int32 Unit::MeleeDamageBonusDone(Unit* victim, int32 damage, WeaponAttackType attType, DamageEffectType damagetype, SpellInfo const* spellProto /*= nullptr*/, Mechanics mechanic /*= MECHANIC_NONE*/, bool useSpellBonusData /*= true*/, SpellSchoolMask damageSchoolMask /*= SPELL_SCHOOL_MASK_NORMAL*/, Spell* spell /*= nullptr*/, AuraEffect const* aurEff /*= nullptr*/) +int32 Unit::MeleeDamageBonusDone(Unit* victim, int32 damage, WeaponAttackType attType, DamageEffectType damagetype, SpellInfo const* spellProto /*= nullptr*/, Mechanics mechanic /*= MECHANIC_NONE*/, SpellSchoolMask damageSchoolMask /*= SPELL_SCHOOL_MASK_NORMAL*/, Spell* spell /*= nullptr*/, AuraEffect const* aurEff /*= nullptr*/) { if (!victim || damage == 0) return 0; @@ -7625,18 +7595,6 @@ int32 Unit::MeleeDamageBonusDone(Unit* victim, int32 damage, WeaponAttackType at DoneFlatBenefit += int32(APbonus / 14.0f * GetAPMultiplier(attType, normalized)); } - if (spellProto && useSpellBonusData) - { - float attackPowerCoeff = spellProto->BonusCoefficient; - - // Check for table values - if (SpellBonusEntry const* bonus = sSpellMgr->GetSpellBonusData(spellProto->Id)) - attackPowerCoeff = bonus->ap_bonus; - - if (attackPowerCoeff > 0.f) - DoneFlatBenefit += attackPowerCoeff * GetTotalAttackPowerValue(attType); - } - // Done total percent damage auras float DoneTotalMod = 1.0f; diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h index 95b3bc8308..0fa7a902ce 100644 --- a/src/server/game/Entities/Unit/Unit.h +++ b/src/server/game/Entities/Unit/Unit.h @@ -1570,7 +1570,7 @@ class TC_GAME_API Unit : public WorldObject float SpellHealingPctDone(Unit* victim, SpellInfo const* spellProto) const; int32 SpellHealingBonusTaken(Unit* caster, SpellInfo const* spellProto, int32 healamount, DamageEffectType damagetype) const; - int32 MeleeDamageBonusDone(Unit* pVictim, int32 damage, WeaponAttackType attType, DamageEffectType damagetype, SpellInfo const* spellProto = nullptr, Mechanics mechanic = MECHANIC_NONE, bool useSpellBonusData = true, SpellSchoolMask damageSchoolMask = SPELL_SCHOOL_MASK_NORMAL, Spell* spell = nullptr, AuraEffect const* aurEff = nullptr); + int32 MeleeDamageBonusDone(Unit* pVictim, int32 damage, WeaponAttackType attType, DamageEffectType damagetype, SpellInfo const* spellProto = nullptr, Mechanics mechanic = MECHANIC_NONE, SpellSchoolMask damageSchoolMask = SPELL_SCHOOL_MASK_NORMAL, Spell* spell = nullptr, AuraEffect const* aurEff = nullptr); int32 MeleeDamageBonusTaken(Unit* attacker, int32 pdamage, WeaponAttackType attType, SpellInfo const* spellProto = nullptr, SpellSchoolMask damageSchoolMask = SPELL_SCHOOL_MASK_NORMAL); bool IsBlockCritical() const; diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp index b3e079072d..5aad12e55e 100644 --- a/src/server/game/Spells/SpellEffects.cpp +++ b/src/server/game/Spells/SpellEffects.cpp @@ -2784,14 +2784,14 @@ void Spell::EffectWeaponDmg(SpellEffIndex effIndex) { case SPELL_EFFECT_WEAPON_DAMAGE: case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL: - fixed_bonus += damage; + fixed_bonus += CalculateDamage(j, unitTarget); break; case SPELL_EFFECT_NORMALIZED_WEAPON_DMG: - fixed_bonus += damage; + fixed_bonus += CalculateDamage(j, unitTarget); normalized = true; break; case SPELL_EFFECT_WEAPON_PERCENT_DAMAGE: - ApplyPct(weaponDamagePercentMod, damage); + ApplyPct(weaponDamagePercentMod, CalculateDamage(j, unitTarget)); break; default: continue; // not weapon damage effect, just skip @@ -2805,21 +2805,6 @@ void Spell::EffectWeaponDmg(SpellEffIndex effIndex) { switch (m_spellInfo->SpellFamilyName) { - case SPELLFAMILY_ROGUE: - { - // Hemorrhage - if (m_spellInfo->SpellFamilyFlags[0] & 0x2000000) - { - if (unitCaster->GetTypeId() == TYPEID_PLAYER) - unitCaster->ToPlayer()->AddComboPoints(unitTarget, 1, this); - // 45% more damage with daggers - if (unitCaster->GetTypeId() == TYPEID_PLAYER) - if (Item* item = unitCaster->ToPlayer()->GetWeaponForAttack(m_attackType, true)) - if (item->GetTemplate()->GetSubClass() == ITEM_SUBCLASS_WEAPON_DAGGER) - totalDamagePercentMod *= 1.45f; - } - break; - } case SPELLFAMILY_SHAMAN: { // Skyshatter Harness item set bonus @@ -2948,7 +2933,7 @@ void Spell::EffectWeaponDmg(SpellEffIndex effIndex) weaponDamage = std::max(weaponDamage, 0); // Add melee damage bonuses (also check for negative) - weaponDamage = unitCaster->MeleeDamageBonusDone(unitTarget, weaponDamage, m_attackType, SPELL_DIRECT_DAMAGE, m_spellInfo, mechanic, !useWeaponDamage, m_spellSchoolMask, this); + weaponDamage = unitCaster->MeleeDamageBonusDone(unitTarget, weaponDamage, m_attackType, SPELL_DIRECT_DAMAGE, m_spellInfo, mechanic, m_spellSchoolMask, this); m_damage += unitTarget->MeleeDamageBonusTaken(unitCaster, weaponDamage, m_attackType, m_spellInfo); } diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp index 370556d501..43ff7cb5bf 100644 --- a/src/server/game/Spells/SpellInfo.cpp +++ b/src/server/game/Spells/SpellInfo.cpp @@ -890,7 +890,7 @@ SpellInfo::SpellInfo(SpellEntry const* spellEntry, SpellEffectEntry const** effe SchoolMask = spellEntry->SchoolMask; RuneCostID = spellEntry->RuneCostID; SpellDifficultyId = spellEntry->Difficulty; - BonusCoefficient = spellEntry->BonusCoefficient; + BonusCoefficientFromAP = spellEntry->BonusCoefficient; SpellScalingId = spellEntry->ScalingID; SpellAuraOptionsId = spellEntry->AuraOptionsID; SpellAuraRestrictionsId = spellEntry->AuraRestrictionsID; diff --git a/src/server/game/Spells/SpellInfo.h b/src/server/game/Spells/SpellInfo.h index f0828757bc..9d2f36a4bf 100644 --- a/src/server/game/Spells/SpellInfo.h +++ b/src/server/game/Spells/SpellInfo.h @@ -423,7 +423,7 @@ class TC_GAME_API SpellInfo int32 AreaGroupId; uint32 SchoolMask; uint32 SpellDifficultyId; - float BonusCoefficient; + float BonusCoefficientFromAP; uint32 SpellScalingId; uint32 SpellAuraOptionsId; uint32 SpellAuraRestrictionsId; diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp index 336741ab44..29a078801f 100644 --- a/src/server/game/Spells/SpellMgr.cpp +++ b/src/server/game/Spells/SpellMgr.cpp @@ -571,22 +571,6 @@ bool SpellMgr::CanSpellTriggerProcOnEvent(SpellProcEntry const& procEntry, ProcE return true; } -SpellBonusEntry const* SpellMgr::GetSpellBonusData(uint32 spellId) const -{ - // Lookup data - SpellBonusMap::const_iterator itr = mSpellBonusMap.find(spellId); - if (itr != mSpellBonusMap.end()) - return &itr->second; - // Not found, try lookup for 1 spell rank if exist - if (uint32 rank_1 = GetFirstSpellInChain(spellId)) - { - SpellBonusMap::const_iterator itr2 = mSpellBonusMap.find(rank_1); - if (itr2 != mSpellBonusMap.end()) - return &itr2->second; - } - return nullptr; -} - SpellThreatEntry const* SpellMgr::GetSpellThreatEntry(uint32 spellID) const { SpellThreatMap::const_iterator itr = mSpellThreatMap.find(spellID); @@ -1925,45 +1909,6 @@ void SpellMgr::LoadSpellProcs() TC_LOG_INFO("server.loading", ">> Generated spell proc data for %u spells in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); } -void SpellMgr::LoadSpellBonuses() -{ - uint32 oldMSTime = getMSTime(); - - mSpellBonusMap.clear(); // need for reload case - - // 0 1 2 3 4 - QueryResult result = WorldDatabase.Query("SELECT entry, direct_bonus, dot_bonus, ap_bonus, ap_dot_bonus FROM spell_bonus_data"); - if (!result) - { - TC_LOG_INFO("server.loading", ">> Loaded 0 spell bonus data. DB table `spell_bonus_data` is empty."); - return; - } - - uint32 count = 0; - do - { - Field* fields = result->Fetch(); - uint32 entry = fields[0].GetUInt32(); - - SpellInfo const* spell = GetSpellInfo(entry); - if (!spell) - { - TC_LOG_ERROR("sql.sql", "The spell %u listed in `spell_bonus_data` does not exist.", entry); - continue; - } - - SpellBonusEntry& sbe = mSpellBonusMap[entry]; - sbe.direct_damage = fields[1].GetFloat(); - sbe.dot_damage = fields[2].GetFloat(); - sbe.ap_bonus = fields[3].GetFloat(); - sbe.ap_dot_bonus = fields[4].GetFloat(); - - ++count; - } while (result->NextRow()); - - TC_LOG_INFO("server.loading", ">> Loaded %u extra spell bonus data in %u ms", count, GetMSTimeDiffToNow(oldMSTime)); -} - void SpellMgr::LoadSpellThreats() { uint32 oldMSTime = getMSTime(); @@ -3499,7 +3444,7 @@ void SpellMgr::LoadSpellInfoCorrections() 47134 // Quest Complete }, [](SpellInfo* spellInfo) { - //! HACK: This spell break quest complete for alliance and on retail not used °_O + //! HACK: This spell break quest complete for alliance and on retail not used �_O spellInfo->Effects[EFFECT_0].Effect = 0; }); diff --git a/src/server/game/Spells/SpellMgr.h b/src/server/game/Spells/SpellMgr.h index 09faf5443c..e0a9ebeac3 100644 --- a/src/server/game/Spells/SpellMgr.h +++ b/src/server/game/Spells/SpellMgr.h @@ -290,16 +290,6 @@ struct SpellEnchantProcEntry typedef std::unordered_map SpellEnchantProcEventMap; -struct SpellBonusEntry -{ - float direct_damage; - float dot_damage; - float ap_bonus; - float ap_dot_bonus; -}; - -typedef std::unordered_map SpellBonusMap; - enum SpellGroup { SPELL_GROUP_NONE = 0, @@ -662,9 +652,6 @@ class TC_GAME_API SpellMgr SpellProcEntry const* GetSpellProcEntry(uint32 spellId) const; static bool CanSpellTriggerProcOnEvent(SpellProcEntry const& procEntry, ProcEventInfo& eventInfo); - // Spell bonus data table - SpellBonusEntry const* GetSpellBonusData(uint32 spellId) const; - // Spell threat table SpellThreatEntry const* GetSpellThreatEntry(uint32 spellID) const; @@ -716,7 +703,6 @@ class TC_GAME_API SpellMgr void LoadSpellGroups(); void LoadSpellGroupStackRules(); void LoadSpellProcs(); - void LoadSpellBonuses(); void LoadSpellThreats(); void LoadSkillLineAbilityMap(); void LoadSpellPetAuras(); @@ -748,7 +734,6 @@ class TC_GAME_API SpellMgr SpellGroupStackMap mSpellGroupStack; SameEffectStackMap mSpellSameEffectStack; SpellProcMap mSpellProcMap; - SpellBonusMap mSpellBonusMap; SpellThreatMap mSpellThreatMap; SpellPetAuraMap mSpellPetAuraMap; SpellLinkedMap mSpellLinkedMap; diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp index 69bba7576d..5a1b85c00f 100644 --- a/src/server/game/World/World.cpp +++ b/src/server/game/World/World.cpp @@ -1847,9 +1847,6 @@ void World::SetInitialWorldSettings() TC_LOG_INFO("server.loading", "Loading Spell Proc conditions and data..."); sSpellMgr->LoadSpellProcs(); - TC_LOG_INFO("server.loading", "Loading Spell Bonus Data..."); - sSpellMgr->LoadSpellBonuses(); - TC_LOG_INFO("server.loading", "Loading Aggro Spells Definitions..."); sSpellMgr->LoadSpellThreats(); diff --git a/src/server/scripts/Commands/cs_reload.cpp b/src/server/scripts/Commands/cs_reload.cpp index 262722d5da..bf5dbb735e 100644 --- a/src/server/scripts/Commands/cs_reload.cpp +++ b/src/server/scripts/Commands/cs_reload.cpp @@ -142,7 +142,6 @@ public: { "smart_scripts", rbac::RBAC_PERM_COMMAND_RELOAD_SMART_SCRIPTS, true, &HandleReloadSmartScripts, "" }, { "spell_required", rbac::RBAC_PERM_COMMAND_RELOAD_SPELL_REQUIRED, true, &HandleReloadSpellRequiredCommand, "" }, { "spell_area", rbac::RBAC_PERM_COMMAND_RELOAD_SPELL_AREA, true, &HandleReloadSpellAreaCommand, "" }, - { "spell_bonus_data", rbac::RBAC_PERM_COMMAND_RELOAD_SPELL_BONUS_DATA, true, &HandleReloadSpellBonusesCommand, "" }, { "spell_group", rbac::RBAC_PERM_COMMAND_RELOAD_SPELL_GROUP, true, &HandleReloadSpellGroupsCommand, "" }, { "spell_learn_spell", rbac::RBAC_PERM_COMMAND_RELOAD_SPELL_LEARN_SPELL, true, &HandleReloadSpellLearnSpellCommand, "" }, { "spell_loot_template", rbac::RBAC_PERM_COMMAND_RELOAD_SPELL_LOOT_TEMPLATE, true, &HandleReloadLootTemplatesSpellCommand, "" }, @@ -283,7 +282,6 @@ public: HandleReloadSpellLearnSpellCommand(handler, "a"); HandleReloadSpellLinkedSpellCommand(handler, "a"); HandleReloadSpellProcsCommand(handler, "a"); - HandleReloadSpellBonusesCommand(handler, "a"); HandleReloadSpellTargetPositionCommand(handler, "a"); HandleReloadSpellThreatsCommand(handler, "a"); HandleReloadSpellGroupStackRulesCommand(handler, "a"); @@ -854,14 +852,6 @@ public: return true; } - static bool HandleReloadSpellBonusesCommand(ChatHandler* handler, char const* /*args*/) - { - TC_LOG_INFO("misc", "Re-Loading Spell Bonus Data..."); - sSpellMgr->LoadSpellBonuses(); - handler->SendGlobalGMSysMessage("DB table `spell_bonus_data` (spell damage/healing coefficients) reloaded."); - return true; - } - static bool HandleReloadSpellTargetPositionCommand(ChatHandler* handler, char const* /*args*/) { TC_LOG_INFO("misc", "Re-Loading Spell target coordinates..."); diff --git a/src/server/scripts/Spells/spell_dk.cpp b/src/server/scripts/Spells/spell_dk.cpp index f95f51f663..cdf6981cc1 100644 --- a/src/server/scripts/Spells/spell_dk.cpp +++ b/src/server/scripts/Spells/spell_dk.cpp @@ -1863,6 +1863,20 @@ class spell_dk_strangulate : public SpellScript OnEffectHitTarget.Register(&spell_dk_strangulate::HandleCreatureInterrupt, EFFECT_0, SPELL_EFFECT_APPLY_AURA); } }; + +// 45477 - Icy Touch +class spell_dk_icy_touch : public SpellScript +{ + void CalculateDamage(Unit* /*victim*/, int32& /*damage*/, int32& flatMod, float& /*pctMod*/) + { + flatMod += GetCaster()->GetTotalAttackPowerValue(BASE_ATTACK) * 0.2f; + } + + void Register() override + { + CalcDamage.Register(&spell_dk_icy_touch::CalculateDamage); + } +}; } void AddSC_deathknight_spell_scripts() @@ -1901,6 +1915,7 @@ void AddSC_deathknight_spell_scripts() RegisterSpellScript(spell_dk_ghoul_taunt); RegisterSpellScript(spell_dk_howling_blast); RegisterSpellScript(spell_dk_icebound_fortitude); + RegisterSpellScript(spell_dk_icy_touch); RegisterSpellScript(spell_dk_improved_presence); RegisterSpellScript(spell_dk_killing_machine); RegisterSpellScript(spell_dk_necrotic_strike); @@ -1920,4 +1935,4 @@ void AddSC_deathknight_spell_scripts() RegisterSpellScript(spell_dk_unholy_command); RegisterSpellScript(spell_dk_vampiric_blood); RegisterSpellScript(spell_dk_will_of_the_necropolis); -} +} \ No newline at end of file diff --git a/src/server/scripts/Spells/spell_generic.cpp b/src/server/scripts/Spells/spell_generic.cpp index dc6766710a..c9b11b0182 100644 --- a/src/server/scripts/Spells/spell_generic.cpp +++ b/src/server/scripts/Spells/spell_generic.cpp @@ -5108,18 +5108,14 @@ class spell_gen_wounded : public SpellScript // 69041 - Rocket Barrage (Racial) class spell_gen_rocket_barrage : public SpellScript { - void HandleDamage(SpellEffIndex effIndex) + void CalculateDamage(Unit* /*victim*/, int32& /*damage*/, int32& flatMod, float& /*pctMod*/) { - Unit* caster = GetCaster(); - int32 basePoints = GetEffectValue() + caster->getLevel() * 2; - basePoints += caster->SpellBaseDamageBonusDone(GetSpellInfo()->GetSchoolMask()) * GetSpellInfo()->Effects[effIndex].BonusMultiplier; - basePoints += caster->GetTotalAttackPowerValue(caster->getClass() != CLASS_HUNTER ? BASE_ATTACK : RANGED_ATTACK) * GetSpellInfo()->BonusCoefficient; - SetEffectValue(basePoints); + flatMod += GetCaster()->getLevel() * 2; } void Register() override { - OnEffectLaunchTarget.Register(&spell_gen_rocket_barrage::HandleDamage, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE); + CalcDamage.Register(&spell_gen_rocket_barrage::CalculateDamage); } }; @@ -5494,4 +5490,4 @@ void AddSC_generic_spell_scripts() RegisterSpellScript(spell_gen_vehicle_control_link); RegisterSpellScript(spell_gen_polymorph_cast_visual); RegisterSpellScript(spell_gen_prevent_emotes); -} +} \ No newline at end of file diff --git a/src/server/scripts/Spells/spell_hunter.cpp b/src/server/scripts/Spells/spell_hunter.cpp index 4007587bb4..6c876e8af0 100644 --- a/src/server/scripts/Spells/spell_hunter.cpp +++ b/src/server/scripts/Spells/spell_hunter.cpp @@ -137,6 +137,20 @@ 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*/) + { + flatMod += GetCaster()->GetTotalAttackPowerValue(RANGED_ATTACK) * 0.0493f; + } + + void Register() override + { + CalcDamage.Register(&spell_hun_arcane_shot::CalculateDamage); + } +}; + // Universal helper to get the serpent sting aura of all variants of it (original and the procced versions of Serpent Spread) static Aura* GetSerpentStingAura(Unit* target, ObjectGuid casterGUID) { @@ -655,6 +669,11 @@ class spell_hun_steady_shot : public SpellScript return ValidateSpellInfo({ SPELL_HUNTER_STEADY_SHOT_FOCUS }); } + void CalculateDamage(Unit* /*victim*/, int32& /*damage*/, int32& flatMod, float& /*pctMod*/) + { + flatMod += GetCaster()->GetTotalAttackPowerValue(RANGED_ATTACK) * 0.021f; + } + void HandleLaunch(SpellEffIndex /*effIndex*/) { Unit* caster = GetCaster(); @@ -676,6 +695,7 @@ class spell_hun_steady_shot : public SpellScript void Register() override { + CalcDamage.Register(&spell_hun_steady_shot::CalculateDamage); OnEffectLaunch.Register(&spell_hun_steady_shot::HandleLaunch, EFFECT_0, SPELL_EFFECT_NORMALIZED_WEAPON_DMG); } }; @@ -1444,6 +1464,7 @@ void AddSC_hunter_spell_scripts() { using namespace Spells::Hunter; RegisterSpellScript(spell_hun_ancient_hysteria); + RegisterSpellScript(spell_hun_arcane_shot); RegisterSpellScript(spell_hun_camouflage); RegisterSpellScript(spell_hun_camouflage_duration); RegisterSpellScript(spell_hun_camouflage_triggered); @@ -1484,4 +1505,4 @@ void AddSC_hunter_spell_scripts() RegisterSpellScript(spell_hun_tnt); RegisterSpellScript(spell_hun_trap_launcher); RegisterSpellScript(spell_hun_wild_quiver); -} +} \ No newline at end of file diff --git a/src/server/scripts/Spells/spell_rogue.cpp b/src/server/scripts/Spells/spell_rogue.cpp index ff8447566a..6fb7250e8b 100644 --- a/src/server/scripts/Spells/spell_rogue.cpp +++ b/src/server/scripts/Spells/spell_rogue.cpp @@ -1286,6 +1286,37 @@ class spell_rog_gouge : public AuraScript } }; +// 16511 - Hemorrhage +class spell_rog_hemorrhage : public SpellScript +{ + bool Load() override + { + return GetCaster()->IsPlayer(); + } + + void CalculateDamage(Unit* /*victim*/, int32& /*damage*/, int32& /*flatMod*/, float& pctMod) + { + for (WeaponAttackType attType : { BASE_ATTACK, OFF_ATTACK }) + { + // Dealing additional 45% damage when a dagger is equipped + if (Item* item = GetCaster()->ToPlayer()->GetWeaponForAttack(attType, true)) + { + if (item->GetTemplate()->GetSubClass() == ITEM_SUBCLASS_WEAPON_DAGGER) + { + pctMod *= 1.45f; + return; + } + } + } + } + + void Register() override + { + CalcDamage.Register(&spell_rog_hemorrhage::CalculateDamage); + } +}; + + // -11327 - Vanish class spell_rog_vanish : public AuraScript { @@ -1388,6 +1419,7 @@ void AddSC_rogue_spell_scripts() RegisterSpellScript(spell_rog_eviscerate); RegisterSpellScript(spell_rog_glyph_of_hemorrhage); RegisterSpellScript(spell_rog_gouge); + RegisterSpellScript(spell_rog_hemorrhage); RegisterSpellScript(spell_rog_improved_expose_armor); new spell_rog_killing_spree(); RegisterSpellScript(spell_rog_main_gauche); @@ -1410,4 +1442,4 @@ void AddSC_rogue_spell_scripts() RegisterSpellScript(spell_rog_honor_among_thieves); RegisterSpellScript(spell_rog_vanish); RegisterSpellScript(spell_rogue_venomous_wounds); -} +} \ No newline at end of file diff --git a/src/server/scripts/Spells/spell_warrior.cpp b/src/server/scripts/Spells/spell_warrior.cpp index 4edec63236..ada154a93f 100644 --- a/src/server/scripts/Spells/spell_warrior.cpp +++ b/src/server/scripts/Spells/spell_warrior.cpp @@ -48,6 +48,7 @@ enum WarriorSpells SPELL_WARRIOR_DEEP_WOUNDS_PERIODIC = 12721, SPELL_WARRIOR_EXECUTE = 20647, SPELL_WARRIOR_GLYPH_OF_EXECUTION = 58367, + SPELL_WARRIOR_IMPENDING_VICTORY = 80128, SPELL_WARRIOR_INTERCEPT = 20252, SPELL_WARRIOR_JUGGERNAUT_CRIT_BONUS_BUFF = 65156, SPELL_WARRIOR_JUGGERNAUT_CRIT_BONUS_TALENT = 64976, @@ -95,10 +96,9 @@ class spell_warr_bloodthirst : public SpellScript return ValidateSpellInfo({ SPELL_WARRIOR_BLOODTHIRST }); } - void HandleDamage(SpellEffIndex /*effIndex*/) + void CalculateDamage(Unit* /*victim*/, int32& damage, int32& /*flatMod*/, float& /*pctMod*/) { - if (Unit* caster = GetCaster()) - SetEffectValue(CalculatePct(caster->GetTotalAttackPowerValue(BASE_ATTACK) * GetEffectValue(), 1)); + damage = CalculatePct(GetCaster()->GetTotalAttackPowerValue(BASE_ATTACK), damage); } void HandleBloodthirstHealEffect() @@ -108,7 +108,7 @@ class spell_warr_bloodthirst : public SpellScript void Register() override { - OnEffectLaunchTarget.Register(&spell_warr_bloodthirst::HandleDamage, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE); + CalcDamage.Register(&spell_warr_bloodthirst::CalculateDamage); AfterHit.Register(&spell_warr_bloodthirst::HandleBloodthirstHealEffect); } }; @@ -175,16 +175,17 @@ class spell_warr_charge : public SpellScript }; /// Updated 4.3.4 +// 12809 - Concussion Blow class spell_warr_concussion_blow : public SpellScript { - void HandleDummy(SpellEffIndex /*effIndex*/) + void CalculateDamage(Unit* victim, int32& damage, int32& flatMod, float& pctMod) { - SetEffectValue(CalculatePct(GetCaster()->GetTotalAttackPowerValue(BASE_ATTACK), GetSpellInfo()->Effects[EFFECT_2].CalcValue())); + damage = CalculatePct(GetCaster()->GetTotalAttackPowerValue(BASE_ATTACK), GetSpellInfo()->Effects[EFFECT_2].CalcValue()); } void Register() override { - OnEffectLaunchTarget.Register(&spell_warr_concussion_blow::HandleDummy, EFFECT_1, SPELL_EFFECT_SCHOOL_DAMAGE); + CalcDamage.Register(&spell_warr_concussion_blow::CalculateDamage); } }; @@ -237,6 +238,7 @@ class spell_warr_deep_wounds : public AuraScript }; /// Updated 4.3.4 +// 5308 - Execute class spell_warr_execute : public SpellScript { bool Validate(SpellInfo const* /*spellInfo*/) override @@ -244,36 +246,50 @@ class spell_warr_execute : public SpellScript return ValidateSpellInfo({ SPELL_WARRIOR_SUDDEN_DEATH }); } - void HandleEffect(SpellEffIndex /*effIndex*/) + // Formula: ${10+$AP*0.437*$m1/100} plus up to $m2 additional rage for up to ${10+$AP*0.437*$m1/100} extra damage + void CalculateDamage(Unit* /*victim*/, int32& damage, int32& /*flatMod*/, float& /*pctMod*/) { Unit* caster = GetCaster(); - if (!GetHitUnit()) + int apPct = GetSpellInfo()->Effects[EFFECT_0].CalcValue(caster); + + damage = static_cast(10 + CalculatePct(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.437, apPct)); + + int32 additionalRageCap = GetSpellInfo()->Effects[EFFECT_1].CalcValue(caster) * 10; + if (!additionalRageCap) return; - // Formula taken from DBC: "${10+$AP*0.437*$m1/100}" - int32 bp = int32(10 + caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.437f * GetEffectValue() / 100.0f); + int32 additionalRage = std::min(caster->GetPower(POWER_RAGE) - GetSpell()->GetPowerCost(), additionalRageCap); - // Up to 20 additional Rage can be converted into damage - // Formula taken from DBC: "to ${$ap*0.874*$m1/100-1}" - int32 additionalRage = std::min(caster->GetPower(POWER_RAGE) - GetSpell()->GetPowerCost(), GetSpellInfo()->Effects[EFFECT_1].CalcValue() * 10); - if (additionalRage > 0) - bp += (additionalRage * (caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.874f * GetEffectValue() / 100.0f - 1) / 200); + // Based on the pct of extra rage consumed the damage will be increased + float extraRagePct = additionalRage / additionalRageCap; + int32 bonusDamage = std::max(0, CalculatePct(caster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.874f, apPct) - 1); - SetEffectValue(bp); + damage += bonusDamage * extraRagePct; + + _additionalRageConsumed = additionalRage; + } + + void ConsumeAdditionalRage() + { + if (_additionalRageConsumed == 0) + return; - int32 preservedRage = 0; // Sudden Death bonus (keep 5/10 Rage after using Execute) - if (Aura const* aura = caster->GetAuraOfRankedSpell(SPELL_WARRIOR_SUDDEN_DEATH, caster->GetGUID())) + int32 preservedRage = 0; + if (Aura const* aura = GetCaster()->GetAuraOfRankedSpell(SPELL_WARRIOR_SUDDEN_DEATH, GetCaster()->GetGUID())) if (AuraEffect const* suddenDeath = aura->GetEffect(EFFECT_0)) - preservedRage = std::min(suddenDeath->GetAmount() * 10, GetSpell()->GetPowerCost() + additionalRage); + preservedRage = std::min(suddenDeath->GetAmount() * 10, GetSpell()->GetPowerCost() + _additionalRageConsumed); - caster->ModifyPower(POWER_RAGE, -(additionalRage - preservedRage)); + GetCaster()->ModifyPower(POWER_RAGE, -(_additionalRageConsumed - preservedRage)); } void Register() override { - OnEffectLaunchTarget.Register(&spell_warr_execute::HandleEffect, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE); + CalcDamage.Register(&spell_warr_execute::CalculateDamage); + AfterCast.Register(&spell_warr_execute::ConsumeAdditionalRage); } +private: + int32 _additionalRageConsumed = 0; }; // 58387 - Glyph of Sunder Armor @@ -479,6 +495,7 @@ class spell_warr_shattering_throw : public SpellScript }; /// Updated 4.3.4 +// 1464 - Slam class spell_warr_slam : public SpellScript { bool Validate(SpellInfo const* /*spellInfo*/) override @@ -535,27 +552,21 @@ class spell_warr_slam_triggered : public SpellScript _affectedByBloodsurge = GetCaster()->GetAuraEffect(SPELL_AURA_ADD_PCT_MODIFIER, SPELLFAMILY_WARRIOR, 0x0, 0x1000000, 0x0, GetCaster()->GetGUID()) != nullptr; } - void HandleBonusDamage(SpellEffIndex /*effIndex*/) + void CalculateDamage(Unit* /*victim*/, int32& /*damage*/, int32& /*flatMod*/, float& pctMod) { - Unit* caster = GetCaster(); - if (!caster) + // Bloodsurge damage bonus + if (!_affectedByBloodsurge) return; - int32 basePoints = GetEffectValue(); - - // Bloodsurge damage bonus - if (_affectedByBloodsurge) - if (Aura const* aura = caster->GetAuraOfRankedSpell(SPELL_WARRIOR_BLOODSURGE_R1)) - if (AuraEffect const* effect = aura->GetEffect(EFFECT_0)) - AddPct(basePoints, effect->GetAmount()); - - SetEffectValue(basePoints); + if (Aura const* aura = GetCaster()->GetAuraOfRankedSpell(SPELL_WARRIOR_BLOODSURGE_R1)) + if (AuraEffect const* effect = aura->GetEffect(EFFECT_0)) + AddPct(pctMod, effect->GetAmount()); } void Register() override { BeforeCast.Register(&spell_warr_slam_triggered::HandleBeforeCast); - OnEffectLaunchTarget.Register(&spell_warr_slam_triggered::HandleBonusDamage, EFFECT_1, SPELL_EFFECT_WEAPON_PERCENT_DAMAGE); + CalcDamage.Register(&spell_warr_slam_triggered::CalculateDamage); } private: bool _affectedByBloodsurge = false; @@ -688,7 +699,7 @@ private: // -46951 - Sword and Board class spell_warr_sword_and_board : public AuraScript -{private: +{ bool Validate(SpellInfo const* /*spellInfo*/) override { return ValidateSpellInfo({ SPELL_WARRIOR_SHIELD_SLAM }); @@ -719,39 +730,33 @@ class spell_warr_victory_rush : public SpellScript }); } - void HandleDamage(SpellEffIndex /*effIndex*/) + // ${$AP*$m1/100} + void CalculateDamage(Unit* /*victim*/, int32& damage, int32& /*flatMod*/, float& /*pctMod*/) { - SetEffectValue(CalculatePct(GetCaster()->GetTotalAttackPowerValue(BASE_ATTACK), GetSpellInfo()->Effects[EFFECT_0].CalcValue())); + damage = CalculatePct(GetCaster()->GetTotalAttackPowerValue(BASE_ATTACK), damage); } - void HandleImpendingVictoryHeal(SpellEffIndex effIndex) + void CalculateHeal(Unit* /*victim*/, int32& heal, int32& /*flatMod*/, float& /*pctMod*/) { - if (Unit* caster = GetCaster()) - { - // Impending Victory also allows players to cast Victory Rush but with 5% healing effect only - if (caster->HasAura(SPELL_WARRIOR_VICTORIOUS_IMPENDING_VICTORY)) - { - int32 damage = 5; + Unit* caster = GetCaster(); - // Glyph: Victory Rush - if (Player* modOwner = caster->GetSpellModOwner()) - modOwner->ApplySpellMod(GetSpellInfo(), SpellModOp::PointsIndex2, damage); - - SetEffectValue(damage); - } - else - SetEffectValue(GetSpellInfo()->Effects[effIndex].CalcValue()); - - caster->RemoveAurasDueToSpell(SPELL_WARRIOR_VICTORIOUS); - caster->RemoveAurasDueToSpell(SPELL_WARRIOR_VICTORIOUS_IMPENDING_VICTORY); - } + // Impending Victory has a chance to allow casting Victory rush but it only heals for $s1% of our health + if (caster->HasAura(SPELL_WARRIOR_VICTORIOUS_IMPENDING_VICTORY, caster->GetGUID())) + if (AuraEffect const* impendingVictoryEff = caster->GetAuraEffectOfRankedSpell(SPELL_WARRIOR_VICTORIOUS_IMPENDING_VICTORY, EFFECT_0, caster->GetGUID())) + heal = caster->CountPctFromMaxHealth(impendingVictoryEff->GetAmount()); } + void RemoveVictorious() + { + GetCaster()->RemoveAurasDueToSpell(SPELL_WARRIOR_VICTORIOUS); + GetCaster()->RemoveAurasDueToSpell(SPELL_WARRIOR_VICTORIOUS_IMPENDING_VICTORY); + } void Register() override { - OnEffectLaunchTarget.Register(&spell_warr_victory_rush::HandleDamage, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE); - OnEffectHitTarget.Register(&spell_warr_victory_rush::HandleImpendingVictoryHeal, EFFECT_2, SPELL_EFFECT_HEAL_PCT); + CalcDamage.Register(&spell_warr_victory_rush::CalculateDamage); + CalcHealing.Register(&spell_warr_victory_rush::CalculateHeal); + AfterCast.Register(&spell_warr_victory_rush::RemoveVictorious); } }; @@ -889,7 +894,7 @@ class spell_warr_thunder_clap : public SpellScript OnEffectHitTarget.Register(&spell_warr_thunder_clap::HandleHit, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE); } private: - bool _allowRendSpread; + bool _allowRendSpread = false; }; class spell_warr_shield_specialization : public AuraScript @@ -932,17 +937,18 @@ class spell_warr_blood_craze : public AuraScript // 46968 - Shockwave class spell_warr_shockwave : public SpellScript { - void HandleDamage(SpellEffIndex /*effIndex*/) + void CalculateDamage(Unit* /*victim*/, int32& damage, int32& /*flatMod*/, float& /*pctMod*/) { - SetEffectValue(CalculatePct(GetCaster()->GetTotalAttackPowerValue(BASE_ATTACK), GetSpellInfo()->Effects[EFFECT_2].CalcValue())); + damage = CalculatePct(GetCaster()->GetTotalAttackPowerValue(BASE_ATTACK), GetSpellInfo()->Effects[EFFECT_2].CalcValue(GetCaster())); } void Register() override { - OnEffectLaunchTarget.Register(&spell_warr_shockwave::HandleDamage, EFFECT_1, SPELL_EFFECT_SCHOOL_DAMAGE); + CalcDamage.Register(&spell_warr_shockwave::CalculateDamage); } }; +// 20243 - Devastate class spell_warr_devastate : public SpellScript { bool Validate(SpellInfo const* /*spellInfo*/) override @@ -1133,4 +1139,4 @@ void AddSC_warrior_spell_scripts() RegisterSpellScript(spell_warr_vigilance); RegisterSpellScript(spell_warr_vigilance_trigger); RegisterSpellScript(spell_warr_whirlwind); -} +} \ No newline at end of file