#region References using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; using Server; using Server.Gumps; using Server.Items; using Server.Mobiles; using Server.Multis; using Server.Network; #endregion namespace Knives.TownHouses { public enum Intu { Neither, No, Yes } [Flipable(0xC0B, 0xC0C)] public class TownHouseSign : Item { private static readonly List s_TownHouseSigns = new List(); public static List AllSigns { get { return s_TownHouseSigns; } } private Point3D c_BanLoc, c_SignLoc; private int c_Locks, c_Secures, c_Price, c_MinZ, c_MaxZ, c_MinTotalSkill, c_MaxTotalSkill, c_ItemsPrice, c_RTOPayments; private bool c_YoungOnly, c_RecurRent, c_KeepItems, c_LeaveItems, c_RentToOwn, c_Free, c_ForcePrivate, c_ForcePublic, c_NoBanning; private string c_Skill; private double c_SkillReq; private ArrayList c_DecoreItemInfos, c_PreviewItems; private Timer c_DemolishTimer, c_RentTimer, c_PreviewTimer; private DateTime c_DemolishTime, c_RentTime; private TimeSpan c_RentByTime, c_OriginalRentTime; private Intu c_Murderers; [CommandProperty(AccessLevel.GameMaster)] public Point3D BanLoc { get { return c_BanLoc; } set { c_BanLoc = value; InvalidateProperties(); if (Owned) { House.Region.GoLocation = value; } } } [CommandProperty(AccessLevel.GameMaster)] public Point3D SignLoc { get { return c_SignLoc; } set { c_SignLoc = value; InvalidateProperties(); if (Owned) { House.Sign.Location = value; House.Hanger.Location = value; } } } [CommandProperty(AccessLevel.GameMaster)] public int Locks { get { return c_Locks; } set { c_Locks = value; InvalidateProperties(); if (Owned) { House.MaxLockDowns = value; } } } [CommandProperty(AccessLevel.GameMaster)] public int Secures { get { return c_Secures; } set { c_Secures = value; InvalidateProperties(); if (Owned) { House.MaxSecures = value; } } } [CommandProperty(AccessLevel.GameMaster)] public int Price { get { return c_Price; } set { c_Price = value; InvalidateProperties(); } } [CommandProperty(AccessLevel.GameMaster)] public int MinZ { get { return c_MinZ; } set { if (value > c_MaxZ) { c_MaxZ = value + 1; } c_MinZ = value; if (Owned) { RUOVersion.UpdateRegion(this); } } } [CommandProperty(AccessLevel.GameMaster)] public int MaxZ { get { return c_MaxZ; } set { if (value < c_MinZ) { value = c_MinZ; } c_MaxZ = value; if (Owned) { RUOVersion.UpdateRegion(this); } } } [CommandProperty(AccessLevel.GameMaster)] public int MinTotalSkill { get { return c_MinTotalSkill; } set { if (value > c_MaxTotalSkill) { value = c_MaxTotalSkill; } c_MinTotalSkill = value; ValidateOwnership(); InvalidateProperties(); } } [CommandProperty(AccessLevel.GameMaster)] public int MaxTotalSkill { get { return c_MaxTotalSkill; } set { if (value < c_MinTotalSkill) { value = c_MinTotalSkill; } c_MaxTotalSkill = value; ValidateOwnership(); InvalidateProperties(); } } [CommandProperty(AccessLevel.GameMaster)] public bool YoungOnly { get { return c_YoungOnly; } set { c_YoungOnly = value; if (c_YoungOnly) { c_Murderers = Intu.Neither; } ValidateOwnership(); InvalidateProperties(); } } [CommandProperty(AccessLevel.GameMaster)] public TimeSpan RentByTime { get { return c_RentByTime; } set { c_RentByTime = value; c_OriginalRentTime = value; if (value == TimeSpan.Zero) { ClearRentTimer(); } else { ClearRentTimer(); BeginRentTimer(value); } InvalidateProperties(); } } [CommandProperty(AccessLevel.GameMaster)] public bool RecurRent { get { return c_RecurRent; } set { c_RecurRent = value; if (!value) { c_RentToOwn = false; } InvalidateProperties(); } } [CommandProperty(AccessLevel.GameMaster)] public bool KeepItems { get { return c_KeepItems; } set { c_LeaveItems = false; c_KeepItems = value; InvalidateProperties(); } } [CommandProperty(AccessLevel.GameMaster)] public bool Free { get { return c_Free; } set { c_Free = value; c_Price = 1; InvalidateProperties(); } } [CommandProperty(AccessLevel.GameMaster)] public Intu Murderers { get { return c_Murderers; } set { c_Murderers = value; ValidateOwnership(); InvalidateProperties(); } } [CommandProperty(AccessLevel.GameMaster)] public bool ForcePrivate { get { return c_ForcePrivate; } set { c_ForcePrivate = value; if (value) { c_ForcePublic = false; if (House != null) { House.Public = false; } } } } [CommandProperty(AccessLevel.GameMaster)] public bool ForcePublic { get { return c_ForcePublic; } set { c_ForcePublic = value; if (value) { c_ForcePrivate = false; if (House != null) { House.Public = true; } } } } [CommandProperty(AccessLevel.GameMaster)] public bool NoBanning { get { return c_NoBanning; } set { c_NoBanning = value; if (value && House != null) { House.Bans.Clear(); } } } [CommandProperty(AccessLevel.GameMaster)] public Type Currency { get; set; } public ArrayList Blocks { get; set; } [CommandProperty(AccessLevel.GameMaster)] public string Skill { get { return c_Skill; } set { c_Skill = value; ValidateOwnership(); InvalidateProperties(); } } [CommandProperty(AccessLevel.GameMaster)] public double SkillReq { get { return c_SkillReq; } set { c_SkillReq = value; ValidateOwnership(); InvalidateProperties(); } } [CommandProperty(AccessLevel.GameMaster)] public bool LeaveItems { get { return c_LeaveItems; } set { c_LeaveItems = value; InvalidateProperties(); } } [CommandProperty(AccessLevel.GameMaster)] public bool RentToOwn { get { return c_RentToOwn; } set { c_RentToOwn = value; InvalidateProperties(); } } [CommandProperty(AccessLevel.GameMaster)] public bool Relock { get; set; } [CommandProperty(AccessLevel.GameMaster)] public bool NoTrade { get; set; } [CommandProperty(AccessLevel.GameMaster)] public int ItemsPrice { get { return c_ItemsPrice; } set { c_ItemsPrice = value; InvalidateProperties(); } } [CommandProperty(AccessLevel.GameMaster)] public TownHouse House { get; set; } public Timer DemolishTimer { get { return c_DemolishTimer; } } [CommandProperty(AccessLevel.GameMaster)] public DateTime DemolishTime { get { return c_DemolishTime; } } [CommandProperty(AccessLevel.GameMaster)] public bool Owned { get { return House != null && !House.Deleted; } } [CommandProperty(AccessLevel.GameMaster)] public int Floors { get { return (c_MaxZ - c_MinZ) / 20 + 1; } } public bool BlocksReady { get { return Blocks.Count != 0; } } public bool FloorsReady { get { return (BlocksReady && MinZ != short.MinValue); } } public bool SignReady { get { return (FloorsReady && SignLoc != Point3D.Zero); } } public bool BanReady { get { return (SignReady && BanLoc != Point3D.Zero); } } public bool LocSecReady { get { return (BanReady && Locks != 0 && Secures != 0); } } public bool ItemsReady { get { return LocSecReady; } } public bool LengthReady { get { return ItemsReady; } } public bool PriceReady { get { return (LengthReady && Price != 0); } } [CommandProperty(AccessLevel.GameMaster)] public string PriceType { get { if (c_RentByTime == TimeSpan.Zero) { return "Sale"; } if (c_RentByTime == TimeSpan.FromDays(1)) { return "Daily"; } if (c_RentByTime == TimeSpan.FromDays(7)) { return "Weekly"; } if (c_RentByTime == TimeSpan.FromDays(30)) { return "Monthly"; } return "Sale"; } } [CommandProperty(AccessLevel.GameMaster)] public string PriceTypeShort { get { if (c_RentByTime == TimeSpan.Zero) { return "Sale"; } if (c_RentByTime == TimeSpan.FromDays(1)) { return "Day"; } if (c_RentByTime == TimeSpan.FromDays(7)) { return "Week"; } if (c_RentByTime == TimeSpan.FromDays(30)) { return "Month"; } return "Sale"; } } [Constructable] public TownHouseSign() : base(0xC0B) { Name = "This building is for sale or rent!"; Movable = false; Blocks = new ArrayList(); c_BanLoc = Point3D.Zero; c_SignLoc = Point3D.Zero; c_Skill = ""; c_DecoreItemInfos = new ArrayList(); c_PreviewItems = new ArrayList(); c_DemolishTime = DateTime.UtcNow; c_RentTime = DateTime.UtcNow; c_RentByTime = TimeSpan.Zero; c_RecurRent = true; c_MinZ = short.MinValue; c_MaxZ = short.MaxValue; Currency = typeof(Gold); s_TownHouseSigns.Add(this); } private void SearchForHouse() { foreach (var house in TownHouse.AllTownHouses.Where(house => house.ForSaleSign == this)) { House = house; break; } } public void UpdateBlocks() { if (!Owned) { return; } if (Blocks.Count == 0) { UnconvertDoors(); } RUOVersion.UpdateRegion(this); ConvertItems(false); House.InitSectorDefinition(); } public void ShowAreaPreview(Mobile m) { ClearPreview(); var point = Point2D.Zero; var blocks = new ArrayList(); foreach (Rectangle2D rect in Blocks) { for (var x = rect.Start.X; x < rect.End.X; ++x) { for (var y = rect.Start.Y; y < rect.End.Y; ++y) { point = new Point2D(x, y); if (!blocks.Contains(point)) { blocks.Add(point); } } } } if (blocks.Count > 500) { m.SendMessage("Due to size of the area, skipping the preview."); return; } foreach (Point2D p in blocks) { var avgz = Map.GetAverageZ(p.X, p.Y); c_PreviewItems.Add( new Item(0x1766) { Name = "Area Preview", Movable = false, Location = new Point3D(p.X, p.Y, (avgz <= m.Z ? m.Z + 2 : avgz + 2)), Map = Map }); } c_PreviewTimer = Timer.DelayCall(TimeSpan.FromSeconds(100), ClearPreview); } public void ShowSignPreview() { ClearPreview(); var sign = new Item(0xBD2) { Name = "Sign Preview", Movable = false, Location = SignLoc, Map = Map }; c_PreviewItems.Add(sign); sign = new Item(0xB98) { Name = "Sign Preview", Movable = false, Location = SignLoc, Map = Map }; c_PreviewItems.Add(sign); c_PreviewTimer = Timer.DelayCall(TimeSpan.FromSeconds(100), ClearPreview); } public void ShowBanPreview() { ClearPreview(); var ban = new Item(0x17EE) { Name = "Ban Loc Preview", Movable = false, Location = BanLoc, Map = Map }; c_PreviewItems.Add(ban); c_PreviewTimer = Timer.DelayCall(TimeSpan.FromSeconds(100), ClearPreview); } public void ShowFloorsPreview(Mobile m) { ClearPreview(); var item = new Item(0x7BD) { Name = "Bottom Floor Preview", Movable = false, Location = m.Location, Z = c_MinZ, Map = Map }; c_PreviewItems.Add(item); item = new Item(0x7BD) { Name = "Top Floor Preview", Movable = false, Location = m.Location, Z = c_MaxZ, Map = Map }; c_PreviewItems.Add(item); c_PreviewTimer = Timer.DelayCall(TimeSpan.FromSeconds(100), ClearPreview); } public void ClearPreview() { foreach (Item item in new ArrayList(c_PreviewItems)) { c_PreviewItems.Remove(item); item.Delete(); } if (c_PreviewTimer != null) { c_PreviewTimer.Stop(); } c_PreviewTimer = null; } public void Purchase(Mobile m) { Purchase(m, false); } public void Purchase(Mobile m, bool sellitems) { try { if (Owned) { m.SendMessage("Someone already owns this house!"); return; } if (!PriceReady) { m.SendMessage("The setup for this house is not yet complete."); return; } var price = c_Price; if (sellitems) { price += c_ItemsPrice; } if (c_Free) { price = 0; } var currency = Currency != null && Currency != typeof(Gold); if (currency) { if (m.AccessLevel < AccessLevel.Counselor && !m.BankBox.ConsumeTotal(Currency, price) && !m.Backpack.ConsumeTotal(Currency, price)) { m.SendMessage("You cannot afford this house."); return; } } else if (m.AccessLevel < AccessLevel.Counselor && !Banker.Withdraw(m, price)) { m.SendMessage("You cannot afford this house."); return; } if (currency && m.AccessLevel < AccessLevel.Counselor) { m.SendMessage( "You pay {0} {1} to purchase this house.", price.ToString("#,0"), SpaceWords(Currency.Name)); } else if (m.AccessLevel < AccessLevel.Counselor) { m.SendLocalizedMessage( 1060398, price.ToString("#,0")); // ~1_AMOUNT~ gold has been withdrawn from your bank box. } Visible = false; var minX = ((Rectangle2D)Blocks[0]).Start.X; var minY = ((Rectangle2D)Blocks[0]).Start.Y; var maxX = ((Rectangle2D)Blocks[0]).End.X; var maxY = ((Rectangle2D)Blocks[0]).End.Y; foreach (Rectangle2D rect in Blocks) { if (rect.Start.X < minX) { minX = rect.Start.X; } if (rect.Start.Y < minY) { minY = rect.Start.Y; } if (rect.End.X > maxX) { maxX = rect.End.X; } if (rect.End.Y > maxY) { maxY = rect.End.Y; } } House = new TownHouse(m, this, c_Locks, c_Secures); House.Components.Resize(maxX - minX, maxY - minY); House.Components.Add(0x520, House.Components.Width - 1, House.Components.Height - 1, -5); House.Location = new Point3D(minX, minY, Map.GetAverageZ(minX, minY)); House.Map = Map; House.Region.GoLocation = c_BanLoc; House.Sign.Location = c_SignLoc; House.Hanger = new Item(0xB98) { Location = c_SignLoc, Map = Map, Movable = false }; if (c_ForcePublic) { House.Public = true; } House.Price = (RentByTime <= TimeSpan.Zero ? c_Price : 1); RUOVersion.UpdateRegion(this); House.Price = Math.Max(1, House.Price); if (c_RentByTime != TimeSpan.Zero) { BeginRentTimer(c_RentByTime); } c_RTOPayments = 1; HideOtherSigns(); c_DecoreItemInfos = new ArrayList(); ConvertItems(sellitems); } catch (Exception e) { Errors.Report("An error occurred during home purchasing. More information available on the console."); Console.WriteLine(e.Message); Console.WriteLine(e.Source); Console.WriteLine(e.StackTrace); } } private void HideOtherSigns() { foreach (var item in House.Sign.GetItemsInRange(0)) { if (!(item is HouseSign)) { if (item.ItemID == 0xB95 || item.ItemID == 0xB96 || item.ItemID == 0xC43 || item.ItemID == 0xC44 || (item.ItemID > 0xBA3 && item.ItemID < 0xC0E)) { item.Visible = false; } } } } public virtual void ConvertItems(bool keep) { if (House == null) { return; } var items = new ArrayList(); foreach (Rectangle2D rect in Blocks) { foreach (var item in Map.GetItemsInBounds(rect)) { if (House.Region.Contains(item.Location) && item.RootParent == null && !items.Contains(item)) { items.Add(item); } } } foreach (Item item in new ArrayList(items)) { if (item is HouseSign || item is BaseMulti || item is BaseAddon || item is AddonComponent || item == House.Hanger || !item.Visible || item.IsLockedDown || item.IsSecure || item.Movable || c_PreviewItems.Contains(item)) { continue; } if (item is BaseDoor) { ConvertDoor((BaseDoor)item); } else if (!c_LeaveItems) { c_DecoreItemInfos.Add( new DecoreItemInfo( item.GetType().ToString(), item.Name, item.ItemID, item.Hue, item.Location, item.Map)); if (!c_KeepItems || !keep) { item.Delete(); } else { item.Movable = true; House.LockDown(House.Owner, item, false); } } } } protected void ConvertDoor(BaseDoor door) { if (!Owned) { return; } if (door is ISecurable) { door.Locked = false; House.Doors.Add(door); return; } door.Open = false; var newdoor = new GenericHouseDoor(0, door.ClosedID, door.OpenedSound, door.ClosedSound) { Offset = door.Offset, ClosedID = door.ClosedID, OpenedID = door.OpenedID, Location = door.Location, Map = door.Map }; door.Delete(); foreach (var inneritem in newdoor.GetItemsInRange(1)) { if (inneritem is BaseDoor && inneritem != newdoor && inneritem.Z == newdoor.Z) { ((BaseDoor)inneritem).Link = newdoor; newdoor.Link = (BaseDoor)inneritem; } } House.Doors.Add(newdoor); } public virtual void UnconvertDoors() { if (House == null) { return; } BaseDoor newdoor = null; foreach (BaseDoor door in new ArrayList(House.Doors)) { door.Open = false; if (Relock) { door.Locked = true; } newdoor = new StrongWoodDoor((DoorFacing)0) { ItemID = door.ItemID, ClosedID = door.ClosedID, OpenedID = door.OpenedID, OpenedSound = door.OpenedSound, ClosedSound = door.ClosedSound, Offset = door.Offset, Location = door.Location, Map = door.Map }; door.Delete(); foreach (var inneritem in newdoor.GetItemsInRange(1)) { if (inneritem is BaseDoor && inneritem != newdoor && inneritem.Z == newdoor.Z) { ((BaseDoor)inneritem).Link = newdoor; newdoor.Link = (BaseDoor)inneritem; } } House.Doors.Remove(door); } } public void RecreateItems() { foreach (DecoreItemInfo info in c_DecoreItemInfos) { Item item; if (Insensitive.Contains(info.TypeString, "static")) { item = new Static(info.ItemID); } else { try { item = Activator.CreateInstance(ScriptCompiler.FindTypeByFullName(info.TypeString)) as Item; } catch { continue; } } if (item == null) { continue; } item.ItemID = info.ItemID; item.Name = info.Name; item.Hue = info.Hue; item.Location = info.Location; item.Map = info.Map; item.Movable = false; } } private void TryCatch(Action a) { try { a(); } catch { } } public virtual void ClearHouse() { TryCatch(UnconvertDoors); TryCatch(ClearDemolishTimer); TryCatch(ClearRentTimer); TryCatch(PackUpItems); TryCatch(RecreateItems); House = null; Visible = true; if (c_RentToOwn) { c_RentByTime = c_OriginalRentTime; } } public virtual void ValidateOwnership() { if (!Owned) { return; } if (House.Owner == null) { House.Delete(); return; } if (House.Owner.AccessLevel != AccessLevel.Player) { return; } if (!CanBuyHouse(House.Owner) && c_DemolishTimer == null) { BeginDemolishTimer(); } else { ClearDemolishTimer(); } } public int CalcVolume() { var floors = 1; if (c_MaxZ - c_MinZ < 100) { floors = 1 + Math.Abs((c_MaxZ - c_MinZ) / 20); } var point = Point3D.Zero; var blocks = new ArrayList(); foreach (Rectangle2D rect in Blocks) { for (var x = rect.Start.X; x < rect.End.X; ++x) { for (var y = rect.Start.Y; y < rect.End.Y; ++y) { for (var z = 0; z < floors; z++) { point = new Point3D(x, y, z); if (!blocks.Contains(point)) { blocks.Add(point); } } } } } return blocks.Count; } private void StartTimers() { if (c_DemolishTime > DateTime.UtcNow) { BeginDemolishTimer(c_DemolishTime - DateTime.UtcNow); } else if (c_RentByTime != TimeSpan.Zero) { BeginRentTimer(c_RentByTime); } } #region Demolish public void ClearDemolishTimer() { if (c_DemolishTimer == null) { return; } c_DemolishTimer.Stop(); c_DemolishTimer = null; c_DemolishTime = DateTime.UtcNow; if (!House.Deleted && Owned) { House.Owner.SendMessage("Demolition canceled."); } } public void CheckDemolishTimer() { if (c_DemolishTimer == null || !Owned) { return; } DemolishAlert(); } protected void BeginDemolishTimer() { BeginDemolishTimer(TimeSpan.FromHours(24)); } protected void BeginDemolishTimer(TimeSpan time) { if (!Owned) { return; } c_DemolishTime = DateTime.UtcNow + time; c_DemolishTimer = Timer.DelayCall(time, PackUpHouse); DemolishAlert(); } protected virtual void DemolishAlert() { House.Owner.SendMessage( "You no longer meet the requirements for your town house, which will be demolished automatically in {0}:{1}:{2}.", (c_DemolishTime - DateTime.UtcNow).Hours, (c_DemolishTime - DateTime.UtcNow).Minutes, (c_DemolishTime - DateTime.UtcNow).Seconds); } protected void PackUpHouse() { if (!Owned || House.Deleted) { return; } TryCatch(PackUpItems); House.Owner.BankBox.DropItem(new BankCheck(House.Price)); try { House.Delete(); } catch { Errors.Report("The infamous SVN bug has occured."); } } protected void PackUpItems() { if (House == null || House.Deleted || House.Map == null || House.Map == Map.Internal) { return; } Container bag = new Bag(); bag.Name = "Town House Belongings"; if (House.LockDowns != null) { TryCatch( () => { foreach (var item in House.LockDowns.Keys.ToArray()) { TryCatch( () => { House.LockDowns.Remove(item); item.IsLockedDown = false; item.Movable = true; bag.DropItem(item); }); } }); } if (House.Secures != null) { TryCatch( () => { foreach (var info in House.Secures.ToArray()) { TryCatch( () => { House.Secures.Remove(info); if (info.Item != null) { info.Item.IsLockedDown = false; info.Item.IsSecure = false; info.Item.Movable = true; info.Item.SetLastMoved(); bag.DropItem(info.Item); } }); } }); } if (Blocks != null) { TryCatch( () => { foreach (var rect in Blocks.OfType().ToArray()) { TryCatch( () => { var items = House.Map.GetItemsInBounds(rect); foreach (var item in items.Where(i => i != null && !i.Deleted)) { TryCatch( () => { if (!(item is HouseSign) && !(item is BaseDoor) && !(item is BaseMulti) && !(item is IAddon) && !(item is AddonComponent) && !(item is AddonContainerComponent) && !(item is AddonToolComponent) && item.Visible && !item.IsLockedDown && !item.IsSecure && item.Movable && item.Map == House.Map && House.Region.Contains(item.Location)) { bag.DropItem(item); } }); } items.Free(); }); } }); } if (bag.Items.Count == 0) { bag.Delete(); return; } House.Owner.BankBox.DropItem(bag); } #endregion #region Rent public void ClearRentTimer() { if (c_RentTimer != null) { c_RentTimer.Stop(); c_RentTimer = null; } c_RentTime = DateTime.UtcNow; } private void BeginRentTimer() { BeginRentTimer(TimeSpan.FromDays(1)); } private void BeginRentTimer(TimeSpan time) { if (!Owned) { return; } c_RentTimer = Timer.DelayCall(time, RentDue); c_RentTime = DateTime.UtcNow + time; } public void CheckRentTimer() { if (c_RentTimer == null || !Owned) { return; } House.Owner.SendMessage( "This rent cycle ends in {0} days, {1}:{2}:{3}.", (c_RentTime - DateTime.UtcNow).Days, (c_RentTime - DateTime.UtcNow).Hours, (c_RentTime - DateTime.UtcNow).Minutes, (c_RentTime - DateTime.UtcNow).Seconds); } private void RentDue() { if (!Owned || House.Owner == null) { return; } if (!c_RecurRent) { House.Owner.SendMessage( "Your town house rental contract has expired, and the bank has once again taken possession."); PackUpHouse(); return; } var currency = Currency != null && Currency != typeof(Gold); if (currency && !c_Free && House.Owner.AccessLevel < AccessLevel.Counselor && !House.Owner.BankBox.ConsumeTotal(Currency, c_Price) && !House.Owner.Backpack.ConsumeTotal(Currency, c_Price)) { House.Owner.SendMessage("Since you can not afford the rent, the bank has reclaimed your town house."); PackUpHouse(); return; } if (!currency && !c_Free && House.Owner.AccessLevel < AccessLevel.Counselor && !Banker.Withdraw(House.Owner, c_Price)) { House.Owner.SendMessage("Since you can not afford the rent, the bank has reclaimed your town house."); PackUpHouse(); return; } if (!c_Free && !currency) { House.Owner.SendMessage("The bank has withdrawn {0} gold rent for your town house.", c_Price); } if (!c_Free && currency) { House.Owner.SendMessage("You pay your rent with {0} {1}.", c_Price, SpaceWords(Currency.Name)); } OnRentPaid(); if (c_RentToOwn) { c_RTOPayments++; var complete = false; if (c_RentByTime == TimeSpan.FromDays(1) && c_RTOPayments >= 60) { complete = true; House.Price = c_Price * 60; } if (c_RentByTime == TimeSpan.FromDays(7) && c_RTOPayments >= 9) { complete = true; House.Price = c_Price * 9; } if (c_RentByTime == TimeSpan.FromDays(30) && c_RTOPayments >= 2) { complete = true; House.Price = c_Price * 2; } if (complete) { House.Owner.SendMessage("You now own your rental home."); c_RentByTime = TimeSpan.Zero; return; } } BeginRentTimer(c_RentByTime); } protected virtual void OnRentPaid() { } public void NextPriceType() { if (c_RentByTime == TimeSpan.Zero) { RentByTime = TimeSpan.FromDays(1); } else if (c_RentByTime == TimeSpan.FromDays(1)) { RentByTime = TimeSpan.FromDays(7); } else if (c_RentByTime == TimeSpan.FromDays(7)) { RentByTime = TimeSpan.FromDays(30); } else { RentByTime = TimeSpan.Zero; } } public void PrevPriceType() { if (c_RentByTime == TimeSpan.Zero) { RentByTime = TimeSpan.FromDays(30); } else if (c_RentByTime == TimeSpan.FromDays(30)) { RentByTime = TimeSpan.FromDays(7); } else if (c_RentByTime == TimeSpan.FromDays(7)) { RentByTime = TimeSpan.FromDays(1); } else { RentByTime = TimeSpan.Zero; } } #endregion public bool CanBuyHouse(Mobile m) { if (c_Skill != "") { try { var index = (SkillName)Enum.Parse(typeof(SkillName), c_Skill, true); if (m.Skills[index].Value < c_SkillReq) { return false; } } catch { return false; } } if (c_MinTotalSkill != 0 && m.SkillsTotal / 10 < c_MinTotalSkill) { return false; } if (c_MaxTotalSkill != 0 && m.SkillsTotal / 10 > c_MaxTotalSkill) { return false; } if (c_YoungOnly && m.Player && !((PlayerMobile)m).Young) { return false; } if (c_Murderers == Intu.Yes && m.Kills < 5) { return false; } if (c_Murderers == Intu.No && m.Kills >= 5) { return false; } return true; } public override void OnDoubleClick(Mobile m) { if (m.AccessLevel != AccessLevel.Player) { m.SendGump(new TownHouseSetupGump(m, this)); return; } if (!Visible) { return; } if (!CanBuyHouse(m) || BaseHouse.AtAccountHouseLimit(m)) { m.SendMessage("You cannot purchase this house."); return; } m.SendGump(new TownHouseConfirmGump(m, this)); } public override void Delete() { if (House == null || House.Deleted) { base.Delete(); } else { PublicOverheadMessage( MessageType.Regular, 0x0, true, "You cannot delete this while the home is owned."); } if (Deleted) { s_TownHouseSigns.Remove(this); } } public override void GetProperties(ObjectPropertyList list) { base.GetProperties(list); var currencyName = Currency != null && Currency != typeof(Gold) ? SpaceWords(Currency.Name) : "Gold"; if (c_Free) { list.Add(1060658, "Price\tFree"); } else if (c_RentByTime == TimeSpan.Zero) { list.Add( 1060658, "Price\t{0} {1} {2}", c_Price, currencyName, c_KeepItems ? "(+" + c_ItemsPrice + " for the items)" : ""); } else if (c_RecurRent) { list.Add( 1060658, "{0}\t{1} {2}\t{3}", PriceType + (c_RentToOwn ? " Rent-to-Own" : " Recurring"), c_Price, currencyName, c_KeepItems ? "(+" + c_ItemsPrice + " for the items)" : ""); } else { list.Add( 1060658, "One {0}\t{1} {2} {3}", PriceTypeShort, c_Price, currencyName, c_KeepItems ? "(+" + c_ItemsPrice + " for the items)" : ""); } list.Add(1060659, "Lockdowns\t{0}", c_Locks); list.Add(1060660, "Secures\t{0}", c_Secures); if (c_SkillReq != 0.0) { list.Add(1060661, "Requires\t{0}", c_SkillReq + " in " + c_Skill); } if (c_MinTotalSkill != 0) { list.Add(1060662, "Requires more than\t{0} total skills", c_MinTotalSkill); } if (c_MaxTotalSkill != 0) { list.Add(1060663, "Requires less than\t{0} total skills", c_MaxTotalSkill); } if (c_YoungOnly) { list.Add(1063483, "Must be\tYoung"); } else if (c_Murderers == Intu.Yes) { list.Add(1063483, "Must be\ta murderer"); } else if (c_Murderers == Intu.No) { list.Add(1063483, "Must be\tinnocent"); } } public TownHouseSign(Serial serial) : base(serial) { } public override void Serialize(GenericWriter writer) { base.Serialize(writer); writer.Write(14); // Version 14 writer.Write(Currency != null ? Currency.FullName : null); // Version 13 writer.Write(c_ForcePrivate); writer.Write(c_ForcePublic); writer.Write(NoTrade); // Version 12 writer.Write(c_Free); // Version 11 writer.Write((int)c_Murderers); // Version 10 writer.Write(c_LeaveItems); // Version 9 writer.Write(c_RentToOwn); writer.Write(c_OriginalRentTime); writer.Write(c_RTOPayments); // Version 7 writer.WriteItemList(c_PreviewItems, true); // Version 6 writer.Write(c_ItemsPrice); writer.Write(c_KeepItems); // Version 5 writer.Write(c_DecoreItemInfos.Count); foreach (DecoreItemInfo info in c_DecoreItemInfos) { info.Save(writer); } writer.Write(Relock); // Version 4 writer.Write(c_RecurRent); writer.Write(c_RentByTime); writer.Write(c_RentTime); writer.Write(c_DemolishTime); writer.Write(c_YoungOnly); writer.Write(c_MinTotalSkill); writer.Write(c_MaxTotalSkill); // Version 3 writer.Write(c_MinZ); writer.Write(c_MaxZ); // Version 2 writer.Write(House); // Version 1 writer.Write(c_Price); writer.Write(c_Locks); writer.Write(c_Secures); writer.Write(c_BanLoc); writer.Write(c_SignLoc); writer.Write(c_Skill); writer.Write(c_SkillReq); writer.Write(Blocks.Count); foreach (Rectangle2D rect in Blocks) { writer.Write(rect); } } public override void Deserialize(GenericReader reader) { base.Deserialize(reader); var version = reader.ReadInt(); if (version >= 14) Currency = ScriptCompiler.FindTypeByFullName(reader.ReadString()); if(Currency == null) Currency = typeof(Gold); if (version >= 13) { c_ForcePrivate = reader.ReadBool(); c_ForcePublic = reader.ReadBool(); NoTrade = reader.ReadBool(); } if (version >= 12) { c_Free = reader.ReadBool(); } if (version >= 11) { c_Murderers = (Intu)reader.ReadInt(); } if (version >= 10) { c_LeaveItems = reader.ReadBool(); } if (version >= 9) { c_RentToOwn = reader.ReadBool(); c_OriginalRentTime = reader.ReadTimeSpan(); c_RTOPayments = reader.ReadInt(); } c_PreviewItems = new ArrayList(); if (version >= 7) { c_PreviewItems = reader.ReadItemList(); } if (version >= 6) { c_ItemsPrice = reader.ReadInt(); c_KeepItems = reader.ReadBool(); } c_DecoreItemInfos = new ArrayList(); if (version >= 5) { var decorecount = reader.ReadInt(); DecoreItemInfo info; for (var i = 0; i < decorecount; ++i) { info = new DecoreItemInfo(); info.Load(reader); c_DecoreItemInfos.Add(info); } Relock = reader.ReadBool(); } if (version >= 4) { c_RecurRent = reader.ReadBool(); c_RentByTime = reader.ReadTimeSpan(); c_RentTime = reader.ReadDateTime(); c_DemolishTime = reader.ReadDateTime(); c_YoungOnly = reader.ReadBool(); c_MinTotalSkill = reader.ReadInt(); c_MaxTotalSkill = reader.ReadInt(); } if (version >= 3) { c_MinZ = reader.ReadInt(); c_MaxZ = reader.ReadInt(); } if (version >= 2) { House = (TownHouse)reader.ReadItem(); } c_Price = reader.ReadInt(); c_Locks = reader.ReadInt(); c_Secures = reader.ReadInt(); c_BanLoc = reader.ReadPoint3D(); c_SignLoc = reader.ReadPoint3D(); c_Skill = reader.ReadString(); c_SkillReq = reader.ReadDouble(); var count = reader.ReadInt(); Blocks = new ArrayList(count); for (var i = 0; i < count; ++i) { Blocks.Add(reader.ReadRect2D()); } if (c_RentTime > DateTime.UtcNow) { BeginRentTimer(c_RentTime - DateTime.UtcNow); } Timer.DelayCall(TimeSpan.Zero, StartTimers); ClearPreview(); s_TownHouseSigns.Add(this); } private static readonly Regex _SpaceWordsRegex = new Regex(@"((?<=\p{Ll})\p{Lu})|((?!\A)\p{Lu}(?>\p{Ll}))"); private static string SpaceWords(string str, params char[] whiteSpaceAlias) { if (String.IsNullOrWhiteSpace(str)) { return str ?? String.Empty; } if (whiteSpaceAlias == null || whiteSpaceAlias.Length == 0) { whiteSpaceAlias = new[] {'_'}; } str = whiteSpaceAlias.Aggregate(str, (s, c) => s.Replace(c, ' ')); str = _SpaceWordsRegex.Replace(str, " $0"); str = String.Join(" ", str.Split(' ').Where(s => !String.IsNullOrWhiteSpace(s))); return str; } } }