fix: Fixes double calls with Target cancel and spell sequences (#1840)

### Summary
- Cleans up target cancellation being called incorrectly.
- An invalid target type (which should never happen), now calls `OnTargetUntargetable` instead of `OnTargetCanceled`
- Removes double calls to `FinishSequence` in Spells.
This commit is contained in:
Kamron Batman 2024-06-17 15:19:06 -07:00 committed by GitHub
parent 9c0b57213a
commit b8ad5c671d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
80 changed files with 201 additions and 406 deletions

View file

@ -38,7 +38,7 @@ public abstract class Target
public static void Cancel(Mobile m)
{
m.NetState.SendCancelTarget();
m.Target?.OnTargetCancel(m, TargetCancelType.Canceled);
m.Target?.Cancel(m, TargetCancelType.Canceled);
}
public void BeginTimeout(Mobile from, long delay)
@ -57,15 +57,14 @@ public abstract class Target
m_TimeoutTimer = null;
}
public void Timeout(Mobile from)
public void Timeout(Mobile m)
{
m.NetState.SendCancelTarget();
CancelTimeout();
from.ClearTarget();
m.ClearTarget();
Cancel(from);
OnTargetCancel(from, TargetCancelType.Timeout);
OnTargetFinish(from);
OnTargetCancel(m, TargetCancelType.Timeout);
OnTargetFinish(m);
}
public virtual void SendTargetTo(NetState ns) => ns.SendTargetReq(this);
@ -84,7 +83,6 @@ public abstract class Target
if (!AllowGround)
{
// We should actually never get here. If we do, it's probably a misbehaving client/macro.
OnTargetCancel(from, TargetCancelType.Canceled);
return false;
}
@ -161,7 +159,7 @@ public abstract class Target
Map map = null;
Item item = null;
Mobile mobile = null;
bool isValidTargetType = true;
var isValidTargetType = true;
bool valid = targeted switch
{
@ -176,13 +174,10 @@ public abstract class Target
{
if (!isValidTargetType)
{
OnTargetCancel(from, TargetCancelType.Canceled);
OnTargetUntargetable(from, targeted);
}
OnTargetFinish(from);
}
if (map == null || map != from.Map || Range >= 0 && !from.InRange(loc, Range))
else if (map == null || map != from.Map || Range >= 0 && !from.InRange(loc, Range))
{
OnTargetOutOfRange(from, targeted);
}
@ -206,7 +201,7 @@ public abstract class Target
{
OnTargetUntargetable(from, targeted);
}
else if (mobile?.CheckTarget(from, this, mobile) == false)
else if (mobile?.CheckTarget(from, this, targeted) == false)
{
OnTargetUntargetable(from, mobile);
}
@ -271,20 +266,20 @@ public abstract class Target
private class TimeoutTimer : Timer
{
private readonly Mobile m_Mobile;
private readonly Target m_Target;
private readonly Mobile _mobile;
private readonly Target _target;
public TimeoutTimer(Target target, Mobile m, TimeSpan delay) : base(delay)
{
m_Target = target;
m_Mobile = m;
_target = target;
_mobile = m;
}
protected override void OnTick()
{
if (m_Mobile.Target == m_Target)
if (_mobile.Target == _target)
{
m_Target.Timeout(m_Mobile);
_target.Timeout(_mobile);
}
}
}

View file

@ -59,19 +59,9 @@ public partial class Scissors : Item
// Didn't your parents ever tell you not to run with scissors in your hand?!
from.SendLocalizedMessage(1063305);
}
else if (targeted is Item item && !item.Movable)
else if (targeted is Item item and IScissorable scissorable && (targeted is PlagueBeastInnard or PlagueBeastMutationCore || item.Movable))
{
if (item is IScissorable obj && obj is PlagueBeastInnard or PlagueBeastMutationCore)
{
if (CanScissor(from, obj) && obj.Scissor(from, m_Item))
{
from.PlaySound(0x248);
}
}
}
else if (targeted is IScissorable obj)
{
if (CanScissor(from, obj) && obj.Scissor(from, m_Item))
if (CanScissor(from, scissorable) && scissorable.Scissor(from, m_Item))
{
from.PlaySound(0x248);
}
@ -84,13 +74,15 @@ public partial class Scissors : Item
protected override void OnNonlocalTarget(Mobile from, object targeted)
{
if (targeted is not (IScissorable obj and (PlagueBeastInnard or PlagueBeastMutationCore)))
if (targeted is not PlagueBeastInnard and not PlagueBeastMutationCore)
{
base.OnNonlocalTarget(from, targeted);
return;
}
if (CanScissor(from, obj) && obj.Scissor(from, m_Item))
var scissorable = (IScissorable)targeted;
if (CanScissor(from, scissorable) && scissorable.Scissor(from, m_Item))
{
from.PlaySound(0x248);
}

View file

@ -98,8 +98,6 @@ namespace Server.Spells.Chivalry
AOS.Damage(Caster, Caster, damage, 0, 100, 0, 0, 0, true);
}
FinishSequence();
}
public override bool CheckCast()

