fix: Fixes travel restriction messages (#1263)

- [X] `BaseRegion.CheckTravel` now properly cascades through parent regions
- [X] `SpellHelper.CheckTravel` now returns a failure message instead of sending one internally.
- [X] Consolidates travel restriction messages so they aren't duplicated.
This commit is contained in:
Kamron Batman 2022-11-22 16:57:42 -08:00 • committed by GitHub
parent 2057fe74a2
commit 1d8e8ec0a8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 121 additions and 69 deletions

View file

@ -233,13 +233,15 @@ namespace Server.Items
return false; return false;
} }
if (!SpellHelper.CheckTravel(from, TravelCheckType.RecallFrom)) if (!SpellHelper.CheckTravel(from, TravelCheckType.RecallFrom, out var failureMessage))
{ {
failureMessage.SendMessageTo(from);
return false; 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; return false;
} }

View file

@ -166,5 +166,14 @@ public class BaseRegion : Region
public override string ToString() => Name ?? RuneName ?? GetType().Name; 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;
}
} }

View file

@ -17,8 +17,11 @@ public class GreenAcresRegion : BaseRegion
public override bool AllowHousing(Mobile from, Point3D p) => public override bool AllowHousing(Mobile from, Point3D p) =>
from.AccessLevel != AccessLevel.Player && base.AllowHousing(from, p); from.AccessLevel != AccessLevel.Player && base.AllowHousing(from, p);
public override bool CheckTravel(Mobile m, Point3D newLocation, TravelCheckType travelType) => public override bool CheckTravel(Mobile m, Point3D newLocation, TravelCheckType travelType, out TextDefinition message)
m.AccessLevel != AccessLevel.Player; {
message = null; // Use default message
return m.AccessLevel != AccessLevel.Player;
}
public override bool OnBeginSpellCast(Mobile m, ISpell s) public override bool OnBeginSpellCast(Mobile m, ISpell s)
{ {

View file

@ -43,15 +43,17 @@ public class JailRegion : BaseRegion
global = LightCycle.JailLevel; 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) if (m?.AccessLevel == AccessLevel.Player)
{ {
m.SendLocalizedMessage(1114345); // You'll need a better jailbreak plan than that! message = _jailBreakPlan;
return false; return false;
} }
return base.CheckTravel(m, newLocation, travelType); return base.CheckTravel(m, newLocation, travelType, out message);
} }
public override bool OnBeginSpellCast(Mobile from, ISpell s) public override bool OnBeginSpellCast(Mobile from, ISpell s)

View file

@ -1,5 +1,3 @@
using Server.Spells.Sixth;
namespace Server.Regions; namespace Server.Regions;
public class MondainRegion : NoTravelSpellsAllowedRegion public class MondainRegion : NoTravelSpellsAllowedRegion
@ -13,15 +11,4 @@ public class MondainRegion : NoTravelSpellsAllowedRegion
: base(name, map, parent, priority, area) : 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);
}
} }

View file

@ -14,6 +14,10 @@ public class NoTravelSpellsAllowedRegion : DungeonRegion
{ {
} }
public override bool CheckTravel(Mobile m, Point3D newLocation, TravelCheckType travelType) => public override bool CheckTravel(Mobile m, Point3D newLocation, TravelCheckType travelType, out TextDefinition message)
m.AccessLevel == AccessLevel.Player; {
message = null; // Use default message
return m.AccessLevel > AccessLevel.Player ||
travelType is not TravelCheckType.TeleportFrom or TravelCheckType.TeleportTo;
}
} }

View file

