diff options
Diffstat (limited to 'src/server/game/Spells/Spell.cpp')
| -rw-r--r-- | src/server/game/Spells/Spell.cpp | 255 |
1 files changed, 134 insertions, 121 deletions
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp index 2a7b550392a..b37a44d6e70 100644 --- a/src/server/game/Spells/Spell.cpp +++ b/src/server/game/Spells/Spell.cpp @@ -592,7 +592,7 @@ m_caster((info->HasAttribute(SPELL_ATTR6_CAST_BY_CHARMER) && caster->GetCharmerO m_healing = 0; m_procAttacker = 0; m_procVictim = 0; - m_procEx = 0; + m_hitMask = 0; focusObject = NULL; m_cast_count = 0; m_glyphIndex = 0; @@ -1481,7 +1481,7 @@ void Spell::SelectImplicitChainTargets(SpellEffIndex effIndex, SpellImplicitTarg { uint32 maxTargets = m_spellInfo->Effects[effIndex].ChainTarget; if (Player* modOwner = m_caster->GetSpellModOwner()) - modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_JUMP_TARGETS, maxTargets, this); + modOwner->ApplySpellMod<SPELLMOD_JUMP_TARGETS>(m_spellInfo->Id, maxTargets, this); if (maxTargets > 1) { @@ -1947,12 +1947,11 @@ GameObject* Spell::SearchSpellFocus() return focus; } -void Spell::prepareDataForTriggerSystem(AuraEffect const* /*triggeredByAura*/) +void Spell::prepareDataForTriggerSystem() { //========================================================================================== // Now fill data for trigger system, need know: - // can spell trigger another or not (m_canTrigger) - // Create base triggers flags for Attacker and Victim (m_procAttacker, m_procVictim and m_procEx) + // Create base triggers flags for Attacker and Victim (m_procAttacker, m_procVictim and m_hitMask) //========================================================================================== m_procVictim = m_procAttacker = 0; @@ -1982,7 +1981,7 @@ void Spell::prepareDataForTriggerSystem(AuraEffect const* /*triggeredByAura*/) break; default: if (m_spellInfo->EquippedItemClass == ITEM_CLASS_WEAPON && - m_spellInfo->EquippedItemSubClassMask & (1<<ITEM_SUBCLASS_WEAPON_WAND) + m_spellInfo->EquippedItemSubClassMask & (1 << ITEM_SUBCLASS_WEAPON_WAND) && m_spellInfo->HasAttribute(SPELL_ATTR2_AUTOREPEAT_FLAG)) // Wands auto attack { m_procAttacker = PROC_FLAG_DONE_RANGED_AUTO_ATTACK; @@ -1991,7 +1990,7 @@ void Spell::prepareDataForTriggerSystem(AuraEffect const* /*triggeredByAura*/) // For other spells trigger procflags are set in Spell::DoAllEffectOnTarget // Because spell positivity is dependant on target } - m_procEx = PROC_EX_NONE; + m_hitMask = PROC_HIT_NONE; // Hunter trap spells - activation proc for Lock and Load, Entrapment and Misdirection if (m_spellInfo->SpellFamilyName == SPELLFAMILY_HUNTER && @@ -2000,29 +1999,12 @@ void Spell::prepareDataForTriggerSystem(AuraEffect const* /*triggeredByAura*/) m_spellInfo->SpellFamilyFlags[2] & 0x00024000)) // Explosive and Immolation Trap m_procAttacker |= PROC_FLAG_DONE_TRAP_ACTIVATION; - /* Effects which are result of aura proc from triggered spell cannot proc - to prevent chain proc of these spells */ - // Hellfire Effect - trigger as DOT if (m_spellInfo->SpellFamilyName == SPELLFAMILY_WARLOCK && m_spellInfo->SpellFamilyFlags[0] & 0x00000040) { m_procAttacker = PROC_FLAG_DONE_PERIODIC; m_procVictim = PROC_FLAG_TAKEN_PERIODIC; } - - // Ranged autorepeat attack is set as triggered spell - ignore it - if (!(m_procAttacker & PROC_FLAG_DONE_RANGED_AUTO_ATTACK)) - { - if (_triggeredCastFlags & TRIGGERED_DISALLOW_PROC_EVENTS && - (m_spellInfo->HasAttribute(SPELL_ATTR2_TRIGGERED_CAN_TRIGGER_PROC) || - m_spellInfo->HasAttribute(SPELL_ATTR3_TRIGGERED_CAN_TRIGGER_PROC_2))) - m_procEx |= PROC_EX_INTERNAL_CANT_PROC; - else if (_triggeredCastFlags & TRIGGERED_DISALLOW_PROC_EVENTS) - m_procEx |= PROC_EX_INTERNAL_TRIGGERED; - } - // Totem casts require spellfamilymask defined in spell_proc_event to proc - if (m_originalCaster && m_caster != m_originalCaster && m_caster->GetTypeId() == TYPEID_UNIT && m_caster->IsTotem() && m_caster->IsControlledByPlayer()) - m_procEx |= PROC_EX_INTERNAL_REQ_FAMILY; } void Spell::CleanupTargetList() @@ -2033,6 +2015,32 @@ void Spell::CleanupTargetList() m_delayMoment = 0; } +class ProcReflectDelayed : public BasicEvent +{ + public: + ProcReflectDelayed(Unit* owner, ObjectGuid casterGuid) : _victim(owner), _casterGuid(casterGuid) { } + + bool Execute(uint64 /*e_time*/, uint32 /*p_time*/) override + { + Unit* caster = ObjectAccessor::GetUnit(*_victim, _casterGuid); + if (!caster) + return true; + + uint32 const typeMaskActor = PROC_FLAG_NONE; + uint32 const typeMaskActionTarget = PROC_FLAG_TAKEN_SPELL_MAGIC_DMG_CLASS_NEG | PROC_FLAG_TAKEN_SPELL_NONE_DMG_CLASS_NEG; + uint32 const spellTypeMask = PROC_SPELL_TYPE_DAMAGE | PROC_SPELL_TYPE_NO_DMG_HEAL; + uint32 const spellPhaseMask = PROC_SPELL_PHASE_NONE; + uint32 const hitMask = PROC_HIT_REFLECT; + + caster->ProcSkillsAndAuras(_victim, typeMaskActor, typeMaskActionTarget, spellTypeMask, spellPhaseMask, hitMask, nullptr, nullptr, nullptr); + return true; + } + + private: + Unit* _victim; + ObjectGuid _casterGuid; +}; + void Spell::AddUnitTarget(Unit* target, uint32 effectMask, bool checkIfValid /*= true*/, bool implicit /*= true*/, Position const* losPosition /*= nullptr*/) { for (uint32 effIndex = 0; effIndex < MAX_SPELL_EFFECTS; ++effIndex) @@ -2112,20 +2120,20 @@ void Spell::AddUnitTarget(Unit* target, uint32 effectMask, bool checkIfValid /*= targetInfo.timeDelay = (uint64)std::floor(dist / m_spellInfo->Speed * 1000.0f); // Calculate minimum incoming time - if (m_delayMoment == 0 || m_delayMoment > targetInfo.timeDelay) + if (!m_delayMoment || m_delayMoment > targetInfo.timeDelay) m_delayMoment = targetInfo.timeDelay; } else - targetInfo.timeDelay = 0LL; + targetInfo.timeDelay = 0ULL; // If target reflect spell back to caster if (targetInfo.missCondition == SPELL_MISS_REFLECT) { // Calculate reflected spell result on caster - targetInfo.reflectResult = m_caster->SpellHitResult(m_caster, m_spellInfo, m_canReflect); + targetInfo.reflectResult = m_caster->SpellHitResult(m_caster, m_spellInfo, false); // can't reflect twice - if (targetInfo.reflectResult == SPELL_MISS_REFLECT) // Impossible reflect again, so simply deflect spell - targetInfo.reflectResult = SPELL_MISS_PARRY; + // Proc spell reflect aura when missile hits the original target + target->m_Events.AddEvent(new ProcReflectDelayed(target, m_originalCasterGUID), target->m_Events.CalculateTime(targetInfo.timeDelay)); // Increase time interval for reflected spells by 1.5 targetInfo.timeDelay += targetInfo.timeDelay >> 1; @@ -2147,14 +2155,14 @@ void Spell::AddGOTarget(GameObject* go, uint32 effectMask) { switch (m_spellInfo->Effects[effIndex].Effect) { - case SPELL_EFFECT_GAMEOBJECT_DAMAGE: - case SPELL_EFFECT_GAMEOBJECT_REPAIR: - case SPELL_EFFECT_GAMEOBJECT_SET_DESTRUCTION_STATE: - if (go->GetGoType() != GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING) - effectMask &= ~(1 << effIndex); - break; - default: - break; + case SPELL_EFFECT_GAMEOBJECT_DAMAGE: + case SPELL_EFFECT_GAMEOBJECT_REPAIR: + case SPELL_EFFECT_GAMEOBJECT_SET_DESTRUCTION_STATE: + if (go->GetGoType() != GAMEOBJECT_TYPE_DESTRUCTIBLE_BUILDING) + effectMask &= ~(1 << effIndex); + break; + default: + break; } } } @@ -2189,7 +2197,7 @@ void Spell::AddGOTarget(GameObject* go, uint32 effectMask) if (dist < 5.0f) dist = 5.0f; target.timeDelay = uint64(floor(dist / m_spellInfo->Speed * 1000.0f)); - if (m_delayMoment == 0 || m_delayMoment > target.timeDelay) + if (!m_delayMoment || m_delayMoment > target.timeDelay) m_delayMoment = target.timeDelay; } else @@ -2297,13 +2305,13 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target) // Fill base trigger info uint32 procAttacker = m_procAttacker; uint32 procVictim = m_procVictim; - uint32 procEx = m_procEx; + uint32 hitMask = m_hitMask; - m_spellAura = NULL; // Set aura to null for every target-make sure that pointer is not used for unit without aura applied + m_spellAura = nullptr; // Set aura to null for every target-make sure that pointer is not used for unit without aura applied - //Spells with this flag cannot trigger if effect is cast on self - bool canEffectTrigger = !m_spellInfo->HasAttribute(SPELL_ATTR3_CANT_TRIGGER_PROC) && unitTarget->CanProc() && (CanExecuteTriggersOnHit(mask) || missInfo == SPELL_MISS_IMMUNE || missInfo == SPELL_MISS_IMMUNE2); - Unit* spellHitTarget = NULL; + // Spells with this flag cannot trigger if effect is cast on self + bool canEffectTrigger = !m_spellInfo->HasAttribute(SPELL_ATTR3_CANT_TRIGGER_PROC) && (CanExecuteTriggersOnHit(mask) || missInfo == SPELL_MISS_IMMUNE || missInfo == SPELL_MISS_IMMUNE2); + Unit* spellHitTarget = nullptr; if (missInfo == SPELL_MISS_NONE) // In case spell hit target, do all effect on that target spellHitTarget = unit; @@ -2331,23 +2339,15 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target) if (missInfo2 != SPELL_MISS_MISS) m_caster->SendSpellMiss(unit, m_spellInfo->Id, missInfo2); m_damage = 0; - spellHitTarget = NULL; + spellHitTarget = nullptr; } } // Do not take combo points on dodge and miss - if (missInfo != SPELL_MISS_NONE && m_needComboPoints && - m_targets.GetUnitTargetGUID() == target->targetGUID) - { + if (missInfo != SPELL_MISS_NONE && m_needComboPoints && m_targets.GetUnitTargetGUID() == target->targetGUID) m_needComboPoints = false; - // Restore spell mods for a miss/dodge/parry Cold Blood - /// @todo check how broad this rule should be - if (m_caster->GetTypeId() == TYPEID_PLAYER && (missInfo == SPELL_MISS_MISS || - missInfo == SPELL_MISS_DODGE || missInfo == SPELL_MISS_PARRY)) - m_caster->ToPlayer()->RestoreSpellMods(this, 14177); - } - // Trigger info was not filled in spell::preparedatafortriggersystem - we do it now + // Trigger info was not filled in Spell::prepareDataForTriggerSystem - we do it now if (canEffectTrigger && !procAttacker && !procVictim) { bool positive = true; @@ -2394,19 +2394,20 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target) uint32 addhealth = m_healing; if (crit) { - procEx |= PROC_EX_CRITICAL_HIT; - addhealth = caster->SpellCriticalHealingBonus(m_spellInfo, addhealth, NULL); + hitMask |= PROC_HIT_CRITICAL; + addhealth = caster->SpellCriticalHealingBonus(m_spellInfo, addhealth, nullptr); } else - procEx |= PROC_EX_NORMAL_HIT; + hitMask |= PROC_HIT_NORMAL; - int32 gain = caster->HealBySpell(unitTarget, m_spellInfo, addhealth, crit); - unitTarget->getHostileRefManager().threatAssist(caster, float(gain) * 0.5f, m_spellInfo); - m_healing = gain; + HealInfo healInfo(caster, unitTarget, addhealth, m_spellInfo, m_spellInfo->GetSchoolMask()); + caster->HealBySpell(healInfo, crit); + unitTarget->getHostileRefManager().threatAssist(caster, float(healInfo.GetEffectiveHeal()) * 0.5f, m_spellInfo); + m_healing = healInfo.GetEffectiveHeal(); - // Do triggers for unit (reflect triggers passed on hit phase for correct drop charge) - if (canEffectTrigger && missInfo != SPELL_MISS_REFLECT) - caster->ProcDamageAndSpell(unitTarget, procAttacker, procVictim, procEx, addhealth, m_attackType, m_spellInfo, m_triggeredByAuraSpell); + // Do triggers for unit + if (canEffectTrigger) + caster->ProcSkillsAndAuras(unitTarget, procAttacker, procVictim, PROC_SPELL_TYPE_HEAL, PROC_SPELL_PHASE_HIT, hitMask, this, nullptr, &healInfo); } // Do damage and triggers else if (m_damage > 0) @@ -2421,16 +2422,18 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target) // Send log damage message to client caster->SendSpellNonMeleeDamageLog(&damageInfo); - procEx |= createProcExtendMask(&damageInfo, missInfo); + hitMask |= createProcHitMask(&damageInfo, missInfo); procVictim |= PROC_FLAG_TAKEN_DAMAGE; - // Do triggers for unit (reflect triggers passed on hit phase for correct drop charge) - if (canEffectTrigger && missInfo != SPELL_MISS_REFLECT) + // Do triggers for unit + if (canEffectTrigger) { - caster->ProcDamageAndSpell(unitTarget, procAttacker, procVictim, procEx, damageInfo.damage, m_attackType, m_spellInfo, m_triggeredByAuraSpell); - if (caster->GetTypeId() == TYPEID_PLAYER && m_spellInfo->HasAttribute(SPELL_ATTR0_STOP_ATTACK_TARGET) == 0 && - (m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_MELEE || m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_RANGED)) - caster->ToPlayer()->CastItemCombatSpell(unitTarget, m_attackType, procVictim, procEx); + DamageInfo spellDamageInfo(damageInfo, SPELL_DIRECT_DAMAGE, m_attackType, hitMask); + caster->ProcSkillsAndAuras(unitTarget, procAttacker, procVictim, PROC_SPELL_TYPE_DAMAGE, PROC_SPELL_PHASE_HIT, hitMask, this, &spellDamageInfo, nullptr); + + if (caster->GetTypeId() == TYPEID_PLAYER && !m_spellInfo->HasAttribute(SPELL_ATTR0_STOP_ATTACK_TARGET) && + (m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_MELEE || m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_RANGED)) + caster->ToPlayer()->CastItemCombatSpell(spellDamageInfo); } m_damage = damageInfo.damage; @@ -2442,10 +2445,17 @@ void Spell::DoAllEffectOnTarget(TargetInfo* target) { // Fill base damage struct (unitTarget - is real spell target) SpellNonMeleeDamage damageInfo(caster, unitTarget, m_spellInfo->Id, m_spellSchoolMask); - procEx |= createProcExtendMask(&damageInfo, missInfo); - // Do triggers for unit (reflect triggers passed on hit phase for correct drop charge) - if (canEffectTrigger && missInfo != SPELL_MISS_REFLECT) - caster->ProcDamageAndSpell(unit, procAttacker, procVictim, procEx, 0, m_attackType, m_spellInfo, m_triggeredByAuraSpell); + hitMask |= createProcHitMask(&damageInfo, missInfo); + // Do triggers for unit + if (canEffectTrigger) + { + DamageInfo spellNoDamageInfo(damageInfo, NODAMAGE, m_attackType, hitMask); + caster->ProcSkillsAndAuras(unitTarget, procAttacker, procVictim, PROC_SPELL_TYPE_NO_DMG_HEAL, PROC_SPELL_PHASE_HIT, hitMask, this, &spellNoDamageInfo, nullptr); + + if (caster->GetTypeId() == TYPEID_PLAYER && !m_spellInfo->HasAttribute(SPELL_ATTR0_STOP_ATTACK_TARGET) && + (m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_MELEE || m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_RANGED)) + caster->ToPlayer()->CastItemCombatSpell(spellNoDamageInfo); + } // Failed Pickpocket, reveal rogue if (missInfo == SPELL_MISS_RESIST && m_spellInfo->HasAttribute(SPELL_ATTR0_CU_PICKPOCKET) && unitTarget->GetTypeId() == TYPEID_UNIT) @@ -2815,7 +2825,7 @@ bool Spell::UpdateChanneledTargetList() { range = m_spellInfo->GetMaxRange(m_spellInfo->IsPositive()); if (Player* modOwner = m_caster->GetSpellModOwner()) - modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RANGE, range, this); + modOwner->ApplySpellMod<SPELLMOD_RANGE>(m_spellInfo->Id, range, this); } for (std::list<TargetInfo>::iterator ihit= m_UniqueTargetInfo.begin(); ihit != m_UniqueTargetInfo.end(); ++ihit) @@ -2953,7 +2963,7 @@ void Spell::prepare(SpellCastTargets const* targets, AuraEffect const* triggered } // Prepare data for triggers - prepareDataForTriggerSystem(triggeredByAura); + prepareDataForTriggerSystem(); if (Player* player = m_caster->ToPlayer()) { @@ -3061,10 +3071,6 @@ void Spell::cancel() SendInterrupted(0); SendCastResult(SPELL_FAILED_INTERRUPTED); - // spell is canceled-take mods and clear list - if (m_caster->GetTypeId() == TYPEID_PLAYER) - m_caster->ToPlayer()->RemoveSpellMods(this); - m_appliedMods.clear(); break; @@ -3299,6 +3305,25 @@ void Spell::cast(bool skipCheck) if (Creature* creatureCaster = m_caster->ToCreature()) creatureCaster->ReleaseFocus(this); + + if (!m_originalCaster) + return; + + // Handle procs on cast + uint32 procAttacker = m_procAttacker; + if (!procAttacker) + { + if (m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_MAGIC) + procAttacker = m_spellInfo->IsPositive() ? PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_POS : PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_NEG; + else + procAttacker = m_spellInfo->IsPositive() ? PROC_FLAG_DONE_SPELL_NONE_DMG_CLASS_POS : PROC_FLAG_DONE_SPELL_NONE_DMG_CLASS_NEG; + } + + uint32 hitMask = m_hitMask; + if (!(hitMask & PROC_HIT_CRITICAL)) + hitMask |= PROC_HIT_NORMAL; + + m_originalCaster->ProcSkillsAndAuras(nullptr, procAttacker, PROC_FLAG_NONE, PROC_SPELL_TYPE_MASK_ALL, PROC_SPELL_PHASE_CAST, hitMask, this, nullptr, nullptr); } void Spell::handle_immediate() @@ -3312,7 +3337,7 @@ void Spell::handle_immediate() // First mod_duration then haste - see Missile Barrage // Apply duration mod if (Player* modOwner = m_caster->GetSpellModOwner()) - modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_DURATION, duration); + modOwner->ApplySpellMod<SPELLMOD_DURATION>(m_spellInfo->Id, duration); // Apply haste mods m_caster->ModSpellDurationTime(m_spellInfo, duration, this); @@ -3455,22 +3480,8 @@ void Spell::_handle_immediate_phase() } // process items - for (std::list<ItemTargetInfo>::iterator ihit= m_UniqueItemInfo.begin(); ihit != m_UniqueItemInfo.end(); ++ihit) + for (std::list<ItemTargetInfo>::iterator ihit = m_UniqueItemInfo.begin(); ihit != m_UniqueItemInfo.end(); ++ihit) DoAllEffectOnTarget(&(*ihit)); - - if (!m_originalCaster) - return; - // Handle procs on cast - /// @todo finish new proc system:P - if (m_UniqueTargetInfo.empty() && m_targets.HasDst()) - { - uint32 procAttacker = m_procAttacker; - if (!procAttacker) - procAttacker |= PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_POS; - - // Proc the spells that have DEST target - m_originalCaster->ProcDamageAndSpell(NULL, procAttacker, 0, m_procEx | PROC_EX_NORMAL_HIT, 0, BASE_ATTACK, m_spellInfo, m_triggeredByAuraSpell); - } } void Spell::_handle_finish_phase() @@ -3494,7 +3505,24 @@ void Spell::_handle_finish_phase() m_caster->m_extraAttacks = 0; } - /// @todo trigger proc phase finish here + // Handle procs on finish + if (!m_originalCaster) + return; + + uint32 procAttacker = m_procAttacker; + if (!procAttacker) + { + if (m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_MAGIC) + procAttacker = m_spellInfo->IsPositive() ? PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_POS : PROC_FLAG_DONE_SPELL_MAGIC_DMG_CLASS_NEG; + else + procAttacker = m_spellInfo->IsPositive() ? PROC_FLAG_DONE_SPELL_NONE_DMG_CLASS_POS : PROC_FLAG_DONE_SPELL_NONE_DMG_CLASS_NEG; + } + + uint32 hitMask = m_hitMask; + if (!(hitMask & PROC_HIT_CRITICAL)) + hitMask |= PROC_HIT_NORMAL; + + m_originalCaster->ProcSkillsAndAuras(nullptr, procAttacker, PROC_FLAG_NONE, PROC_SPELL_TYPE_MASK_ALL, PROC_SPELL_PHASE_FINISH, hitMask, this, nullptr, nullptr); } void Spell::SendSpellCooldown() @@ -3658,18 +3686,6 @@ void Spell::finish(bool ok) m_caster->ToPlayer()->UpdatePotionCooldown(this); } - if (Player* modOwner = m_caster->GetSpellModOwner()) - { - // triggered spell pointer can be not set in some cases - // this is needed for proper apply of triggered spell mods - modOwner->SetSpellModTakingSpell(this, true); - - // Take mods after trigger spell (needed for 14177 to affect 48664) - // mods are taken only on succesfull cast and independantly from targets of the spell - modOwner->RemoveSpellMods(this); - modOwner->SetSpellModTakingSpell(this, false); - } - // Stop Attack for some spells if (m_spellInfo->HasAttribute(SPELL_ATTR0_STOP_ATTACK_TARGET)) m_caster->AttackStop(); @@ -4387,7 +4403,7 @@ void Spell::TakePower() hit = false; //lower spell cost on fail (by talent aura) if (Player* modOwner = m_caster->ToPlayer()->GetSpellModOwner()) - modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_SPELL_COST_REFUND_ON_FAIL, m_powerCost); + modOwner->ApplySpellMod<SPELLMOD_SPELL_COST_REFUND_ON_FAIL>(m_spellInfo->Id, m_powerCost); } break; } @@ -4479,7 +4495,7 @@ SpellCastResult Spell::CheckRuneCost(uint32 runeCostID) { runeCost[i] = src->RuneCost[i]; if (Player* modOwner = m_caster->GetSpellModOwner()) - modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_COST, runeCost[i], this); + modOwner->ApplySpellMod<SPELLMOD_COST>(m_spellInfo->Id, runeCost[i], this); } runeCost[RUNE_DEATH] = MAX_RUNES; // calculated later @@ -4519,7 +4535,7 @@ void Spell::TakeRunePower(bool didHit) { runeCost[i] = runeCostData->RuneCost[i]; if (Player* modOwner = m_caster->GetSpellModOwner()) - modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_COST, runeCost[i], this); + modOwner->ApplySpellMod<SPELLMOD_COST>(m_spellInfo->Id, runeCost[i], this); } // Let's say we use a skill that requires a Frost rune. This is the order: @@ -5896,7 +5912,7 @@ std::pair<float, float> Spell::GetMinMaxRange(bool strict) maxRange *= ranged->GetTemplate()->RangedModRange * 0.01f; if (Player* modOwner = m_caster->GetSpellModOwner()) - modOwner->ApplySpellMod(m_spellInfo->Id, SPELLMOD_RANGE, maxRange, this); + modOwner->ApplySpellMod<SPELLMOD_RANGE>(m_spellInfo->Id, maxRange, this); maxRange += rangeMod; @@ -6465,7 +6481,7 @@ void Spell::Delayed() // only called in DealDamage() //check pushback reduce int32 delaytime = 500; // spellcasting delay is normally 500ms int32 delayReduce = 100; // must be initialized to 100 for percent modifiers - m_caster->ToPlayer()->ApplySpellMod(m_spellInfo->Id, SPELLMOD_NOT_LOSE_CASTING_TIME, delayReduce, this); + m_caster->ToPlayer()->ApplySpellMod<SPELLMOD_NOT_LOSE_CASTING_TIME>(m_spellInfo->Id, delayReduce, this); delayReduce += m_caster->GetTotalAuraModifier(SPELL_AURA_REDUCE_PUSHBACK) - 100; if (delayReduce >= 100) return; @@ -6503,7 +6519,7 @@ void Spell::DelayedChannel() int32 delaytime = CalculatePct(duration, 25); // channeling delay is normally 25% of its time per hit int32 delayReduce = 100; // must be initialized to 100 for percent modifiers - m_caster->ToPlayer()->ApplySpellMod(m_spellInfo->Id, SPELLMOD_NOT_LOSE_CASTING_TIME, delayReduce, this); + m_caster->ToPlayer()->ApplySpellMod<SPELLMOD_NOT_LOSE_CASTING_TIME>(m_spellInfo->Id, delayReduce, this); delayReduce += m_caster->GetTotalAuraModifier(SPELL_AURA_REDUCE_PUSHBACK) - 100; if (delayReduce >= 100) return; @@ -7428,15 +7444,12 @@ void Spell::TriggerGlobalCooldown() if (m_spellInfo->StartRecoveryTime >= MIN_GCD && m_spellInfo->StartRecoveryTime <= MAX_GCD) { // gcd modifier auras are applied only to own spells and only players have such mods - if (m_caster->GetTypeId() == TYPEID_PLAYER) - m_caster->ToPlayer()->ApplySpellMod(m_spellInfo->Id, SPELLMOD_GLOBAL_COOLDOWN, gcd, this); + if (Player* modOwner = m_caster->GetSpellModOwner()) + modOwner->ApplySpellMod<SPELLMOD_GLOBAL_COOLDOWN>(m_spellInfo->Id, gcd, this); // Apply haste rating gcd = int32(float(gcd) * m_caster->GetFloatValue(UNIT_MOD_CAST_SPEED)); - if (gcd < MIN_GCD) - gcd = MIN_GCD; - else if (gcd > MAX_GCD) - gcd = MAX_GCD; + RoundToInterval<int32>(gcd, MIN_GCD, MAX_GCD); } m_caster->GetSpellHistory()->AddGlobalCooldown(m_spellInfo, gcd); |