View file

@ -78,8 +78,6 @@ namespace Server.Spells.Chivalry
m.FixedParticles(0x376A, 1, 62, 9923, 3, 3, EffectLayer.Waist);
m.FixedParticles(0x3779, 1, 46, 9502, 5, 3, EffectLayer.Waist);
}
FinishSequence();
}
public override bool CheckCast()

View file

@ -124,8 +124,6 @@ namespace Server.Spells.Chivalry
m.PlaySound(0x1DF);
}
}
FinishSequence();
}
public override bool CheckCast()

View file

@ -109,8 +109,6 @@ namespace Server.Spells.Chivalry
Caster.MoveToWorld(loc, map);
Caster.PlaySound(0x1FC);
}
FinishSequence();
}
public override void OnCast()
@ -122,6 +120,7 @@ namespace Server.Spells.Chivalry
else
{
Effect(m_Entry.Location, m_Entry.Map, true);
FinishSequence();
}
}

View file

@ -40,8 +40,6 @@ namespace Server.Spells.Eighth
BaseCreature.Summon(new EnergyVortex(), false, Caster, new Point3D(p), 0x212, duration);
}
FinishSequence();
}
public override bool CheckCast()

View file

@ -64,8 +64,6 @@ namespace Server.Spells.Eighth
m.CloseGump<ResurrectGump>();
m.SendGump(new ResurrectGump(m, Caster));
}
FinishSequence();
}
public override bool CheckCast()

View file

@ -37,8 +37,6 @@ namespace Server.Spells.Fifth
var duration = TimeSpan.FromSeconds(Core.AOS ? 120 : Utility.Random(80, 40));
BaseCreature.Summon(new BladeSpirits(), false, Caster, new Point3D(p), 0x212, duration);
}
FinishSequence();
}
public override TimeSpan GetCastDelay()

View file

@ -47,8 +47,6 @@ namespace Server.Spells.Fifth
item.Delete();
}
FinishSequence();
}
public override void OnCast()

View file

@ -99,8 +99,6 @@ namespace Server.Spells.Fifth
BuffInfo.AddBuff(Caster, new BuffInfo(BuffIcon.MagicReflection, 1075817, buffFormat, true));
}
}
FinishSequence();
}
else
{
@ -129,9 +127,9 @@ namespace Server.Spells.Fifth
Caster.SendLocalizedMessage(1005385); // The spell will not adhere to you at this time.
}
}
FinishSequence();
}
FinishSequence();
}
public static void EndReflect(Mobile m)

View file

@ -106,8 +106,6 @@ namespace Server.Spells.Fifth
SpellHelper.Damage(this, target, damage, 0, 0, 100, 0, 0);
}
FinishSequence();
}
public override void OnCast()

View file

@ -78,8 +78,6 @@ namespace Server.Spells.Fifth
HarmfulSpell(m);
}
FinishSequence();
}
public override void OnCast()

View file

@ -53,8 +53,6 @@ public class PoisonFieldSpell : MagerySpell, ISpellTargetingPoint3D
new PoisonField(itemID, targetLoc, Caster, Caster.Map, duration, i);
}
}
FinishSequence();
}
public override void OnCast()

View file

@ -43,8 +43,6 @@ namespace Server.Spells.First
HarmfulSpell(m);
}
FinishSequence();
}
public override void OnCast()

View file

@ -45,8 +45,6 @@ namespace Server.Spells.First
HarmfulSpell(m);
}
FinishSequence();
}
public override void OnCast()

View file

@ -69,8 +69,6 @@ namespace Server.Spells.First
m.FixedParticles(0x376A, 9, 32, 5005, EffectLayer.Waist);
m.PlaySound(0x1F2);
}
FinishSequence();
}
public override bool CheckCast()

View file

@ -64,8 +64,6 @@ namespace Server.Spells.First
SpellHelper.Damage(this, m, damage, 0, 100, 0, 0, 0);
}
FinishSequence();
}
public override void OnCast()

View file

