From 96975fcd6bbbc6151d32e1c1e99c5dfb8ded2f77 Mon Sep 17 00:00:00 2001 From: Ovahlord Date: Sat, 7 Jun 2025 11:33:17 +0200 Subject: [PATCH] Core/Spells: fixed combo points damage calculation * added GameTable class to simplify access to game table values --- src/server/game/DataStores/GameTable.cpp | 32 ++++++++++ src/server/game/DataStores/GameTable.h | 31 +++++++++ src/server/game/Miscellaneous/SharedDefines.h | 2 +- src/server/game/Spells/SpellInfo.cpp | 64 ++++++++++++------- src/server/game/Spells/SpellInfo.h | 1 + src/server/scripts/Spells/spell_rogue.cpp | 32 +++------- 6 files changed, 117 insertions(+), 45 deletions(-) create mode 100644 src/server/game/DataStores/GameTable.cpp create mode 100644 src/server/game/DataStores/GameTable.h diff --git a/src/server/game/DataStores/GameTable.cpp b/src/server/game/DataStores/GameTable.cpp new file mode 100644 index 0000000000..b11efb977e --- /dev/null +++ b/src/server/game/DataStores/GameTable.cpp @@ -0,0 +1,32 @@ +/* +* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#include "GameTable.h" +#include "DBCStores.h" +#include "DBCStructure.h" + +/*static*/ float GameTable::GetSpellScalingValue(uint8 level, UnitClass unitClass) +{ + if (level > GT_MAX_LEVEL) + return 0.0f; + + GtSpellScalingEntry const* gt = sGtSpellScalingStore.LookupEntry((unitClass - 1) * 100 + level -1); + if (!gt) + return 0.0f; + + return gt->value; +} diff --git a/src/server/game/DataStores/GameTable.h b/src/server/game/DataStores/GameTable.h new file mode 100644 index 0000000000..dc42f7ef79 --- /dev/null +++ b/src/server/game/DataStores/GameTable.h @@ -0,0 +1,31 @@ +/* +* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +#ifndef __GAMETABLE_H +#define __GAMETABLE_H + +#include "Define.h" + +enum UnitClass : uint8; + +class GameTable +{ +public: + static float GetSpellScalingValue(uint8 level, UnitClass unitClass); +}; + +#endif // __GAMETABLE_H diff --git a/src/server/game/Miscellaneous/SharedDefines.h b/src/server/game/Miscellaneous/SharedDefines.h index bf118f0de4..694eae0af1 100644 --- a/src/server/game/Miscellaneous/SharedDefines.h +++ b/src/server/game/Miscellaneous/SharedDefines.h @@ -139,7 +139,7 @@ enum Classes (1<<(CLASS_DEATH_KNIGHT-1))) // valid classes for creature_template.unit_class -enum UnitClass +enum UnitClass : uint8 { UNIT_CLASS_WARRIOR = 1, UNIT_CLASS_PALADIN = 2, diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp index a4dba7d7ac..8c2f12b72f 100644 --- a/src/server/game/Spells/SpellInfo.cpp +++ b/src/server/game/Spells/SpellInfo.cpp @@ -21,6 +21,7 @@ #include "Creature.h" #include "DBCStores.h" #include "GameClient.h" +#include "GameTable.h" #include "InstanceScript.h" #include "Item.h" #include "ItemTemplate.h" @@ -441,13 +442,18 @@ int32 SpellEffectInfo::CalcValue(WorldObject const* caster /*= nullptr*/, int32 // TODO: this needs to be a float, not rounded int basePoints = CalcBaseValue(caster, target); double value = bp ? *bp : basePoints; - double comboDamage = PointsPerComboPoint; Unit const* casterUnit = nullptr; if (caster) casterUnit = caster->ToUnit(); - if (DieSides) + if (Scaling.Variance != 0.0f) + { + float delta = fabs(Scaling.Variance * 0.5f); + double valueVariance = frand(-delta, delta); + value += double(basePoints) * valueVariance; + } + else if (DieSides) { // roll in a range <1;EffectDieSides> as of patch 3.3.3 if (DieSides == 1) @@ -455,20 +461,9 @@ int32 SpellEffectInfo::CalcValue(WorldObject const* caster /*= nullptr*/, int32 else value += (DieSides >= 1) ? irand(1, DieSides) : irand(DieSides, 1); } - else if (Scaling.Variance != 0.0f) - { - float delta = fabs(Scaling.Variance * 0.5f); - double valueVariance = frand(-delta, delta); - value += double(basePoints) * valueVariance; - } // base amount modification based on spell lvl vs caster lvl - if (Scaling.Coefficient != 0.0f) - { - if (Scaling.ComboPointsCoefficient != 0.0f) - comboDamage = Scaling.ComboPointsCoefficient * value; - } - else + if (Scaling.Coefficient == 0.0f) { if (casterUnit && basePointsPerLevel != 0.0) { @@ -484,12 +479,12 @@ int32 SpellEffectInfo::CalcValue(WorldObject const* caster /*= nullptr*/, int32 } } - // random damage - if (casterUnit) + // bonus amount from combo points + if (casterUnit && _spellInfo->HasAttribute(SPELL_ATTR1_FINISHING_MOVE_DAMAGE)) { - // bonus amount from combo points - if (comboDamage) - if (int32 comboPoints = casterUnit->GetGameClientMovingMe()->GetBasePlayer()->GetComboPoints()) + double comboDamage = CalcPointsPerResource(casterUnit); + if (comboDamage != 0.0) + if (uint8 comboPoints = casterUnit->GetGameClientMovingMe()->GetBasePlayer()->GetComboPoints()) value += comboDamage * comboPoints; } @@ -523,9 +518,7 @@ int32 SpellEffectInfo::CalcBaseValue(WorldObject const* caster, Unit const* targ if (!_spellInfo->Scaling.Class) return 0; - if (GtSpellScalingEntry const* gtScaling = sGtSpellScalingStore.LookupEntry(((_spellInfo->Scaling.Class > 0 ? _spellInfo->Scaling.Class : ((MAX_CLASSES - 1 /*last class*/) - _spellInfo->Scaling.Class)) - 1) * 100 + level - 1)) - value = gtScaling->value; - + value = GameTable::GetSpellScalingValue(level, static_cast(_spellInfo->Scaling.Class > 0 ? _spellInfo->Scaling.Class: (MAX_CLASSES - 1 /*last class*/) - _spellInfo->Scaling.Class)); value *= _spellInfo->GetSpellScalingMultiplier(level, false); } @@ -542,6 +535,33 @@ int32 SpellEffectInfo::CalcBaseValue(WorldObject const* caster, Unit const* targ } } +// Based on client function QuestTextParser::Spell_C_GetPointsPerResource (build 15595) +double SpellEffectInfo::CalcPointsPerResource(WorldObject const* caster) const +{ + double value = 0.0; + if (caster && caster->IsUnit()) + { + if (Scaling.Coefficient != 0.0f) + { + if (!_spellInfo->Scaling.Class) + return 0.0; + + int32 scalingClass = _spellInfo->Scaling.Class; + if (scalingClass < 0) + scalingClass = (MAX_CLASSES - 1 /*last class*/) - scalingClass; + + float scaledAmount = GameTable::GetSpellScalingValue(caster->ToUnit()->getLevel(), static_cast(scalingClass)); + scaledAmount *= _spellInfo->GetSpellScalingMultiplier(caster->ToUnit()->getLevel(), false) * Scaling.ComboPointsCoefficient; + value = scaledAmount; + } + } + + if (std::fabs(value) < 0.00000023841858 && PointsPerComboPoint != 0.0f) + return PointsPerComboPoint; + + return value; +} + float SpellEffectInfo::CalcValueMultiplier(WorldObject* caster, Spell* spell) const { float multiplier = Amplitude; diff --git a/src/server/game/Spells/SpellInfo.h b/src/server/game/Spells/SpellInfo.h index 7917f1dcf3..f0828757bc 100644 --- a/src/server/game/Spells/SpellInfo.h +++ b/src/server/game/Spells/SpellInfo.h @@ -295,6 +295,7 @@ public: int32 CalcValue(WorldObject const* caster = nullptr, int32 const* basePoints = nullptr, Unit const* target = nullptr) const; int32 CalcBaseValue(WorldObject const* caster, Unit const* target) const; + double CalcPointsPerResource(WorldObject const* caster) const; float CalcValueMultiplier(WorldObject* caster, Spell* spell = nullptr) const; float CalcDamageMultiplier(WorldObject* caster, Spell* spell = nullptr) const; diff --git a/src/server/scripts/Spells/spell_rogue.cpp b/src/server/scripts/Spells/spell_rogue.cpp index ab7c546048..ff8447566a 100644 --- a/src/server/scripts/Spells/spell_rogue.cpp +++ b/src/server/scripts/Spells/spell_rogue.cpp @@ -875,30 +875,18 @@ class spell_rog_eviscerate : public SpellScript return true; } - void ChangeDamage(SpellEffIndex /*effIndex*/) + void CalculateDamage(Unit* victim, int32& /*damage*/, int32& flatMod, float& pctMod) { - Unit* caster = GetCaster(); - Unit* target = GetHitUnit(); - if (!caster || !target) - return; + Player const* playerCaster = GetCaster()->ToPlayer(); + uint8 comboPoints = playerCaster->GetComboPoints(); + flatMod += static_cast(comboPoints * playerCaster->GetTotalAttackPowerValue(BASE_ATTACK) * 0.091f); - if (Player* player = caster->ToPlayer()) - { - int32 damage = GetEffectValue(); - damage += int32(player->GetComboPoints() * (player->GetTotalAttackPowerValue(BASE_ATTACK) * 0.091f)); + // Eviscerate and Envenom Bonus Damage (item set effect) + if (AuraEffect* aurEff = playerCaster->GetAuraEffect(SPELL_ROGUE_EVISCERATE_AND_ENVENOM_BONUS_DAMAGE, EFFECT_0)) + flatMod += comboPoints * aurEff->GetAmount(); - // Eviscerate and Envenom Bonus Damage (item set effect) - if (AuraEffect* aurEff = caster->GetAuraEffect(SPELL_ROGUE_EVISCERATE_AND_ENVENOM_BONUS_DAMAGE, EFFECT_0)) - damage += player->GetComboPoints() * aurEff->GetAmount(); - - if (AuraEffect* const revealingStrike = target->GetAuraEffect(SPELL_ROGUE_REVEALING_STRIKE, EFFECT_2, caster->GetGUID())) - { - damage += CalculatePct(damage, revealingStrike->GetAmount()); - revealingStrike->GetBase()->Remove(); - } - - SetEffectValue(damage); - } + if (AuraEffect* const revealingStrike = victim->GetAuraEffect(SPELL_ROGUE_REVEALING_STRIKE, EFFECT_2, playerCaster->GetGUID())) + AddPct(pctMod, revealingStrike->GetAmount()); } void HandleSerratedBlades(SpellEffIndex /*effIndex*/) @@ -916,7 +904,7 @@ class spell_rog_eviscerate : public SpellScript void Register() override { - OnEffectLaunchTarget.Register(&spell_rog_eviscerate::ChangeDamage, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE); + CalcDamage.Register(&spell_rog_eviscerate::CalculateDamage); OnEffectHitTarget.Register(&spell_rog_eviscerate::HandleSerratedBlades, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE); } };