ModernUO/Projects/UOContent/Regions/Custom/AutoStable.cs

144 lines
3.9 KiB
C#

using System.Collections.Generic;
using Server.Mobiles;
namespace Server.Custom;
public static class AutoStable
{
// Keeps track of the exact mount that this system stored for each player.
//
// We intentionally do NOT use PlayerMobile.Stabled as the identifier,
// because the player may already have other pets in their stable.
//
// This is runtime state. The mount itself remains safely in the player's
// Stabled collection, but the association is rebuilt only by another
// StoreMount() call after a server restart.
private static readonly Dictionary<Serial, BaseMount> _storedMounts = new();
public static void StoreMount(PlayerMobile player)
{
if (player == null || player.Deleted)
{
return;
}
if (player.Mount is not BaseMount mount || mount.Deleted)
{
return;
}
// If we already have this exact mount tracked, that's okay.
// We are entering the region again and need to store it again.
_storedMounts[player.Serial] = mount;
BaseMount.Dismount(player);
mount.ControlTarget = null;
mount.ControlOrder = OrderType.Stay;
mount.Internalize();
mount.SetControlMaster(null);
mount.SummonMaster = null;
mount.IsStabled = true;
mount.StabledBy = player;
mount.Loyalty = BaseCreature.MaxLoyalty;
player.AddStabled(mount);
}
public static void RestoreMount(PlayerMobile player)
{
if (player == null || player.Deleted)
{
return;
}
if (!_storedMounts.TryGetValue(player.Serial, out var mount))
{
return;
}
// Mount was deleted while stored.
if (mount == null || mount.Deleted)
{
_storedMounts.Remove(player.Serial);
return;
}
// Never mount a dead player.
if (!player.Alive)
{
return;
}
// Don't interfere with another mount the player may already be using.
if (player.Mounted)
{
return;
}
// Make sure this creature is still actually being held by this
// player's stable. If something else changed its state, abandon
// our tracking entry rather than grabbing it unexpectedly.
if (!mount.IsStabled || mount.StabledBy != player)
{
_storedMounts.Remove(player.Serial);
return;
}
// The player must have room for the mount's follower slots.
// IMPORTANT: We intentionally keep the tracking entry if this fails.
if (player.Followers + mount.ControlSlots > player.FollowersMax)
{
player.SendLocalizedMessage(1049612, mount.Name);
return;
}
// Remove the exact mount from the stable first.
player.RemoveStabled(mount);
mount.IsStabled = false;
mount.StabledBy = null;
mount.SetControlMaster(player);
mount.ControlTarget = player;
mount.ControlOrder = OrderType.Follow;
mount.Loyalty = BaseCreature.MaxLoyalty;
// We're done with this dungeon trip.
_storedMounts.Remove(player.Serial);
// Put the actual creature next to the player.
mount.MoveToWorld(player.Location, player.Map);
// This equips the mount item and mounts the creature.
mount.Rider = player;
}
public static bool HasStoredMount(PlayerMobile player)
{
if (player == null)
{
return false;
}
return _storedMounts.TryGetValue(player.Serial, out var mount) &&
mount != null &&
!mount.Deleted;
}
public static void ForgetMount(PlayerMobile player)
{
if (player == null)
{
return;
}
_storedMounts.Remove(player.Serial);
}
}