@ -1,80 +1,58 @@
using System;
using Server.Targeting;
namespace Server.Spells.First
namespace Server.Spells.First;
public class NightSightSpell : MagerySpell, ISpellTargetingMobile
{
public class NightSightSpell : MagerySpell
private static readonly SpellInfo _info = new(
"Night Sight",
"In Lor",
236,
9031,
Reagent.SulfurousAsh,
Reagent.SpidersSilk
);
public NightSightSpell(Mobile caster, Item scroll = null) : base(caster, scroll, _info)
{
private static readonly SpellInfo _info = new(
"Night Sight",
"In Lor",
236,
9031,
Reagent.SulfurousAsh,
Reagent.SpidersSilk
);
}
public NightSightSpell(Mobile caster, Item scroll = null) : base(caster, scroll, _info)
public override SpellCircle Circle => SpellCircle.First;
public override void OnCast()
{
Caster.Target = new SpellTargetMobile(this, TargetFlags.Beneficial, 12);
}
public void Target(Mobile m)
{
if (CheckBSequence(m))
{
}
SpellHelper.Turn(Caster, m);
public override SpellCircle Circle => SpellCircle.First;
public override void OnCast()
{
Caster.Target = new NightSightTarget(this);
}
private class NightSightTarget : Target
{
private readonly Spell m_Spell;
public NightSightTarget(Spell spell) : base(12, false, TargetFlags.Beneficial) => m_Spell = spell;
protected override void OnTarget(Mobile from, object targeted)
if (m.BeginAction<LightCycle>())
{
if (targeted is Mobile targ && m_Spell.CheckBSequence(targ))
{
SpellHelper.Turn(m_Spell.Caster, targ);
new LightCycle.NightSightTimer(m).Start();
if (targ.BeginAction<LightCycle>())
{
new LightCycle.NightSightTimer(targ).Start();
var level =
(int)(LightCycle.DungeonLevel *
((Core.AOS
? targ.Skills.Magery.Value
: from.Skills.Magery.Value) / 100));
var skill = (Core.AOS ? m.Skills.Magery.Value : Caster.Skills.Magery.Value) / 100;
var level = (int)(LightCycle.DungeonLevel * skill);
targ.LightLevel = Math.Max(level, 0);
m.LightLevel = Math.Max(level, 0);
targ.FixedParticles(0x376A, 9, 32, 5007, EffectLayer.Waist);
targ.PlaySound(0x1E3);
m.FixedParticles(0x376A, 9, 32, 5007, EffectLayer.Waist);
m.PlaySound(0x1E3);
BuffInfo.AddBuff(
targ,
new BuffInfo(BuffIcon.NightSight, 1075643)
); // Night Sight/You ignore lighting effects
}
else
{
if (from == targ)
{
from.SendMessage("You already have nightsight.");
}
else
{
from.SendMessage("They already have nightsight.");
}
}
}
m_Spell.FinishSequence();
// Night Sight/You ignore lighting effects
BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.NightSight, 1075643));
}
protected override void OnTargetFinish(Mobile from)
else if (m == Caster)
{
m_Spell.FinishSequence();
m.SendMessage("You already have nightsight.");
}
else
{
m.SendMessage("They already have nightsight.");
}
}
}

View file

@ -43,8 +43,6 @@ namespace Server.Spells.First
HarmfulSpell(m);
}
FinishSequence();
}
public override void OnCast()

View file

@ -91,8 +91,6 @@ namespace Server.Spells.Fourth
}
}
}
FinishSequence();
}
public override void OnCast()

View file

@ -29,10 +29,14 @@ namespace Server.Spells.Fourth
public void Target(IPoint3D p)
{
if (Caster.Map == null)
{
return;
}
if (CheckSequence())
{
SpellHelper.Turn(Caster, p);
SpellHelper.GetSurfaceTop(ref p);
var loc = new Point3D(p);
@ -42,12 +46,6 @@ namespace Server.Spells.Fourth
Effects.PlaySound(loc, Caster.Map, 0x299);
}
if (Caster.Map == null)
{
FinishSequence();
return;
}
using var targets = PooledRefQueue<Mobile>.Create();
foreach (var m in Caster.Map.GetMobilesInRange(loc, Core.AOS ? 2 : 3))
{
@ -92,8 +90,6 @@ namespace Server.Spells.Fourth
}
}
}
FinishSequence();
}
public override void OnCast()

View file

@ -101,8 +101,6 @@ namespace Server.Spells.Fourth
DoHurtFizzle();
}
}
FinishSequence();
}
public override void OnCast()

View file

@ -56,8 +56,6 @@ public class FireFieldSpell : MagerySpell, ISpellTargetingPoint3D
new FireFieldItem(itemID, targetLoc, Caster, Caster.Map, duration, i);
}
}
FinishSequence();
}
public override void OnCast()

View file