@ -617,42 +617,41 @@ namespace Server.Spells
return false; 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. TravelCheckType.RecallTo or TravelCheckType.GateTo => _travelTo,
} TravelCheckType.RecallFrom or TravelCheckType.TeleportFrom => _travelFrom,
else if (type == TravelCheckType.TeleportTo) TravelCheckType.TeleportTo => _teleportTo,
{ _ => _genericSpell
caster.SendLocalizedMessage(501035); // You cannot teleport from here to the destination. };
}
else
{
caster.SendLocalizedMessage(501802); // Thy spell doth not appear to work...
}
} }
public static bool CheckTravel(Mobile caster, TravelCheckType type) => public static bool CheckTravel(Mobile caster, TravelCheckType type, out TextDefinition message) =>
CheckTravel(caster, caster.Map, caster.Location, type); 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 (IsInvalid(map, loc)) // null, internal, out of bounds
{ {
if (caster != null) message = InvalidTravelMessage(type);
{
SendInvalidMessage(caster, type);
}
return false; return false;
} }
// Always allow monsters to teleport // Always allow monsters to teleport
if (caster is BaseCreature { Controlled: false, Summoned: false } && if (type is TravelCheckType.TeleportTo or TravelCheckType.TeleportFrom &&
type is TravelCheckType.TeleportTo or TravelCheckType.TeleportFrom) caster is BaseCreature { Controlled: false, Summoned: false })
{ {
return true; return true;
} }
@ -668,7 +667,7 @@ namespace Server.Spells
var destination = Region.Find(loc, map) as BaseRegion; var destination = Region.Find(loc, map) as BaseRegion;
var current = Region.Find(caster.Location, caster.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; isValid = false;
} }
@ -679,12 +678,7 @@ namespace Server.Spells
isValid = m_Rules[v, i] || !m_Validators[i](map, loc); isValid = m_Rules[v, i] || !m_Validators[i](map, loc);
} }
if (!isValid && caster != null) return !isValid;
{
SendInvalidMessage(caster, type);
}
return isValid;
} }
public static bool IsWindLoc(Point3D loc) public static bool IsWindLoc(Point3D loc)

View file

@ -48,11 +48,13 @@ namespace Server.Spells.Chivalry
{ {
Caster.SendLocalizedMessage(1005569); // You can not recall to another facet. 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) else if (map == Map.Felucca && Caster is PlayerMobile { Young: true } mobile)
{ {
@ -154,7 +156,13 @@ namespace Server.Spells.Chivalry
return false; return false;
} }
return SpellHelper.CheckTravel(Caster, TravelCheckType.RecallFrom); if (!SpellHelper.CheckTravel(Caster, TravelCheckType.RecallFrom, out var failureMessage))
{
failureMessage.SendMessageTo(Caster);
return false;
}
return true;
} }
} }
} }

View file

@ -48,11 +48,13 @@ namespace Server.Spells.Fourth
{ {
Caster.SendLocalizedMessage(1005569); // You can not recall to another facet. 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) else if (map == Map.Felucca && Caster is PlayerMobile mobile && mobile.Young)
{ {
@ -157,7 +159,13 @@ namespace Server.Spells.Fourth
return false; return false;
} }
return SpellHelper.CheckTravel(Caster, TravelCheckType.RecallFrom); if (!SpellHelper.CheckTravel(Caster, TravelCheckType.RecallFrom, out var failureMessage))
{
failureMessage.SendMessageTo(Caster);
return false;
}
return true;
} }
} }
} }

View file

@ -51,9 +51,13 @@ namespace Server.Spells.Ninjitsu
{ {
Caster.SendLocalizedMessage(502359, "", 0x22); // Thou art too encumbered to move. 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))
!SpellHelper.CheckTravel(Caster, map, to, TravelCheckType.TeleportTo))
{ {
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) else if (map?.CanSpawnMobile(p.X, p.Y, p.Z) != true)
{ {

View file

@ -39,11 +39,13 @@ namespace Server.Spells.Seventh
{ {
Caster.SendLocalizedMessage(1005570); // You can not gate to another facet. 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) else if (map == Map.Felucca && Caster is PlayerMobile mobile && mobile.Young)
{ {
@ -124,7 +126,13 @@ namespace Server.Spells.Seventh
return false; 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) private static bool GateExistsAt(Map map, Point3D loc)

View file

@ -35,8 +35,9 @@ namespace Server.Spells.Sixth
Caster.Name 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)) 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); 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;
}
} }
} }

View file

@ -43,11 +43,13 @@ namespace Server.Spells.Third
{ {
Caster.SendLocalizedMessage(502359, "", 0x22); // Thou art too encumbered to move. 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) else if (map?.CanSpawnMobile(p.X, p.Y, p.Z) != true)
{ {
@ -125,7 +127,13 @@ namespace Server.Spells.Third
return false; 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() public override void OnCast()