diff --git a/Projects/UOContent/Items/Special/Solen Items/BraceletOfBinding.cs b/Projects/UOContent/Items/Special/Solen Items/BraceletOfBinding.cs index b116ca657..6ab02460e 100644 --- a/Projects/UOContent/Items/Special/Solen Items/BraceletOfBinding.cs +++ b/Projects/UOContent/Items/Special/Solen Items/BraceletOfBinding.cs @@ -233,13 +233,15 @@ namespace Server.Items return false; } - if (!SpellHelper.CheckTravel(from, TravelCheckType.RecallFrom)) + if (!SpellHelper.CheckTravel(from, TravelCheckType.RecallFrom, out var failureMessage)) { + failureMessage.SendMessageTo(from); return false; } - if (!SpellHelper.CheckTravel(from, boundRoot.Map, boundRoot.Location, TravelCheckType.RecallTo)) + if (!SpellHelper.CheckTravel(from, boundRoot.Map, boundRoot.Location, TravelCheckType.RecallTo, out failureMessage)) { + failureMessage.SendMessageTo(from); return false; } diff --git a/Projects/UOContent/Regions/BaseRegion.cs b/Projects/UOContent/Regions/BaseRegion.cs index f3e7873a8..ce450bd66 100644 --- a/Projects/UOContent/Regions/BaseRegion.cs +++ b/Projects/UOContent/Regions/BaseRegion.cs @@ -166,5 +166,14 @@ public class BaseRegion : Region public override string ToString() => Name ?? RuneName ?? GetType().Name; - public virtual bool CheckTravel(Mobile m, Point3D newLocation, TravelCheckType travelType) => true; + public virtual bool CheckTravel(Mobile m, Point3D newLocation, TravelCheckType travelType, out TextDefinition message) + { + if (Parent is BaseRegion parent) + { + return parent.CheckTravel(m, newLocation, travelType, out message); + } + + message = null; + return true; + } } diff --git a/Projects/UOContent/Regions/GreenAcresRegion.cs b/Projects/UOContent/Regions/GreenAcresRegion.cs index c827032d8..1eee08276 100644 --- a/Projects/UOContent/Regions/GreenAcresRegion.cs +++ b/Projects/UOContent/Regions/GreenAcresRegion.cs @@ -17,8 +17,11 @@ public class GreenAcresRegion : BaseRegion public override bool AllowHousing(Mobile from, Point3D p) => from.AccessLevel != AccessLevel.Player && base.AllowHousing(from, p); - public override bool CheckTravel(Mobile m, Point3D newLocation, TravelCheckType travelType) => - m.AccessLevel != AccessLevel.Player; + public override bool CheckTravel(Mobile m, Point3D newLocation, TravelCheckType travelType, out TextDefinition message) + { + message = null; // Use default message + return m.AccessLevel != AccessLevel.Player; + } public override bool OnBeginSpellCast(Mobile m, ISpell s) { diff --git a/Projects/UOContent/Regions/JailRegion.cs b/Projects/UOContent/Regions/JailRegion.cs index d02e490b5..b6ba508b6 100644 --- a/Projects/UOContent/Regions/JailRegion.cs +++ b/Projects/UOContent/Regions/JailRegion.cs @@ -43,15 +43,17 @@ public class JailRegion : BaseRegion global = LightCycle.JailLevel; } - public override bool CheckTravel(Mobile m, Point3D newLocation, TravelCheckType travelType) + private static TextDefinition _jailBreakPlan = 1114345; // You'll need a better jailbreak plan than that! + + public override bool CheckTravel(Mobile m, Point3D newLocation, TravelCheckType travelType, out TextDefinition message) { if (m?.AccessLevel == AccessLevel.Player) { - m.SendLocalizedMessage(1114345); // You'll need a better jailbreak plan than that! + message = _jailBreakPlan; return false; } - return base.CheckTravel(m, newLocation, travelType); + return base.CheckTravel(m, newLocation, travelType, out message); } public override bool OnBeginSpellCast(Mobile from, ISpell s) diff --git a/Projects/UOContent/Regions/MondainRegion.cs b/Projects/UOContent/Regions/MondainRegion.cs index 46103a2ec..0cc8c80c7 100644 --- a/Projects/UOContent/Regions/MondainRegion.cs +++ b/Projects/UOContent/Regions/MondainRegion.cs @@ -1,5 +1,3 @@ -using Server.Spells.Sixth; - namespace Server.Regions; public class MondainRegion : NoTravelSpellsAllowedRegion @@ -13,15 +11,4 @@ public class MondainRegion : NoTravelSpellsAllowedRegion : base(name, map, parent, priority, area) { } - - public override bool OnBeginSpellCast(Mobile m, ISpell s) - { - if (m.Player && s is MarkSpell) - { - m.SendLocalizedMessage(501802); // Thy spell doth not appear to work... - return false; - } - - return base.OnBeginSpellCast(m, s); - } } diff --git a/Projects/UOContent/Regions/NoTravelSpellsAllowedRegion.cs b/Projects/UOContent/Regions/NoTravelSpellsAllowedRegion.cs index 8d5b437e3..6c7112be1 100644 --- a/Projects/UOContent/Regions/NoTravelSpellsAllowedRegion.cs +++ b/Projects/UOContent/Regions/NoTravelSpellsAllowedRegion.cs @@ -14,6 +14,10 @@ public class NoTravelSpellsAllowedRegion : DungeonRegion { } - public override bool CheckTravel(Mobile m, Point3D newLocation, TravelCheckType travelType) => - m.AccessLevel == AccessLevel.Player; + public override bool CheckTravel(Mobile m, Point3D newLocation, TravelCheckType travelType, out TextDefinition message) + { + message = null; // Use default message + return m.AccessLevel > AccessLevel.Player || + travelType is not TravelCheckType.TeleportFrom or TravelCheckType.TeleportTo; + } } diff --git a/Projects/UOContent/Spells/Base/SpellHelper.cs b/Projects/UOContent/Spells/Base/SpellHelper.cs index 8eceb2591..95e22b9e3 100644 --- a/Projects/UOContent/Spells/Base/SpellHelper.cs +++ b/Projects/UOContent/Spells/Base/SpellHelper.cs @@ -617,42 +617,41 @@ namespace Server.Spells return false; } - public static void SendInvalidMessage(Mobile caster, TravelCheckType type) + private static TextDefinition _travelTo = 1019004; // You are not allowed to travel there. + private static TextDefinition _travelFrom = 502361; // You cannot teleport into that area from here. + private static TextDefinition _teleportTo = 501035; // You cannot teleport from here to the destination. + private static TextDefinition _genericSpell = 501802; // Thy spell doth not appear to work... + + public static TextDefinition InvalidTravelMessage(TravelCheckType type) { - if (type is TravelCheckType.RecallTo or TravelCheckType.GateTo) + return type switch { - caster.SendLocalizedMessage(1019004); // You are not allowed to travel there. - } - else if (type == TravelCheckType.TeleportTo) - { - caster.SendLocalizedMessage(501035); // You cannot teleport from here to the destination. - } - else - { - caster.SendLocalizedMessage(501802); // Thy spell doth not appear to work... - } + TravelCheckType.RecallTo or TravelCheckType.GateTo => _travelTo, + TravelCheckType.RecallFrom or TravelCheckType.TeleportFrom => _travelFrom, + TravelCheckType.TeleportTo => _teleportTo, + _ => _genericSpell + }; } - public static bool CheckTravel(Mobile caster, TravelCheckType type) => - CheckTravel(caster, caster.Map, caster.Location, type); + public static bool CheckTravel(Mobile caster, TravelCheckType type, out TextDefinition message) => + CheckTravel(caster, caster.Map, caster.Location, type, out message); - public static bool CheckTravel(Map map, Point3D loc, TravelCheckType type) => CheckTravel(null, map, loc, type); + public static bool CheckTravel(Map map, Point3D loc, TravelCheckType type, out TextDefinition message) => + CheckTravel(null, map, loc, type, out message); - public static bool CheckTravel(Mobile caster, Map map, Point3D loc, TravelCheckType type) + public static bool CheckTravel(Mobile caster, Map map, Point3D loc, TravelCheckType type, out TextDefinition message) { + message = null; + if (IsInvalid(map, loc)) // null, internal, out of bounds { - if (caster != null) - { - SendInvalidMessage(caster, type); - } - + message = InvalidTravelMessage(type); return false; } // Always allow monsters to teleport - if (caster is BaseCreature { Controlled: false, Summoned: false } && - type is TravelCheckType.TeleportTo or TravelCheckType.TeleportFrom) + if (type is TravelCheckType.TeleportTo or TravelCheckType.TeleportFrom && + caster is BaseCreature { Controlled: false, Summoned: false }) { return true; } @@ -668,7 +667,7 @@ namespace Server.Spells var destination = Region.Find(loc, map) as BaseRegion; var current = Region.Find(caster.Location, caster.Map) as BaseRegion; - if (destination?.CheckTravel(caster, loc, type) == false || current?.CheckTravel(caster, loc, type) == false) + if (destination?.CheckTravel(caster, loc, type, out message) == false || current?.CheckTravel(caster, loc, type, out message) == false) { isValid = false; } @@ -679,12 +678,7 @@ namespace Server.Spells isValid = m_Rules[v, i] || !m_Validators[i](map, loc); } - if (!isValid && caster != null) - { - SendInvalidMessage(caster, type); - } - - return isValid; + return !isValid; } public static bool IsWindLoc(Point3D loc) diff --git a/Projects/UOContent/Spells/Chivalry/SacredJourney.cs b/Projects/UOContent/Spells/Chivalry/SacredJourney.cs index 0022fafc1..bd5b1e4fd 100644 --- a/Projects/UOContent/Spells/Chivalry/SacredJourney.cs +++ b/Projects/UOContent/Spells/Chivalry/SacredJourney.cs @@ -48,11 +48,13 @@ namespace Server.Spells.Chivalry { Caster.SendLocalizedMessage(1005569); // You can not recall to another facet. } - else if (!SpellHelper.CheckTravel(Caster, TravelCheckType.RecallFrom)) + else if (!SpellHelper.CheckTravel(Caster, TravelCheckType.RecallFrom, out var failureMessage)) { + failureMessage.SendMessageTo(Caster); } - else if (!SpellHelper.CheckTravel(Caster, map, loc, TravelCheckType.RecallTo)) + else if (!SpellHelper.CheckTravel(Caster, map, loc, TravelCheckType.RecallTo, out failureMessage)) { + failureMessage.SendMessageTo(Caster); } else if (map == Map.Felucca && Caster is PlayerMobile { Young: true } mobile) { @@ -154,7 +156,13 @@ namespace Server.Spells.Chivalry return false; } - return SpellHelper.CheckTravel(Caster, TravelCheckType.RecallFrom); + if (!SpellHelper.CheckTravel(Caster, TravelCheckType.RecallFrom, out var failureMessage)) + { + failureMessage.SendMessageTo(Caster); + return false; + } + + return true; } } } diff --git a/Projects/UOContent/Spells/Fourth/Recall.cs b/Projects/UOContent/Spells/Fourth/Recall.cs index f9ea8cd1e..11cf61ad0 100644 --- a/Projects/UOContent/Spells/Fourth/Recall.cs +++ b/Projects/UOContent/Spells/Fourth/Recall.cs @@ -48,11 +48,13 @@ namespace Server.Spells.Fourth { Caster.SendLocalizedMessage(1005569); // You can not recall to another facet. } - else if (!SpellHelper.CheckTravel(Caster, TravelCheckType.RecallFrom)) + else if (!SpellHelper.CheckTravel(Caster, TravelCheckType.RecallFrom, out var failureMessage)) { + failureMessage.SendMessageTo(Caster); } - else if (!SpellHelper.CheckTravel(Caster, map, loc, TravelCheckType.RecallTo)) + else if (!SpellHelper.CheckTravel(Caster, map, loc, TravelCheckType.RecallTo, out failureMessage)) { + failureMessage.SendMessageTo(Caster); } else if (map == Map.Felucca && Caster is PlayerMobile mobile && mobile.Young) { @@ -157,7 +159,13 @@ namespace Server.Spells.Fourth return false; } - return SpellHelper.CheckTravel(Caster, TravelCheckType.RecallFrom); + if (!SpellHelper.CheckTravel(Caster, TravelCheckType.RecallFrom, out var failureMessage)) + { + failureMessage.SendMessageTo(Caster); + return false; + } + + return true; } } } diff --git a/Projects/UOContent/Spells/Ninjitsu/ShadowJump.cs b/Projects/UOContent/Spells/Ninjitsu/ShadowJump.cs index e8dab71e9..6e0cdb770 100644 --- a/Projects/UOContent/Spells/Ninjitsu/ShadowJump.cs +++ b/Projects/UOContent/Spells/Ninjitsu/ShadowJump.cs @@ -51,9 +51,13 @@ namespace Server.Spells.Ninjitsu { Caster.SendLocalizedMessage(502359, "", 0x22); // Thou art too encumbered to move. } - else if (!SpellHelper.CheckTravel(Caster, TravelCheckType.TeleportFrom) || - !SpellHelper.CheckTravel(Caster, map, to, TravelCheckType.TeleportTo)) + else if (!SpellHelper.CheckTravel(Caster, TravelCheckType.TeleportFrom, out var failureMessage)) { + failureMessage.SendMessageTo(Caster); + } + else if (!SpellHelper.CheckTravel(Caster, map, to, TravelCheckType.TeleportTo, out failureMessage)) + { + failureMessage.SendMessageTo(Caster); } else if (map?.CanSpawnMobile(p.X, p.Y, p.Z) != true) { diff --git a/Projects/UOContent/Spells/Seventh/GateTravel.cs b/Projects/UOContent/Spells/Seventh/GateTravel.cs index 83d46565c..e250e0dcf 100644 --- a/Projects/UOContent/Spells/Seventh/GateTravel.cs +++ b/Projects/UOContent/Spells/Seventh/GateTravel.cs @@ -39,11 +39,13 @@ namespace Server.Spells.Seventh { Caster.SendLocalizedMessage(1005570); // You can not gate to another facet. } - else if (!SpellHelper.CheckTravel(Caster, TravelCheckType.GateFrom)) + else if (!SpellHelper.CheckTravel(Caster, TravelCheckType.GateFrom, out var failureMessage)) { + failureMessage.SendMessageTo(Caster); } - else if (!SpellHelper.CheckTravel(Caster, map, loc, TravelCheckType.GateTo)) + else if (!SpellHelper.CheckTravel(Caster, map, loc, TravelCheckType.GateTo, out failureMessage)) { + failureMessage.SendMessageTo(Caster); } else if (map == Map.Felucca && Caster is PlayerMobile mobile && mobile.Young) { @@ -124,7 +126,13 @@ namespace Server.Spells.Seventh return false; } - return SpellHelper.CheckTravel(Caster, TravelCheckType.GateFrom); + if (!SpellHelper.CheckTravel(Caster, TravelCheckType.GateFrom, out var failureMessage)) + { + failureMessage.SendMessageTo(Caster); + return false; + } + + return true; } private static bool GateExistsAt(Map map, Point3D loc) diff --git a/Projects/UOContent/Spells/Sixth/Mark.cs b/Projects/UOContent/Spells/Sixth/Mark.cs index d656ea5bd..8df1892e7 100644 --- a/Projects/UOContent/Spells/Sixth/Mark.cs +++ b/Projects/UOContent/Spells/Sixth/Mark.cs @@ -35,8 +35,9 @@ namespace Server.Spells.Sixth Caster.Name ); } - else if (!SpellHelper.CheckTravel(Caster, TravelCheckType.Mark)) + else if (!SpellHelper.CheckTravel(Caster, TravelCheckType.Mark, out var failureMessage)) { + failureMessage.SendMessageTo(Caster); } else if (SpellHelper.CheckMulti(Caster.Location, Caster.Map, !Core.AOS)) { @@ -63,6 +64,20 @@ namespace Server.Spells.Sixth Caster.Target = new SpellTargetItem(this, range: Core.ML ? 10 : 12); } - public override bool CheckCast() => base.CheckCast() && SpellHelper.CheckTravel(Caster, TravelCheckType.Mark); + public override bool CheckCast() + { + if (base.CheckCast()) + { + return true; + } + + if (!SpellHelper.CheckTravel(Caster, TravelCheckType.Mark, out var failureMessage)) + { + failureMessage.SendMessageTo(Caster); + return false; + } + + return true; + } } } diff --git a/Projects/UOContent/Spells/Third/Teleport.cs b/Projects/UOContent/Spells/Third/Teleport.cs index eda47e8fc..8f2546893 100644 --- a/Projects/UOContent/Spells/Third/Teleport.cs +++ b/Projects/UOContent/Spells/Third/Teleport.cs @@ -43,11 +43,13 @@ namespace Server.Spells.Third { Caster.SendLocalizedMessage(502359, "", 0x22); // Thou art too encumbered to move. } - else if (!SpellHelper.CheckTravel(Caster, TravelCheckType.TeleportFrom)) + else if (!SpellHelper.CheckTravel(Caster, TravelCheckType.TeleportFrom, out var failureMessage)) { + failureMessage.SendMessageTo(Caster); } - else if (!SpellHelper.CheckTravel(Caster, map, to, TravelCheckType.TeleportTo)) + else if (!SpellHelper.CheckTravel(Caster, map, to, TravelCheckType.TeleportTo, out failureMessage)) { + failureMessage.SendMessageTo(Caster); } else if (map?.CanSpawnMobile(p.X, p.Y, p.Z) != true) { @@ -125,7 +127,13 @@ namespace Server.Spells.Third return false; } - return SpellHelper.CheckTravel(Caster, TravelCheckType.TeleportFrom); + if (!SpellHelper.CheckTravel(Caster, TravelCheckType.TeleportFrom, out var failureMessage)) + { + failureMessage.SendMessageTo(Caster); + return false; + } + + return true; } public override void OnCast()