mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-23 10:26:28 +01:00
Core/Spells: Implementation of QAston proc system
- Move checks from Unit::IsTriggeredAtSpellProcEvent (old system) to Aura::IsProcTriggeredOnEvent (new system) - Templatize SpellModOp param of Player::ApplySpellMod, also killed charge counter from SpellModifier and Player system for handling charges... no point in having 3 different systems doing the same thing - Automatically add default entries to spellProcMap, based on spellinfo (else auras won't proc without an entry) Based on old Unit::ProcDamageAndSpellFor - Old Unit::ProcDamageAndSpellFor renamed to Unit::ProcSkillsAndReactives and made private, will no longer handle auras. - Start making use of HealInfo::AbsorbHeal in unit calculations, add effective healing info to HealInfo struct - Changes in spell reflection system, emulates old behaviour, delaying aura drop - Removed old charge count hacks in SpellMgr::LoadSpellInfoCorrections - Removed bogus error log when procChance is 0: Some auras have initial 0 procChance but modified by SPELLMOD_CHANCE_OF_SUCCESS - Fixed TriggerAurasProcOnEvent logic that tried to trigger twice from actor. - Allow non damaging spells with DamageClass Melee or Ranged to proc character enchants. Ref issue #17034: * http://web.archive.org/web/20110309092008/http://elitistjerks.com/f47/t49865-paladin_retribution_pve/ * When an auto-attack lands (does not dodge/parry/miss) that can proc a seal the of the following things happen independently of each other (see 2 roll system). * 1) A "hidden strike" which uses melee combat mechanics occurs. If it lands it refreshes/stacks SoV DoT. Only white swings can trigger a refresh or stack. (This hidden strike mechanic can also proc things like berserking..) * 2) A weapon damage based proc will occur if you used a special (CS/DS/judge) or if you have a 5 stack (from auto attacks). This attack can not be avoided. * Holy Vengeance is the "hidden strike" it has an apply aura effect and damage class melee. - Fixed Blood Tap interaction with Death Runes (btw, don't know what was going on with those MiscValueB, spell 45529 doesn't have any MiscValueB in SPELL_EFFECT_ACTIVATE_RUNE) - Ported some AuraEffect checks from old Unit.cpp function. added new AuraScript hook to check procs of an specific effect - Allow only AuraEffects that passed the check to proc, this won't block whole aura from proccing (and lose charges) if at least one of the effects procs, though - Changes in spell mod system (for SPELLMOD_CASTING_TIME). fixes #17558. - Added an exception for SPELLMOD_CRITICAL_CHANCE too, fixes #15193
This commit is contained in:
@@ -594,7 +594,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;
|
||||
@@ -1474,7 +1474,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)
|
||||
{
|
||||
@@ -1943,12 +1943,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;
|
||||
@@ -1978,7 +1977,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;
|
||||
@@ -1987,7 +1986,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 &&
|
||||
@@ -1998,29 +1997,12 @@ void Spell::prepareDataForTriggerSystem(AuraEffect const* /*triggeredByAura*/)
|
||||
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()
|
||||
@@ -2031,6 +2013,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)
|
||||
@@ -2114,20 +2122,20 @@ void Spell::AddUnitTarget(Unit* target, uint32 effectMask, bool checkIfValid /*=
|
||||
targetInfo.timeDelay = uint64(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;
|
||||
@@ -2149,14 +2157,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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2196,7 +2204,7 @@ void Spell::AddGOTarget(GameObject* go, uint32 effectMask)
|
||||
else
|
||||
target.timeDelay = uint64(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
|
||||
@@ -2304,13 +2312,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;
|
||||
@@ -2338,23 +2346,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;
|
||||
@@ -2401,19 +2401,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)
|
||||
@@ -2428,16 +2429,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;
|
||||
@@ -2449,10 +2452,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)
|
||||
@@ -2819,7 +2829,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)
|
||||
@@ -2961,7 +2971,7 @@ void Spell::prepare(SpellCastTargets const* targets, AuraEffect const* triggered
|
||||
}
|
||||
|
||||
// Prepare data for triggers
|
||||
prepareDataForTriggerSystem(triggeredByAura);
|
||||
prepareDataForTriggerSystem();
|
||||
|
||||
if (Player* player = m_caster->ToPlayer())
|
||||
{
|
||||
@@ -3073,10 +3083,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;
|
||||
|
||||
@@ -3310,7 +3316,25 @@ void Spell::cast(bool skipCheck)
|
||||
SetExecutedCurrently(false);
|
||||
|
||||
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()
|
||||
@@ -3324,7 +3348,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);
|
||||
@@ -3467,22 +3491,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()
|
||||
@@ -3509,7 +3519,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()
|
||||
@@ -3675,18 +3702,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();
|
||||
@@ -4425,7 +4440,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;
|
||||
}
|
||||
@@ -4514,7 +4529,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
|
||||
@@ -4554,7 +4569,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:
|
||||
@@ -6000,7 +6015,7 @@ SpellCastResult Spell::CheckRange(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;
|
||||
|
||||
@@ -6530,7 +6545,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;
|
||||
@@ -6568,7 +6583,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;
|
||||
@@ -7491,8 +7506,8 @@ 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);
|
||||
|
||||
bool isMeleeOrRangedSpell = m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_MELEE ||
|
||||
m_spellInfo->DmgClass == SPELL_DAMAGE_CLASS_RANGED ||
|
||||
|
||||
Reference in New Issue
Block a user