@ -57,8 +57,6 @@ namespace Server.Spells.Fourth
m.FixedParticles(0x376A, 9, 32, 5030, EffectLayer.Waist);
m.PlaySound(0x202);
}
FinishSequence();
}
public override bool CheckCast()

View file

@ -53,8 +53,6 @@ namespace Server.Spells.Fourth
SpellHelper.Damage(this, m, damage, 0, 0, 0, 0, 100);
}
FinishSequence();
}
public override void OnCast()

View file

@ -73,8 +73,6 @@ namespace Server.Spells.Fourth
HarmfulSpell(m);
}
FinishSequence();
}
public override void OnCast()

View file

@ -101,8 +101,6 @@ namespace Server.Spells.Fourth
Caster.MoveToWorld(loc, map);
Caster.PlaySound(0x1FC);
}
FinishSequence();
}
public override void GetCastSkills(out double min, out double max)
@ -130,6 +128,7 @@ namespace Server.Spells.Fourth
else
{
Effect(m_Entry.Location, m_Entry.Map, true);
FinishSequence();
}
}

View file

@ -51,12 +51,10 @@ public class AnimatedWeaponSpell : MysticSpell, ISpellTargetingPoint3D
Effects.SendTargetParticles(summon, 0x3728, 10, 10, 0x13AA, (EffectLayer)255);
}
FinishSequence();
}
public override void OnCast()
{
Caster.Target = new SpellTargetPoint3D(this);
}
}
}

View file

@ -26,63 +26,61 @@ public class BombardSpell : MysticSpell, ISpellTargetingMobile
public override void OnCast()
{
Caster.Target = new SpellTargetMobile(this, TargetFlags.Harmful);
}
Caster.Target = new SpellTargetMobile(this, TargetFlags.Harmful);
}
public void Target(Mobile m)
{
if (CheckHSequence(m))
if (CheckHSequence(m))
{
SpellHelper.Turn(Caster, m);
if (HasDelayedDamageContext(m))
{
SpellHelper.Turn(Caster, m);
DoHurtFizzle();
return;
}
if (HasDelayedDamageContext(m))
var source = Caster;
if (SpellHelper.CheckReflect(6, ref source, ref m))
{
Timer.StartTimer(TimeSpan.FromSeconds(0.5), () =>
{
DoHurtFizzle();
return;
}
var source = Caster;
if (SpellHelper.CheckReflect(6, ref source, ref m))
{
Timer.StartTimer(TimeSpan.FromSeconds(0.5), () =>
{
source.MovingEffect(m, 0x1363, 12, 1, false, true, 0, 0);
source.PlaySound(0x64B);
});
}
Caster.MovingEffect(m, 0x1363, 12, 1, false, true, 0, 0);
Caster.PlaySound(0x64B);
SpellHelper.Damage(this, m, GetNewAosDamage(40, 1, 5, m), 100, 0, 0, 0, 0);
Timer.StartTimer(TimeSpan.FromSeconds(1.2), () =>
{
if (CheckResisted(m))
{
return;
}
var damageSkill = GetDamageSkill(Caster);
var resist = GetResistSkill(m);
int secs = Math.Max(0, (int)(damageSkill / 10 - resist / 10));
if (secs > 0)
{
m.Paralyze(TimeSpan.FromSeconds(secs));
}
// Up to 12% chance by checking mysticism + imbuing/focus against resist
var knockBackChance = (GetBaseSkill(Caster) + damageSkill - resist) / 20;
if (knockBackChance > 0 && Utility.RandomDouble() < knockBackChance)
{
m.Move(Caster.GetDirectionTo(m));
}
source.MovingEffect(m, 0x1363, 12, 1, false, true, 0, 0);
source.PlaySound(0x64B);
});
}
FinishSequence();
Caster.MovingEffect(m, 0x1363, 12, 1, false, true, 0, 0);
Caster.PlaySound(0x64B);
SpellHelper.Damage(this, m, GetNewAosDamage(40, 1, 5, m), 100, 0, 0, 0, 0);
Timer.StartTimer(TimeSpan.FromSeconds(1.2), () =>
{
if (CheckResisted(m))
{
return;
}
var damageSkill = GetDamageSkill(Caster);
var resist = GetResistSkill(m);
int secs = Math.Max(0, (int)(damageSkill / 10 - resist / 10));
if (secs > 0)
{
m.Paralyze(TimeSpan.FromSeconds(secs));
}
// Up to 12% chance by checking mysticism + imbuing/focus against resist
var knockBackChance = (GetBaseSkill(Caster) + damageSkill - resist) / 20;
if (knockBackChance > 0 && Utility.RandomDouble() < knockBackChance)
{
m.Move(Caster.GetDirectionTo(m));
}
});
}
}
}
}

View file

