aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Spells/SpellInfo.cpp
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2018-09-17 23:30:58 +0200
committerShauren <shauren.trinity@gmail.com>2018-09-17 23:30:58 +0200
commit573dd01c6c51c0898ac17bb3073a5a7e7db89193 (patch)
tree2efc5e5fa4cef609ad347d56b83841b003045a7b /src/server/game/Spells/SpellInfo.cpp
parent0c38fa1cf4dbec41452b851f214e8dc81f960bf6 (diff)
Core/Spells: Updated spell effect value calculation
Diffstat (limited to 'src/server/game/Spells/SpellInfo.cpp')
-rw-r--r--src/server/game/Spells/SpellInfo.cpp227
1 files changed, 137 insertions, 90 deletions
diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp
index d1dfa32f7cb..4a8695a60f5 100644
--- a/src/server/game/Spells/SpellInfo.cpp
+++ b/src/server/game/Spells/SpellInfo.cpp
@@ -368,6 +368,7 @@ SpellImplicitTargetInfo::StaticData SpellImplicitTargetInfo::_data[TOTAL_SPELL_
{TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 147
{TARGET_OBJECT_TYPE_NONE, TARGET_REFERENCE_TYPE_NONE, TARGET_SELECT_CATEGORY_NYI, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 148
{TARGET_OBJECT_TYPE_DEST, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_RANDOM}, // 149
+ {TARGET_OBJECT_TYPE_UNIT, TARGET_REFERENCE_TYPE_CASTER, TARGET_SELECT_CATEGORY_DEFAULT, TARGET_CHECK_DEFAULT, TARGET_DIR_NONE}, // 150
};
SpellEffectInfo::SpellEffectInfo(SpellInfo const* spellInfo, uint8 effIndex, SpellEffectEntry const* _effect)
@@ -377,7 +378,6 @@ SpellEffectInfo::SpellEffectInfo(SpellInfo const* spellInfo, uint8 effIndex, Spe
Effect = _effect ? _effect->Effect : 0;
ApplyAuraName = _effect ? _effect->EffectAura : 0;
ApplyAuraPeriod = _effect ? _effect->EffectAuraPeriod : 0;
- DieSides = _effect ? _effect->EffectDieSides : 0;
RealPointsPerLevel = _effect ? _effect->EffectRealPointsPerLevel : 0.0f;
BasePoints = _effect ? _effect->EffectBasePoints : 0;
PointsPerResource = _effect ? _effect->EffectPointsPerResource : 0.0f;
@@ -488,21 +488,32 @@ int32 SpellEffectInfo::CalcValue(Unit const* caster /*= nullptr*/, int32 const*
if (!_spellInfo->Scaling.Class)
return 0;
- if (!_spellInfo->Scaling.ScalesFromItemLevel)
+ uint32 effectiveItemLevel = itemLevel != -1 ? uint32(itemLevel) : 1u;
+ if (_spellInfo->Scaling.ScalesFromItemLevel || _spellInfo->HasAttribute(SPELL_ATTR11_SCALES_WITH_ITEM_LEVEL))
{
- if (!_spellInfo->HasAttribute(SPELL_ATTR11_SCALES_WITH_ITEM_LEVEL))
- value = GetSpellScalingColumnForClass(sSpellScalingGameTable.GetRow(level), _spellInfo->Scaling.Class);
- else
+ if (_spellInfo->Scaling.ScalesFromItemLevel)
+ effectiveItemLevel = _spellInfo->Scaling.ScalesFromItemLevel;
+
+ if (_spellInfo->Scaling.Class == -8)
{
- uint32 effectiveItemLevel = itemLevel != -1 ? uint32(itemLevel) : 1u;
- value = GetRandomPropertyPoints(effectiveItemLevel, ITEM_QUALITY_RARE, INVTYPE_CHEST, 0);
- if (IsAura() && ApplyAuraName == SPELL_AURA_MOD_RATING)
- if (GtCombatRatingsMultByILvl const* ratingMult = sCombatRatingsMultByILvlGameTable.GetRow(effectiveItemLevel))
- value *= ratingMult->ArmorMultiplier;
+ RandPropPointsEntry const* randPropPoints = sRandPropPointsStore.LookupEntry(effectiveItemLevel);
+ if (!randPropPoints)
+ randPropPoints = sRandPropPointsStore.AssertEntry(sRandPropPointsStore.GetNumRows() - 1);
+
+ value = randPropPoints->DamageReplaceStat;
}
+ else
+ value = GetRandomPropertyPoints(effectiveItemLevel, ITEM_QUALITY_RARE, INVTYPE_CHEST, 0);
}
else
- value = GetRandomPropertyPoints(_spellInfo->Scaling.ScalesFromItemLevel, ITEM_QUALITY_RARE, INVTYPE_CHEST, 0);
+ value = GetSpellScalingColumnForClass(sSpellScalingGameTable.GetRow(level), _spellInfo->Scaling.Class);
+
+ if (_spellInfo->Scaling.Class == -7)
+ {
+ // todo: get inventorytype here
+ if (GtCombatRatingsMultByILvl const* ratingMult = sCombatRatingsMultByILvlGameTable.GetRow(effectiveItemLevel))
+ value *= ratingMult->ArmorMultiplier;
+ }
}
value *= Scaling.Coefficient;
@@ -526,33 +537,36 @@ int32 SpellEffectInfo::CalcValue(Unit const* caster /*= nullptr*/, int32 const*
}
else
{
- if (caster)
+ int32 level = caster ? int32(caster->getLevel()) : 0;
+ float value = basePoints;
+ ExpectedStatType stat = GetScalingExpectedStat();
+ if (stat != ExpectedStatType::None)
{
- int32 level = int32(caster->getLevel());
- if (level > int32(_spellInfo->MaxLevel) && _spellInfo->MaxLevel > 0)
- level = int32(_spellInfo->MaxLevel);
- else if (level < int32(_spellInfo->BaseLevel))
- level = int32(_spellInfo->BaseLevel);
- level -= int32(_spellInfo->SpellLevel);
- basePoints += int32(level * basePointsPerLevel);
+ if (_spellInfo->HasAttribute(SPELL_ATTR0_LEVEL_DAMAGE_CALCULATION))
+ stat = ExpectedStatType::CreatureAutoAttackDps;
+
+ // TODO - add expansion and content tuning id args?
+ value = sDB2Manager.EvaluateExpectedStat(stat, level, -2, 0, CLASS_NONE) * value / 100.0f;
}
- // roll in a range <1;EffectDieSides> as of patch 3.3.3
- int32 randomPoints = int32(DieSides);
- switch (randomPoints)
+ if (Scaling.Variance)
{
- case 0: break;
- case 1: basePoints += 1; break; // range 1..1
- default:
- {
- // range can have positive (1..rand) and negative (rand..1) values, so order its for irand
- int32 randvalue = (randomPoints >= 1)
- ? irand(1, randomPoints)
- : irand(randomPoints, 1);
+ float delta = fabs(Scaling.Variance * 0.5f);
+ float valueVariance = frand(-delta, delta);
+ value += value * valueVariance;
- basePoints += randvalue;
- break;
- }
+ if (variance)
+ *variance = valueVariance;
+ }
+
+ if (stat == ExpectedStatType::None)
+ {
+ if (level > int32(_spellInfo->MaxLevel) && _spellInfo->MaxLevel > 0)
+ level = int32(_spellInfo->MaxLevel);
+ level -= int32(_spellInfo->BaseLevel);
+ if (level < 0)
+ level = 0;
+ value += level * basePointsPerLevel;
}
}
@@ -567,58 +581,6 @@ int32 SpellEffectInfo::CalcValue(Unit const* caster /*= nullptr*/, int32 const*
value += comboDamage * comboPoints;
value = caster->ApplyEffectModifiers(_spellInfo, EffectIndex, value);
-
- // amount multiplication based on caster's level
- if (!caster->IsControlledByPlayer() &&
- _spellInfo->SpellLevel && _spellInfo->SpellLevel != caster->getLevel() &&
- !basePointsPerLevel && (_spellInfo->HasAttribute(SPELL_ATTR0_LEVEL_DAMAGE_CALCULATION)))
- {
- bool canEffectScale = false;
- switch (Effect)
- {
- case SPELL_EFFECT_SCHOOL_DAMAGE:
- case SPELL_EFFECT_DUMMY:
- case SPELL_EFFECT_POWER_DRAIN:
- case SPELL_EFFECT_HEALTH_LEECH:
- case SPELL_EFFECT_HEAL:
- case SPELL_EFFECT_WEAPON_DAMAGE:
- case SPELL_EFFECT_POWER_BURN:
- case SPELL_EFFECT_SCRIPT_EFFECT:
- case SPELL_EFFECT_NORMALIZED_WEAPON_DMG:
- case SPELL_EFFECT_FORCE_CAST_WITH_VALUE:
- case SPELL_EFFECT_TRIGGER_SPELL_WITH_VALUE:
- case SPELL_EFFECT_TRIGGER_MISSILE_SPELL_WITH_VALUE:
- canEffectScale = true;
- break;
- default:
- break;
- }
-
- switch (ApplyAuraName)
- {
- case SPELL_AURA_PERIODIC_DAMAGE:
- case SPELL_AURA_DUMMY:
- case SPELL_AURA_PERIODIC_HEAL:
- case SPELL_AURA_DAMAGE_SHIELD:
- case SPELL_AURA_PROC_TRIGGER_DAMAGE:
- case SPELL_AURA_PERIODIC_LEECH:
- case SPELL_AURA_PERIODIC_MANA_LEECH:
- case SPELL_AURA_SCHOOL_ABSORB:
- case SPELL_AURA_PERIODIC_TRIGGER_SPELL_WITH_VALUE:
- canEffectScale = true;
- break;
- default:
- break;
- }
-
- if (canEffectScale)
- {
- GtNpcManaCostScalerEntry const* spellScaler = sNpcManaCostScalerGameTable.GetRow(_spellInfo->SpellLevel);
- GtNpcManaCostScalerEntry const* casterScaler = sNpcManaCostScalerGameTable.GetRow(caster->getLevel());
- if (spellScaler && casterScaler)
- value *= casterScaler->Scaler / spellScaler->Scaler;
- }
- }
}
return int32(value);
@@ -626,10 +588,7 @@ int32 SpellEffectInfo::CalcValue(Unit const* caster /*= nullptr*/, int32 const*
int32 SpellEffectInfo::CalcBaseValue(int32 value) const
{
- if (DieSides == 0)
- return value;
- else
- return value - 1;
+ return value;
}
float SpellEffectInfo::CalcValueMultiplier(Unit* caster, Spell* spell) const
@@ -723,6 +682,94 @@ SpellTargetObjectTypes SpellEffectInfo::GetUsedTargetObjectType() const
return _data[Effect].UsedTargetObjectType;
}
+ExpectedStatType SpellEffectInfo::GetScalingExpectedStat() const
+{
+ switch (Effect)
+ {
+ case SPELL_EFFECT_SCHOOL_DAMAGE:
+ case SPELL_EFFECT_ENVIRONMENTAL_DAMAGE:
+ case SPELL_EFFECT_HEALTH_LEECH:
+ case SPELL_EFFECT_WEAPON_DAMAGE_NOSCHOOL:
+ case SPELL_EFFECT_WEAPON_DAMAGE:
+ return ExpectedStatType::CreatureSpellDamage;
+ case SPELL_EFFECT_HEAL:
+ case SPELL_EFFECT_HEAL_MECHANICAL:
+ return ExpectedStatType::PlayerHealth;
+ case SPELL_EFFECT_ENERGIZE:
+ case SPELL_EFFECT_POWER_BURN:
+ if (!MiscValue)
+ return ExpectedStatType::PlayerMana;
+ return ExpectedStatType::None;
+ case SPELL_EFFECT_POWER_DRAIN:
+ return ExpectedStatType::PlayerMana;
+ case SPELL_EFFECT_APPLY_AURA:
+ case SPELL_EFFECT_PERSISTENT_AREA_AURA:
+ case SPELL_EFFECT_APPLY_AREA_AURA_PARTY:
+ case SPELL_EFFECT_APPLY_AREA_AURA_RAID:
+ case SPELL_EFFECT_APPLY_AREA_AURA_PET:
+ case SPELL_EFFECT_APPLY_AREA_AURA_FRIEND:
+ case SPELL_EFFECT_APPLY_AREA_AURA_ENEMY:
+ case SPELL_EFFECT_APPLY_AREA_AURA_OWNER:
+ case SPELL_EFFECT_APPLY_AURA_ON_PET:
+ case SPELL_EFFECT_202:
+ switch (ApplyAuraName)
+ {
+ case SPELL_AURA_PERIODIC_DAMAGE:
+ case SPELL_AURA_MOD_DAMAGE_DONE:
+ case SPELL_AURA_DAMAGE_SHIELD:
+ case SPELL_AURA_PROC_TRIGGER_DAMAGE:
+ case SPELL_AURA_PERIODIC_LEECH:
+ case SPELL_AURA_MOD_DAMAGE_DONE_CREATURE:
+ case SPELL_AURA_PERIODIC_HEALTH_FUNNEL:
+ case SPELL_AURA_MOD_MELEE_ATTACK_POWER_VERSUS:
+ case SPELL_AURA_MOD_RANGED_ATTACK_POWER_VERSUS:
+ case SPELL_AURA_MOD_FLAT_SPELL_DAMAGE_VERSUS:
+ return ExpectedStatType::CreatureSpellDamage;
+ case SPELL_AURA_PERIODIC_HEAL:
+ case SPELL_AURA_MOD_DAMAGE_TAKEN:
+ case SPELL_AURA_MOD_INCREASE_HEALTH:
+ case SPELL_AURA_SCHOOL_ABSORB:
+ case SPELL_AURA_MOD_REGEN:
+ case SPELL_AURA_MANA_SHIELD:
+ case SPELL_AURA_MOD_HEALING:
+ case SPELL_AURA_MOD_HEALING_DONE:
+ case SPELL_AURA_MOD_HEALTH_REGEN_IN_COMBAT:
+ case SPELL_AURA_MOD_MAX_HEALTH:
+ case SPELL_AURA_MOD_INCREASE_HEALTH_2:
+ case SPELL_AURA_SCHOOL_HEAL_ABSORB:
+ return ExpectedStatType::PlayerHealth;
+ case SPELL_AURA_PERIODIC_MANA_LEECH:
+ return ExpectedStatType::PlayerMana;
+ case SPELL_AURA_MOD_STAT:
+ case SPELL_AURA_MOD_ATTACK_POWER:
+ case SPELL_AURA_MOD_RANGED_ATTACK_POWER:
+ return ExpectedStatType::PlayerPrimaryStat;
+ case SPELL_AURA_MOD_RATING:
+ return ExpectedStatType::PlayerSecondaryStat;
+ case SPELL_AURA_MOD_RESISTANCE:
+ case SPELL_AURA_MOD_BASE_RESISTANCE:
+ case SPELL_AURA_MOD_TARGET_RESISTANCE:
+ case SPELL_AURA_MOD_BONUS_ARMOR:
+ return ExpectedStatType::ArmorConstant;
+ case SPELL_AURA_PERIODIC_ENERGIZE:
+ case SPELL_AURA_MOD_INCREASE_ENERGY:
+ case SPELL_AURA_MOD_POWER_COST_SCHOOL:
+ case SPELL_AURA_MOD_POWER_REGEN:
+ case SPELL_AURA_POWER_BURN:
+ case SPELL_AURA_MOD_MAX_POWER:
+ if (!MiscValue)
+ return ExpectedStatType::PlayerMana;
+ return ExpectedStatType::None;
+ default:
+ break;
+ }
+ default:
+ break;
+ }
+
+ return ExpectedStatType::None;
+}
+
SpellEffectInfo::StaticData SpellEffectInfo::_data[TOTAL_SPELL_EFFECTS] =
{
// implicit target type used target object type
@@ -1042,7 +1089,7 @@ SpellInfo::SpellInfo(SpellInfoLoadHelper const& data, SpellEffectEntryMap const&
// SpellAuraOptionsEntry
SpellAuraOptionsEntry const* _options = data.AuraOptions;
SpellProcsPerMinuteEntry const* _ppm = _options ? sSpellProcsPerMinuteStore.LookupEntry(_options->SpellProcsPerMinuteID) : nullptr;
- ProcFlags = _options ? _options->ProcTypeMask : 0;
+ ProcFlags = _options ? _options->ProcTypeMask[0] : 0;
ProcChance = _options ? _options->ProcChance : 0;
ProcCharges = _options ? _options->ProcCharges : 0;
ProcCooldown = _options ? _options->ProcCategoryRecovery : 0;