fix: Magic NPCs now use spell range (#1870)
### Summary - Drastically streamlines the spell targeting by collapsing the target classes into a single `SpellTarget<T>` class. - Moves TargetRange to the spell itself so it can be used by MageAI. - Changes range check in MageAI to use TargetRange. This should fix target acquisition bugs
This commit is contained in:
parent
91e37fb8d4
commit
9b7fea2c20
85 changed files with 255 additions and 313 deletions
|
|
@ -1,9 +1,6 @@
|
|||
namespace Server.Spells
|
||||
namespace Server.Spells;
|
||||
|
||||
public interface IRecallSpell : IRangedSpell
|
||||
{
|
||||
public interface IRecallSpell
|
||||
{
|
||||
Mobile Caster { get; }
|
||||
void Effect(Point3D loc, Map map, bool checkMulti);
|
||||
void FinishSequence();
|
||||
}
|
||||
void Effect(Point3D loc, Map map, bool checkMulti);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
namespace Server.Spells
|
||||
namespace Server.Spells;
|
||||
|
||||
public interface ISpellTarget<in T> where T : IPoint3D
|
||||
{
|
||||
public interface ISpellTarget
|
||||
{
|
||||
ISpell Spell { get; }
|
||||
}
|
||||
ITargetingSpell<T> Spell { get; }
|
||||
}
|
||||
|
|
|
|||
14
Projects/UOContent/Spells/Targeting/ITargetingSpell.cs
Normal file
14
Projects/UOContent/Spells/Targeting/ITargetingSpell.cs
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
namespace Server.Spells;
|
||||
|
||||
public interface IRangedSpell
|
||||
{
|
||||
Mobile Caster { get; }
|
||||
|
||||
int TargetRange => Core.ML ? 10 : 12;
|
||||
void FinishSequence();
|
||||
}
|
||||
|
||||
public interface ITargetingSpell<in T> : IRangedSpell where T : IPoint3D
|
||||
{
|
||||
void Target(T target);
|
||||
}
|
||||
|
|
@ -10,7 +10,7 @@ public class RecallSpellTarget : Target
|
|||
private readonly IRecallSpell _spell;
|
||||
private readonly bool _toBoat;
|
||||
|
||||
public RecallSpellTarget(IRecallSpell spell, bool toBoat = true) : base(Core.ML ? 10 : 12, false, TargetFlags.None)
|
||||
public RecallSpellTarget(IRecallSpell spell, bool toBoat = true) : base(spell.TargetRange, false, TargetFlags.None)
|
||||
{
|
||||
_spell = spell;
|
||||
_toBoat = toBoat;
|
||||
|
|
@ -68,8 +68,5 @@ public class RecallSpellTarget : Target
|
|||
{
|
||||
}
|
||||
|
||||
protected override void OnTargetFinish(Mobile from)
|
||||
{
|
||||
_spell?.FinishSequence();
|
||||
}
|
||||
protected override void OnTargetFinish(Mobile from) => _spell?.FinishSequence();
|
||||
}
|
||||
|
|
|
|||
58
Projects/UOContent/Spells/Targeting/SpellTarget.cs
Normal file
58
Projects/UOContent/Spells/Targeting/SpellTarget.cs
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
using Server.Targeting;
|
||||
|
||||
namespace Server.Spells;
|
||||
|
||||
public class SpellTarget<T> : Target, ISpellTarget<T> where T : class, IPoint3D
|
||||
{
|
||||
private static readonly bool _canTargetStatic = typeof(T).IsAssignableFrom(typeof(StaticTarget));
|
||||
private static readonly bool _canTargetMobile = typeof(T).IsAssignableFrom(typeof(Mobile));
|
||||
private static readonly bool _canTargetItem = typeof(T).IsAssignableFrom(typeof(Item));
|
||||
|
||||
private readonly bool _retryOnLos;
|
||||
protected readonly ITargetingSpell<T> _spell;
|
||||
|
||||
public SpellTarget(
|
||||
ITargetingSpell<T> spell,
|
||||
TargetFlags flags = TargetFlags.None,
|
||||
bool retryOnLos = false
|
||||
) : this(spell, false, flags, retryOnLos)
|
||||
{
|
||||
}
|
||||
|
||||
public SpellTarget(ITargetingSpell<T> spell, bool allowGround, TargetFlags flags = TargetFlags.None, bool retryOnLos = false)
|
||||
: base(spell.TargetRange, allowGround, flags)
|
||||
{
|
||||
_spell = spell;
|
||||
_retryOnLos = retryOnLos;
|
||||
}
|
||||
|
||||
public ITargetingSpell<T> Spell => _spell;
|
||||
|
||||
protected override bool CanTarget(Mobile from, StaticTarget staticTarget, ref Point3D loc, ref Map map)
|
||||
=> _canTargetStatic;
|
||||
|
||||
protected override bool CanTarget(Mobile from, Mobile mobile, ref Point3D loc, ref Map map) => _canTargetMobile;
|
||||
|
||||
protected override bool CanTarget(Mobile from, Item item, ref Point3D loc, ref Map map) => _canTargetItem;
|
||||
|
||||
protected override void OnCantSeeTarget(Mobile from, object o)
|
||||
{
|
||||
from.SendLocalizedMessage(500237); // Target can not be seen.
|
||||
}
|
||||
|
||||
protected override void OnTarget(Mobile from, object o) => _spell.Target(o as T);
|
||||
|
||||
protected override void OnTargetOutOfLOS(Mobile from, object o)
|
||||
{
|
||||
if (!_retryOnLos)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
from.SendLocalizedMessage(501943); // Target cannot be seen. Try again.
|
||||
from.Target = new SpellTarget<T>(_spell, AllowGround, Flags, true);
|
||||
from.Target.BeginTimeout(from, TimeoutTime - Core.TickCount);
|
||||
}
|
||||
|
||||
protected override void OnTargetFinish(Mobile from) => _spell?.FinishSequence();
|
||||
}
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
using Server.Targeting;
|
||||
|
||||
namespace Server.Spells
|
||||
{
|
||||
public interface ISpellTargetingItem : ISpell
|
||||
{
|
||||
void Target(Item item);
|
||||
}
|
||||
|
||||
public class SpellTargetItem : Target, ISpellTarget
|
||||
{
|
||||
private readonly ISpellTargetingItem _spell;
|
||||
|
||||
public SpellTargetItem(ISpellTargetingItem spell, TargetFlags flags = TargetFlags.None, int range = 12)
|
||||
: base(range, false, flags) => _spell = spell;
|
||||
|
||||
public ISpell Spell => _spell;
|
||||
|
||||
protected override bool CanTarget(Mobile from, StaticTarget staticTarget, ref Point3D loc, ref Map map) => false;
|
||||
protected override bool CanTarget(Mobile from, Mobile mobile, ref Point3D loc, ref Map map) => false;
|
||||
|
||||
protected override void OnCantSeeTarget(Mobile from, object o)
|
||||
{
|
||||
from.SendLocalizedMessage(500237); // Target can not be seen.
|
||||
}
|
||||
|
||||
protected override void OnTarget(Mobile from, object o)
|
||||
{
|
||||
_spell.Target(o as Item);
|
||||
}
|
||||
|
||||
protected override void OnTargetFinish(Mobile from)
|
||||
{
|
||||
_spell?.FinishSequence();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
using Server.Targeting;
|
||||
|
||||
namespace Server.Spells
|
||||
{
|
||||
public interface ISpellTargetingMobile : ISpell
|
||||
{
|
||||
void Target(Mobile m);
|
||||
}
|
||||
|
||||
public class SpellTargetMobile : Target, ISpellTarget
|
||||
{
|
||||
private readonly ISpellTargetingMobile _spell;
|
||||
|
||||
public SpellTargetMobile(ISpellTargetingMobile spell, TargetFlags flags, int range = 12) :
|
||||
base(range, false, flags) => _spell = spell;
|
||||
|
||||
public ISpell Spell => _spell;
|
||||
|
||||
protected override bool CanTarget(Mobile from, StaticTarget staticTarget, ref Point3D loc, ref Map map) => false;
|
||||
protected override bool CanTarget(Mobile from, Item item, ref Point3D loc, ref Map map) => false;
|
||||
|
||||
protected override void OnTarget(Mobile from, object o)
|
||||
{
|
||||
_spell.Target(o as Mobile);
|
||||
}
|
||||
|
||||
protected override void OnTargetFinish(Mobile from)
|
||||
{
|
||||
_spell?.FinishSequence();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,53 +0,0 @@
|
|||
using Server.Targeting;
|
||||
|
||||
namespace Server.Spells
|
||||
{
|
||||
public interface ISpellTargetingPoint3D : ISpell
|
||||
{
|
||||
void Target(IPoint3D p);
|
||||
}
|
||||
|
||||
public class SpellTargetPoint3D : Target, ISpellTarget
|
||||
{
|
||||
private readonly bool _retryOnLos;
|
||||
private ISpellTargetingPoint3D _spell;
|
||||
|
||||
public SpellTargetPoint3D(
|
||||
ISpellTargetingPoint3D spell, TargetFlags flags = TargetFlags.None, int range = 12, bool retryOnLOS = false
|
||||
) : base(range, true, flags)
|
||||
{
|
||||
_spell = spell;
|
||||
_retryOnLos = retryOnLOS;
|
||||
}
|
||||
|
||||
public ISpell Spell => _spell;
|
||||
|
||||
protected override void OnTarget(Mobile from, object o)
|
||||
{
|
||||
_spell.Target(o as IPoint3D);
|
||||
}
|
||||
|
||||
protected override void OnCantSeeTarget(Mobile from, object o)
|
||||
{
|
||||
from.SendLocalizedMessage(500237); // Target can not be seen.
|
||||
}
|
||||
|
||||
protected override void OnTargetOutOfLOS(Mobile from, object o)
|
||||
{
|
||||
if (!_retryOnLos)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
from.SendLocalizedMessage(501943); // Target cannot be seen. Try again.
|
||||
from.Target = new SpellTargetPoint3D(_spell);
|
||||
from.Target.BeginTimeout(from, TimeoutTime - Core.TickCount);
|
||||
_spell = null; // Needed?
|
||||
}
|
||||
|
||||
protected override void OnTargetFinish(Mobile from)
|
||||
{
|
||||
_spell?.FinishSequence();
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue