Core/SAI: allow creatures to handle gameobject spellhit SAI events.
Port From (https://github.com/TrinityCore/TrinityCore/commit/83a9222c390110ae082512ed858a5580a958aa21)
This commit is contained in:
@@ -662,11 +662,21 @@ namespace Game.AI
|
|||||||
GetScript().ProcessEventsFor(SmartEvents.SpellHit, caster, 0, 0, false, spellInfo);
|
GetScript().ProcessEventsFor(SmartEvents.SpellHit, caster, 0, 0, false, spellInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void SpellHitByGameObject(GameObject obj, SpellInfo spellInfo)
|
||||||
|
{
|
||||||
|
GetScript().ProcessEventsFor(SmartEvents.SpellHit, null, 0, 0, false, spellInfo, obj);
|
||||||
|
}
|
||||||
|
|
||||||
public override void SpellHitTarget(Unit target, SpellInfo spellInfo)
|
public override void SpellHitTarget(Unit target, SpellInfo spellInfo)
|
||||||
{
|
{
|
||||||
GetScript().ProcessEventsFor(SmartEvents.SpellHitTarget, target, 0, 0, false, spellInfo);
|
GetScript().ProcessEventsFor(SmartEvents.SpellHitTarget, target, 0, 0, false, spellInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void SpellHitTargetGameObject(GameObject target, SpellInfo spellInfo)
|
||||||
|
{
|
||||||
|
GetScript().ProcessEventsFor(SmartEvents.SpellHitTarget, null, 0, 0, false, spellInfo, target);
|
||||||
|
}
|
||||||
|
|
||||||
public override void DamageTaken(Unit attacker, ref uint damage)
|
public override void DamageTaken(Unit attacker, ref uint damage)
|
||||||
{
|
{
|
||||||
GetScript().ProcessEventsFor(SmartEvents.Damaged, attacker, damage);
|
GetScript().ProcessEventsFor(SmartEvents.Damaged, attacker, damage);
|
||||||
|
|||||||
+158
-158
@@ -7862,193 +7862,193 @@ namespace Game.Spells
|
|||||||
// Get original caster (if exist) and calculate damage/healing from him data
|
// Get original caster (if exist) and calculate damage/healing from him data
|
||||||
// Skip if m_originalCaster not available
|
// Skip if m_originalCaster not available
|
||||||
Unit caster = spell.GetOriginalCaster() ? spell.GetOriginalCaster() : spell.GetCaster().ToUnit();
|
Unit caster = spell.GetOriginalCaster() ? spell.GetOriginalCaster() : spell.GetCaster().ToUnit();
|
||||||
if (caster == null)
|
if (caster != null)
|
||||||
return;
|
|
||||||
|
|
||||||
// Fill base trigger info
|
|
||||||
ProcFlags procAttacker = spell.m_procAttacker;
|
|
||||||
ProcFlags procVictim = spell.m_procVictim;
|
|
||||||
ProcFlagsSpellType procSpellType = ProcFlagsSpellType.None;
|
|
||||||
ProcFlagsHit hitMask = ProcFlagsHit.None;
|
|
||||||
|
|
||||||
// Spells with this flag cannot trigger if effect is cast on self
|
|
||||||
bool canEffectTrigger = !spell.m_spellInfo.HasAttribute(SpellAttr3.CantTriggerProc) && spell.unitTarget.CanProc() &&
|
|
||||||
(spell.CanExecuteTriggersOnHit(EffectMask) || MissCondition == SpellMissInfo.Immune || MissCondition == SpellMissInfo.Immune2);
|
|
||||||
|
|
||||||
// Trigger info was not filled in Spell::prepareDataForTriggerSystem - we do it now
|
|
||||||
if (canEffectTrigger && procAttacker == 0 && procVictim == 0)
|
|
||||||
{
|
{
|
||||||
bool positive = true;
|
// Fill base trigger info
|
||||||
if (spell.m_damage > 0)
|
ProcFlags procAttacker = spell.m_procAttacker;
|
||||||
positive = false;
|
ProcFlags procVictim = spell.m_procVictim;
|
||||||
else if (spell.m_healing == 0)
|
ProcFlagsSpellType procSpellType = ProcFlagsSpellType.None;
|
||||||
{
|
ProcFlagsHit hitMask = ProcFlagsHit.None;
|
||||||
for (uint i = 0; i < SpellConst.MaxEffects; ++i)
|
|
||||||
{
|
|
||||||
// in case of immunity, check all effects to choose correct procFlags, as none has technically hit
|
|
||||||
if (EffectMask != 0 && (EffectMask & (1 << (int)i)) == 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!spell.m_spellInfo.IsPositiveEffect(i))
|
// Spells with this flag cannot trigger if effect is cast on self
|
||||||
|
bool canEffectTrigger = !spell.m_spellInfo.HasAttribute(SpellAttr3.CantTriggerProc) && spell.unitTarget.CanProc() &&
|
||||||
|
(spell.CanExecuteTriggersOnHit(EffectMask) || MissCondition == SpellMissInfo.Immune || MissCondition == SpellMissInfo.Immune2);
|
||||||
|
|
||||||
|
// Trigger info was not filled in Spell::prepareDataForTriggerSystem - we do it now
|
||||||
|
if (canEffectTrigger && procAttacker == 0 && procVictim == 0)
|
||||||
|
{
|
||||||
|
bool positive = true;
|
||||||
|
if (spell.m_damage > 0)
|
||||||
|
positive = false;
|
||||||
|
else if (spell.m_healing == 0)
|
||||||
|
{
|
||||||
|
for (uint i = 0; i < spell.m_spellInfo.GetEffects().Count; ++i)
|
||||||
{
|
{
|
||||||
positive = false;
|
// in case of immunity, check all effects to choose correct procFlags, as none has technically hit
|
||||||
break;
|
if (EffectMask != 0 && (EffectMask & (1 << (int)i)) == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!spell.m_spellInfo.IsPositiveEffect(i))
|
||||||
|
{
|
||||||
|
positive = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch (spell.m_spellInfo.DmgClass)
|
||||||
|
{
|
||||||
|
case SpellDmgClass.Magic:
|
||||||
|
if (positive)
|
||||||
|
{
|
||||||
|
procAttacker |= ProcFlags.DoneSpellMagicDmgClassPos;
|
||||||
|
procVictim |= ProcFlags.TakenSpellMagicDmgClassPos;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
procAttacker |= ProcFlags.DoneSpellMagicDmgClassNeg;
|
||||||
|
procVictim |= ProcFlags.TakenSpellMagicDmgClassNeg;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SpellDmgClass.None:
|
||||||
|
if (positive)
|
||||||
|
{
|
||||||
|
procAttacker |= ProcFlags.DoneSpellNoneDmgClassPos;
|
||||||
|
procVictim |= ProcFlags.TakenSpellNoneDmgClassPos;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
procAttacker |= ProcFlags.DoneSpellNoneDmgClassNeg;
|
||||||
|
procVictim |= ProcFlags.TakenSpellNoneDmgClassNeg;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (spell.m_spellInfo.DmgClass)
|
// All calculated do it!
|
||||||
|
// Do healing
|
||||||
|
DamageInfo spellDamageInfo = null;
|
||||||
|
HealInfo healInfo = null;
|
||||||
|
if (spell.m_healing > 0)
|
||||||
{
|
{
|
||||||
case SpellDmgClass.Magic:
|
int addhealth = spell.m_healing;
|
||||||
if (positive)
|
if (IsCrit)
|
||||||
{
|
{
|
||||||
procAttacker |= ProcFlags.DoneSpellMagicDmgClassPos;
|
hitMask |= ProcFlagsHit.Critical;
|
||||||
procVictim |= ProcFlags.TakenSpellMagicDmgClassPos;
|
addhealth = Unit.SpellCriticalHealingBonus(caster, spell.m_spellInfo, addhealth, null);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
hitMask |= ProcFlagsHit.Normal;
|
||||||
procAttacker |= ProcFlags.DoneSpellMagicDmgClassNeg;
|
|
||||||
procVictim |= ProcFlags.TakenSpellMagicDmgClassNeg;
|
healInfo = new(caster, spell.unitTarget, (uint)addhealth, spell.m_spellInfo, spell.m_spellInfo.GetSchoolMask());
|
||||||
}
|
caster.HealBySpell(healInfo, IsCrit);
|
||||||
break;
|
spell.unitTarget.GetThreatManager().ForwardThreatForAssistingMe(caster, healInfo.GetEffectiveHeal() * 0.5f, spell.m_spellInfo);
|
||||||
case SpellDmgClass.None:
|
spell.m_healing = (int)healInfo.GetEffectiveHeal();
|
||||||
if (positive)
|
|
||||||
{
|
procSpellType |= ProcFlagsSpellType.Heal;
|
||||||
procAttacker |= ProcFlags.DoneSpellNoneDmgClassPos;
|
|
||||||
procVictim |= ProcFlags.TakenSpellNoneDmgClassPos;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
procAttacker |= ProcFlags.DoneSpellNoneDmgClassNeg;
|
|
||||||
procVictim |= ProcFlags.TakenSpellNoneDmgClassNeg;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// All calculated do it!
|
// Do damage
|
||||||
// Do healing
|
if (spell.m_damage > 0)
|
||||||
DamageInfo spellDamageInfo = null;
|
|
||||||
HealInfo healInfo = null;
|
|
||||||
if (spell.m_healing > 0)
|
|
||||||
{
|
|
||||||
int addhealth = spell.m_healing;
|
|
||||||
if (IsCrit)
|
|
||||||
{
|
{
|
||||||
hitMask |= ProcFlagsHit.Critical;
|
// Fill base damage struct (unitTarget - is real spell target)
|
||||||
addhealth = Unit.SpellCriticalHealingBonus(caster, spell.m_spellInfo, addhealth, null);
|
SpellNonMeleeDamage damageInfo = new(caster, spell.unitTarget, spell.m_spellInfo, spell.m_SpellVisual, spell.m_spellSchoolMask, spell.m_castId);
|
||||||
|
// Check damage immunity
|
||||||
|
if (spell.unitTarget.IsImmunedToDamage(spell.m_spellInfo))
|
||||||
|
{
|
||||||
|
hitMask = ProcFlagsHit.Immune;
|
||||||
|
spell.m_damage = 0;
|
||||||
|
|
||||||
|
// no packet found in sniffs
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Add bonuses and fill damageInfo struct
|
||||||
|
caster.CalculateSpellDamageTaken(damageInfo, spell.m_damage, spell.m_spellInfo, spell.m_attackType, IsCrit);
|
||||||
|
Unit.DealDamageMods(damageInfo.attacker, damageInfo.target, ref damageInfo.damage, ref damageInfo.absorb);
|
||||||
|
|
||||||
|
hitMask |= Unit.CreateProcHitMask(damageInfo, MissCondition);
|
||||||
|
procVictim |= ProcFlags.TakenDamage;
|
||||||
|
|
||||||
|
spell.m_damage = (int)damageInfo.damage;
|
||||||
|
|
||||||
|
caster.DealSpellDamage(damageInfo, true);
|
||||||
|
|
||||||
|
// Send log damage message to client
|
||||||
|
caster.SendSpellNonMeleeDamageLog(damageInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do triggers for unit
|
||||||
|
if (canEffectTrigger)
|
||||||
|
{
|
||||||
|
spellDamageInfo = new(damageInfo, DamageEffectType.SpellDirect, spell.m_attackType, hitMask);
|
||||||
|
procSpellType |= ProcFlagsSpellType.Damage;
|
||||||
|
|
||||||
|
if (caster.IsPlayer() && !spell.m_spellInfo.HasAttribute(SpellAttr0.StopAttackTarget) && !spell.m_spellInfo.HasAttribute(SpellAttr4.SuppressWeaponProcs) &&
|
||||||
|
(spell.m_spellInfo.DmgClass == SpellDmgClass.Melee || spell.m_spellInfo.DmgClass == SpellDmgClass.Ranged))
|
||||||
|
caster.ToPlayer().CastItemCombatSpell(spellDamageInfo);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
hitMask |= ProcFlagsHit.Normal;
|
|
||||||
|
|
||||||
healInfo = new(caster, spell.unitTarget, (uint)addhealth, spell.m_spellInfo, spell.m_spellInfo.GetSchoolMask());
|
// Passive spell hits/misses or active spells only misses (only triggers)
|
||||||
caster.HealBySpell(healInfo, IsCrit);
|
if (spell.m_damage <= 0 && spell.m_healing <= 0)
|
||||||
spell.unitTarget.GetThreatManager().ForwardThreatForAssistingMe(caster, healInfo.GetEffectiveHeal() * 0.5f, spell.m_spellInfo);
|
|
||||||
spell.m_healing = (int)healInfo.GetEffectiveHeal();
|
|
||||||
|
|
||||||
procSpellType |= ProcFlagsSpellType.Heal;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do damage
|
|
||||||
if (spell.m_damage > 0)
|
|
||||||
{
|
|
||||||
// Fill base damage struct (unitTarget - is real spell target)
|
|
||||||
SpellNonMeleeDamage damageInfo = new(caster, spell.unitTarget, spell.m_spellInfo, spell.m_SpellVisual, spell.m_spellSchoolMask, spell.m_castId);
|
|
||||||
// Check damage immunity
|
|
||||||
if (spell.unitTarget.IsImmunedToDamage(spell.m_spellInfo))
|
|
||||||
{
|
{
|
||||||
hitMask = ProcFlagsHit.Immune;
|
// Fill base damage struct (unitTarget - is real spell target)
|
||||||
spell.m_damage = 0;
|
SpellNonMeleeDamage damageInfo = new(caster, spell.unitTarget, spell.m_spellInfo, spell.m_SpellVisual, spell.m_spellSchoolMask);
|
||||||
|
|
||||||
// no packet found in sniffs
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Add bonuses and fill damageInfo struct
|
|
||||||
caster.CalculateSpellDamageTaken(damageInfo, spell.m_damage, spell.m_spellInfo, spell.m_attackType, IsCrit);
|
|
||||||
Unit.DealDamageMods(damageInfo.attacker, damageInfo.target, ref damageInfo.damage, ref damageInfo.absorb);
|
|
||||||
|
|
||||||
hitMask |= Unit.CreateProcHitMask(damageInfo, MissCondition);
|
hitMask |= Unit.CreateProcHitMask(damageInfo, MissCondition);
|
||||||
procVictim |= ProcFlags.TakenDamage;
|
// Do triggers for unit
|
||||||
|
if (canEffectTrigger)
|
||||||
|
{
|
||||||
|
spellDamageInfo = new(damageInfo, DamageEffectType.NoDamage, spell.m_attackType, hitMask);
|
||||||
|
procSpellType |= ProcFlagsSpellType.NoDmgHeal;
|
||||||
|
}
|
||||||
|
|
||||||
spell.m_damage = (int)damageInfo.damage;
|
// Failed Pickpocket, reveal rogue
|
||||||
|
if (MissCondition == SpellMissInfo.Resist && spell.m_spellInfo.HasAttribute(SpellCustomAttributes.PickPocket) && spell.unitTarget.IsCreature())
|
||||||
caster.DealSpellDamage(damageInfo, true);
|
{
|
||||||
|
Unit unitCaster = spell.GetCaster().ToUnit();
|
||||||
// Send log damage message to client
|
unitCaster.RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.Interacting);
|
||||||
caster.SendSpellNonMeleeDamageLog(damageInfo);
|
spell.unitTarget.ToCreature().EngageWithTarget(unitCaster);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do triggers for unit
|
// Do triggers for unit
|
||||||
if (canEffectTrigger)
|
if (canEffectTrigger)
|
||||||
{
|
{
|
||||||
spellDamageInfo = new(damageInfo, DamageEffectType.SpellDirect, spell.m_attackType, hitMask);
|
Unit.ProcSkillsAndAuras(caster, spell.unitTarget, procAttacker, procVictim, procSpellType, ProcFlagsSpellPhase.Hit, hitMask, spell, spellDamageInfo, healInfo);
|
||||||
procSpellType |= ProcFlagsSpellType.Damage;
|
|
||||||
|
|
||||||
if (caster.IsPlayer() && !spell.m_spellInfo.HasAttribute(SpellAttr0.StopAttackTarget) && !spell.m_spellInfo.HasAttribute(SpellAttr4.SuppressWeaponProcs) &&
|
// item spells (spell hit of non-damage spell may also activate items, for example seal of corruption hidden hit)
|
||||||
(spell.m_spellInfo.DmgClass == SpellDmgClass.Melee || spell.m_spellInfo.DmgClass == SpellDmgClass.Ranged))
|
if (caster.IsPlayer() && procSpellType.HasAnyFlag(ProcFlagsSpellType.Damage | ProcFlagsSpellType.NoDmgHeal))
|
||||||
caster.ToPlayer().CastItemCombatSpell(spellDamageInfo);
|
{
|
||||||
}
|
if (spell.m_spellInfo.DmgClass == SpellDmgClass.Melee || spell.m_spellInfo.DmgClass == SpellDmgClass.Ranged)
|
||||||
}
|
if (!spell.m_spellInfo.HasAttribute(SpellAttr0.StopAttackTarget) && !spell.m_spellInfo.HasAttribute(SpellAttr4.SuppressWeaponProcs))
|
||||||
|
caster.ToPlayer().CastItemCombatSpell(spellDamageInfo);
|
||||||
// Passive spell hits/misses or active spells only misses (only triggers)
|
}
|
||||||
if (spell.m_damage <= 0 && spell.m_healing <= 0)
|
|
||||||
{
|
|
||||||
// Fill base damage struct (unitTarget - is real spell target)
|
|
||||||
SpellNonMeleeDamage damageInfo = new(caster, spell.unitTarget, spell.m_spellInfo, spell.m_SpellVisual, spell.m_spellSchoolMask);
|
|
||||||
hitMask |= Unit.CreateProcHitMask(damageInfo, MissCondition);
|
|
||||||
// Do triggers for unit
|
|
||||||
if (canEffectTrigger)
|
|
||||||
{
|
|
||||||
spellDamageInfo = new(damageInfo, DamageEffectType.NoDamage, spell.m_attackType, hitMask);
|
|
||||||
procSpellType |= ProcFlagsSpellType.NoDmgHeal;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Failed Pickpocket, reveal rogue
|
// set hitmask for finish procs
|
||||||
if (MissCondition == SpellMissInfo.Resist && spell.m_spellInfo.HasAttribute(SpellCustomAttributes.PickPocket) && spell.unitTarget.IsCreature())
|
spell.m_hitMask |= hitMask;
|
||||||
|
|
||||||
|
// Do not take combo points on dodge and miss
|
||||||
|
if (MissCondition != SpellMissInfo.None && spell.m_needComboPoints && spell.m_targets.GetUnitTargetGUID() == TargetGUID)
|
||||||
|
spell.m_needComboPoints = false;
|
||||||
|
|
||||||
|
// _spellHitTarget can be null if spell is missed in DoSpellHitOnUnit
|
||||||
|
if (MissCondition != SpellMissInfo.Evade && _spellHitTarget && !spell.GetCaster().IsFriendlyTo(unit) && (!spell.IsPositive() || spell.m_spellInfo.HasEffect(SpellEffectName.Dispel)))
|
||||||
{
|
{
|
||||||
Unit unitCaster = spell.GetCaster().ToUnit();
|
Unit unitCaster = spell.GetCaster().ToUnit();
|
||||||
unitCaster.RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.Interacting);
|
if (unitCaster != null)
|
||||||
spell.unitTarget.ToCreature().EngageWithTarget(unitCaster);
|
unitCaster.AtTargetAttacked(unit, spell.m_spellInfo.HasInitialAggro());
|
||||||
|
|
||||||
|
if (!unit.IsStandState())
|
||||||
|
unit.SetStandState(UnitStandStateType.Stand);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check for SPELL_ATTR7_INTERRUPT_ONLY_NONPLAYER
|
||||||
|
if (MissCondition == SpellMissInfo.None && spell.m_spellInfo.HasAttribute(SpellAttr7.InterruptOnlyNonplayer) && !unit.IsPlayer())
|
||||||
|
caster.CastSpell(unit, 32747, new CastSpellExtraArgs(TriggerCastFlags.FullMask).SetOriginalCastId(spell.m_castId));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do triggers for unit
|
|
||||||
if (canEffectTrigger)
|
|
||||||
{
|
|
||||||
Unit.ProcSkillsAndAuras(caster, spell.unitTarget, procAttacker, procVictim, procSpellType, ProcFlagsSpellPhase.Hit, hitMask, spell, spellDamageInfo, healInfo);
|
|
||||||
|
|
||||||
// item spells (spell hit of non-damage spell may also activate items, for example seal of corruption hidden hit)
|
|
||||||
if (caster.IsPlayer() && procSpellType.HasAnyFlag(ProcFlagsSpellType.Damage | ProcFlagsSpellType.NoDmgHeal))
|
|
||||||
{
|
|
||||||
if (spell.m_spellInfo.DmgClass == SpellDmgClass.Melee || spell.m_spellInfo.DmgClass == SpellDmgClass.Ranged)
|
|
||||||
if (!spell.m_spellInfo.HasAttribute(SpellAttr0.StopAttackTarget) && !spell.m_spellInfo.HasAttribute(SpellAttr4.SuppressWeaponProcs))
|
|
||||||
caster.ToPlayer().CastItemCombatSpell(spellDamageInfo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// set hitmask for finish procs
|
|
||||||
spell.m_hitMask |= hitMask;
|
|
||||||
|
|
||||||
// Do not take combo points on dodge and miss
|
|
||||||
if (MissCondition != SpellMissInfo.None && spell.m_needComboPoints && spell.m_targets.GetUnitTargetGUID() == TargetGUID)
|
|
||||||
spell.m_needComboPoints = false;
|
|
||||||
|
|
||||||
// _spellHitTarget can be null if spell is missed in DoSpellHitOnUnit
|
|
||||||
if (MissCondition != SpellMissInfo.Evade && _spellHitTarget && !spell.GetCaster().IsFriendlyTo(unit) && (!spell.IsPositive() || spell.m_spellInfo.HasEffect(SpellEffectName.Dispel)))
|
|
||||||
{
|
|
||||||
Unit unitCaster = spell.GetCaster().ToUnit();
|
|
||||||
if (unitCaster != null)
|
|
||||||
unitCaster.AtTargetAttacked(unit, spell.m_spellInfo.HasInitialAggro());
|
|
||||||
|
|
||||||
if (!unit.IsStandState())
|
|
||||||
unit.SetStandState(UnitStandStateType.Stand);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for SPELL_ATTR7_INTERRUPT_ONLY_NONPLAYER
|
|
||||||
if (MissCondition == SpellMissInfo.None && spell.m_spellInfo.HasAttribute(SpellAttr7.InterruptOnlyNonplayer) && !unit.IsPlayer())
|
|
||||||
caster.CastSpell(unit, 32747, new CastSpellExtraArgs(TriggerCastFlags.FullMask).SetOriginalCastId(spell.m_castId));
|
|
||||||
|
|
||||||
if (_spellHitTarget)
|
if (_spellHitTarget)
|
||||||
{
|
{
|
||||||
//AI functions
|
//AI functions
|
||||||
|
|||||||
Reference in New Issue
Block a user