@ -129,8 +129,6 @@ public class CleansingWindsSpell : MysticSpell, ISpellTargetingMobile
}
}
}
FinishSequence();
}
public static int RemoveCurses(Mobile m)
@ -212,4 +210,4 @@ public class CleansingWindsSpell : MysticSpell, ISpellTargetingMobile
return curseLevel;
}
}
}

View file

@ -51,8 +51,6 @@ public class EagleStrikeSpell : MysticSpell, ISpellTargetingMobile
Timer.StartTimer(TimeSpan.FromSeconds(1.0), () => Damage(m));
}
FinishSequence();
}
public override void OnCast()
@ -73,4 +71,4 @@ public class EagleStrikeSpell : MysticSpell, ISpellTargetingMobile
to.PlaySound(0x64D);
}
}
}

View file

@ -69,8 +69,6 @@ public class HailStormSpell : MysticSpell, ISpellTargetingPoint3D
}
}
}
FinishSequence();
}
public override void OnCast()
@ -122,4 +120,4 @@ public class HailStormSpell : MysticSpell, ISpellTargetingPoint3D
0x4
);
}
}
}

View file

@ -85,8 +85,6 @@ public class NetherCycloneSpell : MysticSpell, ISpellTargetingPoint3D
}
}
}
FinishSequence();
}
public override void OnCast()
@ -136,4 +134,4 @@ public class NetherCycloneSpell : MysticSpell, ISpellTargetingPoint3D
0x4
);
}
}
}

View file

@ -35,13 +35,13 @@ public class SpellPlagueSpell : MysticSpell, ISpellTargetingMobile
Caster.Target = new SpellTargetMobile(this, TargetFlags.Harmful);
}
public void Target(Mobile targeted)
public void Target(Mobile m)
{
if (CheckHSequence(targeted))
if (CheckHSequence(m))
{
SpellHelper.Turn(Caster, targeted);
SpellHelper.Turn(Caster, m);
SpellHelper.CheckReflect(6, Caster, ref targeted);
SpellHelper.CheckReflect(6, Caster, ref m);
/* The target is hit with an explosion of chaos damage and then inflicted
* with the spell plague curse. Each time the target is damaged while under
@ -53,26 +53,24 @@ public class SpellPlagueSpell : MysticSpell, ISpellTargetingMobile
* plagues so that they are applied one after the other.
*/
VisualEffect(targeted);
VisualEffect(m);
// Before Time of Legends, SDI was not applied to initial damage.
var damage = GetNewAosDamage(33, 1, 5, Core.TOL, targeted);
SpellHelper.Damage(this, targeted, damage, 0, 0, 0, 0, 0);
var damage = GetNewAosDamage(33, 1, 5, Core.TOL, m);
SpellHelper.Damage(this, m, damage, 0, 0, 0, 0, 0);
var timer = new SpellPlagueTimer(this, targeted);
var timer = new SpellPlagueTimer(this, m);
if (_table.TryGetValue(targeted, out var oldtimer))
if (_table.TryGetValue(m, out var oldtimer))
{
oldtimer.SetNext(timer);
}
else
{
_table[targeted] = timer;
_table[m] = timer;
timer.StartPlague();
}
}
FinishSequence();
}
public static bool UnderEffect(Mobile m) => _table.ContainsKey(m);

View file

@ -92,8 +92,6 @@ public class BloodOathSpell : NecromancerSpell, ISpellTargetingMobile
_table[m] = timer;
HarmfulSpell(m);
}
FinishSequence();
}
public override void OnCast()
@ -156,4 +154,4 @@ public class BloodOathSpell : NecromancerSpell, ISpellTargetingMobile
}
}
}
}
}

View file

@ -91,8 +91,6 @@ public class CorpseSkinSpell : NecromancerSpell, ISpellTargetingMobile
HarmfulSpell(m);
}
FinishSequence();
}
public override void OnCast()
@ -141,4 +139,4 @@ public class CorpseSkinSpell : NecromancerSpell, ISpellTargetingMobile
DoExpire();
}
}
}
}

View file

@ -66,8 +66,6 @@ public class EvilOmenSpell : NecromancerSpell, ISpellTargetingMobile
BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.EvilOmen, 1075647, 1075648, duration, m));
}
FinishSequence();
}
public override void OnCast()
@ -85,4 +83,4 @@ public class EvilOmenSpell : NecromancerSpell, ISpellTargetingMobile
return false;
}
}
}

View file

@ -59,8 +59,6 @@ public class MindRotSpell : NecromancerSpell, ISpellTargetingMobile
HarmfulSpell(m);
}
FinishSequence();
}
public override void OnCast()
@ -133,4 +131,4 @@ public class MRExpireTimer : Timer
Stop();
}
}
}
}

