144 lines
3.9 KiB
C#
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);
|
|
}
|
|
}
|