using System; using Server; using Server.Items; using Server.Mobiles; using Server.Custom.InnRooms; using Server.Multis; using System.Collections.Generic; using Server.ContextMenus; namespace Server.Custom.InnRooms { public class InnDoor : Item { private Mobile m_Renter; private InnRoomHouse m_House; private DateTime m_RentExpires; private Point3D m_RoomLocation; private Map m_RoomMap; private bool m_AutoRenew; private TimeSpan m_RentDuration = TimeSpan.FromDays(7); private Rectangle2D m_RoomArea; private int m_RentCost; [CommandProperty(AccessLevel.GameMaster)] public Rectangle2D RoomArea { get { return m_RoomArea; } set { m_RoomArea = value; } } [CommandProperty(AccessLevel.GameMaster)] public bool AutoRenew { get { return m_AutoRenew; } set { m_AutoRenew = value; } } public DateTime RentExpires { get { return m_RentExpires; } set { m_RentExpires = value; } } public int RentCost { get { return m_RentCost; } } public TimeSpan RentDuration { get { return m_RentDuration; } } public InnRoomHouse House { get { return m_House; } } [CommandProperty(AccessLevel.GameMaster)] public bool ForceEviction { get { return false; } set { if (value == true) { EvictTenant(); } } } [CommandProperty(AccessLevel.GameMaster)] public Mobile Renter { get { return m_Renter; } set { m_Renter = value; InvalidateProperties(); } } [CommandProperty(AccessLevel.GameMaster)] public Point3D RoomLocation { get { return m_RoomLocation; } set { m_RoomLocation = value; } } [CommandProperty(AccessLevel.GameMaster)] public Map RoomMap { get { return m_RoomMap; } set { m_RoomMap = value; } } [Constructable] public InnDoor() : this(0x6E5) { } [Constructable] public InnDoor(int itemID, Rectangle2D roomArea, int rentCost) : base(itemID) { Movable = false; Name = "A Vacant Inn Room"; m_RoomArea = roomArea; m_RentCost = rentCost; } public InnDoor(Serial serial) : base(serial) { } public static bool HasAccountInnRoom(Mobile m) { if (m == null || m.Account == null) return false; foreach (Item item in World.Items.Values) { if (item is InnDoor) { InnDoor door = (InnDoor)item; if (door.Renter != null && door.Renter.Account == m.Account) return true; } } return false; } public override void OnDoubleClick(Mobile from) { if (!from.InRange(GetWorldLocation(), 2)) { from.LocalOverheadMessage(Server.Network.MessageType.Regular, 0x3B2, 1019045); return; } if (m_Renter == null) { if (RoomLocation == Point3D.Zero || RoomMap == null) { from.SendMessage(33, "This door is out of order (No Room Linked)."); return; } if (HasAccountInnRoom(from)) { from.SendMessage(33, "You already have an active inn room rental on this account."); return; } if (Banker.Withdraw(from, m_RentCost)) { m_Renter = from; m_RentExpires = DateTime.UtcNow + m_RentDuration; m_AutoRenew = true; Name = from.Name + "'s Inn Room"; m_House = new InnRoomHouse(from, m_RoomArea); Point3D buriedLocation = new Point3D(RoomLocation.X, RoomLocation.Y, RoomLocation.Z - 20); m_House.MoveToWorld(buriedLocation, RoomMap); from.PlaySound(0x249); from.SendMessage(68, $"You have rented this room for {m_RentDuration.Days} days."); TeleportToRoom(from); } else { from.SendMessage(33, $"You need {m_RentCost} gold in your bank to rent this room."); } } else { if (DateTime.UtcNow > m_RentExpires) { if (m_AutoRenew && m_Renter != null && Banker.Withdraw(m_Renter, m_RentCost)) { m_RentExpires += m_RentDuration; InvalidateProperties(); if (from == m_Renter) from.SendMessage(68, $"Your auto-renew just processed {m_RentCost} gold from your bank!"); } else { EvictTenant(); from.SendMessage(33, "The rent expired and the room has been cleared. It is now vacant."); return; } } if (m_House != null && (m_House.IsOwner(from) || m_House.IsFriend(from) || m_House.HasAccess(from))) { TeleportToRoom(from); } else { from.SendMessage(33, "The door is locked and you do not have permission to enter."); } } } private void TeleportToRoom(Mobile m) { Point3D dest = RoomLocation; if (RoomMap != null) { IPooledEnumerable eable = RoomMap.GetItemsInRange(RoomLocation, 8); foreach (Item item in eable) { if (item is InnExitDoor) { if (m_RoomArea.Contains(new Point2D(item.X, item.Y))) { dest = item.Location; break; } } } eable.Free(); } if (m is PlayerMobile) { PlayerMobile pm = (PlayerMobile)m; pm.LastInnLocation = m.Location; pm.LastInnMap = m.Map; } m.PlaySound(0x1EA); m.MoveToWorld(dest, RoomMap); m.SendMessage(0x3B2, "You enter the inn room."); } public void EvictTenant() { if (m_Renter != null && m_House != null && !m_House.Deleted) { BankBox bank = m_Renter.BankBox; if (bank != null) { InnEvictionCrate crate = new InnEvictionCrate(); for (int i = m_House.Secures.Count - 1; i >= 0; --i) { SecureInfo info = m_House.Secures[i] as SecureInfo; if (info != null && info.Item != null) { Container secureContainer = info.Item; secureContainer.IsSecure = false; secureContainer.IsLockedDown = false; secureContainer.Movable = true; crate.DropItem(secureContainer); } } m_House.Secures.Clear(); for (int i = m_House.LockDowns.Count - 1; i >= 0; --i) { Item item = m_House.LockDowns[i] as Item; if (item != null) { item.IsLockedDown = false; item.Movable = true; crate.DropItem(item); } } m_House.LockDowns.Clear(); if (crate.Items.Count > 0) { bank.DropItem(crate); m_Renter.SendMessage(33, "Your inn room rent has expired. Your belongings have been packed into a crate and placed in your bank box."); } else { crate.Delete(); } } m_House.Delete(); List insideMobiles = m_House.GetMobiles(); foreach (Mobile m in insideMobiles) { if (m is PlayerMobile) { PlayerMobile pm = (PlayerMobile)m; pm.MoveToWorld(this.Location, this.Map); pm.LastInnLocation = Point3D.Zero; pm.LastInnMap = null; pm.SendMessage(33, "The rent has expired and you have been evicted from the room."); } } } m_Renter = null; m_House = null; m_AutoRenew = false; Name = "A Vacant Inn Room"; } public override void GetProperties(ObjectPropertyList list) { base.GetProperties(list); if (m_Renter != null) { list.Add(1060658, "Rent Cost\tPaid"); list.Add(1060659, "Expires\t{0}", m_RentExpires.ToString("g")); } else { list.Add(1060658, "Rent Cost\t{0} Gold", m_RentCost); } } public override void Serialize(GenericWriter writer) { base.Serialize(writer); writer.Write((int)3); writer.Write(m_RentCost); writer.Write(m_RoomArea); writer.Write(m_AutoRenew); writer.Write(m_Renter); writer.WriteItem(m_House); writer.Write(m_RentExpires); writer.Write(m_RoomLocation); writer.Write(m_RoomMap); } public override void Deserialize(GenericReader reader) { base.Deserialize(reader); int version = reader.ReadInt(); if (version >= 3) { m_RentCost = reader.ReadInt(); } else { m_RentCost = 5000; } if (version >= 2) { m_RoomArea = reader.ReadRect2D(); } if (version >= 1) { m_AutoRenew = reader.ReadBool(); } m_Renter = reader.ReadMobile(); m_House = reader.ReadItem() as InnRoomHouse; m_RentExpires = reader.ReadDateTime(); m_RoomLocation = reader.ReadPoint3D(); m_RoomMap = reader.ReadMap(); } public override void GetContextMenuEntries(Mobile from, List list) { base.GetContextMenuEntries(from, list); if (from.Alive && m_Renter == from) { list.Add(new ManageRoomEntry(from, this)); } } private class ManageRoomEntry : ContextMenuEntry { private Mobile m_From; private InnDoor m_Door; public ManageRoomEntry(Mobile from, InnDoor door) : base(1063490, 2) { m_From = from; m_Door = door; } public override void OnClick() { if (m_Door.Deleted || m_Door.Renter != m_From) return; m_From.SendGump(new InnRoomManagementGump((PlayerMobile)m_From, m_Door)); } } public override bool OnDragDrop(Mobile from, Item dropped) { if (from == m_Renter && dropped is Gold) { if (dropped.Amount == m_RentCost) { dropped.Delete(); m_RentExpires += m_RentDuration; from.PlaySound(0x249); from.SendMessage(68, $"You hand the gold to the landlord and extend your rent."); from.SendMessage(68, $"Your room is now paid until: {m_RentExpires.ToString("g")}"); InvalidateProperties(); return true; } else { from.SendMessage(33, $"You must drop exactly {m_RentCost} gold on the door to renew it."); return false; } } return base.OnDragDrop(from, dropped); } } public class InnEvictionCrate : WoodenBox { public override int DefaultMaxItems { get { return 500; } } public override int DefaultMaxWeight { get { return 5000; } } [Constructable] public InnEvictionCrate() { Name = "Evicted Inn Room Belongings"; Hue = 33; } public InnEvictionCrate(Serial serial) : base(serial) { } public override bool CheckHold(Mobile m, Item item, bool message, bool checkItems, int plusItems, int plusWeight) { if (m.AccessLevel < AccessLevel.GameMaster) { if (message) m.SendLocalizedMessage(1061145); return false; } return base.CheckHold(m, item, message, checkItems, plusItems, plusWeight); } public override void OnItemRemoved(Item item) { base.OnItemRemoved(item); if (this.TotalItems == 0) { Delete(); } } public override void Serialize(GenericWriter writer) { base.Serialize(writer); writer.Write((int)0); } public override void Deserialize(GenericReader reader) { base.Deserialize(reader); int version = reader.ReadInt(); } } }