diff options
author | Shauren <shauren.trinity@gmail.com> | 2018-12-07 18:26:26 +0100 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2018-12-07 18:26:26 +0100 |
commit | 83bc1cbe647cf312bcffa937ff2224cf214af7ef (patch) | |
tree | f5c194c6477799c01f382b6e3d215a66cc1c4990 /src | |
parent | fb817ed24bddad984b9abbaa6247e4953a84bf08 (diff) |
Core/Spells: Improved spell value calculation - variance will not be applied to spells with forced basepoints from CastCustomSpell
Diffstat (limited to 'src')
-rw-r--r-- | src/server/game/Spells/Auras/SpellAuraEffects.cpp | 2 | ||||
-rw-r--r-- | src/server/game/Spells/Spell.cpp | 122 | ||||
-rw-r--r-- | src/server/game/Spells/Spell.h | 7 | ||||
-rw-r--r-- | src/server/game/Spells/SpellInfo.cpp | 112 | ||||
-rw-r--r-- | src/server/game/Spells/SpellInfo.h | 2 |
5 files changed, 82 insertions, 163 deletions
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp index a45c8a84ab4..3ed8cc430de 100644 --- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp +++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp @@ -563,7 +563,7 @@ pAuraEffectHandler AuraEffectHandler[TOTAL_AURAS]= AuraEffect::AuraEffect(Aura* base, uint32 effIndex, int32 *baseAmount, Unit* caster) : m_base(base), m_spellInfo(base->GetSpellInfo()), _effectInfo(base->GetSpellEffectInfo(effIndex)), -m_baseAmount(baseAmount ? *baseAmount : base->GetSpellEffectInfo(effIndex)->BasePoints), +m_baseAmount(baseAmount ? *baseAmount : _effectInfo->CalcBaseValue(caster, base->GetType() == UNIT_AURA_TYPE ? base->GetOwner()->ToUnit() : nullptr, base->GetCastItemLevel())), m_damage(0), m_critChance(0.0f), m_donePct(1.0f), m_spellmod(NULL), m_periodicTimer(0), m_tickNumber(0), m_effIndex(effIndex), m_canBeRecalculated(true), m_isPeriodic(false) diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 2ef7508616b..09d994e985d 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -491,7 +491,7 @@ void SpellCastTargets::OutDebug() const TC_LOG_DEBUG("spells", "pitch: %f", m_pitch); } -SpellValue::SpellValue(Difficulty diff, SpellInfo const* proto) +SpellValue::SpellValue(Difficulty diff, SpellInfo const* proto, Unit const* caster) { // todo 6.x SpellEffectInfoVector effects = proto->GetEffectsForDifficulty(diff); @@ -499,8 +499,9 @@ SpellValue::SpellValue(Difficulty diff, SpellInfo const* proto) memset(EffectBasePoints, 0, sizeof(EffectBasePoints)); for (SpellEffectInfo const* effect : effects) if (effect) - EffectBasePoints[effect->EffectIndex] = effect->BasePoints; + EffectBasePoints[effect->EffectIndex] = effect->CalcBaseValue(caster, nullptr, -1); + CustomBasePointsMask = 0; MaxAffectedTargets = proto->MaxAffectedTargets; RadiusMod = 1.0f; AuraStackAmount = 1; @@ -521,7 +522,7 @@ protected: Spell::Spell(Unit* caster, SpellInfo const* info, TriggerCastFlags triggerFlags, ObjectGuid originalCasterGUID, bool skipCheck) : m_spellInfo(info), m_caster((info->HasAttribute(SPELL_ATTR6_CAST_BY_CHARMER) && caster->GetCharmerOrOwner()) ? caster->GetCharmerOrOwner() : caster), -m_spellValue(new SpellValue(caster->GetMap()->GetDifficultyID(), m_spellInfo)) +m_spellValue(new SpellValue(caster->GetMap()->GetDifficultyID(), m_spellInfo, caster)) { _effects = info->GetEffectsForDifficulty(caster->GetMap()->GetDifficultyID()); @@ -537,7 +538,6 @@ m_spellValue(new SpellValue(caster->GetMap()->GetDifficultyID(), m_spellInfo)) m_delayAtDamageCount = 0; m_applyMultiplierMask = 0; - m_auraScaleMask = 0; memset(m_damageMultipliers, 0, sizeof(m_damageMultipliers)); // Get data for type of attack @@ -791,31 +791,6 @@ void Spell::SelectSpellTargets() } } } - else if (m_auraScaleMask) - { - bool checkLvl = !m_UniqueTargetInfo.empty(); - for (std::vector<TargetInfo>::iterator ihit = m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end();) - { - // remove targets which did not pass min level check - if (m_auraScaleMask && ihit->effectMask == m_auraScaleMask) - { - // Do not check for selfcast - if (!ihit->scaleAura && ihit->targetGUID != m_caster->GetGUID()) - { - ihit = m_UniqueTargetInfo.erase(ihit); - continue; - } - } - - ++ihit; - } - - if (checkLvl && m_UniqueTargetInfo.empty()) - { - SendCastResult(SPELL_FAILED_LOWLEVEL); - finish(false); - } - } } if (m_targets.HasDst()) @@ -2132,13 +2107,6 @@ void Spell::AddUnitTarget(Unit* target, uint32 effectMask, bool checkIfValid /*= if (targetGUID == ihit->targetGUID) // Found in list { ihit->effectMask |= effectMask; // Immune effects removed from mask - ihit->scaleAura = false; - if (m_auraScaleMask && ihit->effectMask == m_auraScaleMask && m_caster != target) - { - SpellInfo const* auraSpell = m_spellInfo->GetFirstRankSpell(); - if (uint32(target->GetLevelForTarget(m_caster) + 10) >= auraSpell->SpellLevel) - ihit->scaleAura = true; - } return; } } @@ -2153,13 +2121,6 @@ void Spell::AddUnitTarget(Unit* target, uint32 effectMask, bool checkIfValid /*= targetInfo.alive = target->IsAlive(); targetInfo.damage = 0; targetInfo.crit = false; - targetInfo.scaleAura = false; - if (m_auraScaleMask && targetInfo.effectMask == m_auraScaleMask && m_caster != target) - { - SpellInfo const* auraSpell = m_spellInfo->GetFirstRankSpell(); - if (uint32(target->GetLevelForTarget(m_caster) + 10) >= auraSpell->SpellLevel) - targetInfo.scaleAura = true; - } // Calculate hit result if (m_originalCaster) @@ -2402,7 +2363,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target) if (unit->IsPvP() && m_caster->GetTypeId() == TYPEID_PLAYER) enablePvP = true; // Decide on PvP flagging now, but act on it later. - SpellMissInfo missInfo2 = DoSpellHitOnUnit(spellHitTarget, mask, target->scaleAura); + SpellMissInfo missInfo2 = DoSpellHitOnUnit(spellHitTarget, mask); if (missInfo2 != SPELL_MISS_NONE) { @@ -2595,7 +2556,7 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target) } } -SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleAura) +SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask) { if (!unit || !effectMask) return SPELL_MISS_EVADE; @@ -2680,34 +2641,19 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleA if (aura_effmask) { - // Select rank for aura with level requirements only in specific cases - // Unit has to be target only of aura effect, both caster and target have to be players, target has to be other than unit target - SpellInfo const* aurSpellInfo = m_spellInfo; - int32 basePoints[MAX_SPELL_EFFECTS]; - if (scaleAura) - { - aurSpellInfo = m_spellInfo->GetAuraRankForLevel(unitTarget->getLevel()); - ASSERT(aurSpellInfo); - for (SpellEffectInfo const* effect : aurSpellInfo->GetEffectsForDifficulty(0)) - { - basePoints[effect->EffectIndex] = effect->BasePoints; - if (SpellEffectInfo const* myEffect = GetEffect(effect->EffectIndex)) - { - if (myEffect->Effect != effect->Effect) - { - aurSpellInfo = m_spellInfo; - break; - } - } - } - } - if (m_originalCaster) { + int32 basePoints[MAX_SPELL_EFFECTS]; + for (SpellEffectInfo const* auraSpellEffect : GetEffects()) + if (auraSpellEffect) + basePoints[auraSpellEffect->EffectIndex] = (m_spellValue->CustomBasePointsMask & (1 << auraSpellEffect->EffectIndex)) ? + m_spellValue->EffectBasePoints[auraSpellEffect->EffectIndex] : + auraSpellEffect->CalcBaseValue(m_originalCaster, unit, m_castItemLevel); + bool refresh = false; bool const resetPeriodicTimer = !(_triggeredCastFlags & TRIGGERED_DONT_RESET_PERIODIC_TIMER); - m_spellAura = Aura::TryRefreshStackOrCreate(aurSpellInfo, m_castId, effectMask, unit, - m_originalCaster, (aurSpellInfo == m_spellInfo) ? m_spellValue->EffectBasePoints : basePoints, + m_spellAura = Aura::TryRefreshStackOrCreate(m_spellInfo, m_castId, effectMask, unit, + m_originalCaster, basePoints, m_CastItem, ObjectGuid::Empty, &refresh, resetPeriodicTimer, ObjectGuid::Empty, m_castItemLevel); if (m_spellAura) { @@ -2722,7 +2668,7 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleA // Now Reduce spell duration using data received at spell hit int32 duration = m_spellAura->GetMaxDuration(); - float diminishMod = unit->ApplyDiminishingToDuration(aurSpellInfo, duration, m_originalCaster, diminishLevel); + float diminishMod = unit->ApplyDiminishingToDuration(m_spellInfo, duration, m_originalCaster, diminishLevel); // unit is immune to aura if it was diminished to 0 duration if (diminishMod == 0.0f) @@ -2743,13 +2689,13 @@ SpellMissInfo Spell::DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleA if (AuraApplication* aurApp = m_spellAura->GetApplicationOfTarget(m_originalCaster->GetGUID())) positive = aurApp->IsPositive(); - duration = m_originalCaster->ModSpellDuration(aurSpellInfo, unit, duration, positive, effectMask); + duration = m_originalCaster->ModSpellDuration(m_spellInfo, unit, duration, positive, effectMask); if (duration > 0) { // Haste modifies duration of channeled spells if (m_spellInfo->IsChanneled()) - m_originalCaster->ModSpellDurationTime(aurSpellInfo, duration, this); + m_originalCaster->ModSpellDurationTime(m_spellInfo, duration, this); else if (m_spellInfo->HasAttribute(SPELL_ATTR5_HASTE_AFFECT_DURATION)) { int32 origDuration = duration; @@ -2954,27 +2900,6 @@ void Spell::prepare(SpellCastTargets const* targets, AuraEffect const* triggered InitExplicitTargets(*targets); - // Fill aura scaling information - if (m_caster->IsControlledByPlayer() && !m_spellInfo->IsPassive() && m_spellInfo->SpellLevel && !m_spellInfo->IsChanneled() && !(_triggeredCastFlags & TRIGGERED_IGNORE_AURA_SCALING)) - { - for (SpellEffectInfo const* effect : GetEffects()) - { - if (effect && effect->Effect == SPELL_EFFECT_APPLY_AURA) - { - // Change aura with ranks only if basepoints are taken from spellInfo and aura is positive - if (m_spellInfo->IsPositiveEffect(effect->EffectIndex)) - { - m_auraScaleMask |= (1 << effect->EffectIndex); - if (m_spellValue->EffectBasePoints[effect->EffectIndex] != effect->BasePoints) - { - m_auraScaleMask = 0; - break; - } - } - } - } - } - m_spellState = SPELL_STATE_PREPARING; if (triggeredByAura) @@ -6036,7 +5961,8 @@ SpellCastResult Spell::CheckArenaAndRatedBattlegroundCastRules() int32 Spell::CalculateDamage(uint8 i, Unit const* target, float* var /*= nullptr*/) const { - return m_caster->CalculateSpellDamage(target, m_spellInfo, i, &m_spellValue->EffectBasePoints[i], var, m_castItemLevel); + bool needRecalculateBasePoints = !(m_spellValue->CustomBasePointsMask & (1 << i)); + return m_caster->CalculateSpellDamage(target, m_spellInfo, i, needRecalculateBasePoints ? nullptr : &m_spellValue->EffectBasePoints[i], var, m_castItemLevel); } bool Spell::CanAutoCast(Unit* target) @@ -7282,7 +7208,7 @@ SpellCastResult Spell::CanOpenLock(uint32 effIndex, uint32 lockId, SkillType& sk skillId = SkillByLockType(LockType(lockInfo->Index[j])); - if (skillId != SKILL_NONE || lockInfo->Index[j] == LOCKTYPE_PICKLOCK) + if (skillId != SKILL_NONE || lockInfo->Index[j] == LOCKTYPE_LOCKPICKING) { reqSkillValue = lockInfo->Skill[j]; @@ -7290,7 +7216,7 @@ SpellCastResult Spell::CanOpenLock(uint32 effIndex, uint32 lockId, SkillType& sk skillValue = 0; if (!m_CastItem && m_caster->GetTypeId() == TYPEID_PLAYER) skillValue = m_caster->ToPlayer()->GetSkillValue(skillId); - else if (lockInfo->Index[j] == LOCKTYPE_PICKLOCK) + else if (lockInfo->Index[j] == LOCKTYPE_LOCKPICKING) skillValue = m_caster->getLevel() * 5; // skill bonus provided by casting spell (mostly item spells) @@ -7317,8 +7243,8 @@ void Spell::SetSpellValue(SpellValueMod mod, int32 value) { if (mod < SPELLVALUE_BASE_POINT_END) { - if (SpellEffectInfo const* effect = GetEffect(mod)) - m_spellValue->EffectBasePoints[mod] = effect->CalcBaseValue(value); + m_spellValue->EffectBasePoints[mod] = value; + m_spellValue->CustomBasePointsMask |= 1 << mod; return; } diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h index 88ca04bd7a8..cd4f3f51a08 100644 --- a/src/server/game/Spells/Spell.h +++ b/src/server/game/Spells/Spell.h @@ -295,8 +295,9 @@ class TC_GAME_API SpellCastTargets struct SpellValue { - explicit SpellValue(Difficulty diff, SpellInfo const* proto); + explicit SpellValue(Difficulty diff, SpellInfo const* proto, Unit const* caster); int32 EffectBasePoints[MAX_SPELL_EFFECTS]; + uint32 CustomBasePointsMask; uint32 MaxAffectedTargets; float RadiusMod; uint8 AuraStackAmount; @@ -787,7 +788,6 @@ class TC_GAME_API Spell bool processed; bool alive; bool crit; - bool scaleAura; }; std::vector<TargetInfo> m_UniqueTargetInfo; uint32 m_channelTargetEffectMask; // Mask req. alive targets @@ -816,7 +816,7 @@ class TC_GAME_API Spell void AddDestTarget(SpellDestination const& dest, uint32 effIndex); void DoAllEffectOnTarget(TargetInfo* target); - SpellMissInfo DoSpellHitOnUnit(Unit* unit, uint32 effectMask, bool scaleAura); + SpellMissInfo DoSpellHitOnUnit(Unit* unit, uint32 effectMask); void DoTriggersOnSpellHit(Unit* unit, uint32 effMask); void DoAllEffectOnTarget(GOTargetInfo* target); void DoAllEffectOnTarget(ItemTargetInfo* target); @@ -883,7 +883,6 @@ class TC_GAME_API Spell SpellInfo const* m_triggeredByAuraSpell; bool m_skipCheck; - uint32 m_auraScaleMask; std::unique_ptr<PathGenerator> m_preGeneratedPath; std::vector<SpellLogEffectPowerDrainParams> _powerDrainTargets[MAX_SPELL_EFFECTS]; diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp index cc39622cc41..d1ae93cd318 100644 --- a/src/server/game/Spells/SpellInfo.cpp +++ b/src/server/game/Spells/SpellInfo.cpp @@ -461,12 +461,59 @@ bool SpellEffectInfo::IsUnitOwnedAuraEffect() const int32 SpellEffectInfo::CalcValue(Unit const* caster /*= nullptr*/, int32 const* bp /*= nullptr*/, Unit const* target /*= nullptr*/, float* variance /*= nullptr*/, int32 itemLevel /*= -1*/) const { float basePointsPerLevel = RealPointsPerLevel; - int32 basePoints = bp ? *bp : BasePoints; + // TODO: this needs to be a float, not rounded + int32 basePoints = CalcBaseValue(caster, target, itemLevel); + float value = bp ? *bp : basePoints; float comboDamage = PointsPerResource; + if (Scaling.Variance) + { + float delta = fabs(Scaling.Variance * 0.5f); + float valueVariance = frand(-delta, delta); + value += basePoints * valueVariance; + + if (variance) + *variance = valueVariance; + } + // base amount modification based on spell lvl vs caster lvl if (Scaling.Coefficient != 0.0f) { + if (Scaling.ResourceCoefficient) + comboDamage = Scaling.ResourceCoefficient * value; + } + else + { + if (GetScalingExpectedStat() == ExpectedStatType::None) + { + int32 level = caster ? int32(caster->getLevel()) : 0; + if (level > int32(_spellInfo->MaxLevel) && _spellInfo->MaxLevel > 0) + level = int32(_spellInfo->MaxLevel); + level -= int32(_spellInfo->BaseLevel); + if (level < 0) + level = 0; + value += level * basePointsPerLevel; + } + } + + // random damage + if (caster) + { + // bonus amount from combo points + if (caster->m_playerMovingMe && comboDamage) + if (uint32 comboPoints = caster->m_playerMovingMe->GetComboPoints()) + value += comboDamage * comboPoints; + + value = caster->ApplyEffectModifiers(_spellInfo, EffectIndex, value); + } + + return int32(round(value)); +} + +int32 SpellEffectInfo::CalcBaseValue(Unit const* caster, Unit const* target, int32 itemLevel) const +{ + if (Scaling.Coefficient != 0.0f) + { uint32 level = _spellInfo->SpellLevel; if (target && _spellInfo->IsPositiveEffect(EffectIndex) && (Effect == SPELL_EFFECT_APPLY_AURA)) level = target->getLevel(); @@ -520,25 +567,11 @@ int32 SpellEffectInfo::CalcValue(Unit const* caster /*= nullptr*/, int32 const* if (value != 0.0f && value < 1.0f) value = 1.0f; - if (Scaling.Variance) - { - float delta = fabs(Scaling.Variance * 0.5f); - float valueVariance = frand(-delta, delta); - value += value * valueVariance; - - if (variance) - *variance = valueVariance; - } - - basePoints = int32(round(value)); - - if (Scaling.ResourceCoefficient) - comboDamage = Scaling.ResourceCoefficient * value; + return int32(round(value)); } else { - int32 level = caster ? int32(caster->getLevel()) : 0; - float value = basePoints; + float value = BasePoints; ExpectedStatType stat = GetScalingExpectedStat(); if (stat != ExpectedStatType::None) { @@ -546,51 +579,12 @@ int32 SpellEffectInfo::CalcValue(Unit const* caster /*= nullptr*/, int32 const* stat = ExpectedStatType::CreatureAutoAttackDps; // TODO - add expansion and content tuning id args? - value = sDB2Manager.EvaluateExpectedStat(stat, level, -2, 0, CLASS_NONE) * value / 100.0f; - } - - if (Scaling.Variance) - { - float delta = fabs(Scaling.Variance * 0.5f); - float valueVariance = frand(-delta, delta); - value += value * valueVariance; - - if (variance) - *variance = valueVariance; + int32 level = caster ? int32(caster->getLevel()) : 1; + value = sDB2Manager.EvaluateExpectedStat(stat, level, -2, 0, CLASS_NONE) * BasePoints / 100.0f; } - 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; - } - - basePoints = int32(round(value)); + return int32(round(value)); } - - float value = float(basePoints); - - // random damage - if (caster) - { - // bonus amount from combo points - if (caster->m_playerMovingMe && comboDamage) - if (uint32 comboPoints = caster->m_playerMovingMe->GetComboPoints()) - value += comboDamage * comboPoints; - - value = caster->ApplyEffectModifiers(_spellInfo, EffectIndex, value); - } - - return int32(value); -} - -int32 SpellEffectInfo::CalcBaseValue(int32 value) const -{ - return value; } float SpellEffectInfo::CalcValueMultiplier(Unit* caster, Spell* spell) const diff --git a/src/server/game/Spells/SpellInfo.h b/src/server/game/Spells/SpellInfo.h index d1f8c40bb4b..0e04e33937d 100644 --- a/src/server/game/Spells/SpellInfo.h +++ b/src/server/game/Spells/SpellInfo.h @@ -368,7 +368,7 @@ public: bool IsUnitOwnedAuraEffect() const; int32 CalcValue(Unit const* caster = nullptr, int32 const* basePoints = nullptr, Unit const* target = nullptr, float* variance = nullptr, int32 itemLevel = -1) const; - int32 CalcBaseValue(int32 value) const; + int32 CalcBaseValue(Unit const* caster, Unit const* target, int32 itemLevel) const; float CalcValueMultiplier(Unit* caster, Spell* spell = NULL) const; float CalcDamageMultiplier(Unit* caster, Spell* spell = NULL) const; |