From ae6013a1bf477e3a67c14926c09b0788a01469d2 Mon Sep 17 00:00:00 2001 From: WarrentyExpired Date: Sun, 6 Sep 2026 20:14:01 -0400 Subject: [PATCH] #W# Added: Auto Dismount/Remount in certian regions. --- Distribution/Data/regions.json | 2 +- .../UOContent/Regions/Custom/AutoStable.cs | 115 ++++++++++++++++++ .../Regions/Custom/GreetingBusinessRegion.cs | 14 +++ .../Regions/Custom/GreetingDungeonRegion.cs | 12 ++ 4 files changed, 142 insertions(+), 1 deletion(-) create mode 100644 Projects/UOContent/Regions/Custom/AutoStable.cs diff --git a/Distribution/Data/regions.json b/Distribution/Data/regions.json index 3a0f4b0ab..5211f2b46 100644 --- a/Distribution/Data/regions.json +++ b/Distribution/Data/regions.json @@ -187,7 +187,7 @@ "Name": "the Bastion Healers Shop", "Priority": 55, "Area": [ - { "x1": 2725, "y1": 1882, "x2": 2734, "y2": 1879 } + { "x1": 2725, "y1": 1882, "x2": 2734, "y2": 1897 } ] }, { diff --git a/Projects/UOContent/Regions/Custom/AutoStable.cs b/Projects/UOContent/Regions/Custom/AutoStable.cs new file mode 100644 index 000000000..e512f00fd --- /dev/null +++ b/Projects/UOContent/Regions/Custom/AutoStable.cs @@ -0,0 +1,115 @@ +using System; +using System.Linq; // Required to use .ToArray() on the HashSet +using Server; +using Server.Mobiles; + +namespace Server.Custom +{ + public static class AutoStable + { + public static void StoreMount(PlayerMobile m) + { + CleanClaimList(m); + + if (m.Mount is BaseCreature horse) + { + Server.Mobiles.BaseMount.Dismount(m); + + horse.ControlTarget = null; + horse.Internalize(); + horse.SetControlMaster(null); + horse.SummonMaster = null; + horse.IsStabled = true; + + horse.Language = "mount"; + + // Bypass the "inaccessible setter" restriction using C# Reflection + if (m.Stabled == null) + { + var prop = typeof(PlayerMobile).GetProperty("Stabled"); + prop?.SetValue(m, new System.Collections.Generic.HashSet()); + } + + // Safely add the horse now that we are certain the list exists + m.Stabled?.Add(horse); + } + } + + public static void RestoreMount(PlayerMobile from) + { + // Prevent crashes if the stable list is null (e.g., during logout) + if (from.Stabled == null || from.Stabled.Count == 0) + return; + + BaseCreature bc = null; + + // Loop through a snapshot of the HashSet to find the mount + foreach (Mobile mob in from.Stabled.ToArray()) + { + if (mob is BaseCreature horse) + { + if (horse.Deleted) + { + horse.IsStabled = false; + from.Stabled.Remove(horse); + } + else if (horse.Language == "mount") + { + bc = horse; + break; + } + } + } + + if (bc != null) + { + if ((from.Followers + bc.ControlSlots) <= from.FollowersMax) + { + bc.SetControlMaster(from); + bc.ControlTarget = from; + bc.MoveToWorld(from.Location, from.Map); + bc.IsStabled = false; + + from.Stabled.Remove(bc); + bc.Language = null; + + if (bc is BaseMount mount) + { + mount.Rider = from; + } + } + else + { + from.SendMessage("You have too many followers active to retrieve your mount."); + bc.Language = null; + } + } + + CleanClaimList(from); + } + + public static void CleanClaimList(PlayerMobile from) + { + // Prevent crashes if the stable list is null + if (from.Stabled == null || from.Stabled.Count == 0) + return; + + // Loop through a snapshot of the HashSet to clean up tags + foreach (Mobile mob in from.Stabled.ToArray()) + { + if (mob is BaseCreature horse) + { + if (horse.Deleted) + { + horse.IsStabled = false; + from.Stabled.Remove(horse); + } + else + { + horse.Language = null; + } + } + } + } + } +} diff --git a/Projects/UOContent/Regions/Custom/GreetingBusinessRegion.cs b/Projects/UOContent/Regions/Custom/GreetingBusinessRegion.cs index eb9d75935..56e830f87 100644 --- a/Projects/UOContent/Regions/Custom/GreetingBusinessRegion.cs +++ b/Projects/UOContent/Regions/Custom/GreetingBusinessRegion.cs @@ -1,5 +1,7 @@ using Server; using Server.Mobiles; +using Server.Custom; + namespace Server.Regions { public class GreetingBusinessRegion : TownRegion @@ -16,11 +18,23 @@ namespace Server.Regions { m.SendMessage($"Welcome to {this.Name}."); } + if (m is PlayerMobile player ) + { + if ( player.Mounted ) + { + player.SendMessage("Your mount is waiting safely for you."); + Server.Custom.AutoStable.StoreMount(player); + } + } } public override void OnExit(Mobile m) { base.OnExit(m); + if ( m is PlayerMobile player ) + { + Server.Custom.AutoStable.RestoreMount(player); + } } } } diff --git a/Projects/UOContent/Regions/Custom/GreetingDungeonRegion.cs b/Projects/UOContent/Regions/Custom/GreetingDungeonRegion.cs index 5ca84511b..0b93423cd 100644 --- a/Projects/UOContent/Regions/Custom/GreetingDungeonRegion.cs +++ b/Projects/UOContent/Regions/Custom/GreetingDungeonRegion.cs @@ -17,11 +17,23 @@ namespace Server.Regions { m.SendMessage($"You entered {this.Name}."); } + if (m is PlayerMobile player ) + { + if ( player.Mounted ) + { + player.SendMessage("Your mount is waiting safely for you."); + Server.Custom.AutoStable.StoreMount(player); + } + } } public override void OnExit(Mobile m) { base.OnExit(m); + if ( m is PlayerMobile player ) + { + Server.Custom.AutoStable.RestoreMount(player); + } } } }