View file

@ -81,8 +81,6 @@ public class PainSpikeSpell : NecromancerSpell, ISpellTargetingMobile
// SpellHelper.Damage( this, m, damage, 100, 0, 0, 0, 0, Misc.DFAlgorithm.PainSpike );
HarmfulSpell(m);
}
FinishSequence();
}
public override void OnCast()
@ -114,4 +112,4 @@ public class PainSpikeSpell : NecromancerSpell, ISpellTargetingMobile
BuffInfo.RemoveBuff(_mobile, BuffIcon.PainSpike);
}
}
}
}

View file

@ -142,12 +142,10 @@ public class PoisonStrikeSpell : NecromancerSpell, ISpellTargetingMobile
}
}
}
FinishSequence();
}
public override void OnCast()
{
Caster.Target = new SpellTargetMobile(this, TargetFlags.Harmful, Core.ML ? 10 : 12);
}
}
}

View file

@ -107,8 +107,6 @@ public class StrangleSpell : NecromancerSpell, ISpellTargetingMobile
var t_Duration = TimeSpan.FromSeconds(length);
BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.Strangle, 1075794, 1075795, t_Duration, m, args));
FinishSequence();
}
public override void OnCast()
@ -226,4 +224,4 @@ public class StrangleSpell : NecromancerSpell, ISpellTargetingMobile
}
}
}
}
}

View file

@ -62,8 +62,6 @@ public class VengefulSpiritSpell : NecromancerSpell, ISpellTargetingMobile
rev.FixedParticles(0x373A, 1, 15, 9909, EffectLayer.Waist);
}
}
FinishSequence();
}
public override void OnCast()
@ -86,4 +84,4 @@ public class VengefulSpiritSpell : NecromancerSpell, ISpellTargetingMobile
return true;
}
}
}

View file

@ -92,8 +92,6 @@ public class Shadowjump : NinjaSpell, ISpellTargetingPoint3D
Stealth.OnUse(m); // stealth check after the shadow jump
}
FinishSequence();
}
public override bool CheckCast()
@ -115,4 +113,4 @@ public class Shadowjump : NinjaSpell, ISpellTargetingPoint3D
Caster.SendLocalizedMessage(1063088); // You prepare to perform a Shadowjump.
Caster.Target = new SpellTargetPoint3D(this, TargetFlags.None, 11);
}
}
}

View file

@ -36,8 +36,6 @@ namespace Server.Spells.Second
BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.Agility, 1075841, length, m, percentage.ToString()));
}
FinishSequence();
}
public override bool CheckCast()

View file

@ -36,8 +36,6 @@ namespace Server.Spells.Second
BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.Cunning, 1075843, length, m, percentage.ToString()));
}
FinishSequence();
}
public override bool CheckCast()

View file

@ -55,8 +55,6 @@ namespace Server.Spells.Second
m.FixedParticles(0x373A, 10, 15, 5012, EffectLayer.Waist);
m.PlaySound(0x1E0);
}
FinishSequence();
}
public override bool CheckCast()

View file

@ -71,8 +71,6 @@ namespace Server.Spells.Second
SpellHelper.Damage(this, m, damage, 0, 0, 100, 0, 0);
}
FinishSequence();
}
public override void OnCast()

View file

@ -78,8 +78,6 @@ namespace Server.Spells.Second
Effects.PlaySound(loc, item.Map, 0x1EF);
}
FinishSequence();
}
public override void OnCast()

View file

@ -48,8 +48,6 @@ namespace Server.Spells.Second
cont.TrapPower = 0;
cont.TrapLevel = 0;
}
FinishSequence();
}
public override void OnCast()

View file

@ -36,8 +36,6 @@ namespace Server.Spells.Second
BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.Strength, 1075845, length, m, percentage.ToString()));
}
FinishSequence();
}
public override bool CheckCast()

View file

@ -95,8 +95,6 @@ namespace Server.Spells.Seventh
}
}
}
FinishSequence();
}
public override void OnCast()

View file

@ -67,8 +67,6 @@ public class EnergyFieldSpell : MagerySpell, ISpellTargetingPoint3D
);
}
}
FinishSequence();
}
public override void OnCast()

View file

@ -54,8 +54,6 @@ namespace Server.Spells.Seventh
SpellHelper.Damage(this, m, damage, 0, 100, 0, 0, 0);
}
FinishSequence();
}
public override void OnCast()

View file

