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);
}
};