diff --git a/modules/mod-paragon/src/Paragon_SC.cpp b/modules/mod-paragon/src/Paragon_SC.cpp index b927d9c..476e36b 100644 --- a/modules/mod-paragon/src/Paragon_SC.cpp +++ b/modules/mod-paragon/src/Paragon_SC.cpp @@ -15,7 +15,6 @@ #include "SharedDefines.h" #include "SpellScript.h" #include "SpellScriptLoader.h" -#include "UnitDefines.h" #include "WorldPacket.h" #include "WorldSession.h" diff --git a/src/server/game/Entities/Unit/StatSystem.cpp b/src/server/game/Entities/Unit/StatSystem.cpp index 24c025a..c66aa3e 100644 --- a/src/server/game/Entities/Unit/StatSystem.cpp +++ b/src/server/game/Entities/Unit/StatSystem.cpp @@ -385,6 +385,13 @@ void Player::UpdateAttackPowerAndDamage(bool ranged) break; } } + else if (getClass() == CLASS_PARAGON) + { + // Fractured class 12: same hybrid curve as requested for Paragon UI + // (level*2 + AGI + STR - 20). Implemented in core so we do not rely + // on PlayerScript hooks in this hot path. + val2 = level * 2.0f + GetStat(STAT_AGILITY) + GetStat(STAT_STRENGTH) - 20.0f; + } else { val2 = GetStat(STAT_AGILITY) - 10.0f; @@ -481,6 +488,10 @@ void Player::UpdateAttackPowerAndDamage(bool ranged) break; } } + else if (getClass() == CLASS_PARAGON) + { + val2 = level * 2.0f + GetStat(STAT_STRENGTH) + GetStat(STAT_AGILITY) - 20.0f; + } else if (IsClass(CLASS_MAGE, CLASS_CONTEXT_STATS) || IsClass(CLASS_PRIEST, CLASS_CONTEXT_STATS) || IsClass(CLASS_WARLOCK, CLASS_CONTEXT_STATS)) { val2 = GetStat(STAT_STRENGTH) - 10.0f; diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 48a75ac..4e84d0a 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -9046,6 +9046,21 @@ int32 Unit::SpellBaseDamageBonusDone(SpellSchoolMask schoolMask) DoneAdvertisedBenefit += ToPlayer()->GetBaseSpellPowerBonus(); DoneAdvertisedBenefit += ToPlayer()->GetBaseSpellDamageBonus(); + // Fractured class 12 (Paragon) intrinsic spell power: + // SP = level*2 + INT + SPI - 20 (clamped at 0) + // Read live from current stats so character-sheet refreshes (via + // UpdateSpellDamageAndHealingBonus) and live spell casts both see the + // up-to-date value with no script hooks or m_baseSpellPower mutation. + if (ToPlayer()->getClass() == CLASS_PARAGON) + { + int32 paragonSP = int32(GetLevel()) * 2 + + int32(GetStat(STAT_INTELLECT)) + + int32(GetStat(STAT_SPIRIT)) + - 20; + if (paragonSP > 0) + DoneAdvertisedBenefit += paragonSP; + } + // Damage bonus from stats AuraEffectList const& mDamageDoneOfStatPercent = GetAuraEffectsByType(SPELL_AURA_MOD_SPELL_DAMAGE_OF_STAT_PERCENT); for (AuraEffectList::const_iterator i = mDamageDoneOfStatPercent.begin(); i != mDamageDoneOfStatPercent.end(); ++i) @@ -9803,6 +9818,20 @@ int32 Unit::SpellBaseHealingBonusDone(SpellSchoolMask schoolMask) AdvertisedBenefit += ToPlayer()->GetBaseSpellPowerBonus(); AdvertisedBenefit += ToPlayer()->GetBaseSpellHealingBonus(); + // Fractured class 12 (Paragon) intrinsic spell power: same level*2 + + // INT + SPI - 20 floor as on the damage side (the character sheet + // shows a single Spell Power value, so both sides must add the same + // bonus). + if (ToPlayer()->getClass() == CLASS_PARAGON) + { + int32 paragonSP = int32(GetLevel()) * 2 + + int32(GetStat(STAT_INTELLECT)) + + int32(GetStat(STAT_SPIRIT)) + - 20; + if (paragonSP > 0) + AdvertisedBenefit += paragonSP; + } + // Healing bonus from stats AuraEffectList const& mHealingDoneOfStatPercent = GetAuraEffectsByType(SPELL_AURA_MOD_SPELL_HEALING_OF_STAT_PERCENT); for (AuraEffectList::const_iterator i = mHealingDoneOfStatPercent.begin(); i != mHealingDoneOfStatPercent.end(); ++i)