@ -94,8 +94,6 @@ public class GateTravelSpell : MagerySpell, IRecallSpell
firstGate.LinkedGate = secondGate;
secondGate.LinkedGate = firstGate;
}
FinishSequence();
}
public override void OnCast()
@ -107,6 +105,7 @@ public class GateTravelSpell : MagerySpell, IRecallSpell
else
{
Effect(m_Entry.Location, m_Entry.Map, true);
FinishSequence();
}
}

View file

@ -75,8 +75,6 @@ namespace Server.Spells.Seventh
HarmfulSpell(m);
}
FinishSequence();
}
public override void OnCast()

View file

@ -72,8 +72,6 @@ namespace Server.Spells.Seventh
}
}
}
FinishSequence();
}
public override void OnCast()

View file

@ -100,8 +100,6 @@ namespace Server.Spells.Seventh
}
}
}
FinishSequence();
}
public override void OnCast()

View file

@ -54,8 +54,6 @@ namespace Server.Spells.Sixth
Caster.SendLocalizedMessage(1010084); // The creature resisted the attempt to dispel it!
}
}
FinishSequence();
}
public override void OnCast()

View file

@ -59,8 +59,6 @@ namespace Server.Spells.Sixth
// Deal the damage
SpellHelper.Damage(this, m, damage, 0, 0, 0, 0, 100);
}
FinishSequence();
}
public override void OnCast()

View file

@ -39,10 +39,8 @@ namespace Server.Spells.Sixth
SpellHelper.Turn(Caster, m);
SpellHelper.CheckReflect((int)Circle, Caster, ref m);
var t = new InternalTimer(this, Caster, defender, m).Start();
new InternalTimer(this, Caster, defender, m).Start();
}
FinishSequence();
}
public override void OnCast()

View file

@ -67,8 +67,6 @@ namespace Server.Spells.Sixth
_table[m] = timerToken;
}
FinishSequence();
}
public override bool CheckCast()

View file

@ -55,8 +55,6 @@ namespace Server.Spells.Sixth
Caster.PlaySound(0x1FA);
Effects.SendLocationEffect(Caster, 14201, 16);
}
FinishSequence();
}
public override void OnCast()

View file

@ -54,8 +54,6 @@ namespace Server.Spells.Sixth
}
}
}
FinishSequence();
}
public override void OnCast()

View file

@ -67,8 +67,6 @@ public class ParalyzeFieldSpell : MagerySpell, ISpellTargetingPoint3D
);
}
}
FinishSequence();
}
public override void OnCast()

View file

@ -51,8 +51,6 @@ namespace Server.Spells.Sixth
}
}
}
FinishSequence();
}
public override void OnCast()

View file

@ -68,8 +68,6 @@ namespace Server.Spells.Spellweaving
BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.GiftOfLife, 1031615, 1075807, duration, m, null, true));
}
FinishSequence();
}
public static void Initialize()

View file

@ -65,8 +65,6 @@ namespace Server.Spells.Spellweaving
);
}
}
FinishSequence();
}
public override void OnCast()

View file

@ -51,8 +51,6 @@ namespace Server.Spells.Spellweaving
new InternalTimer(nf).Start();
}
FinishSequence();
}
public override bool CheckCast()

View file

@ -68,8 +68,6 @@ namespace Server.Spells.Spellweaving
SpellHelper.Damage(this, m, damage, 0, 0, 0, 0, 0, 100);
}
FinishSequence();
}
public override void OnCast()

View file

