diff options
| author | Shauren <shauren.trinity@gmail.com> | 2018-09-17 23:30:58 +0200 |
|---|---|---|
| committer | Shauren <shauren.trinity@gmail.com> | 2018-09-17 23:30:58 +0200 |
| commit | 573dd01c6c51c0898ac17bb3073a5a7e7db89193 (patch) | |
| tree | 2efc5e5fa4cef609ad347d56b83841b003045a7b /src/server/game/Spells/SpellInfo.cpp | |
| parent | 0c38fa1cf4dbec41452b851f214e8dc81f960bf6 (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.cpp | 227 |
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; |
