Core/SAI: Allow gameobjects to be targeted by spell casts
Port From (https://github.com/TrinityCore/TrinityCore/commit/22e43917abef1eea31e86c01070afbee19c0cdbc)
This commit is contained in:
@@ -870,6 +870,7 @@ namespace Game.AI
|
|||||||
_followGuid.Clear();
|
_followGuid.Clear();
|
||||||
_followDist = 0;
|
_followDist = 0;
|
||||||
_followAngle = 0;
|
_followAngle = 0;
|
||||||
|
uint followCredit = _followCredit;
|
||||||
_followCredit = 0;
|
_followCredit = 0;
|
||||||
_followArrivedTimer = 1000;
|
_followArrivedTimer = 1000;
|
||||||
_followArrivedEntry = 0;
|
_followArrivedEntry = 0;
|
||||||
@@ -885,9 +886,9 @@ namespace Game.AI
|
|||||||
if (player != null)
|
if (player != null)
|
||||||
{
|
{
|
||||||
if (_followCreditType == 0)
|
if (_followCreditType == 0)
|
||||||
player.RewardPlayerAndGroupAtEvent(_followCredit, me);
|
player.RewardPlayerAndGroupAtEvent(followCredit, me);
|
||||||
else
|
else
|
||||||
player.GroupEventHappens(_followCredit, me);
|
player.GroupEventHappens(followCredit, me);
|
||||||
}
|
}
|
||||||
|
|
||||||
SetDespawnTime(5000);
|
SetDespawnTime(5000);
|
||||||
|
|||||||
@@ -445,47 +445,48 @@ namespace Game.AI
|
|||||||
bool failedSpellCast = false;
|
bool failedSpellCast = false;
|
||||||
bool successfulSpellCast = false;
|
bool successfulSpellCast = false;
|
||||||
|
|
||||||
foreach (var target in targets)
|
CastSpellExtraArgs args = new();
|
||||||
|
if (e.Action.cast.castFlags.HasAnyFlag((uint)SmartCastFlags.Triggered))
|
||||||
{
|
{
|
||||||
if (_go != null)
|
if (e.Action.cast.triggerFlags != 0)
|
||||||
_go.CastSpell(target.ToUnit(), e.Action.cast.spell);
|
args.TriggerFlags = (TriggerCastFlags)e.Action.cast.triggerFlags;
|
||||||
|
|
||||||
if (!IsUnit(target))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!e.Action.cast.castFlags.HasAnyFlag((uint)SmartCastFlags.AuraNotPresent) || !target.ToUnit().HasAura(e.Action.cast.spell))
|
|
||||||
{
|
|
||||||
TriggerCastFlags triggerFlag = TriggerCastFlags.None;
|
|
||||||
if (e.Action.cast.castFlags.HasAnyFlag((uint)SmartCastFlags.Triggered))
|
|
||||||
{
|
|
||||||
if (e.Action.cast.triggerFlags != 0)
|
|
||||||
triggerFlag = (TriggerCastFlags)e.Action.cast.triggerFlags;
|
|
||||||
else
|
|
||||||
triggerFlag = TriggerCastFlags.FullMask;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_me != null)
|
|
||||||
{
|
|
||||||
if (e.Action.cast.castFlags.HasAnyFlag((uint)SmartCastFlags.InterruptPrevious))
|
|
||||||
_me.InterruptNonMeleeSpells(false);
|
|
||||||
|
|
||||||
SpellCastResult result = _me.CastSpell(target.ToUnit(), e.Action.cast.spell, new CastSpellExtraArgs(triggerFlag));
|
|
||||||
bool spellCastFailed = (result != SpellCastResult.SpellCastOk && result != SpellCastResult.SpellInProgress);
|
|
||||||
|
|
||||||
if (e.Action.cast.castFlags.HasAnyFlag((uint)SmartCastFlags.CombatMove))
|
|
||||||
((SmartAI)_me.GetAI()).SetCombatMove(spellCastFailed, true);
|
|
||||||
|
|
||||||
if (spellCastFailed)
|
|
||||||
failedSpellCast = true;
|
|
||||||
else
|
|
||||||
successfulSpellCast = true;
|
|
||||||
}
|
|
||||||
else if (_go != null)
|
|
||||||
_go.CastSpell(target.ToUnit(), e.Action.cast.spell, new CastSpellExtraArgs(triggerFlag));
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
Log.outDebug(LogFilter.ScriptsAi, "Spell {0} not casted because it has flag SMARTCAST_AURA_NOT_PRESENT and the target (Guid: {1} Entry: {2} Type: {3}) already has the aura",
|
args.TriggerFlags = TriggerCastFlags.FullMask;
|
||||||
e.Action.cast.spell, target.GetGUID(), target.GetEntry(), target.GetTypeId());
|
}
|
||||||
|
|
||||||
|
foreach (WorldObject target in targets)
|
||||||
|
{
|
||||||
|
if (e.Action.cast.castFlags.HasAnyFlag((uint)SmartCastFlags.AuraNotPresent) && (!target.IsUnit() || target.ToUnit().HasAura(e.Action.cast.spell)))
|
||||||
|
{
|
||||||
|
Log.outDebug(LogFilter.ScriptsAi, $"Spell {e.Action.cast.spell} not cast because it has flag SMARTCAST_AURA_NOT_PRESENT and the target ({target.GetGUID()}) already has the aura");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SpellCastResult result = SpellCastResult.BadTargets;
|
||||||
|
if (_me != null)
|
||||||
|
{
|
||||||
|
if (e.Action.cast.castFlags.HasAnyFlag((uint)SmartCastFlags.InterruptPrevious))
|
||||||
|
_me.InterruptNonMeleeSpells(false);
|
||||||
|
|
||||||
|
result = _me.CastSpell(target, e.Action.cast.spell, args);
|
||||||
|
}
|
||||||
|
else if (_go != null)
|
||||||
|
result = _go.CastSpell(target, e.Action.cast.spell, args);
|
||||||
|
|
||||||
|
bool spellCastFailed = result != SpellCastResult.SpellCastOk && result != SpellCastResult.SpellInProgress;
|
||||||
|
if (_me != null && e.Action.cast.castFlags.HasAnyFlag((uint)SmartCastFlags.CombatMove))
|
||||||
|
{
|
||||||
|
// If cast flag SMARTCAST_COMBAT_MOVE is set combat movement will not be allowed unless target is outside spell range, out of mana, or LOS.
|
||||||
|
_me.GetAI<SmartAI>().SetCombatMove(spellCastFailed, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (spellCastFailed)
|
||||||
|
failedSpellCast = true;
|
||||||
|
else
|
||||||
|
successfulSpellCast = true;
|
||||||
|
|
||||||
|
Log.outDebug(LogFilter.ScriptsAi, $"SmartScript::ProcessAction:: SMART_ACTION_CAST:: {(_me != null ? _me.GetGUID() : _go.GetGUID())} casts spell {e.Action.cast.spell} on target {target.GetGUID()} with castflags {e.Action.cast.castFlags}");
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there is at least 1 failed cast and no successful casts at all, retry again on next loop
|
// If there is at least 1 failed cast and no successful casts at all, retry again on next loop
|
||||||
@@ -506,28 +507,24 @@ namespace Game.AI
|
|||||||
if (e.Action.cast.targetsLimit != 0)
|
if (e.Action.cast.targetsLimit != 0)
|
||||||
targets.RandomResize(e.Action.cast.targetsLimit);
|
targets.RandomResize(e.Action.cast.targetsLimit);
|
||||||
|
|
||||||
TriggerCastFlags triggerFlags = TriggerCastFlags.None;
|
CastSpellExtraArgs args = new();
|
||||||
if (e.Action.cast.castFlags.HasAnyFlag((uint)SmartCastFlags.Triggered))
|
if (e.Action.cast.castFlags.HasAnyFlag((uint)SmartCastFlags.Triggered))
|
||||||
{
|
{
|
||||||
if (e.Action.cast.triggerFlags != 0)
|
if (e.Action.cast.triggerFlags != 0)
|
||||||
triggerFlags = (TriggerCastFlags)e.Action.cast.triggerFlags;
|
args.TriggerFlags = (TriggerCastFlags)e.Action.cast.triggerFlags;
|
||||||
else
|
else
|
||||||
triggerFlags = TriggerCastFlags.FullMask;
|
args.TriggerFlags = TriggerCastFlags.FullMask;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (WorldObject target in targets)
|
foreach (WorldObject target in targets)
|
||||||
{
|
{
|
||||||
Unit uTarget = target.ToUnit();
|
if (e.Action.cast.castFlags.HasAnyFlag((uint)SmartCastFlags.AuraNotPresent) && (!target.IsUnit() || target.ToUnit().HasAura(e.Action.cast.spell)))
|
||||||
if (uTarget == null)
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!e.Action.cast.castFlags.HasAnyFlag((uint)SmartCastFlags.AuraNotPresent) || !uTarget.HasAura(e.Action.cast.spell))
|
if (e.Action.cast.castFlags.HasAnyFlag((uint)SmartCastFlags.InterruptPrevious) && target.IsUnit())
|
||||||
{
|
target.ToUnit().InterruptNonMeleeSpells(false);
|
||||||
if (e.Action.cast.castFlags.HasAnyFlag((uint)SmartCastFlags.InterruptPrevious))
|
|
||||||
uTarget.InterruptNonMeleeSpells(false);
|
|
||||||
|
|
||||||
uTarget.CastSpell(uTarget, e.Action.cast.spell, new CastSpellExtraArgs(triggerFlags));
|
target.CastSpell(target, e.Action.cast.spell, args);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -543,33 +540,28 @@ namespace Game.AI
|
|||||||
if (e.Action.cast.targetsLimit != 0)
|
if (e.Action.cast.targetsLimit != 0)
|
||||||
targets.RandomResize(e.Action.cast.targetsLimit);
|
targets.RandomResize(e.Action.cast.targetsLimit);
|
||||||
|
|
||||||
|
CastSpellExtraArgs args = new();
|
||||||
|
if (e.Action.cast.castFlags.HasAnyFlag((uint)SmartCastFlags.Triggered))
|
||||||
|
{
|
||||||
|
if (e.Action.cast.triggerFlags != 0)
|
||||||
|
args.TriggerFlags = (TriggerCastFlags)e.Action.cast.triggerFlags;
|
||||||
|
else
|
||||||
|
args.TriggerFlags = TriggerCastFlags.FullMask;
|
||||||
|
}
|
||||||
|
|
||||||
foreach (var target in targets)
|
foreach (var target in targets)
|
||||||
{
|
{
|
||||||
if (!IsUnit(target))
|
if (e.Action.cast.castFlags.HasAnyFlag((uint)SmartCastFlags.AuraNotPresent) && (!target.IsUnit() || target.ToUnit().HasAura(e.Action.cast.spell)))
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!e.Action.cast.castFlags.HasAnyFlag((uint)SmartCastFlags.AuraNotPresent) || !target.ToUnit().HasAura(e.Action.cast.spell))
|
|
||||||
{
|
{
|
||||||
|
Log.outDebug(LogFilter.ScriptsAi, $"Spell {e.Action.cast.spell} not cast because it has flag SMARTCAST_AURA_NOT_PRESENT and the target ({target.GetGUID()}) already has the aura");
|
||||||
if (e.Action.cast.castFlags.HasAnyFlag((uint)SmartCastFlags.InterruptPrevious))
|
continue;
|
||||||
tempLastInvoker.InterruptNonMeleeSpells(false);
|
|
||||||
|
|
||||||
TriggerCastFlags triggerFlag = TriggerCastFlags.None;
|
|
||||||
if (e.Action.cast.castFlags.HasAnyFlag((uint)SmartCastFlags.Triggered))
|
|
||||||
{
|
|
||||||
if (e.Action.cast.triggerFlags != 0)
|
|
||||||
triggerFlag = (TriggerCastFlags)e.Action.cast.triggerFlags;
|
|
||||||
else
|
|
||||||
triggerFlag = TriggerCastFlags.FullMask;
|
|
||||||
}
|
|
||||||
|
|
||||||
tempLastInvoker.CastSpell(target.ToUnit(), e.Action.cast.spell, new CastSpellExtraArgs(triggerFlag));
|
|
||||||
|
|
||||||
Log.outDebug(LogFilter.ScriptsAi, "SmartScript.ProcessAction. SMART_ACTION_INVOKER_CAST: Invoker {0} casts spell {1} on target {2} with castflags {3}",
|
|
||||||
tempLastInvoker.GetGUID().ToString(), e.Action.cast.spell, target.GetGUID().ToString(), e.Action.cast.castFlags);
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
Log.outDebug(LogFilter.ScriptsAi, "Spell {0} not cast because it has flag SMARTCAST_AURA_NOT_PRESENT and the target ({1}) already has the aura", e.Action.cast.spell, target.GetGUID().ToString());
|
if (e.Action.cast.castFlags.HasAnyFlag((uint)SmartCastFlags.InterruptPrevious))
|
||||||
|
tempLastInvoker.InterruptNonMeleeSpells(false);
|
||||||
|
|
||||||
|
tempLastInvoker.CastSpell(target, e.Action.cast.spell, args);
|
||||||
|
Log.outDebug(LogFilter.ScriptsAi, $"SmartScript::ProcessAction:: SMART_ACTION_INVOKER_CAST: Invoker {tempLastInvoker.GetGUID()} casts spell {e.Action.cast.spell} on target {target.GetGUID()} with castflags {e.Action.cast.castFlags}");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1584,31 +1576,34 @@ namespace Game.AI
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
List<WorldObject> casters = GetTargets(CreateSmartEvent(SmartEvents.UpdateIc, 0, 0, 0, 0, 0, 0, SmartActions.None, 0, 0, 0, 0, 0, 0, 0, (SmartTargets)e.Action.crossCast.targetType, e.Action.crossCast.targetParam1, e.Action.crossCast.targetParam2, e.Action.crossCast.targetParam3, 0, 0), unit);
|
List<WorldObject> casters = GetTargets(CreateSmartEvent(SmartEvents.UpdateIc, 0, 0, 0, 0, 0, 0, SmartActions.None, 0, 0, 0, 0, 0, 0, 0, (SmartTargets)e.Action.crossCast.targetType, e.Action.crossCast.targetParam1, e.Action.crossCast.targetParam2, e.Action.crossCast.targetParam3, 0, 0), unit);
|
||||||
|
|
||||||
|
CastSpellExtraArgs args = new();
|
||||||
|
if (e.Action.crossCast.castFlags.HasAnyFlag((uint)SmartCastFlags.Triggered))
|
||||||
|
args.TriggerFlags = TriggerCastFlags.FullMask;
|
||||||
|
|
||||||
foreach (var caster in casters)
|
foreach (var caster in casters)
|
||||||
{
|
{
|
||||||
if (!IsUnit(caster))
|
Unit casterUnit = caster.ToUnit();
|
||||||
|
if (casterUnit == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
Unit casterUnit = caster.ToUnit();
|
|
||||||
bool interruptedSpell = false;
|
bool interruptedSpell = false;
|
||||||
|
|
||||||
foreach (var target in targets)
|
foreach (var target in targets)
|
||||||
{
|
{
|
||||||
if (!IsUnit(target))
|
if (e.Action.crossCast.castFlags.HasAnyFlag((uint)SmartCastFlags.AuraNotPresent) && (!target.IsUnit() || target.ToUnit().HasAura(e.Action.crossCast.spell)))
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!(e.Action.crossCast.castFlags.HasAnyFlag((uint)SmartCastFlags.AuraNotPresent)) || !target.ToUnit().HasAura(e.Action.crossCast.spell))
|
|
||||||
{
|
{
|
||||||
if (!interruptedSpell && e.Action.crossCast.castFlags.HasAnyFlag((uint)SmartCastFlags.InterruptPrevious))
|
Log.outDebug(LogFilter.ScriptsAi, $"Spell {e.Action.crossCast.spell} not cast because it has flag SMARTCAST_AURA_NOT_PRESENT and the target ({target.GetGUID()}) already has the aura");
|
||||||
{
|
continue;
|
||||||
casterUnit.InterruptNonMeleeSpells(false);
|
|
||||||
interruptedSpell = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
casterUnit.CastSpell(target.ToUnit(), e.Action.crossCast.spell, e.Action.crossCast.castFlags.HasAnyFlag((uint)SmartCastFlags.Triggered));
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
Log.outDebug(LogFilter.ScriptsAi, "Spell {0} not cast because it has flag SMARTCAST_AURA_NOT_PRESENT and the target ({1}) already has the aura", e.Action.crossCast.spell, target.GetGUID().ToString());
|
if (!interruptedSpell && e.Action.crossCast.castFlags.HasAnyFlag((uint)SmartCastFlags.InterruptPrevious))
|
||||||
|
{
|
||||||
|
casterUnit.InterruptNonMeleeSpells(false);
|
||||||
|
interruptedSpell = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
casterUnit.CastSpell(target, e.Action.crossCast.spell, args);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|||||||
Reference in New Issue
Block a user