@ -3,90 +3,73 @@ using Server.Multis;
using Server.Network;
using Server.Targeting;
namespace Server.Spells
namespace Server.Spells;
public class RecallSpellTarget : Target
{
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)
{
private readonly IRecallSpell _spell;
private readonly bool m_ToBoat;
_spell = spell;
_toBoat = toBoat;
_spell.Caster.LocalOverheadMessage(MessageType.Regular, 0x3B2, 501029); // Select Marked item.
}
public RecallSpellTarget(IRecallSpell spell, bool toBoat = true) : base(Core.ML ? 10 : 12, false, TargetFlags.None)
protected override void OnTarget(Mobile from, object o)
{
if (o is RecallRune rune)
{
_spell = spell;
m_ToBoat = toBoat;
_spell.Caster.LocalOverheadMessage(MessageType.Regular, 0x3B2, 501029); // Select Marked item.
if (!rune.Marked)
{
from.SendLocalizedMessage(501805); // That rune is not yet marked.
return;
}
_spell.Effect(rune.Target, rune.TargetMap, true);
}
protected override void OnTarget(Mobile from, object o)
else if (o is Runebook runebook)
{
if (o is RecallRune rune)
{
if (rune.Marked)
{
_spell.Effect(rune.Target, rune.TargetMap, true);
}
else
{
from.SendLocalizedMessage(501805); // That rune is not yet marked.
}
}
else if (o is Runebook runebook)
{
var e = runebook.Default;
var e = runebook.Default;
if (e != null)
{
_spell.Effect(e.Location, e.Map, true);
}
else
{
from.SendLocalizedMessage(502354); // Target is not marked.
}
}
else if (m_ToBoat && o is Key key && key.KeyValue != 0 && key.Link is BaseBoat boat)
if (e == null)
{
if (!boat.Deleted && boat.CheckKey(key.KeyValue))
{
_spell.Effect(boat.GetMarkedLocation(), boat.Map, false);
}
else
{
from.NetState.SendMessageLocalized(
from.Serial,
from.Body,
MessageType.Regular,
0x3B2,
3,
502357, // I can not recall from that object.
from.Name
);
}
}
else if (o is HouseRaffleDeed deed && deed.ValidLocation())
{
_spell.Effect(deed.PlotLocation, deed.PlotFacet, true);
}
else
{
from.NetState.SendMessageLocalized(
from.Serial,
from.Body,
MessageType.Regular,
0x3B2,
3,
502357, // I can not recall from that object.
from.Name
);
from.SendLocalizedMessage(502354); // Target is not marked.
return;
}
_spell.Effect(e.Location, e.Map, true);
}
protected override void OnNonlocalTarget(Mobile from, object o)
else if (_toBoat && o is Key key && key.KeyValue != 0 && key.Link is BaseBoat boat && !boat.Deleted &&
boat.CheckKey(key.KeyValue))
{
_spell.Effect(boat.GetMarkedLocation(), boat.Map, false);
}
protected override void OnTargetFinish(Mobile from)
else if (o is HouseRaffleDeed deed && deed.ValidLocation())
{
_spell?.FinishSequence();
_spell.Effect(deed.PlotLocation, deed.PlotFacet, true);
}
else
{
from.NetState.SendMessageLocalized(
from.Serial,
from.Body,
MessageType.Regular,
0x3B2,
3,
502357, // I can not recall from that object.
from.Name
);
}
}
protected override void OnNonlocalTarget(Mobile from, object o)
{
}
protected override void OnTargetFinish(Mobile from)
{
_spell?.FinishSequence();
}
}

View file

@ -4,7 +4,7 @@ namespace Server.Spells
{
public interface ISpellTargetingMobile : ISpell
{
void Target(Mobile from);
void Target(Mobile m);
}
public class SpellTargetMobile : Target, ISpellTarget

View file

@ -40,8 +40,6 @@ namespace Server.Spells.Third
BuffInfo.AddBuff(m, new BuffInfo(BuffIcon.Bless, 1075847, 1075848, length, m, args));
}
FinishSequence();
}
public override bool CheckCast()

View file

@ -55,8 +55,6 @@ namespace Server.Spells.Third
SpellHelper.Damage(this, m, damage, 0, 100, 0, 0, 0);
}
FinishSequence();
}
public override void OnCast()

View file

@ -58,8 +58,6 @@ namespace Server.Spells.Third
cont.LockLevel = ILockpickable.MagicLock; // signal magic lock
cont.Locked = true;
}
FinishSequence();
}
public override void OnCast()

View file

@ -95,8 +95,6 @@ namespace Server.Spells.Third
HarmfulSpell(m);
}
FinishSequence();
}
public override void OnCast()

View file

@ -68,8 +68,6 @@ namespace Server.Spells.Third
}
}
}
FinishSequence();
}
public override void OnCast()

View file

@ -112,8 +112,6 @@ namespace Server.Spells.Third
queue.Dequeue().OnMoveOver(m);
}
}
FinishSequence();
}
public override bool CheckCast()

View file

@ -80,8 +80,6 @@ namespace Server.Spells.Third
}
}
}
FinishSequence();
}
public override void OnCast()

View file

@ -42,22 +42,16 @@ public class WallOfStoneSpell : MagerySpell, ISpellTargetingPoint3D
var targetLoc = new Point3D(eastToWest ? p.X + i : p.X, eastToWest ? p.Y : p.Y + i, p.Z);
var canFit = SpellHelper.AdjustField(ref targetLoc, Caster.Map, 22, true);
// Effects.SendLocationParticles( EffectItem.Create( loc, Caster.Map, EffectItem.DefaultDuration ), 0x376A, 9, 10, 5025 );
if (!canFit)
{
continue;
}
Item item = new WallOfStone(targetLoc, Caster.Map, Caster);
var item = new WallOfStone(targetLoc, Caster.Map, Caster);
Effects.SendLocationParticles(item, 0x376A, 9, 10, 5025);
// new WallOfStone( loc, Caster.Map, Caster );
}
}
FinishSequence();
}
public override void OnCast()