Core/Spells: fixed combo points damage calculation

* added GameTable class to simplify access to game table values
This commit is contained in:
Ovahlord committed 2025-06-07 11:40:18 +02:00
1 parent 4524c29f2c
commit 96975fcd6b
6 files changed
+117 -45

No files matched your search

+32
View File
@@ -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 <http://www.gnu.org/licenses/>.
*/
#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;
}
+31
View File
@@ -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 <http://www.gnu.org/licenses/>.
*/
#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
@@ -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,
+42 -22
View File
@@ -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<UnitClass>(_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<UnitClass>(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;
+1
View File
@@ -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;
+10 -22
View File
@@ -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<int32>(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);
}
};