From dc5e0577fd3b04961929464af56fae66f2a06361 Mon Sep 17 00:00:00 2001 From: WarrentyExpired Date: Mon, 24 Aug 2026 19:15:14 -0400 Subject: [PATCH] #W# Added Knives TownHouses. Also wrote my own static house system that is configured with a cfg file. --- Data/Config/statichouses.cfg | 3 + Scripts/Items/Houses/GenStaticHouses.cs | 104 ++ Scripts/Items/Houses/Monopoly/Decorate.cs.bak | 1098 ++++++++++++++ .../Monopoly/Gumps/Error Reporting/Errors.cs | 69 + .../Gumps/Error Reporting/ErrorsGump.cs | 55 + .../Gumps/Error Reporting/ErrorsNotifyGump.cs | 24 + .../Gumps/Gumps Plus Light/BackgroundPlus.cs | 23 + .../Gumps/Gumps Plus Light/ButtonPlus.cs | 37 + .../Gumps/Gumps Plus Light/GumpPlusLight.cs | 261 ++++ .../Monopoly/Gumps/Gumps Plus Light/HTML.cs | 20 + .../Gumps/Gumps Plus Light/HtmlPlus.cs | 23 + .../Gumps/Gumps Plus Light/InfoGump.cs | 30 + .../TownHouse Gumps/ContractConfirmGump.cs | 117 ++ .../TownHouse Gumps/ContractSetupGump.cs | 560 +++++++ .../TownHouse Gumps/TownHouseConfirmGump.cs | 63 + .../TownHouse Gumps/TownHouseSetupGump.cs | 1049 +++++++++++++ .../Gumps/TownHouse Gumps/TownHousesGump.cs | 202 +++ .../Houses/Monopoly/Items/RentalContract.cs | 318 ++++ .../Monopoly/Items/RentalContractCopy.cs | 47 + .../Houses/Monopoly/Items/RentalLicense.cs | 53 + .../Items/Houses/Monopoly/Items/SignHammer.cs | 299 ++++ .../Items/Houses/Monopoly/Items/TownHouse.cs | 259 ++++ .../Houses/Monopoly/Items/TownHouseSign.cs | 1334 +++++++++++++++++ .../Items/Houses/Monopoly/Misc/CommandInfo.cs | 36 + .../Houses/Monopoly/Misc/DecoreItemInfo.cs | 64 + Scripts/Items/Houses/Monopoly/Misc/General.cs | 217 +++ .../Houses/Monopoly/Misc/GumpResponse.cs | 167 +++ Scripts/Items/Houses/Monopoly/RUOVersion.cs | 137 ++ Scripts/Items/Houses/StaticHouse.cs | 106 ++ Scripts/Items/Houses/StaticHouseSign.cs | 147 ++ Scripts/TaskManager.cs | 98 +- 31 files changed, 7009 insertions(+), 11 deletions(-) create mode 100644 Data/Config/statichouses.cfg create mode 100644 Scripts/Items/Houses/GenStaticHouses.cs create mode 100644 Scripts/Items/Houses/Monopoly/Decorate.cs.bak create mode 100644 Scripts/Items/Houses/Monopoly/Gumps/Error Reporting/Errors.cs create mode 100644 Scripts/Items/Houses/Monopoly/Gumps/Error Reporting/ErrorsGump.cs create mode 100644 Scripts/Items/Houses/Monopoly/Gumps/Error Reporting/ErrorsNotifyGump.cs create mode 100644 Scripts/Items/Houses/Monopoly/Gumps/Gumps Plus Light/BackgroundPlus.cs create mode 100644 Scripts/Items/Houses/Monopoly/Gumps/Gumps Plus Light/ButtonPlus.cs create mode 100644 Scripts/Items/Houses/Monopoly/Gumps/Gumps Plus Light/GumpPlusLight.cs create mode 100644 Scripts/Items/Houses/Monopoly/Gumps/Gumps Plus Light/HTML.cs create mode 100644 Scripts/Items/Houses/Monopoly/Gumps/Gumps Plus Light/HtmlPlus.cs create mode 100644 Scripts/Items/Houses/Monopoly/Gumps/Gumps Plus Light/InfoGump.cs create mode 100644 Scripts/Items/Houses/Monopoly/Gumps/TownHouse Gumps/ContractConfirmGump.cs create mode 100644 Scripts/Items/Houses/Monopoly/Gumps/TownHouse Gumps/ContractSetupGump.cs create mode 100644 Scripts/Items/Houses/Monopoly/Gumps/TownHouse Gumps/TownHouseConfirmGump.cs create mode 100644 Scripts/Items/Houses/Monopoly/Gumps/TownHouse Gumps/TownHouseSetupGump.cs create mode 100644 Scripts/Items/Houses/Monopoly/Gumps/TownHouse Gumps/TownHousesGump.cs create mode 100644 Scripts/Items/Houses/Monopoly/Items/RentalContract.cs create mode 100644 Scripts/Items/Houses/Monopoly/Items/RentalContractCopy.cs create mode 100644 Scripts/Items/Houses/Monopoly/Items/RentalLicense.cs create mode 100644 Scripts/Items/Houses/Monopoly/Items/SignHammer.cs create mode 100644 Scripts/Items/Houses/Monopoly/Items/TownHouse.cs create mode 100644 Scripts/Items/Houses/Monopoly/Items/TownHouseSign.cs create mode 100644 Scripts/Items/Houses/Monopoly/Misc/CommandInfo.cs create mode 100644 Scripts/Items/Houses/Monopoly/Misc/DecoreItemInfo.cs create mode 100644 Scripts/Items/Houses/Monopoly/Misc/General.cs create mode 100644 Scripts/Items/Houses/Monopoly/Misc/GumpResponse.cs create mode 100644 Scripts/Items/Houses/Monopoly/RUOVersion.cs create mode 100644 Scripts/Items/Houses/StaticHouse.cs create mode 100644 Scripts/Items/Houses/StaticHouseSign.cs diff --git a/Data/Config/statichouses.cfg b/Data/Config/statichouses.cfg new file mode 100644 index 0000000..8a6bc44 --- /dev/null +++ b/Data/Config/statichouses.cfg @@ -0,0 +1,3 @@ +# Map SignX SignY SignZ StartX StartY Width Height MinZ MaxZ Price Locks Secures SignID <0xC0C/0xC0B> +Vaelen 863 595 5 861 583 11 13 0 55 5000 500 500 0xC0C +Vaelen 779 675 0 769 672 11 10 0 55 5000 500 500 0xC0B diff --git a/Scripts/Items/Houses/GenStaticHouses.cs b/Scripts/Items/Houses/GenStaticHouses.cs new file mode 100644 index 0000000..64a85b2 --- /dev/null +++ b/Scripts/Items/Houses/GenStaticHouses.cs @@ -0,0 +1,104 @@ +using System; +using System.IO; +using Server; +using Server.Items; +using Server.Multis; +using Server.Commands; + +namespace Server.Custom.StaticHousing +{ + public class GenStaticHouses + { + public static void Initialize() + { + CommandSystem.Register("GenStaticHouses", AccessLevel.Administrator, new CommandEventHandler(GenStaticHouses_OnCommand)); + } + + [Usage("GenStaticHouses")] + [Description("Generates Static House signs from a configuration file.")] + public static void GenStaticHouses_OnCommand(CommandEventArgs e) + { + string filePath = Path.Combine(Core.BaseDirectory, "Data", "Config", "statichouses.cfg"); + + if (!File.Exists(filePath)) + { + e.Mobile.SendMessage(33, "Error: Data/Config/statichouses.cfg not found!"); + return; + } + + int count = 0; + + using (StreamReader ip = new StreamReader(filePath)) + { + string line; + while ((line = ip.ReadLine()) != null) + { + line = line.Trim(); + if (line.Length == 0 || line.StartsWith("#")) continue; + + string[] split = line.Split(new char[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries); + + if (split.Length >= 13) + { + try + { + Map map = Map.Parse(split[0]); + Point3D signLoc = new Point3D(int.Parse(split[1]), int.Parse(split[2]), int.Parse(split[3])); + + Point2D start = new Point2D(int.Parse(split[4]), int.Parse(split[5])); + Point2D end = new Point2D(start.X + int.Parse(split[6]), start.Y + int.Parse(split[7])); + Rectangle2D area = new Rectangle2D(start, end); + + int minZ = int.Parse(split[8]); + int maxZ = int.Parse(split[9]); + int price = int.Parse(split[10]); + int locks = int.Parse(split[11]); + int secures = int.Parse(split[12]); + + // --- NEW ITEM ID PARSING --- + int itemID = 0xC0B; // Defaults to the East-facing sign + if (split.Length >= 14) + { + if (split[13].StartsWith("0x", StringComparison.OrdinalIgnoreCase)) + itemID = Convert.ToInt32(split[13], 16); + else + itemID = int.Parse(split[13]); + } + + if (map != null && !CheckForExistingHouse(map, signLoc)) + { + // Pass the parsed itemID into the new sign! + StaticHouseSign sign = new StaticHouseSign(itemID, area, minZ, maxZ, price, locks, secures); + sign.MoveToWorld(signLoc, map); + count++; + } + } + catch (Exception ex) + { + Console.WriteLine($"Error parsing statichouses.cfg line: {line}\n{ex.Message}"); + } + } + } + } + e.Mobile.SendMessage(68, $"Generation complete. {count} new Static House signs were spawned."); + } + + private static bool CheckForExistingHouse(Map map, Point3D loc) + { + bool exists = false; + IPooledEnumerable eable = map.GetItemsInRange(loc, 0); + + foreach (Item item in eable) + { + if (item is StaticHouseSign || item is HouseSign) + { + exists = true; + break; + } + } + + eable.Free(); + return exists; + } + } +} diff --git a/Scripts/Items/Houses/Monopoly/Decorate.cs.bak b/Scripts/Items/Houses/Monopoly/Decorate.cs.bak new file mode 100644 index 0000000..dda8917 --- /dev/null +++ b/Scripts/Items/Houses/Monopoly/Decorate.cs.bak @@ -0,0 +1,1098 @@ +using System; +using System.IO; +using System.Collections; +using System.Collections.Generic; +using Server; +using Server.Items; + +namespace Server.Commands +{ + public class Monopoly + { + public static void Initialize() + { + CommandSystem.Register( "Monopoly", AccessLevel.Administrator, new CommandEventHandler( Monopoly_OnCommand ) ); + } + + [Usage( "Monopoly" )] + [Description( "Generates special home items." )] + public static void Monopoly_OnCommand( CommandEventArgs e ) + { + m_Mobile = e.Mobile; + m_Count = 0; + + m_Mobile.SendMessage( "Removing special home items, please wait." ); + + ArrayList targets = new ArrayList(); + foreach ( Item it in World.Items.Values ) + if ( it.Weight == -3 ) + targets.Add( it ); + + for ( int i = 0; i < targets.Count; ++i ) + { + Item item = ( Item )targets[ i ]; + item.Delete(); + } + + m_Mobile.SendMessage( "Generating world decoration, please wait." ); + + Generate( "Data/Decoration/Monopoly/Sosaria", Map.Sosaria ); + Generate( "Data/Decoration/Monopoly/Lodor", Map.Lodor ); + Generate( "Data/Decoration/Monopoly/Serpent", Map.SerpentIsland ); + Generate( "Data/Decoration/Monopoly/IslesOfDread", Map.IslesDread ); + Generate( "Data/Decoration/Monopoly/Savage", Map.SavagedEmpire ); + Generate( "Data/Decoration/Monopoly/Underworld", Map.Underworld ); + + m_Mobile.SendMessage( "Special home items generation complete. {0} items were generated.", m_Count ); + } + + public static void Generate( string folder, params Map[] maps ) + { + if ( !Directory.Exists( folder ) ) + return; + + string[] files = Directory.GetFiles( folder, "*.cfg" ); + + for ( int i = 0; i < files.Length; ++i ) + { + ArrayList list = MonopoliesList.ReadAll( files[i] ); + + for ( int j = 0; j < list.Count; ++j ) + m_Count += ((MonopoliesList)list[j]).Generate( maps ); + } + } + + private static Mobile m_Mobile; + private static int m_Count; + } + + public class MonopoliesList + { + private Type m_Type; + private int m_ItemID; + private string[] m_Params; + private ArrayList m_Entries; + + public MonopoliesList() + { + } + + private static Type typeofStatic = typeof( Static ); + private static Type typeofLocalizedStatic = typeof( LocalizedStatic ); + private static Type typeofBaseDoor = typeof( BaseDoor ); + private static Type typeofAnkhWest = typeof( AnkhWest ); + private static Type typeofAnkhNorth = typeof( AnkhNorth ); + private static Type typeofBeverage = typeof( BaseBeverage ); + private static Type typeofLocalizedSign = typeof( LocalizedSign ); + private static Type typeofWarningItem = typeof( WarningItem ); + private static Type typeofHintItem = typeof( HintItem ); + + public Item Construct() + { + Item item; + + try + { + if ( m_Type == typeofStatic ) + { + item = new Static( m_ItemID ); + } + else if ( m_Type == typeofLocalizedStatic ) + { + int labelNumber = 0; + + for ( int i = 0; i < m_Params.Length; ++i ) + { + if ( m_Params[i].StartsWith( "LabelNumber" ) ) + { + int indexOf = m_Params[i].IndexOf( '=' ); + + if ( indexOf >= 0 ) + { + labelNumber = Utility.ToInt32( m_Params[i].Substring( ++indexOf ) ); + break; + } + } + } + + item = new LocalizedStatic( m_ItemID, labelNumber ); + } + else if ( m_Type == typeofLocalizedSign ) + { + int labelNumber = 0; + + for ( int i = 0; i < m_Params.Length; ++i ) + { + if ( m_Params[i].StartsWith( "LabelNumber" ) ) + { + int indexOf = m_Params[i].IndexOf( '=' ); + + if ( indexOf >= 0 ) + { + labelNumber = Utility.ToInt32( m_Params[i].Substring( ++indexOf ) ); + break; + } + } + } + + item = new LocalizedSign( m_ItemID, labelNumber ); + } + else if ( m_Type == typeofAnkhWest || m_Type == typeofAnkhNorth ) + { + bool bloodied = false; + + for ( int i = 0; !bloodied && i < m_Params.Length; ++i ) + bloodied = ( m_Params[i] == "Bloodied" ); + + if ( m_Type == typeofAnkhWest ) + item = new AnkhWest( bloodied ); + else + item = new AnkhNorth( bloodied ); + } + else if ( m_Type == typeofHintItem ) + { + int range = 0; + int messageNumber = 0; + string messageString = null; + int hintNumber = 0; + string hintString = null; + TimeSpan resetDelay = TimeSpan.Zero; + + for ( int i = 0; i < m_Params.Length; ++i ) + { + if ( m_Params[i].StartsWith( "Range" ) ) + { + int indexOf = m_Params[i].IndexOf( '=' ); + + if ( indexOf >= 0 ) + range = Utility.ToInt32( m_Params[i].Substring( ++indexOf ) ); + } + else if ( m_Params[i].StartsWith( "WarningString" ) ) + { + int indexOf = m_Params[i].IndexOf( '=' ); + + if ( indexOf >= 0 ) + messageString = m_Params[i].Substring( ++indexOf ); + } + else if ( m_Params[i].StartsWith( "WarningNumber" ) ) + { + int indexOf = m_Params[i].IndexOf( '=' ); + + if ( indexOf >= 0 ) + messageNumber = Utility.ToInt32( m_Params[i].Substring( ++indexOf ) ); + } + else if ( m_Params[i].StartsWith( "HintString" ) ) + { + int indexOf = m_Params[i].IndexOf( '=' ); + + if ( indexOf >= 0 ) + hintString = m_Params[i].Substring( ++indexOf ); + } + else if ( m_Params[i].StartsWith( "HintNumber" ) ) + { + int indexOf = m_Params[i].IndexOf( '=' ); + + if ( indexOf >= 0 ) + hintNumber = Utility.ToInt32( m_Params[i].Substring( ++indexOf ) ); + } + else if ( m_Params[i].StartsWith( "ResetDelay" ) ) + { + int indexOf = m_Params[i].IndexOf( '=' ); + + if ( indexOf >= 0 ) + resetDelay = TimeSpan.Parse( m_Params[i].Substring( ++indexOf ) ); + } + } + + HintItem hi = new HintItem( m_ItemID, range, messageNumber, hintNumber ); + + hi.WarningString = messageString; + hi.HintString = hintString; + hi.ResetDelay = resetDelay; + + item = hi; + } + else if ( m_Type == typeofWarningItem ) + { + int range = 0; + int messageNumber = 0; + string messageString = null; + TimeSpan resetDelay = TimeSpan.Zero; + + for ( int i = 0; i < m_Params.Length; ++i ) + { + if ( m_Params[i].StartsWith( "Range" ) ) + { + int indexOf = m_Params[i].IndexOf( '=' ); + + if ( indexOf >= 0 ) + range = Utility.ToInt32( m_Params[i].Substring( ++indexOf ) ); + } + else if ( m_Params[i].StartsWith( "WarningString" ) ) + { + int indexOf = m_Params[i].IndexOf( '=' ); + + if ( indexOf >= 0 ) + messageString = m_Params[i].Substring( ++indexOf ); + } + else if ( m_Params[i].StartsWith( "WarningNumber" ) ) + { + int indexOf = m_Params[i].IndexOf( '=' ); + + if ( indexOf >= 0 ) + messageNumber = Utility.ToInt32( m_Params[i].Substring( ++indexOf ) ); + } + else if ( m_Params[i].StartsWith( "ResetDelay" ) ) + { + int indexOf = m_Params[i].IndexOf( '=' ); + + if ( indexOf >= 0 ) + resetDelay = TimeSpan.Parse( m_Params[i].Substring( ++indexOf ) ); + } + } + + WarningItem wi = new WarningItem( m_ItemID, range, messageNumber ); + + wi.WarningString = messageString; + wi.ResetDelay = resetDelay; + + item = wi; + } + else if ( m_Type.IsSubclassOf( typeofBeverage ) ) + { + BeverageType content = BeverageType.Liquor; + bool fill = false; + + for ( int i = 0; !fill && i < m_Params.Length; ++i ) + { + if ( m_Params[i].StartsWith( "Content" ) ) + { + int indexOf = m_Params[i].IndexOf( '=' ); + + if ( indexOf >= 0 ) + { + content = (BeverageType)Enum.Parse( typeof( BeverageType ), m_Params[i].Substring( ++indexOf ), true ); + fill = true; + } + } + } + + if ( fill ) + item = (Item)Activator.CreateInstance( m_Type, new object[]{ content } ); + else + item = (Item)Activator.CreateInstance( m_Type ); + } + else if ( m_Type.IsSubclassOf( typeofBaseDoor ) ) + { + DoorFacing facing = DoorFacing.WestCW; + + for ( int i = 0; i < m_Params.Length; ++i ) + { + if ( m_Params[i].StartsWith( "Facing" ) ) + { + int indexOf = m_Params[i].IndexOf( '=' ); + + if ( indexOf >= 0 ) + { + facing = (DoorFacing)Enum.Parse( typeof( DoorFacing ), m_Params[i].Substring( ++indexOf ), true ); + break; + } + } + } + + item = (Item)Activator.CreateInstance( m_Type, new object[]{ facing } ); + } + else + { + item = (Item)Activator.CreateInstance( m_Type ); + } + } + catch ( Exception e ) + { + throw new Exception( String.Format( "Bad type: {0}", m_Type ), e ); + } + + if ( item is BaseAddon ) + { + if ( m_ItemID > 0 ) + { + List comps = ((BaseAddon)item).Components; + + for ( int i = 0; i < comps.Count; ++i ) + { + AddonComponent comp = (AddonComponent)comps[i]; + + if ( comp.Offset == Point3D.Zero ) + comp.ItemID = m_ItemID; + } + } + } + else if ( item is BaseLight ) + { + bool unlit = false, unprotected = false; + + for ( int i = 0; i < m_Params.Length; ++i ) + { + if ( !unlit && m_Params[i] == "Unlit" ) + unlit = true; + else if ( !unprotected && m_Params[i] == "Unprotected" ) + unprotected = true; + + if ( unlit && unprotected ) + break; + } + + if ( !unlit ) + ((BaseLight)item).Ignite(); + if ( !unprotected ) + ((BaseLight)item).Protected = true; + + if ( m_ItemID > 0 ) + item.ItemID = m_ItemID; + } + else if ( item is Server.Mobiles.Spawner ) + { + Server.Mobiles.Spawner sp = (Server.Mobiles.Spawner)item; + + sp.NextSpawn = TimeSpan.Zero; + + for ( int i = 0; i < m_Params.Length; ++i ) + { + if ( m_Params[i].StartsWith( "Spawn" ) ) + { + int indexOf = m_Params[i].IndexOf( '=' ); + + if ( indexOf >= 0 ) + sp.SpawnNames.Add( m_Params[i].Substring( ++indexOf ) ); + } + else if ( m_Params[i].StartsWith( "MinDelay" ) ) + { + int indexOf = m_Params[i].IndexOf( '=' ); + + if ( indexOf >= 0 ) + sp.MinDelay = TimeSpan.Parse( m_Params[i].Substring( ++indexOf ) ); + } + else if ( m_Params[i].StartsWith( "MaxDelay" ) ) + { + int indexOf = m_Params[i].IndexOf( '=' ); + + if ( indexOf >= 0 ) + sp.MaxDelay = TimeSpan.Parse( m_Params[i].Substring( ++indexOf ) ); + } + else if ( m_Params[i].StartsWith( "NextSpawn" ) ) + { + int indexOf = m_Params[i].IndexOf( '=' ); + + if ( indexOf >= 0 ) + sp.NextSpawn = TimeSpan.Parse( m_Params[i].Substring( ++indexOf ) ); + } + else if ( m_Params[i].StartsWith( "Count" ) ) + { + int indexOf = m_Params[i].IndexOf( '=' ); + + if ( indexOf >= 0 ) + sp.Count = Utility.ToInt32( m_Params[i].Substring( ++indexOf ) ); + } + else if ( m_Params[i].StartsWith( "Team" ) ) + { + int indexOf = m_Params[i].IndexOf( '=' ); + + if ( indexOf >= 0 ) + sp.Team = Utility.ToInt32( m_Params[i].Substring( ++indexOf ) ); + } + else if ( m_Params[i].StartsWith( "HomeRange" ) ) + { + int indexOf = m_Params[i].IndexOf( '=' ); + + if ( indexOf >= 0 ) + sp.HomeRange = Utility.ToInt32( m_Params[i].Substring( ++indexOf ) ); + } + else if ( m_Params[i].StartsWith( "Running" ) ) + { + int indexOf = m_Params[i].IndexOf( '=' ); + + if ( indexOf >= 0 ) + sp.Running = Utility.ToBoolean( m_Params[i].Substring( ++indexOf ) ); + } + else if ( m_Params[i].StartsWith( "Group" ) ) + { + int indexOf = m_Params[i].IndexOf( '=' ); + + if ( indexOf >= 0 ) + sp.Group = Utility.ToBoolean( m_Params[i].Substring( ++indexOf ) ); + } + } + } + else if ( item is RecallRune ) + { + RecallRune rune = (RecallRune)item; + + for ( int i = 0; i < m_Params.Length; ++i ) + { + if ( m_Params[i].StartsWith( "Description" ) ) + { + int indexOf = m_Params[i].IndexOf( '=' ); + + if ( indexOf >= 0 ) + rune.Description = m_Params[i].Substring( ++indexOf ); + } + else if ( m_Params[i].StartsWith( "Marked" ) ) + { + int indexOf = m_Params[i].IndexOf( '=' ); + + if ( indexOf >= 0 ) + rune.Marked = Utility.ToBoolean( m_Params[i].Substring( ++indexOf ) ); + } + else if ( m_Params[i].StartsWith( "TargetMap" ) ) + { + int indexOf = m_Params[i].IndexOf( '=' ); + + if ( indexOf >= 0 ) + rune.TargetMap = Map.Parse( m_Params[i].Substring( ++indexOf ) ); + } + else if ( m_Params[i].StartsWith( "Target" ) ) + { + int indexOf = m_Params[i].IndexOf( '=' ); + + if ( indexOf >= 0 ) + rune.Target = Point3D.Parse( m_Params[i].Substring( ++indexOf ) ); + } + } + } + else if ( item is SkillTeleporter ) + { + SkillTeleporter tp = (SkillTeleporter)item; + + for ( int i = 0; i < m_Params.Length; ++i ) + { + if ( m_Params[i].StartsWith( "Skill" ) ) + { + int indexOf = m_Params[i].IndexOf( '=' ); + + if ( indexOf >= 0 ) + tp.Skill = (SkillName)Enum.Parse( typeof( SkillName ), m_Params[i].Substring( ++indexOf ), true ); + } + else if ( m_Params[i].StartsWith( "RequiredFixedPoint" ) ) + { + int indexOf = m_Params[i].IndexOf( '=' ); + + if ( indexOf >= 0 ) + tp.Required = Utility.ToInt32( m_Params[i].Substring( ++indexOf ) ) * 0.01; + } + else if ( m_Params[i].StartsWith( "Required" ) ) + { + int indexOf = m_Params[i].IndexOf( '=' ); + + if ( indexOf >= 0 ) + tp.Required = Utility.ToDouble( m_Params[i].Substring( ++indexOf ) ); + } + else if ( m_Params[i].StartsWith( "MessageString" ) ) + { + int indexOf = m_Params[i].IndexOf( '=' ); + + if ( indexOf >= 0 ) + tp.MessageString = m_Params[i].Substring( ++indexOf ); + } + else if ( m_Params[i].StartsWith( "MessageNumber" ) ) + { + int indexOf = m_Params[i].IndexOf( '=' ); + + if ( indexOf >= 0 ) + tp.MessageNumber = Utility.ToInt32( m_Params[i].Substring( ++indexOf ) ); + } + else if ( m_Params[i].StartsWith( "PointDest" ) ) + { + int indexOf = m_Params[i].IndexOf( '=' ); + + if ( indexOf >= 0 ) + tp.PointDest = Point3D.Parse( m_Params[i].Substring( ++indexOf ) ); + } + else if ( m_Params[i].StartsWith( "MapDest" ) ) + { + int indexOf = m_Params[i].IndexOf( '=' ); + + if ( indexOf >= 0 ) + tp.MapDest = Map.Parse( m_Params[i].Substring( ++indexOf ) ); + } + else if ( m_Params[i].StartsWith( "Creatures" ) ) + { + int indexOf = m_Params[i].IndexOf( '=' ); + + if ( indexOf >= 0 ) + tp.Creatures = Utility.ToBoolean( m_Params[i].Substring( ++indexOf ) ); + } + else if ( m_Params[i].StartsWith( "SourceEffect" ) ) + { + int indexOf = m_Params[i].IndexOf( '=' ); + + if ( indexOf >= 0 ) + tp.SourceEffect = Utility.ToBoolean( m_Params[i].Substring( ++indexOf ) ); + } + else if ( m_Params[i].StartsWith( "DestEffect" ) ) + { + int indexOf = m_Params[i].IndexOf( '=' ); + + if ( indexOf >= 0 ) + tp.DestEffect = Utility.ToBoolean( m_Params[i].Substring( ++indexOf ) ); + } + else if ( m_Params[i].StartsWith( "SoundID" ) ) + { + int indexOf = m_Params[i].IndexOf( '=' ); + + if ( indexOf >= 0 ) + tp.SoundID = Utility.ToInt32( m_Params[i].Substring( ++indexOf ) ); + } + else if ( m_Params[i].StartsWith( "Delay" ) ) + { + int indexOf = m_Params[i].IndexOf( '=' ); + + if ( indexOf >= 0 ) + tp.Delay = TimeSpan.Parse( m_Params[i].Substring( ++indexOf ) ); + } + } + + if ( m_ItemID > 0 ) + item.ItemID = m_ItemID; + } + else if ( item is KeywordTeleporter ) + { + KeywordTeleporter tp = (KeywordTeleporter)item; + + for ( int i = 0; i < m_Params.Length; ++i ) + { + if ( m_Params[i].StartsWith( "Substring" ) ) + { + int indexOf = m_Params[i].IndexOf( '=' ); + + if ( indexOf >= 0 ) + tp.Substring = m_Params[i].Substring( ++indexOf ); + } + else if ( m_Params[i].StartsWith( "Keyword" ) ) + { + int indexOf = m_Params[i].IndexOf( '=' ); + + if ( indexOf >= 0 ) + tp.Keyword = Utility.ToInt32( m_Params[i].Substring( ++indexOf ) ); + } + else if ( m_Params[i].StartsWith( "Range" ) ) + { + int indexOf = m_Params[i].IndexOf( '=' ); + + if ( indexOf >= 0 ) + tp.Range = Utility.ToInt32( m_Params[i].Substring( ++indexOf ) ); + } + else if ( m_Params[i].StartsWith( "PointDest" ) ) + { + int indexOf = m_Params[i].IndexOf( '=' ); + + if ( indexOf >= 0 ) + tp.PointDest = Point3D.Parse( m_Params[i].Substring( ++indexOf ) ); + } + else if ( m_Params[i].StartsWith( "MapDest" ) ) + { + int indexOf = m_Params[i].IndexOf( '=' ); + + if ( indexOf >= 0 ) + tp.MapDest = Map.Parse( m_Params[i].Substring( ++indexOf ) ); + } + else if ( m_Params[i].StartsWith( "Creatures" ) ) + { + int indexOf = m_Params[i].IndexOf( '=' ); + + if ( indexOf >= 0 ) + tp.Creatures = Utility.ToBoolean( m_Params[i].Substring( ++indexOf ) ); + } + else if ( m_Params[i].StartsWith( "SourceEffect" ) ) + { + int indexOf = m_Params[i].IndexOf( '=' ); + + if ( indexOf >= 0 ) + tp.SourceEffect = Utility.ToBoolean( m_Params[i].Substring( ++indexOf ) ); + } + else if ( m_Params[i].StartsWith( "DestEffect" ) ) + { + int indexOf = m_Params[i].IndexOf( '=' ); + + if ( indexOf >= 0 ) + tp.DestEffect = Utility.ToBoolean( m_Params[i].Substring( ++indexOf ) ); + } + else if ( m_Params[i].StartsWith( "SoundID" ) ) + { + int indexOf = m_Params[i].IndexOf( '=' ); + + if ( indexOf >= 0 ) + tp.SoundID = Utility.ToInt32( m_Params[i].Substring( ++indexOf ) ); + } + else if ( m_Params[i].StartsWith( "Delay" ) ) + { + int indexOf = m_Params[i].IndexOf( '=' ); + + if ( indexOf >= 0 ) + tp.Delay = TimeSpan.Parse( m_Params[i].Substring( ++indexOf ) ); + } + } + + if ( m_ItemID > 0 ) + item.ItemID = m_ItemID; + } + else if ( item is Teleporter ) + { + Teleporter tp = (Teleporter)item; + + for ( int i = 0; i < m_Params.Length; ++i ) + { + if ( m_Params[i].StartsWith( "PointDest" ) ) + { + int indexOf = m_Params[i].IndexOf( '=' ); + + if ( indexOf >= 0 ) + tp.PointDest = Point3D.Parse( m_Params[i].Substring( ++indexOf ) ); + } + else if ( m_Params[i].StartsWith( "MapDest" ) ) + { + int indexOf = m_Params[i].IndexOf( '=' ); + + if ( indexOf >= 0 ) + tp.MapDest = Map.Parse( m_Params[i].Substring( ++indexOf ) ); + } + else if ( m_Params[i].StartsWith( "Creatures" ) ) + { + int indexOf = m_Params[i].IndexOf( '=' ); + + if ( indexOf >= 0 ) + tp.Creatures = Utility.ToBoolean( m_Params[i].Substring( ++indexOf ) ); + } + else if ( m_Params[i].StartsWith( "SourceEffect" ) ) + { + int indexOf = m_Params[i].IndexOf( '=' ); + + if ( indexOf >= 0 ) + tp.SourceEffect = Utility.ToBoolean( m_Params[i].Substring( ++indexOf ) ); + } + else if ( m_Params[i].StartsWith( "DestEffect" ) ) + { + int indexOf = m_Params[i].IndexOf( '=' ); + + if ( indexOf >= 0 ) + tp.DestEffect = Utility.ToBoolean( m_Params[i].Substring( ++indexOf ) ); + } + else if ( m_Params[i].StartsWith( "SoundID" ) ) + { + int indexOf = m_Params[i].IndexOf( '=' ); + + if ( indexOf >= 0 ) + tp.SoundID = Utility.ToInt32( m_Params[i].Substring( ++indexOf ) ); + } + else if ( m_Params[i].StartsWith( "Delay" ) ) + { + int indexOf = m_Params[i].IndexOf( '=' ); + + if ( indexOf >= 0 ) + tp.Delay = TimeSpan.Parse( m_Params[i].Substring( ++indexOf ) ); + } + } + + if ( m_ItemID > 0 ) + item.ItemID = m_ItemID; + } + else if ( item is moongates) // ADDED THIS TO MAKE MY OWN MOONGATES THAT CAN BE DECORATED // + { + moongates tp = (moongates)item; + + for ( int i = 0; i < m_Params.Length; ++i ) + { + if ( m_Params[i].StartsWith( "PointDest" ) ) + { + int indexOf = m_Params[i].IndexOf( '=' ); + + if ( indexOf >= 0 ) + tp.PointDest = Point3D.Parse( m_Params[i].Substring( ++indexOf ) ); + } + else if ( m_Params[i].StartsWith( "MapDest" ) ) + { + int indexOf = m_Params[i].IndexOf( '=' ); + + if ( indexOf >= 0 ) + tp.MapDest = Map.Parse( m_Params[i].Substring( ++indexOf ) ); + } + else if ( m_Params[i].StartsWith( "Creatures" ) ) + { + int indexOf = m_Params[i].IndexOf( '=' ); + + if ( indexOf >= 0 ) + tp.Creatures = Utility.ToBoolean( m_Params[i].Substring( ++indexOf ) ); + } + else if ( m_Params[i].StartsWith( "SourceEffect" ) ) + { + int indexOf = m_Params[i].IndexOf( '=' ); + + if ( indexOf >= 0 ) + tp.SourceEffect = Utility.ToBoolean( m_Params[i].Substring( ++indexOf ) ); + } + else if ( m_Params[i].StartsWith( "DestEffect" ) ) + { + int indexOf = m_Params[i].IndexOf( '=' ); + + if ( indexOf >= 0 ) + tp.DestEffect = Utility.ToBoolean( m_Params[i].Substring( ++indexOf ) ); + } + else if ( m_Params[i].StartsWith( "SoundID" ) ) + { + int indexOf = m_Params[i].IndexOf( '=' ); + + if ( indexOf >= 0 ) + tp.SoundID = Utility.ToInt32( m_Params[i].Substring( ++indexOf ) ); + } + else if ( m_Params[i].StartsWith( "Delay" ) ) + { + int indexOf = m_Params[i].IndexOf( '=' ); + + if ( indexOf >= 0 ) + tp.Delay = TimeSpan.Parse( m_Params[i].Substring( ++indexOf ) ); + } + } + + if ( m_ItemID > 0 ) + item.ItemID = m_ItemID; + } + else if ( m_ItemID > 0 ) + { + item.ItemID = m_ItemID; + } + + item.Movable = false; + + for ( int i = 0; i < m_Params.Length; ++i ) + { + if ( m_Params[i].StartsWith( "Light" ) ) + { + int indexOf = m_Params[i].IndexOf( '=' ); + + if ( indexOf >= 0 ) + item.Light = (LightType)Enum.Parse( typeof( LightType ), m_Params[i].Substring( ++indexOf ), true ); + } + else if ( m_Params[i].StartsWith( "Hue" ) ) + { + int indexOf = m_Params[i].IndexOf( '=' ); + + if ( indexOf >= 0 ) + { + int hue = Utility.ToInt32( m_Params[i].Substring( ++indexOf ) ); + + if ( item is DyeTub ) + ((DyeTub)item).DyedHue = hue; + else + item.Hue = hue; + } + } + else if ( m_Params[i].StartsWith( "Name" ) ) + { + int indexOf = m_Params[i].IndexOf( '=' ); + + if ( indexOf >= 0 ) + item.Name = m_Params[i].Substring( ++indexOf ); + } + else if ( m_Params[i].StartsWith( "Amount" ) ) + { + int indexOf = m_Params[i].IndexOf( '=' ); + + if ( indexOf >= 0 ) + { + // Must supress stackable warnings + + bool wasStackable = item.Stackable; + + item.Stackable = true; + item.Amount = Utility.ToInt32( m_Params[i].Substring( ++indexOf ) ); + item.Stackable = wasStackable; + } + } + } + + item.Weight = -3; + + return item; + } + + private static Queue m_DeleteQueue = new Queue(); + + private static bool FindItem( int x, int y, int z, Map map, Item srcItem ) + { + int itemID = srcItem.ItemID; + + bool res = false; + + IPooledEnumerable eable; + + if ( srcItem is BaseDoor ) + { + eable = map.GetItemsInRange( new Point3D( x, y, z ), 1 ); + + foreach ( Item item in eable ) + { + if ( !(item is BaseDoor) ) + continue; + + BaseDoor bd = (BaseDoor)item; + Point3D p; + int bdItemID; + + if ( bd.Open ) + { + p = new Point3D( bd.X - bd.Offset.X, bd.Y - bd.Offset.Y, bd.Z - bd.Offset.Z ); + bdItemID = bd.ClosedID; + } + else + { + p = bd.Location; + bdItemID = bd.ItemID; + } + + if ( p.X != x || p.Y != y ) + continue; + + if ( item.Z == z && bdItemID == itemID ) + res = true; + else if ( Math.Abs( item.Z - z ) < 8 ) + m_DeleteQueue.Enqueue( item ); + } + } + else if ( (TileData.ItemTable[itemID & TileData.MaxItemValue].Flags & TileFlag.LightSource) != 0 ) + { + eable = map.GetItemsInRange( new Point3D( x, y, z ), 0 ); + + LightType lt = srcItem.Light; + string srcName = srcItem.ItemData.Name; + + foreach ( Item item in eable ) + { + if ( item.Z == z ) + { + if ( item.ItemID == itemID ) + { + if ( item.Light != lt ) + m_DeleteQueue.Enqueue( item ); + else + res = true; + } + else if ( (item.ItemData.Flags & TileFlag.LightSource) != 0 && item.ItemData.Name == srcName ) + { + m_DeleteQueue.Enqueue( item ); + } + } + } + } + else if ( srcItem is Teleporter || srcItem is BaseBook ) + { + eable = map.GetItemsInRange( new Point3D( x, y, z ), 0 ); + + Type type = srcItem.GetType(); + + foreach ( Item item in eable ) + { + if ( item.Z == z && item.ItemID == itemID ) + { + if ( item.GetType() != type ) + m_DeleteQueue.Enqueue( item ); + else + res = true; + } + } + } + else + { + eable = map.GetItemsInRange( new Point3D( x, y, z ), 0 ); + + foreach ( Item item in eable ) + { + if ( item.Z == z && item.ItemID == itemID ) + { + eable.Free(); + return true; + } + } + } + + eable.Free(); + + while ( m_DeleteQueue.Count > 0 ) + ((Item)m_DeleteQueue.Dequeue()).Delete(); + + return res; + } + + public int Generate( Map[] maps ) + { + int count = 0; + + Item item = null; + + for ( int i = 0; i < m_Entries.Count; ++i ) + { + MonopoliesEntry entry = (MonopoliesEntry)m_Entries[i]; + Point3D loc = entry.Location; + string extra = entry.Extra; + + for ( int j = 0; j < maps.Length; ++j ) + { + if ( item == null ) + item = Construct(); + + if ( item == null ) + continue; + + if ( FindItem( loc.X, loc.Y, loc.Z, maps[j], item ) ) + { + } + else + { + item.MoveToWorld( loc, maps[j] ); + ++count; + + if ( item is BaseDoor ) + { + IPooledEnumerable eable = maps[j].GetItemsInRange( loc, 1 ); + + Type itemType = item.GetType(); + + foreach ( Item link in eable ) + { + if ( link != item && link.Z == item.Z && link.GetType() == itemType ) + { + ((BaseDoor)item).Link = (BaseDoor)link; + ((BaseDoor)link).Link = (BaseDoor)item; + break; + } + } + + eable.Free(); + } + + item = null; + } + } + } + + if ( item != null ) + item.Delete(); + + return count; + } + + public static ArrayList ReadAll( string path ) + { + using ( StreamReader ip = new StreamReader( path ) ) + { + ArrayList list = new ArrayList(); + + for ( MonopoliesList v = Read( ip ); v != null; v = Read( ip ) ) + list.Add( v ); + + return list; + } + } + + private static string[] m_EmptyParams = new string[0]; + + public static MonopoliesList Read( StreamReader ip ) + { + string line; + + while ( (line = ip.ReadLine()) != null ) + { + line = line.Trim(); + + if ( line.Length > 0 && !line.StartsWith( "#" ) ) + break; + } + + if ( string.IsNullOrEmpty( line ) ) + return null; + + MonopoliesList list = new MonopoliesList(); + + int indexOf = line.IndexOf( ' ' ); + + list.m_Type = ScriptCompiler.FindTypeByName( line.Substring( 0, indexOf++ ), true ); + + if ( list.m_Type == null ) + throw new ArgumentException( String.Format( "Type not found for header: '{0}'", line ) ); + + line = line.Substring( indexOf ); + indexOf = line.IndexOf( '(' ); + if ( indexOf >= 0 ) + { + list.m_ItemID = Utility.ToInt32( line.Substring( 0, indexOf - 1 ) ); + + string parms = line.Substring( ++indexOf ); + + if ( line.EndsWith( ")" ) ) + parms = parms.Substring( 0, parms.Length - 1 ); + + list.m_Params = parms.Split( ';' ); + + for ( int i = 0; i < list.m_Params.Length; ++i ) + list.m_Params[i] = list.m_Params[i].Trim(); + } + else + { + list.m_ItemID = Utility.ToInt32( line ); + list.m_Params = m_EmptyParams; + } + + list.m_Entries = new ArrayList(); + + while ( (line = ip.ReadLine()) != null ) + { + line = line.Trim(); + + if ( line.Length == 0 ) + break; + + if ( line.StartsWith( "#" ) ) + continue; + + list.m_Entries.Add( new MonopoliesEntry( line ) ); + } + + return list; + } + } + + public class MonopoliesEntry + { + private Point3D m_Location; + private string m_Extra; + + public Point3D Location{ get{ return m_Location; } } + public string Extra{ get{ return m_Extra; } } + + public MonopoliesEntry( string line ) + { + string x, y, z; + + Pop( out x, ref line ); + Pop( out y, ref line ); + Pop( out z, ref line ); + + m_Location = new Point3D( Utility.ToInt32( x ), Utility.ToInt32( y ), Utility.ToInt32( z ) ); + m_Extra = line; + } + + public void Pop( out string v, ref string line ) + { + int space = line.IndexOf( ' ' ); + + if ( space >= 0 ) + { + v = line.Substring( 0, space++ ); + line = line.Substring( space ); + } + else + { + v = line; + line = ""; + } + } + } +} \ No newline at end of file diff --git a/Scripts/Items/Houses/Monopoly/Gumps/Error Reporting/Errors.cs b/Scripts/Items/Houses/Monopoly/Gumps/Error Reporting/Errors.cs new file mode 100644 index 0000000..4b82b94 --- /dev/null +++ b/Scripts/Items/Houses/Monopoly/Gumps/Error Reporting/Errors.cs @@ -0,0 +1,69 @@ +using System; +using System.Collections; +using Server; +using Server.Network; + +namespace Knives.TownHouses +{ + public class Errors + { + private static ArrayList s_ErrorLog = new ArrayList(); + private static ArrayList s_Checked = new ArrayList(); + + public static ArrayList ErrorLog{ get{ return s_ErrorLog; } } + public static ArrayList Checked{ get{ return s_Checked; } } + + public static void Initialize() + { + RUOVersion.AddCommand("TownHouseErrors", AccessLevel.Counselor, new TownHouseCommandHandler(OnErrors)); + RUOVersion.AddCommand("the", AccessLevel.Counselor, new TownHouseCommandHandler(OnErrors)); + + EventSink.Login += new LoginEventHandler( OnLogin ); + } + + private static void OnErrors( CommandInfo e ) + { + if ( e.ArgString == null || e.ArgString == "" ) + new ErrorsGump( e.Mobile ); + else + Report( e.ArgString + " - " + e.Mobile.Name ); + } + + private static void OnLogin( LoginEventArgs e ) + { + if ( e.Mobile.AccessLevel != AccessLevel.Player + && s_ErrorLog.Count != 0 + && !s_Checked.Contains( e.Mobile ) ) + new ErrorsNotifyGump( e.Mobile ); + } + + public static void Report( string error ) + { + s_ErrorLog.Add( String.Format( "{0}
{1}
", DateTime.Now, error ) ); + + s_Checked.Clear(); + + Notify(); + } + + private static void Notify() + { + foreach( NetState state in NetState.Instances ) + { + if ( state.Mobile == null ) + continue; + + if ( state.Mobile.AccessLevel != AccessLevel.Player ) + Notify( state.Mobile ); + } + } + + public static void Notify( Mobile m ) + { + if ( m.HasGump( typeof( ErrorsGump ) ) ) + new ErrorsGump( m ); + else + new ErrorsNotifyGump( m ); + } + } +} \ No newline at end of file diff --git a/Scripts/Items/Houses/Monopoly/Gumps/Error Reporting/ErrorsGump.cs b/Scripts/Items/Houses/Monopoly/Gumps/Error Reporting/ErrorsGump.cs new file mode 100644 index 0000000..645e308 --- /dev/null +++ b/Scripts/Items/Houses/Monopoly/Gumps/Error Reporting/ErrorsGump.cs @@ -0,0 +1,55 @@ +using System; +using Server; + +namespace Knives.TownHouses +{ + public class ErrorsGump : GumpPlusLight + { + public ErrorsGump( Mobile m ) : base( m, 100, 100 ) + { + Errors.Checked.Add(m); + + m.CloseGump( typeof( ErrorsGump ) ); + } + + protected override void BuildGump() + { + int width = 400; + int y = 10; + + AddHtml(0, y, width, "
TownHouse Errors"); + AddImage(width / 2 - 100, y + 2, 0x39); + AddImage(width / 2 + 70, y + 2, 0x3B); + + AddButton(width - 20, y, 0x5689, 0x5689, "Help", new GumpCallback(Help)); + + string str = HTML.Black; + foreach( string text in Errors.ErrorLog ) + str += text; + + AddHtml( 20, y+=25, width-40, 200, str, true, true ); + + y += 200; + + if ( Owner.AccessLevel >= AccessLevel.Administrator ) + { + AddButton( width/2-30, y+=10, 0x98B, 0x98B, "Clear", new GumpCallback( ClearLog ) ); + AddHtml( width/2-23, y+3, 51, "
Clear"); + } + + AddBackgroundZero(0, 0, width, y + 40, 0x1400); + } + + private void Help() + { + NewGump(); + new InfoGump( Owner, 300, 300, HTML.White + " Errors reported by either the TownHouse system or other staff members! Administrators have the power to clear this list. All staff members can report an error using the [TownHouseErrors command.", true ); + } + + private void ClearLog() + { + Errors.ErrorLog.Clear(); + NewGump(); + } + } +} \ No newline at end of file diff --git a/Scripts/Items/Houses/Monopoly/Gumps/Error Reporting/ErrorsNotifyGump.cs b/Scripts/Items/Houses/Monopoly/Gumps/Error Reporting/ErrorsNotifyGump.cs new file mode 100644 index 0000000..786b85d --- /dev/null +++ b/Scripts/Items/Houses/Monopoly/Gumps/Error Reporting/ErrorsNotifyGump.cs @@ -0,0 +1,24 @@ +using System; +using Server; + +namespace Knives.TownHouses +{ + public class ErrorsNotifyGump : GumpPlusLight + { + public ErrorsNotifyGump( Mobile m ) : base( m, 250, 100 ) + { + m.CloseGump( typeof( ErrorsNotifyGump ) ); + } + + protected override void BuildGump() + { + AddButton( 0, 0, 0x1590, 0x1590, "Errors", new GumpCallback( Errors ) ); + AddItem(20, 20, 0x22C4); + } + + private void Errors() + { + new ErrorsGump( Owner ); + } + } +} \ No newline at end of file diff --git a/Scripts/Items/Houses/Monopoly/Gumps/Gumps Plus Light/BackgroundPlus.cs b/Scripts/Items/Houses/Monopoly/Gumps/Gumps Plus Light/BackgroundPlus.cs new file mode 100644 index 0000000..99fdc3b --- /dev/null +++ b/Scripts/Items/Houses/Monopoly/Gumps/Gumps Plus Light/BackgroundPlus.cs @@ -0,0 +1,23 @@ +using System; +using Server; +using Server.Gumps; + +namespace Knives.TownHouses +{ + public class BackgroundPlus : GumpBackground + { + private bool c_Override; + + public bool Override{ get{ return c_Override; } set{ c_Override = value; } } + + public BackgroundPlus( int x, int y, int width, int height, int back ) : base( x, y, width, height, back ) + { + c_Override = true; + } + + public BackgroundPlus( int x, int y, int width, int height, int back, bool over ) : base( x, y, width, height, back ) + { + c_Override = over; + } + } +} \ No newline at end of file diff --git a/Scripts/Items/Houses/Monopoly/Gumps/Gumps Plus Light/ButtonPlus.cs b/Scripts/Items/Houses/Monopoly/Gumps/Gumps Plus Light/ButtonPlus.cs new file mode 100644 index 0000000..ca1fbcc --- /dev/null +++ b/Scripts/Items/Houses/Monopoly/Gumps/Gumps Plus Light/ButtonPlus.cs @@ -0,0 +1,37 @@ +using System; +using Server; +using Server.Gumps; + +namespace Knives.TownHouses +{ + public class ButtonPlus : GumpButton + { + private string c_Name; + private object c_Callback; + private object c_Param; + + public string Name{ get{ return c_Name; } } + + public ButtonPlus( int x, int y, int normalID, int pressedID, int buttonID, string name, GumpCallback back ) : base( x, y, normalID, pressedID, buttonID, GumpButtonType.Reply, 0 ) + { + c_Name = name; + c_Callback = back; + c_Param = ""; + } + + public ButtonPlus( int x, int y, int normalID, int pressedID, int buttonID, string name, GumpStateCallback back, object param ) : base( x, y, normalID, pressedID, buttonID, GumpButtonType.Reply, 0 ) + { + c_Name = name; + c_Callback = back; + c_Param = param; + } + + public void Invoke() + { + if ( c_Callback is GumpCallback ) + ((GumpCallback)c_Callback)(); + else if ( c_Callback is GumpStateCallback ) + ((GumpStateCallback)c_Callback)( c_Param ); + } + } +} \ No newline at end of file diff --git a/Scripts/Items/Houses/Monopoly/Gumps/Gumps Plus Light/GumpPlusLight.cs b/Scripts/Items/Houses/Monopoly/Gumps/Gumps Plus Light/GumpPlusLight.cs new file mode 100644 index 0000000..1d8a1e8 --- /dev/null +++ b/Scripts/Items/Houses/Monopoly/Gumps/Gumps Plus Light/GumpPlusLight.cs @@ -0,0 +1,261 @@ +using System; +using System.Collections; +using Server; +using Server.Gumps; +using Server.Network; + +namespace Knives.TownHouses +{ + public delegate void GumpStateCallback(object obj); + public delegate void GumpCallback(); + + public abstract class GumpPlusLight : Gump + { + public static void RefreshGump(Mobile m, Type type) + { + if (m.NetState == null) + return; + + foreach (Gump g in m.NetState.Gumps) + if (g is GumpPlusLight && g.GetType() == type) + { + m.CloseGump(type); + ((GumpPlusLight)g).NewGump(); + return; + } + } + + private Mobile c_Owner; + private Hashtable c_Buttons, c_Fields; + + public Mobile Owner{ get{ return c_Owner; } } + + public GumpPlusLight( Mobile m, int x, int y ) : base( x, y ) + { + c_Owner = m; + + c_Buttons = new Hashtable(); + c_Fields = new Hashtable(); + + Timer.DelayCall(TimeSpan.FromSeconds(0), new TimerCallback(NewGump)); + } + + public void Clear() + { + Entries.Clear(); + c_Buttons.Clear(); + c_Fields.Clear(); + } + + public virtual void NewGump() + { + NewGump( true ); + } + + public void NewGump( bool clear ) + { + if ( clear ) + Clear(); + + BuildGump(); + + c_Owner.SendGump( this ); + } + + public void SameGump() + { + c_Owner.SendGump( this ); + } + + protected abstract void BuildGump(); + + private int UniqueButton() + { + int random = 0; + + do + { + random = Utility.Random( 20000 ); + + }while( c_Buttons[random] != null ); + + return random; + } + + private int UniqueTextId() + { + int random = 0; + + do + { + random = Utility.Random(20000); + + } while (c_Buttons[random] != null); + + return random; + } + + public void AddBackgroundZero(int x, int y, int width, int height, int back) + { + AddBackgroundZero(x, y, width, height, back, true); + } + + public void AddBackgroundZero(int x, int y, int width, int height, int back, bool over) + { + BackgroundPlus plus = new BackgroundPlus(x, y, width, height, back, over); + + Entries.Insert(0, plus); + } + + public new void AddBackground(int x, int y, int width, int height, int back) + { + AddBackground(x, y, width, height, back, true); + } + + public void AddBackground(int x, int y, int width, int height, int back, bool over) + { + BackgroundPlus plus = new BackgroundPlus(x, y, width, height, back, over); + + Add(plus); + } + + public void AddButton(int x, int y, int id, GumpCallback callback) + { + AddButton(x, y, id, id, "None", callback); + } + + public void AddButton(int x, int y, int id, GumpStateCallback callback, object arg) + { + AddButton(x, y, id, id, "None", callback, arg); + } + + public void AddButton(int x, int y, int id, string name, GumpCallback callback) + { + AddButton(x, y, id, id, name, callback); + } + + public void AddButton(int x, int y, int id, string name, GumpStateCallback callback, object arg) + { + AddButton(x, y, id, id, name, callback, arg); + } + + public void AddButton(int x, int y, int up, int down, GumpCallback callback) + { + AddButton(x, y, up, down, "None", callback); + } + + public void AddButton(int x, int y, int up, int down, string name, GumpCallback callback) + { + int id = UniqueButton(); + + ButtonPlus button = new ButtonPlus( x, y, up, down, id, name, callback ); + + Add( button ); + + c_Buttons[id] = button; + } + + public void AddButton( int x, int y, int up, int down, GumpStateCallback callback, object arg ) + { + AddButton( x, y, up, down, "None", callback, arg ); + } + + public void AddButton( int x, int y, int up, int down, string name, GumpStateCallback callback, object arg ) + { + int id = UniqueButton(); + + ButtonPlus button = new ButtonPlus( x, y, up, down, id, name, callback, arg ); + + Add( button ); + + c_Buttons[id] = button; + } + + public void AddHtml(int x, int y, int width, string text) + { + AddHtml(x, y, width, 21, HTML.White + text, false, false, true, false); + } + + public void AddHtml(int x, int y, int width, string text, bool over) + { + AddHtml(x, y, width, 21, HTML.White + text, false, false, over, false); + } + + public void AddHtml(int x, int y, int width, int height, string text, bool back, bool scroll) + { + AddHtml(x, y, width, height, HTML.White + text, back, scroll, false); + } + + public void AddHtml(int x, int y, int width, int height, string text, bool back, bool scroll, bool over, bool useBlackTextOutline = false) + { + HtmlPlus html = new HtmlPlus(x, y, width, height, HTML.White + text, back, scroll, over); + + Add(html); + } + + public void AddTextField(int x, int y, int width, int height, int color, int back, string name, string text) + { + int id = UniqueTextId(); + + AddImageTiled(x, y, width, height, back); + base.AddTextEntry(x, y, width, height, color, id, text); + + c_Fields[id] = name; + c_Fields[name] = text; + } + + public string GetTextField( string name ) + { + if ( c_Fields[name] == null ) + return ""; + + return c_Fields[name].ToString(); + } + + public int GetTextFieldInt(string name) + { + return Utility.ToInt32(GetTextField(name)); + } + + protected virtual void OnClose() + { + } + + public override void OnResponse( NetState state, RelayInfo info ) + { + string name = ""; + + try + { + if (info.ButtonID == -5) + { + NewGump(); + return; + } + + foreach (TextRelay t in info.TextEntries) + c_Fields[c_Fields[t.EntryID].ToString()] = t.Text; + + if (info.ButtonID == 0) + OnClose(); + + if (c_Buttons[info.ButtonID] == null || !(c_Buttons[info.ButtonID] is ButtonPlus)) + return; + + name = ((ButtonPlus)c_Buttons[info.ButtonID]).Name; + + ((ButtonPlus)c_Buttons[info.ButtonID]).Invoke(); + + } + catch (Exception e) + { + Errors.Report("An error occured during a gump response. More information can be found on the console."); + if (name != "") + Console.WriteLine("{0} gump name triggered an error.", name); + Console.WriteLine(e.Message); + Console.WriteLine(e.Source); + Console.WriteLine(e.StackTrace); + } + } + } +} \ No newline at end of file diff --git a/Scripts/Items/Houses/Monopoly/Gumps/Gumps Plus Light/HTML.cs b/Scripts/Items/Houses/Monopoly/Gumps/Gumps Plus Light/HTML.cs new file mode 100644 index 0000000..f5f5a4e --- /dev/null +++ b/Scripts/Items/Houses/Monopoly/Gumps/Gumps Plus Light/HTML.cs @@ -0,0 +1,20 @@ +using System; +using Server; + +namespace Knives.TownHouses +{ + public class HTML + { + public static string White{ get { return ""; } } + public static string Red{ get { return ""; } } + public static string AshRed{ get { return ""; } } + public static string Green{ get { return ""; } } + public static string Blue{ get { return ""; } } + public static string Gray{ get { return ""; } } + public static string DarkGray{ get { return ""; } } + public static string Black{ get { return ""; } } + public static string Yellow{ get { return ""; } } + public static string Purple{ get { return ""; } } + public static string LightPurple{ get { return ""; } } + } +} \ No newline at end of file diff --git a/Scripts/Items/Houses/Monopoly/Gumps/Gumps Plus Light/HtmlPlus.cs b/Scripts/Items/Houses/Monopoly/Gumps/Gumps Plus Light/HtmlPlus.cs new file mode 100644 index 0000000..52ba38b --- /dev/null +++ b/Scripts/Items/Houses/Monopoly/Gumps/Gumps Plus Light/HtmlPlus.cs @@ -0,0 +1,23 @@ +using System; +using Server; +using Server.Gumps; + +namespace Knives.TownHouses +{ + public class HtmlPlus : GumpHtml + { + private bool c_Override; + + public bool Override{ get{ return c_Override; } set{ c_Override = value; } } + + public HtmlPlus( int x, int y, int width, int height, string text, bool back, bool scroll ) : base( x, y, width, height, text, back, scroll ) + { + c_Override = true; + } + + public HtmlPlus( int x, int y, int width, int height, string text, bool back, bool scroll, bool over ) : base( x, y, width, height, text, back, scroll ) + { + c_Override = over; + } + } +} \ No newline at end of file diff --git a/Scripts/Items/Houses/Monopoly/Gumps/Gumps Plus Light/InfoGump.cs b/Scripts/Items/Houses/Monopoly/Gumps/Gumps Plus Light/InfoGump.cs new file mode 100644 index 0000000..fb3bf90 --- /dev/null +++ b/Scripts/Items/Houses/Monopoly/Gumps/Gumps Plus Light/InfoGump.cs @@ -0,0 +1,30 @@ +using System; +using Server; +using Server.Gumps; + +namespace Knives.TownHouses +{ + public class InfoGump : GumpPlusLight + { + private int c_Width, c_Height; + private string c_Text; + private bool c_Scroll; + + public InfoGump( Mobile m, int width, int height, string text, bool scroll ) : base( m, 100, 100 ) + { + c_Width = width; + c_Height = height; + c_Text= text; + c_Scroll = scroll; + + NewGump(); + } + + protected override void BuildGump() + { + AddBackground( 0, 0, c_Width, c_Height, 3600 ); + + AddHtml( 20, 20, c_Width-40, c_Height-40, HTML.White + c_Text, false, c_Scroll ); + } + } +} diff --git a/Scripts/Items/Houses/Monopoly/Gumps/TownHouse Gumps/ContractConfirmGump.cs b/Scripts/Items/Houses/Monopoly/Gumps/TownHouse Gumps/ContractConfirmGump.cs new file mode 100644 index 0000000..a80179f --- /dev/null +++ b/Scripts/Items/Houses/Monopoly/Gumps/TownHouse Gumps/ContractConfirmGump.cs @@ -0,0 +1,117 @@ +using System; +using Server; + +namespace Knives.TownHouses +{ + public class ContractConfirmGump : GumpPlusLight + { + private RentalContract c_Contract; + + public ContractConfirmGump( Mobile m, RentalContract rc ) : base( m, 100, 100 ) + { + m.CloseGump( typeof( ContractConfirmGump ) ); + + c_Contract = rc; + } + + protected override void BuildGump() + { + int width = 300; + int y = 0; + + if ( c_Contract.RentalClient == null ) + AddHtml( 0, y+5, width, HTML.Black + "
Rent this House?"); + else + AddHtml( 0, y+5, width, HTML.Black + "
Rental Agreement"); + + string text = String.Format( " I, {0}, agree to rent this property from {1} for the sum of {2} every {3}. " + + "The funds for this payment will be taken directly from my bank. In the case where " + + "I cannot pay this fee, the property will return to {1}. I may cancel this agreement at any time by " + + "demolishing the property. {1} may also cancel this agreement at any time by either demolishing their " + + "property or canceling the contract, in which case your security deposit will be returned.", + c_Contract.RentalClient == null ? "_____" : c_Contract.RentalClient.Name, + c_Contract.RentalMaster.Name, + c_Contract.Free ? 0 : c_Contract.Price, + c_Contract.PriceTypeShort.ToLower() ); + + text += "
Here is some more info reguarding this property:
"; + + text += String.Format( "
Lockdowns: {0}
", c_Contract.Locks ); + text += String.Format( "Secures: {0}
", c_Contract.Secures ); + text += String.Format( "Floors: {0}
", (c_Contract.MaxZ-c_Contract.MinZ < 200) ? (c_Contract.MaxZ-c_Contract.MinZ)/20+1 : 1 ); + text += String.Format( "Space: {0} cubic units", c_Contract.CalcVolume() ); + + AddHtml( 40, y+=30, width-60, 200, HTML.Black + text, false, true ); + + y += 200; + + if ( c_Contract.RentalClient == null ) + { + AddHtml( 60, y+=20, 60, HTML.Black + "Preview"); + AddButton( 40, y+3, 0x837, 0x838, "Preview", new GumpCallback( Preview ) ); + + bool locsec = c_Contract.ValidateLocSec(); + + if ( Owner != c_Contract.RentalMaster && locsec ) + { + AddHtml( width-100, y, 60, HTML.Black + "Accept"); + AddButton( width-60, y+3, 0x232C, 0x232D, "Accept", new GumpCallback( Accept ) ); + } + else + AddImage( width-60, y-10, 0x232C ); + + if ( !locsec ) + Owner.SendMessage( (Owner == c_Contract.RentalMaster ? "You don't have the lockdowns or secures available for this contract." : "The owner of this contract cannot rent this property at this time.") ); + } + else + { + if ( Owner == c_Contract.RentalMaster ) + { + AddHtml( 60, y+=20, 100, HTML.Black + "Cancel Contract"); + AddButton( 40, y+3, 0x837, 0x838, "Cancel Contract", new GumpCallback( CancelContract ) ); + } + else + AddImage( width-60, y+=20, 0x232C ); + } + + AddBackgroundZero( 0, 0, width, y+23, 0x24A4 ); + } + + protected override void OnClose() + { + c_Contract.ClearPreview(); + } + + private void Preview() + { + c_Contract.ShowAreaPreview(Owner); + NewGump(); + } + + private void CancelContract() + { + if ( Owner == c_Contract.RentalClient ) + c_Contract.House.Delete(); + else + c_Contract.Delete(); + } + + private void Accept() + { + if ( !c_Contract.ValidateLocSec() ) + { + Owner.SendMessage( "The owner of this contract cannot rent this property at this time." ); + return; + } + + c_Contract.Purchase( Owner ); + + if ( !c_Contract.Owned ) + return; + + c_Contract.Visible = true; + c_Contract.RentalClient = Owner; + c_Contract.RentalClient.AddToBackpack( new RentalContractCopy( c_Contract ) ); + } + } +} \ No newline at end of file diff --git a/Scripts/Items/Houses/Monopoly/Gumps/TownHouse Gumps/ContractSetupGump.cs b/Scripts/Items/Houses/Monopoly/Gumps/TownHouse Gumps/ContractSetupGump.cs new file mode 100644 index 0000000..e2ae229 --- /dev/null +++ b/Scripts/Items/Houses/Monopoly/Gumps/TownHouse Gumps/ContractSetupGump.cs @@ -0,0 +1,560 @@ +using System; +using System.Collections; +using Server; +using Server.Targeting; + +namespace Knives.TownHouses +{ + public class ContractSetupGump : GumpPlusLight + { + public enum Page { Blocks, Floors, Sign, LocSec, Length, Price } + public enum TargetType { SignLoc, MinZ, MaxZ, BlockOne, BlockTwo } + + private RentalContract c_Contract; + private Page c_Page; + + public ContractSetupGump( Mobile m, RentalContract contract ) : base( m, 50, 50 ) + { + m.CloseGump( typeof( ContractSetupGump ) ); + + c_Contract = contract; + } + + protected override void BuildGump() + { + int width = 300; + int y = 0; + + switch( c_Page ) + { + case Page.Blocks: BlocksPage(width, ref y); break; + case Page.Floors: FloorsPage(width, ref y); break; + case Page.Sign: SignPage(width, ref y); break; + case Page.LocSec: LocSecPage(width, ref y); break; + case Page.Length: LengthPage(width, ref y); break; + case Page.Price: PricePage(width, ref y); break; + } + + AddBackgroundZero(0, 0, width, y+40, 3600); + } + + private void BlocksPage(int width, ref int y) + { + if ( c_Contract == null ) + return; + + c_Contract.ShowAreaPreview( Owner ); + + AddHtml( 0, y+=10, width, "
Create the Area"); + AddImage(width / 2 - 100, y + 2, 0x39); + AddImage(width / 2 + 70, y + 2, 0x3B); + + y+=25; + + if ( !General.HasOtherContract( c_Contract.ParentHouse, c_Contract ) ) + { + AddHtml( 60, y, 90, "Entire House"); + AddButton( 30, y, c_Contract.EntireHouse ? 0xD3 : 0xD2, "Entire House", new GumpCallback(EntireHouse )); + } + + if ( !c_Contract.EntireHouse ) + { + AddHtml( 170, y, 70, "Add Area"); + AddButton( 240, y, 0x15E1, 0x15E5, "Add Area", new GumpCallback( AddBlock ) ); + + AddHtml( 170, y+=20, 70, "Clear All"); + AddButton( 240, y, 0x15E1, 0x15E5, "Clear All", new GumpCallback( ClearBlocks ) ); + } + + string helptext = String.Format( " Welcome to the rental contract setup menu! To begin, you must " + + "first create the area which you wish to sell. As seen above, there are two ways to do this: " + + "rent the entire house, or parts of it. As you create the area, a simple preview will show you exactly " + + "what area you've selected so far. You can make all sorts of odd shapes by using multiple areas!" ); + + AddHtml( 10, y+=35, width-20, 170, helptext, false, false ); + + y += 170; + + if ( c_Contract.EntireHouse || c_Contract.Blocks.Count != 0 ) + { + AddHtml( width-60, y+=20, 60, "Next"); + AddButton( width-30, y, 0x15E1, 0x15E5, "Next", new GumpStateCallback( ChangePage ), (int)c_Page + ( c_Contract.EntireHouse ? 4 : 1 ) ); + } + } + + private void FloorsPage(int width, ref int y) + { + AddHtml( 0, y+=10, width, "
Floors"); + AddImage(width / 2 - 100, y + 2, 0x39); + AddImage(width / 2 + 70, y + 2, 0x3B); + + AddHtml( 40, y+=25, 80, "Base Floor"); + AddButton( 110, y, 0x15E1, 0x15E5, "Base Floor", new GumpCallback( MinZSelect ) ); + + AddHtml( 160, y, 80, "Top Floor"); + AddButton( 230, y, 0x15E1, 0x15E5, "Top Floor", new GumpCallback( MaxZSelect ) ); + + AddHtml( 100, y+=25, 100, String.Format( "{0} total floor{1}", c_Contract.Floors > 10 ? "1" : "" + c_Contract.Floors, c_Contract.Floors == 1 || c_Contract.Floors > 10 ? "" : "s" )); + + string helptext = String.Format( " Now you will need to target the floors you wish to rent out. " + + "If you only want one floor, you can skip targeting the top floor. Everything within the base " + + "and highest floor will come with the rental, and the more floors, the higher the cost later on." ); + + AddHtml( 10, y+=35, width-20, 120, helptext, false, false ); + + y += 120; + + AddHtml( 30, y+=20, 80, "Previous"); + AddButton( 10, y, 0x15E3, 0x15E7, "Previous", new GumpStateCallback( ChangePage ), (int)c_Page-1 ); + + if ( c_Contract.MinZ != short.MinValue ) + { + AddHtml( width-60, y, 60, "Next"); + AddButton( width-30, y, 0x15E1, 0x15E5, "Next", new GumpStateCallback( ChangePage ), (int)c_Page+1 ); + } + } + + private void SignPage(int width, ref int y) + { + if ( c_Contract == null ) + return; + + c_Contract.ShowSignPreview(); + + AddHtml( 0, y+=10, width, "
Their Sign Location"); + AddImage(width / 2 - 100, y + 2, 0x39); + AddImage(width / 2 + 70, y + 2, 0x3B); + + AddHtml( 100, y+=25, 80, "Set Location"); + AddButton( 180, y, 0x15E1, 0x15E5, "Sign Loc", new GumpCallback( SignLocSelect ) ); + + string helptext = String.Format( " With this sign, the rentee will have all the powers an owner has " + + "over their area. If they use this power to demolish their rental unit, they have broken their " + + "contract and will not receive their security deposit. They can also ban you from their rental home!" ); + + AddHtml( 10, y+=35, width-20, 110, helptext, false, false ); + + y += 110; + + AddHtml( 30, y+=20, 80, "Previous"); + AddButton( 10, y, 0x15E3, 0x15E7, "Previous", new GumpStateCallback( ChangePage ), (int)c_Page-1 ); + + if ( c_Contract.SignLoc != Point3D.Zero ) + { + AddHtml( width-60, y, 60, "Next"); + AddButton( width-30, y, 0x15E1, 0x15E5, "Next", new GumpStateCallback( ChangePage ), (int)c_Page+1 ); + } + } + + private void LocSecPage(int width, ref int y) + { + AddHtml( 0, y+=10, width, "
Lockdowns and Secures"); + AddImage(width / 2 - 100, y + 2, 0x39); + AddImage(width / 2 + 70, y + 2, 0x3B); + + AddHtml(0, y += 25, width, "
Suggest Secures"); + AddButton(width / 2 - 70, y + 3, 0x2716, "Suggest LocSec", new GumpCallback(SuggestLocSec)); + AddButton(width / 2 + 60, y + 3, 0x2716, "Suggest LocSec", new GumpCallback(SuggestLocSec)); + + AddHtml(30, y += 25, width / 2 - 20, "
Secures (Max: " + (General.RemainingSecures(c_Contract.ParentHouse) + c_Contract.Secures) + ")"); + AddTextField( width/2+50, y, 50, 20, 0x480, 0xBBC, "Secures", c_Contract.Secures.ToString() ); + AddButton(width / 2 + 25, y + 3, 0x2716, "Secures", new GumpCallback(Secures)); + + AddHtml(30, y += 20, width / 2 - 20, "
Lockdowns (Max: " + (General.RemainingLocks(c_Contract.ParentHouse) + c_Contract.Locks) + ")"); + AddTextField( width/2+50, y, 50, 20, 0x480, 0xBBC, "Lockdowns", c_Contract.Locks.ToString() ); + AddButton(width / 2 + 25, y + 3, 0x2716, "Lockdowns", new GumpCallback(Lockdowns)); + + string helptext = String.Format( " Without giving storage, this wouldn't be much of a home! Here you give them lockdowns " + + "and secures from your own home. Use the suggest button for an idea of how much you should give. Be very careful when " + + "renting your property: if you use too much storage you begin to use storage you reserved for your clients. " + + "You will receive a 48 hour warning when this happens, but after that the contract disappears!" ); + + AddHtml( 10, y+=35, width-20, 180, helptext, false, false ); + + y += 180; + + AddHtml( 30, y+=20, 80, "Previous"); + AddButton( 10, y, 0x15E3, 0x15E7, "Previous", new GumpStateCallback( ChangePage ), (int)c_Page-1 ); + + if ( c_Contract.Locks != 0 && c_Contract.Secures != 0 ) + { + AddHtml( width-60, y, 60, "Next"); + AddButton( width-30, y, 0x15E1, 0x15E5, "Next", new GumpStateCallback( ChangePage ), (int)c_Page+1 ); + } + } + + private void LengthPage(int width, ref int y) + { + AddHtml( 0, y+=10, width, "
Time Period"); + AddImage(width / 2 - 100, y + 2, 0x39); + AddImage(width / 2 + 70, y + 2, 0x3B); + + AddHtml( 120, y+=25, 50, c_Contract.PriceType); + AddButton( 170, y+8, 0x985, "LengthUp", new GumpCallback( LengthUp ) ); + AddButton( 170, y-2, 0x983, "LengthDown", new GumpCallback( LengthDown ) ); + + string helptext = String.Format( " Every {0} the bank will automatically transfer the rental cost from them to you. " + + "By using the arrows, you can cycle through other time periods to something better fitting your needs.", c_Contract.PriceTypeShort.ToLower() ); + + AddHtml( 10, y+=35, width-20, 100, helptext, false, false ); + + y += 100; + + AddHtml( 30, y+=20, 80, "Previous"); + AddButton( 10, y, 0x15E3, 0x15E7, "Previous", new GumpStateCallback( ChangePage ), (int)c_Page - ( c_Contract.EntireHouse ? 4 : 1 ) ); + + AddHtml( width-60, y, 60, "Next"); + AddButton( width-30, y, 0x15E1, 0x15E5, "Next", new GumpStateCallback( ChangePage ), (int)c_Page+1 ); + } + + private void PricePage(int width, ref int y) + { + AddHtml( 0, y+=10, width, "
Charge Per Period"); + AddImage(width / 2 - 100, y + 2, 0x39); + AddImage(width / 2 + 70, y + 2, 0x3B); + + AddHtml(0, y += 25, width, "
Free"); + AddButton(width / 2 - 80, y, c_Contract.Free ? 0xD3 : 0xD2, "Free", new GumpCallback(Free)); + AddButton(width / 2 + 60, y, c_Contract.Free ? 0xD3 : 0xD2, "Free", new GumpCallback(Free)); + + if ( !c_Contract.Free ) + { + AddHtml( 0, y+=25, width/2-20, "
Per " + c_Contract.PriceTypeShort); + AddTextField( width/2+20, y, 70, 20, 0x480, 0xBBC, "Price", c_Contract.Price.ToString() ); + AddButton(width / 2 - 5, y + 3, 0x2716, "Price", new GumpCallback(Price)); + + AddHtml( 0, y+=20, width, "
Suggest"); + AddButton(width / 2 - 70, y + 3, 0x2716, "Suggest", new GumpCallback(SuggestPrice)); + AddButton(width / 2 + 60, y + 3, 0x2716, "Suggest", new GumpCallback(SuggestPrice)); + } + + string helptext = String.Format( " Now you can finalize the contract by including your price per {0}. " + + "Once you finalize, the only way you can modify it is to dump it and start a new contract! By " + + "using the suggest button, a price will automatically be figured based on the following:
", c_Contract.PriceTypeShort ); + + helptext += String.Format( "
Volume: {0}
", c_Contract.CalcVolume() ); + helptext += String.Format( "Cost per unit: {0} gold
", General.SuggestionFactor ); + helptext += "
You may also give this space away for free using the option above."; + + AddHtml( 10, y+=35, width-20, 150, helptext, false, true ); + + y += 150; + + AddHtml( 30, y+=20, 80, "Previous"); + AddButton( 10, y, 0x15E3, 0x15E7, "Previous", new GumpStateCallback( ChangePage ), (int)c_Page-1 ); + + if ( c_Contract.Price != 0 ) + { + AddHtml( width-70, y, 60, "Finalize"); + AddButton( width-30, y, 0x15E1, 0x15E5, "Finalize", new GumpCallback( FinalizeSetup ) ); + } + } + + protected override void OnClose() + { + c_Contract.ClearPreview(); + } + + private void SuggestPrice() + { + if ( c_Contract == null ) + return; + + c_Contract.Price = c_Contract.CalcVolume()*General.SuggestionFactor; + + if ( c_Contract.RentByTime == TimeSpan.FromDays( 1 ) ) + c_Contract.Price /= 60; + if ( c_Contract.RentByTime == TimeSpan.FromDays( 7 ) ) + c_Contract.Price = (int)((double)c_Contract.Price/8.57); + if ( c_Contract.RentByTime == TimeSpan.FromDays( 30 ) ) + c_Contract.Price /= 2; + + NewGump(); + } + + private void SuggestLocSec() + { + int price = c_Contract.CalcVolume()*General.SuggestionFactor; + c_Contract.Secures = price/75; + c_Contract.Locks = c_Contract.Secures/2; + + c_Contract.FixLocSec(); + + NewGump(); + } + + private void Price() + { + c_Contract.Price = GetTextFieldInt("Price"); + Owner.SendMessage("Price set!"); + NewGump(); + } + + private void Secures() + { + c_Contract.Secures = GetTextFieldInt("Secures"); + Owner.SendMessage("Secures set!"); + NewGump(); + } + + private void Lockdowns() + { + c_Contract.Locks = GetTextFieldInt("Lockdowns"); + Owner.SendMessage("Lockdowns set!"); + NewGump(); + } + + private void ChangePage(object obj) + { + if ( c_Contract == null || !(obj is int) ) + return; + + c_Contract.ClearPreview(); + + c_Page = (Page)(int)obj; + + NewGump(); + } + + private void EntireHouse() + { + if ( c_Contract == null || c_Contract.ParentHouse == null ) + return; + + c_Contract.EntireHouse = !c_Contract.EntireHouse; + + c_Contract.ClearPreview(); + + if ( c_Contract.EntireHouse ) + { + ArrayList list = new ArrayList(); + + bool once = false; + foreach (Rectangle3D rect in RUOVersion.RegionArea(c_Contract.ParentHouse.Region)) + { + list.Add(new Rectangle2D(new Point2D(rect.Start.X, rect.Start.Y), new Point2D(rect.End.X, rect.End.Y))); + + if (once) + continue; + + if (rect.Start.Z >= rect.End.Z) + { + c_Contract.MinZ = rect.End.Z; + c_Contract.MaxZ = rect.Start.Z; + } + else + { + c_Contract.MinZ = rect.Start.Z; + c_Contract.MaxZ = rect.End.Z; + } + + once = true; + } + + c_Contract.Blocks = list; + } + else + { + c_Contract.Blocks.Clear(); + c_Contract.MinZ = short.MinValue; + c_Contract.MaxZ = short.MinValue; + } + + NewGump(); + } + + private void SignLocSelect() + { + Owner.Target = new InternalTarget( this, c_Contract, TargetType.SignLoc ); + } + + private void MinZSelect() + { + Owner.SendMessage( "Target the base floor for your rental area." ); + Owner.Target = new InternalTarget( this, c_Contract, TargetType.MinZ ); + } + + private void MaxZSelect() + { + Owner.SendMessage( "Target the highest floor for your rental area." ); + Owner.Target = new InternalTarget( this, c_Contract, TargetType.MaxZ ); + } + + private void LengthUp() + { + if ( c_Contract == null ) + return; + + c_Contract.NextPriceType(); + + if ( c_Contract.RentByTime == TimeSpan.FromDays( 0 ) ) + c_Contract.RentByTime = TimeSpan.FromDays( 1 ); + + NewGump(); + } + + private void LengthDown() + { + if ( c_Contract == null ) + return; + + c_Contract.PrevPriceType(); + + if ( c_Contract.RentByTime == TimeSpan.FromDays( 0 ) ) + c_Contract.RentByTime = TimeSpan.FromDays( 30 ); + + NewGump(); + } + + private void Free() + { + c_Contract.Free = !c_Contract.Free; + + NewGump(); + } + + private void AddBlock() + { + Owner.SendMessage( "Target the north western corner." ); + Owner.Target = new InternalTarget( this, c_Contract, TargetType.BlockOne ); + } + + private void ClearBlocks() + { + if ( c_Contract == null ) + return; + + c_Contract.Blocks.Clear(); + + c_Contract.ClearPreview(); + + NewGump(); + } + + private void FinalizeSetup() + { + if ( c_Contract == null ) + return; + + if ( c_Contract.Price == 0 ) + { + Owner.SendMessage( "You can't rent the area for 0 gold!" ); + NewGump(); + return; + } + + c_Contract.Completed = true; + c_Contract.BanLoc = c_Contract.ParentHouse.Region.GoLocation; + + if ( c_Contract.EntireHouse ) + { + Point3D point = c_Contract.ParentHouse.Sign.Location; + c_Contract.SignLoc = new Point3D( point.X, point.Y, point.Z-5 ); + c_Contract.Secures = Core.AOS ? c_Contract.ParentHouse.GetAosMaxSecures() : c_Contract.ParentHouse.MaxSecures; + c_Contract.Locks = Core.AOS ? c_Contract.ParentHouse.GetAosMaxLockdowns() : c_Contract.ParentHouse.MaxLockDowns; + } + + Owner.SendMessage( "You have finalized this rental contract. Now find someone to sign it!" ); + } + + private class InternalTarget : Target + { + private ContractSetupGump c_Gump; + private RentalContract c_Contract; + private TargetType c_Type; + private Point3D c_BoundOne; + + public InternalTarget( ContractSetupGump gump, RentalContract contract, TargetType type ) : this( gump, contract, type, Point3D.Zero ){} + + public InternalTarget( ContractSetupGump gump, RentalContract contract, TargetType type, Point3D point ) : base( 20, true, TargetFlags.None ) + { + c_Gump = gump; + c_Contract = contract; + c_Type = type; + c_BoundOne = point; + } + + protected override void OnTarget( Mobile m, object o ) + { + IPoint3D point = (IPoint3D)o; + + if ( c_Contract == null || c_Contract.ParentHouse == null ) + return; + + if ( !c_Contract.ParentHouse.Region.Contains( new Point3D( point.X, point.Y, point.Z ) ) ) + { + m.SendMessage( "You must target within the home." ); + m.Target = new InternalTarget( c_Gump, c_Contract, c_Type, c_BoundOne ); + return; + } + + switch( c_Type ) + { + case TargetType.SignLoc: + c_Contract.SignLoc = new Point3D( point.X, point.Y, point.Z ); + c_Contract.ShowSignPreview(); + c_Gump.NewGump(); + break; + + case TargetType.MinZ: + if (!c_Contract.ParentHouse.Region.Contains(new Point3D(point.X, point.Y, point.Z))) + m.SendMessage( "That isn't within your house." ); + else if ( c_Contract.HasContractedArea( point.Z ) ) + m.SendMessage( "That area is already taken by another rental contract." ); + else + { + c_Contract.MinZ = point.Z; + + if ( c_Contract.MaxZ < c_Contract.MinZ+19 ) + c_Contract.MaxZ = point.Z+19; + } + + c_Contract.ShowFloorsPreview(m); + c_Gump.NewGump(); + break; + + case TargetType.MaxZ: + if ( !c_Contract.ParentHouse.Region.Contains(new Point3D(point.X, point.Y, point.Z)) ) + m.SendMessage( "That isn't within your house." ); + else if ( c_Contract.HasContractedArea( point.Z ) ) + m.SendMessage( "That area is already taken by another rental contract." ); + else + { + c_Contract.MaxZ = point.Z+19; + + if ( c_Contract.MinZ > c_Contract.MaxZ ) + c_Contract.MinZ = point.Z; + } + + c_Contract.ShowFloorsPreview(m); + c_Gump.NewGump(); + break; + + case TargetType.BlockOne: + m.SendMessage( "Now target the south eastern corner." ); + m.Target = new InternalTarget( c_Gump, c_Contract, TargetType.BlockTwo, new Point3D( point.X, point.Y, point.Z ) ); + break; + + case TargetType.BlockTwo: + Rectangle2D rect = TownHouseSetupGump.FixRect( new Rectangle2D( c_BoundOne, new Point3D( point.X+1, point.Y+1, point.Z ) ) ); + + if ( c_Contract.HasContractedArea( rect, point.Z ) ) + m.SendMessage( "That area is already taken by another rental contract." ); + else + { + c_Contract.Blocks.Add( rect ); + c_Contract.ShowAreaPreview( m ); + } + + c_Gump.NewGump(); + break; + } + } + + protected override void OnTargetCancel( Mobile m, TargetCancelType cancelType ) + { + c_Gump.NewGump(); + } + } + } +} diff --git a/Scripts/Items/Houses/Monopoly/Gumps/TownHouse Gumps/TownHouseConfirmGump.cs b/Scripts/Items/Houses/Monopoly/Gumps/TownHouse Gumps/TownHouseConfirmGump.cs new file mode 100644 index 0000000..aac7543 --- /dev/null +++ b/Scripts/Items/Houses/Monopoly/Gumps/TownHouse Gumps/TownHouseConfirmGump.cs @@ -0,0 +1,63 @@ +using System; +using Server; + +namespace Knives.TownHouses +{ + public class TownHouseConfirmGump : GumpPlusLight + { + private TownHouseSign c_Sign; + private bool c_Items; + + public TownHouseConfirmGump( Mobile m, TownHouseSign sign ) : base( m, 100, 100 ) + { + c_Sign = sign; + } + + protected override void BuildGump() + { + int width = 200; + int y = 0; + + AddHtml( 0, y+=10, width, String.Format( "
{0} this House?", c_Sign.RentByTime == TimeSpan.Zero ? "Purchase" : "Rent" )); + AddImage(width / 2 - 100, y + 2, 0x39); + AddImage(width / 2 + 70, y + 2, 0x3B); + + if ( c_Sign.RentByTime == TimeSpan.Zero ) + AddHtml( 0, y+=25, width, String.Format( "
{0}: {1}", "Price", c_Sign.Free ? "Free" : "" + c_Sign.Price )); + else if ( c_Sign.RecurRent ) + AddHtml( 0, y+=25, width, String.Format( "
{0}: {1}", "Recurring " + c_Sign.PriceType, c_Sign.Price )); + else + AddHtml( 0, y+=25, width, String.Format( "
{0}: {1}", "One " + c_Sign.PriceTypeShort, c_Sign.Price )); + + if ( c_Sign.KeepItems ) + { + AddHtml( 0, y+=20, width, "
Cost of Items: " + c_Sign.ItemsPrice); + AddButton( 20, y, c_Items ? 0xD3 : 0xD2, "Items", new GumpCallback( Items ) ); + } + + AddHtml(0, y += 20, width, "
Lockdowns: " + c_Sign.Locks); + AddHtml( 0, y+=20, width, "
Secures: " + c_Sign.Secures); + + AddButton( 10, y+=25, 0xFB1, 0xFB3, "Cancel", new GumpCallback( Cancel ) ); + AddButton( width-40, y, 0xFB7, 0xFB9, "Confirm", new GumpCallback( Confirm ) ); + + AddBackgroundZero(0, 0, width, y+40, 3600); + } + + private void Items() + { + c_Items = !c_Items; + + NewGump(); + } + + private void Cancel() + { + } + + private void Confirm() + { + c_Sign.Purchase( Owner, c_Items ); + } + } +} diff --git a/Scripts/Items/Houses/Monopoly/Gumps/TownHouse Gumps/TownHouseSetupGump.cs b/Scripts/Items/Houses/Monopoly/Gumps/TownHouse Gumps/TownHouseSetupGump.cs new file mode 100644 index 0000000..002c3b2 --- /dev/null +++ b/Scripts/Items/Houses/Monopoly/Gumps/TownHouse Gumps/TownHouseSetupGump.cs @@ -0,0 +1,1049 @@ +using System; +using System.Collections; +using Server; +using Server.Targeting; + +namespace Knives.TownHouses +{ + public class TownHouseSetupGump : GumpPlusLight + { + public static Rectangle2D FixRect( Rectangle2D rect ) + { + Point3D pointOne = Point3D.Zero; + Point3D pointTwo = Point3D.Zero; + + if ( rect.Start.X < rect.End.X ) + { + pointOne.X = rect.Start.X; + pointTwo.X = rect.End.X; + } + else + { + pointOne.X = rect.End.X; + pointTwo.X = rect.Start.X; + } + + if ( rect.Start.Y < rect.End.Y ) + { + pointOne.Y = rect.Start.Y; + pointTwo.Y = rect.End.Y; + } + else + { + pointOne.Y = rect.End.Y; + pointTwo.Y = rect.Start.Y; + } + + return new Rectangle2D( pointOne, pointTwo ); + } + + public enum Page { Welcome, Blocks, Floors, Sign, Ban, LocSec, Items, Length, Price, Skills, Other, Other2 } + public enum TargetType { BanLoc, SignLoc, MinZ, MaxZ, BlockOne, BlockTwo } + + private TownHouseSign c_Sign; + private Page c_Page; + private bool c_Quick; + + public TownHouseSetupGump( Mobile m, TownHouseSign sign ) : base( m, 50, 50 ) + { + m.CloseGump( typeof( TownHouseSetupGump ) ); + + c_Sign = sign; + } + + protected override void BuildGump() + { + if ( c_Sign == null ) + return; + + int width = 300; + int y = 0; + + if (c_Quick) + { + QuickPage(width, ref y); + } + else + { + switch (c_Page) + { + case Page.Welcome: WelcomePage(width, ref y); break; + case Page.Blocks: BlocksPage(width, ref y); break; + case Page.Floors: FloorsPage(width, ref y); break; + case Page.Sign: SignPage(width, ref y); break; + case Page.Ban: BanPage(width, ref y); break; + case Page.LocSec: LocSecPage(width, ref y); break; + case Page.Items: ItemsPage(width, ref y); break; + case Page.Length: LengthPage(width, ref y); break; + case Page.Price: PricePage(width, ref y); break; + case Page.Skills: SkillsPage(width, ref y); break; + case Page.Other: OtherPage(width, ref y); break; + case Page.Other2: OtherPage2(width, ref y); break; + } + + BuildTabs(width, ref y); + } + + AddBackgroundZero(0, 0, width, y+=30, 3600); + + if (c_Sign.PriceReady && !c_Sign.Owned) + { + AddBackground(width / 2 - 50, y, 100, 30, 3600); + AddHtml(width / 2 - 50 + 25, y + 5, 100, "Claim Home"); + AddButton(width / 2 - 50 + 5, y + 10, 0x837, 0x838, "Claim", new GumpCallback(Claim)); + } + } + + private void BuildTabs(int width, ref int y) + { + int x = 20; + + y += 30; + + AddButton(x-5, y - 3, 0x768, "Quick", new GumpCallback(Quick)); + AddLabel(x, y - 3, c_Quick ? 0x34 : 0x47E, "Q"); + + AddButton(x+=20, y, c_Page == Page.Welcome ? 0x939 : 0x93A, "Welcome Page", new GumpStateCallback(ChangePage), 0); + AddButton(x+=20, y, c_Page == Page.Blocks ? 0x939 : 0x93A, "Blocks Page", new GumpStateCallback(ChangePage), 1); + + if ( c_Sign.BlocksReady ) + AddButton( x+=20, y, c_Page == Page.Floors ? 0x939 : 0x93A, "Floors Page", new GumpStateCallback( ChangePage ), 2 ); + + if ( c_Sign.FloorsReady ) + AddButton( x+=20, y, c_Page == Page.Sign ? 0x939 : 0x93A, "Sign Page", new GumpStateCallback( ChangePage ), 3 ); + + if ( c_Sign.SignReady ) + AddButton( x+=20, y, c_Page == Page.Ban ? 0x939 : 0x93A, "Ban Page", new GumpStateCallback( ChangePage ), 4 ); + + if ( c_Sign.BanReady ) + AddButton( x+=20, y, c_Page == Page.LocSec ? 0x939 : 0x93A, "LocSec Page", new GumpStateCallback( ChangePage ), 5 ); + + if ( c_Sign.LocSecReady ) + { + AddButton( x+=20, y, c_Page == Page.Items ? 0x939 : 0x93A, "Items Page", new GumpStateCallback( ChangePage ), 6 ); + + if ( !c_Sign.Owned ) + AddButton( x+=20, y, c_Page == Page.Length ? 0x939 : 0x93A, "Length Page", new GumpStateCallback( ChangePage ), 7 ); + else + x+=20; + + AddButton( x+=20, y, c_Page == Page.Price ? 0x939 : 0x93A, "Price Page", new GumpStateCallback( ChangePage ), 8 ); + } + + if ( c_Sign.PriceReady ) + { + AddButton( x+=20, y, c_Page == Page.Skills ? 0x939 : 0x93A, "Skills Page", new GumpStateCallback( ChangePage ), 9 ); + AddButton(x += 20, y, c_Page == Page.Other ? 0x939 : 0x93A, "Other Page", new GumpStateCallback(ChangePage), 10); + AddButton(x += 20, y, c_Page == Page.Other2 ? 0x939 : 0x93A, "Other Page 2", new GumpStateCallback(ChangePage), 11); + } + } + + private void QuickPage(int width, ref int y) + { + c_Sign.ClearPreview(); + + AddHtml(0, y += 10, width, "
Quick Setup"); + AddImage(width / 2 - 100, y + 2, 0x39); + AddImage(width / 2 + 70, y + 2, 0x3B); + + AddButton(5, 5, 0x768, "Quick", new GumpCallback(Quick)); + AddLabel(10, 5, c_Quick ? 0x34 : 0x47E, "Q"); + + AddHtml(0, y += 25, width / 2 - 55, "
Name"); + AddTextField(width / 2 - 15, y, 100, 20, 0x480, 0xBBC, "Name", c_Sign.Name); + AddButton(width / 2 - 40, y + 3, 0x2716, "Name", new GumpCallback(Name)); + + AddHtml(0, y += 25, width/2, "
Add Area"); + AddButton(width / 4 - 50, y + 3, 0x2716, "Add Area", new GumpCallback(AddBlock)); + AddButton(width / 4 + 40, y + 3, 0x2716, "Add Area", new GumpCallback(AddBlock)); + + AddHtml(width/2, y, width/2, "
Clear All"); + AddButton(width / 4 * 3 - 50, y + 3, 0x2716, "ClearAll", new GumpCallback(ClearAll)); + AddButton(width / 4 * 3 + 40, y + 3, 0x2716, "ClearAll", new GumpCallback(ClearAll)); + + AddHtml(0, y += 25, width, "
Base Floor: " + c_Sign.MinZ.ToString()); + AddButton(width / 2 - 80, y + 3, 0x2716, "Base Floor", new GumpCallback(MinZSelect)); + AddButton(width / 2 + 70, y + 3, 0x2716, "Base Floor", new GumpCallback(MinZSelect)); + + AddHtml(0, y += 17, width, "
Top Floor: " + c_Sign.MaxZ.ToString()); + AddButton(width / 2 - 80, y + 3, 0x2716, "Top Floor", new GumpCallback(MaxZSelect)); + AddButton(width / 2 + 70, y + 3, 0x2716, "Top Floor", new GumpCallback(MaxZSelect)); + + AddHtml(0, y += 25, width / 2, "
Sign Loc"); + AddButton(width / 4 - 50, y + 3, 0x2716, "Sign Loc", new GumpCallback(SignLocSelect)); + AddButton(width / 4 + 40, y + 3, 0x2716, "Sign Loc", new GumpCallback(SignLocSelect)); + + AddHtml(width/2, y, width/2, "
Ban Loc"); + AddButton(width / 4 * 3 - 50, y + 3, 0x2716, "Ban Loc", new GumpCallback(BanLocSelect)); + AddButton(width / 4 * 3 + 40, y + 3, 0x2716, "Ban Loc", new GumpCallback(BanLocSelect)); + + AddHtml(0, y += 25, width, "
Suggest Secures"); + AddButton(width / 2 - 70, y + 3, 0x2716, "Suggest LocSec", new GumpCallback(SuggestLocSec)); + AddButton(width / 2 + 60, y + 3, 0x2716, "Suggest LocSec", new GumpCallback(SuggestLocSec)); + + AddHtml(0, y += 20, width / 2 - 20, "
Secures"); + AddTextField(width / 2 + 20, y, 50, 20, 0x480, 0xBBC, "Secures", c_Sign.Secures.ToString()); + AddButton(width / 2 - 5, y + 3, 0x2716, "Secures", new GumpCallback(Secures)); + + AddHtml(0, y += 22, width / 2 - 20, "
Lockdowns"); + AddTextField(width / 2 + 20, y, 50, 20, 0x480, 0xBBC, "Lockdowns", c_Sign.Locks.ToString()); + AddButton(width / 2 - 5, y + 3, 0x2716, "Lockdowns", new GumpCallback(Lockdowns)); + + AddHtml(0, y += 25, width, "
Give buyer items in home"); + AddButton(width / 2 - 110, y, c_Sign.KeepItems ? 0xD3 : 0xD2, "Keep Items", new GumpCallback(KeepItems)); + AddButton(width / 2 + 90, y, c_Sign.KeepItems ? 0xD3 : 0xD2, "Keep Items", new GumpCallback(KeepItems)); + + if (c_Sign.KeepItems) + { + AddHtml(0, y += 25, width / 2 - 25, "
At cost"); + AddTextField(width / 2 + 15, y, 70, 20, 0x480, 0xBBC, "ItemsPrice", c_Sign.ItemsPrice.ToString()); + AddButton(width / 2 - 10, y + 5, 0x2716, "ItemsPrice", new GumpCallback(ItemsPrice)); + } + else + { + AddHtml(0, y += 25, width, "
Don't delete items"); + AddButton(width / 2 - 110, y, c_Sign.LeaveItems ? 0xD3 : 0xD2, "LeaveItems", new GumpCallback(LeaveItems)); + AddButton(width / 2 + 90, y, c_Sign.LeaveItems ? 0xD3 : 0xD2, "LeaveItems", new GumpCallback(LeaveItems)); + } + + if (!c_Sign.Owned) + { + AddHtml(120, y += 25, 50, c_Sign.PriceType); + AddButton(170, y + 8, 0x985, 0x985, "LengthUp", new GumpCallback(PriceUp)); + AddButton(170, y - 2, 0x983, 0x983, "LengthDown", new GumpCallback(PriceDown)); + } + + if (c_Sign.RentByTime != TimeSpan.Zero) + { + AddHtml(0, y += 25, width, "
Recurring Rent"); + AddButton(width / 2 - 80, y, c_Sign.RecurRent ? 0xD3 : 0xD2, "RecurRent", new GumpCallback(RecurRent)); + AddButton(width / 2 + 60, y, c_Sign.RecurRent ? 0xD3 : 0xD2, "RecurRent", new GumpCallback(RecurRent)); + + if (c_Sign.RecurRent) + { + AddHtml(0, y += 20, width, "
Rent To Own"); + AddButton(width / 2 - 80, y, c_Sign.RentToOwn ? 0xD3 : 0xD2, "RentToOwn", new GumpCallback(RentToOwn)); + AddButton(width / 2 + 60, y, c_Sign.RentToOwn ? 0xD3 : 0xD2, "RentToOwn", new GumpCallback(RentToOwn)); + } + } + + AddHtml(0, y += 25, width, "
Free"); + AddButton(width / 2 - 80, y, c_Sign.Free ? 0xD3 : 0xD2, "Free", new GumpCallback(Free)); + AddButton(width / 2 + 60, y, c_Sign.Free ? 0xD3 : 0xD2, "Free", new GumpCallback(Free)); + + if (!c_Sign.Free) + { + AddHtml(0, y += 25, width / 2 - 20, "
" + c_Sign.PriceType + " Price"); + AddTextField(width / 2 + 20, y, 70, 20, 0x480, 0xBBC, "Price", c_Sign.Price.ToString()); + AddButton(width / 2 - 5, y + 5, 0x2716, "Price", new GumpCallback(Price)); + + AddHtml(0, y += 25, width, "
Suggest Price"); + AddButton(width / 2 - 70, y + 3, 0x2716, "Suggest", new GumpCallback(SuggestPrice)); + AddButton(width / 2 + 50, y + 3, 0x2716, "Suggest", new GumpCallback(SuggestPrice)); + } + } + + private void WelcomePage(int width, ref int y) + { + AddHtml(0, y += 10, width, "
Welcome!"); + AddImage(width / 2 - 100, y + 2, 0x39); + AddImage(width / 2 + 70, y + 2, 0x3B); + + string helptext = ""; + + AddHtml(0, y += 25, width / 2 - 55, "
Name"); + AddTextField(width / 2 - 15, y, 100, 20, 0x480, 0xBBC, "Name", c_Sign.Name); + AddButton(width / 2 - 40, y + 3, 0x2716, "Name", new GumpCallback(Name)); + + if (c_Sign != null && c_Sign.Map != Map.Internal && c_Sign.RootParent == null) + { + AddHtml(0, y += 25, width, "
Goto"); + AddButton(width / 2 - 50, y + 3, 0x2716, "Goto", new GumpCallback(Goto)); + AddButton(width / 2 + 40, y + 3, 0x2716, "Goto", new GumpCallback(Goto)); + } + + if (c_Sign.Owned) + { + helptext = String.Format(" This home is owned by {0}, so be aware that changing anything " + + "through this menu will change the home itself! You can add more area, change the ownership " + + "rules, almost anything! You cannot, however, change the rental status of the home, way too many " + + "ways for things to go ill. If you change the restrictions and the home owner no longer meets them, " + + "they will receive the normal 24 hour demolish warning.", c_Sign.House.Owner.Name); + + AddHtml(10, y += 25, width - 20, 180, helptext, false, false); + + y += 180; + } + else + { + helptext = String.Format(" Welcome to the TownHouse setup menu! This menu will guide you through " + + "each step in the setup process. You can set up any area to be a home, and then detail everything from " + + "lockdowns and price to whether you want to sell or rent the house. Let's begin here with the name of " + + "this new Town House!"); + + AddHtml(10, y += 25, width - 20, 130, helptext, false, false); + + y += 130; + } + + AddHtml(width - 60, y+=15, 60, "Next"); + AddButton(width - 30, y, 0x15E1, 0x15E5, "Next", new GumpStateCallback(ChangePage), (int)c_Page + 1); + } + + private void BlocksPage(int width, ref int y) + { + if ( c_Sign == null ) + return; + + c_Sign.ShowAreaPreview(Owner); + + AddHtml( 0, y+=10, width, "
Create the Area"); + AddImage(width / 2 - 100, y + 2, 0x39); + AddImage(width / 2 + 70, y + 2, 0x3B); + + AddHtml( 0, y+=25, width, "
Add Area"); + AddButton(width / 2 - 50, y + 3, 0x2716, "Add Area", new GumpCallback(AddBlock)); + AddButton(width / 2 + 40, y + 3, 0x2716, "Add Area", new GumpCallback(AddBlock)); + + AddHtml( 0, y+=20, width, "
Clear All"); + AddButton(width / 2 - 50, y + 3, 0x2716, "ClearAll", new GumpCallback(ClearAll)); + AddButton(width / 2 + 40, y + 3, 0x2716, "ClearAll", new GumpCallback(ClearAll)); + + string helptext = String.Format( " Setup begins with defining the area you wish to sell or rent. " + + "You can add as many boxes as you wish, and each time the preview will extend to show what " + + "you've selected so far. If you feel like starting over, just clear them away! You must have " + + "at least one block defined before continuing to the next step." ); + + AddHtml( 10, y+=35, width-20, 140, helptext, false, false ); + + y += 140; + + AddHtml(30, y += 15, 80, "Previous"); + AddButton(10, y, 0x15E3, 0x15E7, "Previous", new GumpStateCallback(ChangePage), (int)c_Page - 1); + + if (c_Sign.BlocksReady) + { + AddHtml( width-60, y, 60, "Next"); + AddButton( width-30, y, 0x15E1, 0x15E5, "Next", new GumpStateCallback( ChangePage ), (int)c_Page+1 ); + } + } + + private void FloorsPage(int width, ref int y) + { + c_Sign.ShowFloorsPreview(Owner); + + AddHtml(0, y += 10, width, "
Floors"); + AddImage(width / 2 - 100, y + 2, 0x39); + AddImage(width / 2 + 70, y + 2, 0x3B); + + AddHtml(0, y += 25, width, "
Base Floor: " + c_Sign.MinZ.ToString()); + AddButton(width / 2 - 80, y + 3, 0x2716, "Base Floor", new GumpCallback(MinZSelect)); + AddButton(width / 2 + 70, y + 3, 0x2716, "Base Floor", new GumpCallback(MinZSelect)); + + AddHtml(0, y += 20, width, "
Top Floor: " + c_Sign.MaxZ.ToString()); + AddButton(width / 2 - 80, y + 3, 0x2716, "Top Floor", new GumpCallback(MaxZSelect)); + AddButton(width / 2 + 70, y + 3, 0x2716, "Top Floor", new GumpCallback(MaxZSelect)); + + string helptext = String.Format( " Now you will need to target the floors you wish to sell. " + + "If you only want one floor, you can skip targeting the top floor. Everything within the base " + + "and highest floor will come with the home, and the more floors, the higher the cost later on."); + + AddHtml( 10, y+=35, width-20, 110, helptext, false, false); + + y += 110; + + AddHtml( 30, y+=15, 80, "Previous"); + AddButton( 10, y, 0x15E3, 0x15E7, "Previous", new GumpStateCallback( ChangePage ), (int)c_Page-1 ); + + if ( c_Sign.FloorsReady ) + { + AddHtml( width-60, y, 60, "Next"); + AddButton( width-30, y, 0x15E1, 0x15E5, "Next", new GumpStateCallback( ChangePage ), (int)c_Page+1 ); + } + } + + private void SignPage(int width, ref int y) + { + if ( c_Sign == null ) + return; + + c_Sign.ShowSignPreview(); + + AddHtml( 0, y+=10, width, "
Sign Location"); + AddImage(width / 2 - 100, y + 2, 0x39); + AddImage(width / 2 + 70, y + 2, 0x3B); + + AddHtml( 0, y+=25, width, "
Set Location"); + AddButton(width / 2 - 60, y + 3, 0x2716, "Sign Loc", new GumpCallback(SignLocSelect)); + AddButton(width / 2 + 50, y + 3, 0x2716, "Sign Loc", new GumpCallback(SignLocSelect)); + + string helptext = String.Format( " With this sign, the owner will have the same home owning rights " + + "as custom or classic homes. If they use the sign to demolish the home, it will automatically " + + "return to sale or rent. The sign players will use to purchase the home will appear in the same " + + "spot, slightly below the normal house sign." ); + + AddHtml( 10, y+=35, width-20, 130, helptext, false, false); + + y += 130; + + AddHtml( 30, y+=15, 80, "Previous"); + AddButton( 10, y, 0x15E3, 0x15E7, "Previous", new GumpStateCallback( ChangePage ), (int)c_Page-1 ); + + if ( c_Sign.SignReady ) + { + AddHtml( width-60, y, 60, "Next"); + AddButton( width-30, y, 0x15E1, 0x15E5, "Next", new GumpStateCallback( ChangePage ), (int)c_Page+1 ); + } + } + + private void BanPage(int width, ref int y) + { + if ( c_Sign == null ) + return; + + c_Sign.ShowBanPreview(); + + AddHtml( 0, y+=10, width, "
Ban Location"); + AddImage(width / 2 - 100, y + 2, 0x39); + AddImage(width / 2 + 70, y + 2, 0x3B); + + AddHtml( 0, y+=25, width, "
Set Location"); + AddButton(width / 2 - 60, y + 3, 0x2716, "Ban Loc", new GumpCallback(BanLocSelect)); + AddButton(width / 2 + 50, y + 3, 0x2716, "Ban Loc", new GumpCallback(BanLocSelect)); + + string helptext = String.Format( " The ban location determines where players are sent when ejected or " + + "banned from a home. If you never set this, they would appear at the south west corner of the outside " + + "of the home."); + + AddHtml( 10, y+=35, width-20, 100, helptext, false, false ); + + y += 100; + + AddHtml( 30, y+=15, 80, "Previous"); + AddButton( 10, y, 0x15E3, 0x15E7, "Previous", new GumpStateCallback( ChangePage ), (int)c_Page-1 ); + + if ( c_Sign.BanReady ) + { + AddHtml( width-60, y, 60, "Next"); + AddButton( width-30, y, 0x15E1, 0x15E5, "Next", new GumpStateCallback( ChangePage ), (int)c_Page+1 ); + } + } + + private void LocSecPage(int width, ref int y) + { + AddHtml( 0, y+=10, width, "
Lockdowns and Secures"); + AddImage(width / 2 - 100, y + 2, 0x39); + AddImage(width / 2 + 70, y + 2, 0x3B); + + AddHtml(0, y+=25, width, "
Suggest"); + AddButton(width / 2 - 50, y + 3, 0x2716, "Suggest LocSec", new GumpCallback(SuggestLocSec)); + AddButton(width / 2 + 40, y + 3, 0x2716, "Suggest LocSec", new GumpCallback(SuggestLocSec)); + + AddHtml(0, y += 25, width / 2 - 20, "
Secures"); + AddTextField( width/2+20, y, 50, 20, 0x480, 0xBBC, "Secures", c_Sign.Secures.ToString() ); + AddButton(width / 2 - 5, y + 3, 0x2716, "Secures", new GumpCallback(Secures)); + + AddHtml( 0, y+=25, width/2-20, "
Lockdowns"); + AddTextField( width/2+20, y, 50, 20, 0x480, 0xBBC, "Lockdowns", c_Sign.Locks.ToString() ); + AddButton(width / 2 - 5, y + 3, 0x2716, "Lockdowns", new GumpCallback(Lockdowns)); + + string helptext = String.Format( " With this step you'll set the amount of storage for the home, or let " + + "the system do so for you using the Suggest button. In general, players get half the number of lockdowns " + + "as secure storage." ); + + AddHtml( 10, y+=35, width-20, 90, helptext, false, false ); + + y += 90; + + AddHtml( 30, y+=15, 80, "Previous"); + AddButton( 10, y, 0x15E3, 0x15E7, "Previous", new GumpStateCallback( ChangePage ), (int)c_Page-1 ); + + if ( c_Sign.LocSecReady ) + { + AddHtml( width-60, y, 60, "Next"); + AddButton( width-30, y, 0x15E1, 0x15E5, "Next", new GumpStateCallback( ChangePage ), (int)c_Page+1 ); + } + } + + private void ItemsPage(int width, ref int y) + { + AddHtml( 0, y+=10, width, "
Decoration Items"); + AddImage(width / 2 - 100, y + 2, 0x39); + AddImage(width / 2 + 70, y + 2, 0x3B); + + AddHtml( 0, y+=25, width, "
Give buyer items in home"); + AddButton(width / 2 - 110, y, c_Sign.KeepItems ? 0xD3 : 0xD2, "Keep Items", new GumpCallback(KeepItems)); + AddButton(width / 2 + 90, y, c_Sign.KeepItems ? 0xD3 : 0xD2, "Keep Items", new GumpCallback(KeepItems)); + + if ( c_Sign.KeepItems ) + { + AddHtml( 0, y+=25, width/2-25, "
At cost"); + AddTextField( width/2+15, y, 70, 20, 0x480, 0xBBC, "ItemsPrice", c_Sign.ItemsPrice.ToString()); + AddButton(width/2-10, y + 5, 0x2716, "ItemsPrice", new GumpCallback(ItemsPrice)); + } + else + { + AddHtml( 0, y+=25, width, "
Don't delete items"); + AddButton(width / 2 - 110, y, c_Sign.LeaveItems ? 0xD3 : 0xD2, "LeaveItems", new GumpCallback(LeaveItems)); + AddButton(width / 2 + 90, y, c_Sign.LeaveItems ? 0xD3 : 0xD2, "LeaveItems", new GumpCallback(LeaveItems)); + } + + string helptext = String.Format( " By default, the system will delete all items non-static items already " + + "in the home at the time of purchase. These items are commonly referred to as Decoration Items. " + + "They do not include home addons, like forges and the like. They do include containers. You can " + + "allow players to keep these items by saying so here, and you may also charge them to do so!"); + + AddHtml( 10, y+=35, width-20, 160, helptext, false, false ); + + y+=160; + + AddHtml( 30, y+=15, 80, "Previous"); + AddButton( 10, y, 0x15E3, 0x15E7, "Previous", new GumpStateCallback( ChangePage ), (int)c_Page-1 ); + + if ( c_Sign.ItemsReady ) + { + AddHtml( width-60, y, 60, "Next"); + AddButton( width-30, y, 0x15E1, 0x15E5, "Next", new GumpStateCallback( ChangePage ), (int)c_Page + ( c_Sign.Owned ? 2: 1 ) ); + } + } + + private void LengthPage(int width, ref int y) + { + AddHtml( 0, y+=10, width, "
Buy or Rent" ); + AddImage(width / 2 - 100, y + 2, 0x39); + AddImage(width / 2 + 70, y + 2, 0x3B); + + AddHtml( 120, y+=25, 50, c_Sign.PriceType); + AddButton( 170, y+8, 0x985, 0x985, "LengthUp", new GumpCallback( PriceUp ) ); + AddButton( 170, y-2, 0x983, 0x983, "LengthDown", new GumpCallback( PriceDown ) ); + + if ( c_Sign.RentByTime != TimeSpan.Zero ) + { + AddHtml( 0, y+=25, width, "
Recurring Rent"); + AddButton(width / 2 - 80, y, c_Sign.RecurRent ? 0xD3 : 0xD2, "RecurRent", new GumpCallback(RecurRent)); + AddButton(width / 2 + 60, y, c_Sign.RecurRent ? 0xD3 : 0xD2, "RecurRent", new GumpCallback(RecurRent)); + + if ( c_Sign.RecurRent ) + { + AddHtml( 0, y+=20, width, "
Rent To Own"); + AddButton(width / 2 - 80, y, c_Sign.RentToOwn ? 0xD3 : 0xD2, "RentToOwn", new GumpCallback(RentToOwn)); + AddButton(width / 2 + 60, y, c_Sign.RentToOwn ? 0xD3 : 0xD2, "RentToOwn", new GumpCallback(RentToOwn)); + } + } + + string helptext = String.Format( " Getting closer to completing the setup! Now you get to specify whether " + + "this is a purchase or rental property. Simply use the arrows until you have the setting you desire. For " + + "rental property, you can also make the purchase non-recuring, meaning after the time is up the player " + + "gets the boot! With recurring, if they have the money available they can continue to rent. You can " + + "also enable Rent To Own, allowing players to own the property after making two months worth of payments." ); + + AddHtml( 10, y+=35, width-20, 160, helptext, false, true ); + + y += 160; + + AddHtml( 30, y+=15, 80, "Previous"); + AddButton( 10, y, 0x15E3, 0x15E7, "Previous", new GumpStateCallback( ChangePage ), (int)c_Page-1 ); + + if ( c_Sign.LengthReady ) + { + AddHtml( width-60, y, 60, "Next"); + AddButton( width-30, y, 0x15E1, 0x15E5, "Next", new GumpStateCallback( ChangePage ), (int)c_Page+1 ); + } + } + + private void PricePage(int width, ref int y) + { + AddHtml( 0, y+=10, width, "
Price"); + AddImage(width / 2 - 100, y + 2, 0x39); + AddImage(width / 2 + 70, y + 2, 0x3B); + + AddHtml( 0, y+=25, width, "
Free"); + AddButton(width / 2 - 80, y, c_Sign.Free ? 0xD3 : 0xD2, "Free", new GumpCallback(Free)); + AddButton(width / 2 + 60, y, c_Sign.Free ? 0xD3 : 0xD2, "Free", new GumpCallback(Free)); + + if ( !c_Sign.Free ) + { + AddHtml( 0, y+=25, width/2-20, "
" + c_Sign.PriceType + " Price"); + AddTextField( width/2+20, y, 70, 20, 0x480, 0xBBC, "Price", c_Sign.Price.ToString()); + AddButton(width / 2 - 5, y + 5, 0x2716, "Price", new GumpCallback(Price)); + + AddHtml( 0, y+=20, width, "
Suggest"); + AddButton(width / 2 - 50, y + 3, 0x2716, "Suggest", new GumpCallback(SuggestPrice)); + AddButton(width / 2 + 40, y + 3, 0x2716, "Suggest", new GumpCallback(SuggestPrice)); + } + + string helptext = String.Format( " Now you get to set the price for the home. Remember, if this is a " + + "rental home, the system will charge them this amount for every period! Luckily the Suggestion " + + "takes this into account. If you don't feel like guessing, let the system suggest a price for you. " + + "You can also give the home away with the Free option." ); + + AddHtml( 10, y+=35, width-20, 130, helptext, false, false ); + + y += 130; + + AddHtml( 30, y+=15, 80, "Previous"); + AddButton( 10, y, 0x15E3, 0x15E7, "Previous", new GumpStateCallback( ChangePage ), (int)c_Page - ( c_Sign.Owned ? 2 : 1 ) ); + + if ( c_Sign.PriceReady ) + { + AddHtml( width-60, y, 60, "Next"); + AddButton( width-30, y, 0x15E1, 0x15E5, "Next", new GumpStateCallback( ChangePage ), (int)c_Page+1 ); + } + } + + private void SkillsPage(int width, ref int y) + { + AddHtml( 0, y+=10, width, "
Skill Restictions"); + AddImage(width / 2 - 100, y + 2, 0x39); + AddImage(width / 2 + 70, y + 2, 0x3B); + + AddHtml( 0, y+=25, width/2-20, "
Skill"); + AddTextField( width/2+20, y, 100, 20, 0x480, 0xBBC, "Skill", c_Sign.Skill.ToString()); + AddButton(width / 2 - 5, y + 5, 0x2716, "Skill", new GumpCallback(Skill)); + + AddHtml(0, y+=25, width / 2 - 20, "
Amount"); + AddTextField(width / 2 + 20, y, 50, 20, 0x480, 0xBBC, "SkillReq", c_Sign.SkillReq.ToString()); + AddButton(width / 2 - 5, y + 5, 0x2716, "Skill", new GumpCallback(Skill)); + + AddHtml(0, y += 25, width/2-20, "
Min Total"); + AddTextField(width / 2 + 20, y, 60, 20, 0x480, 0xBBC, "MinTotalSkill", c_Sign.MinTotalSkill.ToString()); + AddButton(width / 2 - 5, y + 5, 0x2716, "Skill", new GumpCallback(Skill)); + + AddHtml( 0, y+=25, width/2-20, "
Max Total"); + AddTextField(width / 2 + 20, y, 60, 20, 0x480, 0xBBC, "MaxTotalSkill", c_Sign.MaxTotalSkill.ToString()); + AddButton(width / 2 - 5, y + 5, 0x2716, "Skill", new GumpCallback(Skill)); + + string helptext = String.Format( " These settings are all optional. If you want to restrict who can own " + + "this home by their skills, here's the place. You can specify by the skill name and value, or by " + + "player's total skills." ); + + AddHtml( 10, y+=35, width-20, 90, helptext, false, false ); + + y += 90; + + AddHtml( 30, y+=15, 80, "Previous"); + AddButton( 10, y, 0x15E3, 0x15E7, "Previous", new GumpStateCallback( ChangePage ), (int)c_Page-1 ); + + if ( c_Sign.PriceReady ) + { + AddHtml( width-60, y, 60, "Next"); + AddButton( width-30, y, 0x15E1, 0x15E5, "Next", new GumpStateCallback( ChangePage ), (int)c_Page+1 ); + } + } + + private void OtherPage(int width, ref int y) + { + AddHtml(0, y += 10, width, "
Other Options"); + AddImage(width / 2 - 100, y + 2, 0x39); + AddImage(width / 2 + 70, y + 2, 0x3B); + + AddHtml(0, y += 25, width, "
Young"); + AddButton(width / 2 - 80, y, c_Sign.YoungOnly ? 0xD3 : 0xD2, "Young Only", new GumpCallback(Young)); + AddButton(width / 2 + 60, y, c_Sign.YoungOnly ? 0xD3 : 0xD2, "Young Only", new GumpCallback(Young)); + + if (!c_Sign.YoungOnly) + { + AddHtml(0, y += 25, width, "
Innocents"); + AddButton(width / 2 - 80, y, c_Sign.Murderers == Intu.No ? 0xD3 : 0xD2, "No Murderers", new GumpStateCallback(Murderers), Intu.No); + AddButton(width / 2 + 60, y, c_Sign.Murderers == Intu.No ? 0xD3 : 0xD2, "No Murderers", new GumpStateCallback(Murderers), Intu.No); + AddHtml(0, y += 20, width, "
Murderers"); + AddButton(width / 2 - 80, y, c_Sign.Murderers == Intu.Yes ? 0xD3 : 0xD2, "Yes Murderers", new GumpStateCallback(Murderers), Intu.Yes); + AddButton(width / 2 + 60, y, c_Sign.Murderers == Intu.Yes ? 0xD3 : 0xD2, "Yes Murderers", new GumpStateCallback(Murderers), Intu.Yes); + AddHtml(0, y += 20, width, "
All"); + AddButton(width / 2 - 80, y, c_Sign.Murderers == Intu.Neither ? 0xD3 : 0xD2, "Neither Murderers", new GumpStateCallback(Murderers), Intu.Neither); + AddButton(width / 2 + 60, y, c_Sign.Murderers == Intu.Neither ? 0xD3 : 0xD2, "Neither Murderers", new GumpStateCallback(Murderers), Intu.Neither); + } + + AddHtml(0, y += 25, width, "
Relock doors on demolish"); + AddButton(width / 2 - 110, y, c_Sign.Relock ? 0xD3 : 0xD2, "Relock", new GumpCallback(Relock)); + AddButton(width / 2 + 90, y, c_Sign.Relock ? 0xD3 : 0xD2, "Relock", new GumpCallback(Relock)); + + string helptext = String.Format(" These options are also optional. With the young setting, you can restrict " + + "who can buy the home to young players only. Similarly, you can specify whether murderers or innocents are " + + " allowed to own the home. You can also specify whether the doors within the " + + "home are locked when the owner demolishes their property."); + + AddHtml(10, y += 35, width - 20, 180, helptext, false, false); + + y += 180; + + AddHtml(30, y += 15, 80, "Previous"); + AddButton(10, y, 0x15E3, 0x15E7, "Previous", new GumpStateCallback(ChangePage), (int)c_Page - 1); + + AddHtml(width - 60, y, 60, "Next"); + AddButton(width - 30, y, 0x15E1, 0x15E5, "Next", new GumpStateCallback(ChangePage), (int)c_Page + 1); + } + + private void OtherPage2(int width, ref int y) + { + AddHtml(0, y += 10, width, "
Other Options 2"); + AddImage(width / 2 - 100, y + 2, 0x39); + AddImage(width / 2 + 70, y + 2, 0x3B); + + AddHtml(0, y += 25, width, "
Force Public"); + AddButton(width / 2 - 110, y, c_Sign.ForcePublic ? 0xD3 : 0xD2, "Public", new GumpCallback(ForcePublic)); + AddButton(width / 2 + 90, y, c_Sign.ForcePublic ? 0xD3 : 0xD2, "Public", new GumpCallback(ForcePublic)); + + AddHtml(0, y += 25, width, "
Force Private"); + AddButton(width / 2 - 110, y, c_Sign.ForcePrivate ? 0xD3 : 0xD2, "Private", new GumpCallback(ForcePrivate)); + AddButton(width / 2 + 90, y, c_Sign.ForcePrivate ? 0xD3 : 0xD2, "Private", new GumpCallback(ForcePrivate)); + + AddHtml(0, y += 25, width, "
No Trading"); + AddButton(width / 2 - 110, y, c_Sign.NoTrade ? 0xD3 : 0xD2, "NoTrade", new GumpCallback(NoTrade)); + AddButton(width / 2 + 90, y, c_Sign.NoTrade ? 0xD3 : 0xD2, "NoTrade", new GumpCallback(NoTrade)); + + AddHtml(0, y += 25, width, "
No Banning"); + AddButton(width / 2 - 110, y, c_Sign.NoBanning ? 0xD3 : 0xD2, "NoBan", new GumpCallback(NoBan)); + AddButton(width / 2 + 90, y, c_Sign.NoBanning ? 0xD3 : 0xD2, "NoBan", new GumpCallback(NoBan)); + + string helptext = String.Format(" Another page of optional options! Sometimes houses have features you don't want players using. " + + "So here you can force homes to be private or public. You can also prevent trading of the home. Lastly, you can remove their ability to ban players."); + + AddHtml(10, y += 35, width - 20, 180, helptext, false, false); + + y += 180; + + AddHtml(30, y += 15, 80, "Previous"); + AddButton(10, y, 0x15E3, 0x15E7, "Previous", new GumpStateCallback(ChangePage), (int)c_Page - 1); + } + + private bool SkillNameExists(string text) + { + try + { + SkillName index = (SkillName)Enum.Parse( typeof( SkillName ), text, true ); + return true; + } + catch + { + Owner.SendMessage( "You provided an invalid skill name." ); + return false; + } + } + + private void ChangePage( object obj ) + { + if ( c_Sign == null ) + return; + + if ( !(obj is int) ) + return; + + c_Page = (Page)(int)obj; + + c_Sign.ClearPreview(); + + NewGump(); + } + + private void Name() + { + c_Sign.Name = GetTextField("Name"); + Owner.SendMessage("Name set!"); + NewGump(); + } + + private void Goto() + { + Owner.Location = c_Sign.Location; + Owner.Z += 5; + Owner.Map = c_Sign.Map; + + NewGump(); + } + + private void Quick() + { + c_Quick = !c_Quick; + NewGump(); + } + + private void BanLocSelect() + { + Owner.SendMessage( "Target the ban location." ); + Owner.Target = new InternalTarget( this, c_Sign, TargetType.BanLoc ); + } + + private void SignLocSelect() + { + Owner.SendMessage( "Target the location for the home sign." ); + Owner.Target = new InternalTarget( this, c_Sign, TargetType.SignLoc ); + } + + private void MinZSelect() + { + Owner.SendMessage( "Target the base floor." ); + Owner.Target = new InternalTarget( this, c_Sign, TargetType.MinZ ); + } + + private void MaxZSelect() + { + Owner.SendMessage( "Target the highest floor." ); + Owner.Target = new InternalTarget( this, c_Sign, TargetType.MaxZ ); + } + + private void Young() + { + c_Sign.YoungOnly = !c_Sign.YoungOnly; + NewGump(); + } + + private void Murderers( object obj ) + { + if ( !(obj is Intu) ) + return; + + c_Sign.Murderers = (Intu)obj; + + NewGump(); + } + + private void Relock() + { + c_Sign.Relock = !c_Sign.Relock; + NewGump(); + } + + private void ForcePrivate() + { + c_Sign.ForcePrivate = !c_Sign.ForcePrivate; + NewGump(); + } + + private void ForcePublic() + { + c_Sign.ForcePublic = !c_Sign.ForcePublic; + NewGump(); + } + + private void NoTrade() + { + c_Sign.NoTrade = !c_Sign.NoTrade; + NewGump(); + } + + private void NoBan() + { + c_Sign.NoBanning = !c_Sign.NoBanning; + NewGump(); + } + + private void KeepItems() + { + c_Sign.KeepItems = !c_Sign.KeepItems; + NewGump(); + } + + private void LeaveItems() + { + c_Sign.LeaveItems = !c_Sign.LeaveItems; + NewGump(); + } + + private void ItemsPrice() + { + c_Sign.ItemsPrice = GetTextFieldInt("ItemsPrice"); + Owner.SendMessage("Item Price set!"); + NewGump(); + } + + private void RecurRent() + { + c_Sign.RecurRent = !c_Sign.RecurRent; + NewGump(); + } + + private void RentToOwn() + { + c_Sign.RentToOwn = !c_Sign.RentToOwn; + NewGump(); + } + + private void Skill() + { + if (GetTextField("Skill") != "" && SkillNameExists(GetTextField("Skill"))) + c_Sign.Skill = GetTextField("Skill"); + else + c_Sign.Skill = ""; + + c_Sign.SkillReq = GetTextFieldInt("SkillReq"); + c_Sign.MinTotalSkill = GetTextFieldInt("MinTotalSkill"); + c_Sign.MaxTotalSkill = GetTextFieldInt("MaxTotalSkill"); + + Owner.SendMessage("Skill info set!"); + + NewGump(); + } + + private void Claim() + { + new TownHouseConfirmGump( Owner, c_Sign ); + OnClose(); + } + + private void SuggestLocSec() + { + int price = c_Sign.CalcVolume()*General.SuggestionFactor; + c_Sign.Secures = price/75; + c_Sign.Locks = c_Sign.Secures/2; + + NewGump(); + } + + private void Secures() + { + c_Sign.Secures = GetTextFieldInt("Secures"); + Owner.SendMessage("Secures set!"); + NewGump(); + } + + private void Lockdowns() + { + c_Sign.Locks = GetTextFieldInt("Lockdowns"); + Owner.SendMessage("Lockdowns set!"); + NewGump(); + } + + private void SuggestPrice() + { + c_Sign.Price = c_Sign.CalcVolume()*General.SuggestionFactor; + + if ( c_Sign.RentByTime == TimeSpan.FromDays( 1 ) ) + c_Sign.Price /= 60; + if ( c_Sign.RentByTime == TimeSpan.FromDays( 7 ) ) + c_Sign.Price = (int)((double)c_Sign.Price/8.57); + if ( c_Sign.RentByTime == TimeSpan.FromDays( 30 ) ) + c_Sign.Price /= 2; + + NewGump(); + } + + private void Price() + { + c_Sign.Price = GetTextFieldInt("Price"); + Owner.SendMessage("Price set!"); + NewGump(); + } + + private void Free() + { + c_Sign.Free = !c_Sign.Free; + NewGump(); + } + + private void AddBlock() + { + if ( c_Sign == null ) + return; + + Owner.SendMessage( "Target the north western corner." ); + Owner.Target = new InternalTarget( this, c_Sign, TargetType.BlockOne ); + } + + private void ClearAll() + { + if ( c_Sign == null ) + return; + + c_Sign.Blocks.Clear(); + c_Sign.ClearPreview(); + c_Sign.UpdateBlocks(); + + NewGump(); + } + + private void PriceUp() + { + c_Sign.NextPriceType(); + NewGump(); + } + + private void PriceDown() + { + c_Sign.PrevPriceType(); + NewGump(); + } + + protected override void OnClose() + { + c_Sign.ClearPreview(); + } + + private class InternalTarget : Target + { + private TownHouseSetupGump c_Gump; + private TownHouseSign c_Sign; + private TargetType c_Type; + private Point3D c_BoundOne; + + public InternalTarget( TownHouseSetupGump gump, TownHouseSign sign, TargetType type ) : this( gump, sign, type, Point3D.Zero ){} + + public InternalTarget( TownHouseSetupGump gump, TownHouseSign sign, TargetType type, Point3D point ) : base( 20, true, TargetFlags.None ) + { + c_Gump = gump; + c_Sign = sign; + c_Type = type; + c_BoundOne = point; + } + + protected override void OnTarget( Mobile m, object o ) + { + IPoint3D point = (IPoint3D)o; + + switch( c_Type ) + { + case TargetType.BanLoc: + c_Sign.BanLoc = new Point3D( point.X, point.Y, point.Z ); + c_Gump.NewGump(); + break; + + case TargetType.SignLoc: + c_Sign.SignLoc = new Point3D( point.X, point.Y, point.Z ); + c_Sign.MoveToWorld(c_Sign.SignLoc, c_Sign.Map); + c_Sign.Z -= 5; + c_Sign.ShowSignPreview(); + c_Gump.NewGump(); + break; + + case TargetType.MinZ: + c_Sign.MinZ = point.Z; + + if ( c_Sign.MaxZ < c_Sign.MinZ+19 ) + c_Sign.MaxZ = point.Z+19; + + if ( c_Sign.MaxZ == short.MaxValue ) + c_Sign.MaxZ = point.Z+19; + + c_Gump.NewGump(); + break; + + case TargetType.MaxZ: + c_Sign.MaxZ = point.Z+19; + + if ( c_Sign.MinZ > c_Sign.MaxZ ) + c_Sign.MinZ = point.Z; + + c_Gump.NewGump(); + break; + + case TargetType.BlockOne: + m.SendMessage( "Now target the south eastern corner." ); + m.Target = new InternalTarget( c_Gump, c_Sign, TargetType.BlockTwo, new Point3D( point.X, point.Y, point.Z ) ); + break; + + case TargetType.BlockTwo: + c_Sign.Blocks.Add( FixRect( new Rectangle2D( c_BoundOne, new Point3D( point.X+1, point.Y+1, point.Z ) ) ) ); + c_Sign.UpdateBlocks(); + c_Sign.ShowAreaPreview(m); + c_Gump.NewGump(); + break; + } + } + + protected override void OnTargetCancel( Mobile m, TargetCancelType cancelType ) + { + c_Gump.NewGump(); + } + } + } +} diff --git a/Scripts/Items/Houses/Monopoly/Gumps/TownHouse Gumps/TownHousesGump.cs b/Scripts/Items/Houses/Monopoly/Gumps/TownHouse Gumps/TownHousesGump.cs new file mode 100644 index 0000000..3f60828 --- /dev/null +++ b/Scripts/Items/Houses/Monopoly/Gumps/TownHouse Gumps/TownHousesGump.cs @@ -0,0 +1,202 @@ +using System; +using System.Collections; +using Server; +using Server.Multis; +using Server.Gumps; + +namespace Knives.TownHouses +{ + public class TownHousesGump : GumpPlusLight + { + public enum ListPage { Town, House } + + public static void Initialize() + { + RUOVersion.AddCommand("TownHouses", AccessLevel.Counselor, new TownHouseCommandHandler(OnHouses)); + } + + private static void OnHouses(CommandInfo info) + { + new TownHousesGump(info.Mobile); + } + + private ListPage c_ListPage; + private int c_Page; + + public TownHousesGump(Mobile m) + : base(m, 100, 100) + { + m.CloseGump(typeof(TownHousesGump)); + } + + protected override void BuildGump() + { + int width = 400; + int y = 0; + + AddHtml(0, y += 10, width, "
TownHouses Main Menu"); + AddImage(width / 2 - 120, y + 2, 0x39); + AddImage(width / 2 + 90, y + 2, 0x3B); + + int pp = 10; + + if (c_Page != 0) + AddButton(width / 2 - 10, y += 25, 0x25E4, 0x25E5, "Page Down", new GumpCallback(PageDown)); + + ArrayList list = new ArrayList(); + if(c_ListPage == ListPage.Town) + list = new ArrayList(TownHouseSign.AllSigns); + else + foreach(Item item in World.Items.Values) + if(item is BaseHouse) + list.Add(item); + + list.Sort(new InternalSort()); + + AddHtml(0, y += 20, width, "
" + (c_ListPage == ListPage.Town ? "TownHouses" : "Houses") + " Count: " + list.Count); + AddHtml(0, y += 25, width, "
TownHouses / Houses"); + AddButton(width / 2 - 100, y + 3, c_ListPage == ListPage.Town ? 0x939 : 0x2716, "Page", new GumpStateCallback(Page), ListPage.Town); + AddButton(width / 2 + 90, y + 3, c_ListPage == ListPage.House ? 0x939 : 0x2716, "Page", new GumpStateCallback(Page), ListPage.House); + + TownHouseSign sign = null; + BaseHouse house = null; + + y += 5; + + for (int i = c_Page * pp; i < (c_Page + 1) * pp && i < list.Count; ++i) + { + if (c_ListPage == ListPage.Town) + { + sign = (TownHouseSign)list[i]; + + AddHtml(30, y += 20, width / 2 - 20, "
" + sign.Name); + AddButton(15, y + 3, 0x2716, "TownHouse Menu", new GumpStateCallback(TownHouseMenu), sign); + + if (sign.House != null && sign.House.Owner != null) + { + AddHtml(width / 2, y, width / 2 - 40, "
" + sign.House.Owner.RawName); + AddButton(width - 30, y + 3, 0x2716, "House Menu", new GumpStateCallback(HouseMenu), sign.House); + } + } + else + { + house = (BaseHouse)list[i]; + + AddHtml(30, y += 20, width / 2 - 20, "
" + house.Name); + AddButton(15, y + 3, 0x2716, "Goto", new GumpStateCallback(Goto), house); + + if (house.Owner != null) + { + AddHtml(width / 2, y, width / 2 - 40, "
" + house.Owner.RawName); + AddButton(width - 30, y + 3, 0x2716, "House Menu", new GumpStateCallback(HouseMenu), house); + } + } + } + + if (pp * (c_Page + 1) < list.Count) + AddButton(width / 2 - 10, y += 25, 0x25E8, 0x25E9, "Page Up", new GumpCallback(PageUp)); + + if (c_ListPage == ListPage.Town) + { + AddHtml(0, y += 35, width, "
Add New TownHouse"); + AddButton(width / 2 - 80, y + 3, 0x2716, "New", new GumpCallback(New)); + AddButton(width / 2 + 70, y + 3, 0x2716, "New", new GumpCallback(New)); + } + + AddBackgroundZero(0, 0, width, y + 40, 3600); + } + + private void TownHouseMenu(object obj) + { + if (!(obj is TownHouseSign)) + return; + + NewGump(); + + new TownHouseSetupGump(Owner, (TownHouseSign)obj); + } + + private void Page(object obj) + { + c_ListPage = (ListPage)obj; + NewGump(); + } + + private void Goto(object obj) + { + if (!(obj is BaseHouse)) + return; + + Owner.Location = ((BaseHouse)obj).BanLocation; + Owner.Map = ((BaseHouse)obj).Map; + + NewGump(); + } + + private void HouseMenu(object obj) + { + if (!(obj is BaseHouse)) + return; + + NewGump(); + + Owner.SendGump(new HouseGumpAOS((HouseGumpPageAOS)0, Owner, (BaseHouse)obj)); + } + + private void New() + { + TownHouseSign sign = new TownHouseSign(); + Owner.AddToBackpack(sign); + Owner.SendMessage("A new sign is now in your backpack. It will move on it's own during setup, but if you don't complete setup you may want to delete it."); + + NewGump(); + + new TownHouseSetupGump(Owner, sign); + } + + private void PageUp() + { + c_Page++; + NewGump(); + } + + private void PageDown() + { + c_Page--; + NewGump(); + } + + private class InternalSort : IComparer + { + public InternalSort() + { + } + + public int Compare(object x, object y) + { + if (x == null && y == null) + return 0; + + if (x is TownHouseSign) + { + TownHouseSign a = (TownHouseSign)x; + TownHouseSign b = (TownHouseSign)y; + + return Insensitive.Compare(a.Name, b.Name); + } + else + { + BaseHouse a = (BaseHouse)x; + BaseHouse b = (BaseHouse)y; + + if (a.Owner == null && b.Owner != null) + return -1; + if (a.Owner != null && b.Owner == null) + return 1; + + return Insensitive.Compare(a.Owner.RawName, b.Owner.RawName); + } + } + } + } +} diff --git a/Scripts/Items/Houses/Monopoly/Items/RentalContract.cs b/Scripts/Items/Houses/Monopoly/Items/RentalContract.cs new file mode 100644 index 0000000..0ee7c42 --- /dev/null +++ b/Scripts/Items/Houses/Monopoly/Items/RentalContract.cs @@ -0,0 +1,318 @@ +using System; +using System.Collections; +using Server; +using Server.Multis; +using Server.Items; + +namespace Knives.TownHouses +{ + public class RentalContract : TownHouseSign + { + private Mobile c_RentalMaster; + private Mobile c_RentalClient; + private BaseHouse c_ParentHouse; + private bool c_Completed, c_EntireHouse; + + public BaseHouse ParentHouse{ get{ return c_ParentHouse; } } + public Mobile RentalClient{ get{ return c_RentalClient; } set{ c_RentalClient = value; InvalidateProperties(); } } + public Mobile RentalMaster{ get{ return c_RentalMaster; } } + public bool Completed{ get{ return c_Completed; } set{ c_Completed = value; } } + public bool EntireHouse{ get{ return c_EntireHouse; } set{ c_EntireHouse = value; } } + + public RentalContract() : base() + { + ItemID = 0x14F0; + Movable = true; + RentByTime = TimeSpan.FromDays( 1 ); + RecurRent = true; + MaxZ = MinZ; + } + + public bool HasContractedArea( Rectangle2D rect, int z ) + { + foreach( Item item in TownHouseSign.AllSigns ) + if ( item is RentalContract && item != this && item.Map == Map && c_ParentHouse == ((RentalContract)item).ParentHouse ) + foreach( Rectangle2D rect2 in ((RentalContract)item).Blocks ) + for( int x = rect.Start.X; x < rect.End.X; ++x ) + for( int y = rect.Start.Y; y < rect.End.Y; ++y ) + if ( rect2.Contains( new Point2D( x, y ) ) ) + if ( ((RentalContract)item).MinZ <= z && ((RentalContract)item).MaxZ >= z ) + return true; + + return false; + } + + public bool HasContractedArea( int z ) + { + foreach( Item item in TownHouseSign.AllSigns ) + if ( item is RentalContract && item != this && item.Map == Map && c_ParentHouse == ((RentalContract)item).ParentHouse ) + if ( ((RentalContract)item).MinZ <= z && ((RentalContract)item).MaxZ >= z ) + return true; + + return false; + } + + public void DepositTo( Mobile m ) + { + if ( m == null ) + return; + + if ( Free ) + { + m.SendMessage( "Since this home is free, you do not receive the deposit." ); + return; + } + + m.BankBox.DropItem( new Gold( Price ) ); + m.SendMessage( "You have received a {0} gold deposit from your town house.", Price ); + } + + public override void ValidateOwnership() + { + if ( c_Completed && c_RentalMaster == null ) + { + Delete(); + return; + } + + if ( c_RentalClient != null && ( c_ParentHouse == null || c_ParentHouse.Deleted ) ) + { + Delete(); + return; + } + + if ( c_RentalClient != null && !Owned ) + { + Delete(); + return; + } + + if ( ParentHouse == null ) + return; + + if ( !ValidateLocSec() ) + { + if ( DemolishTimer == null ) + BeginDemolishTimer( TimeSpan.FromHours( 48 ) ); + } + else + ClearDemolishTimer(); + } + + protected override void DemolishAlert() + { + if ( ParentHouse == null || c_RentalMaster == null || c_RentalClient == null ) + return; + + c_RentalMaster.SendMessage( "You have begun to use lockdowns reserved for {0}, and their rental unit will collapse in {1}.", c_RentalClient.Name, Math.Round( (DemolishTime-DateTime.Now).TotalHours, 2 ) ); + c_RentalClient.SendMessage( "Alert your land lord, {0}, they are using storage reserved for you. They have violated the rental agreement, which will end in {1} if nothing is done.", c_RentalMaster.Name, Math.Round( (DemolishTime-DateTime.Now).TotalHours, 2 ) ); + } + + public void FixLocSec() + { + int count = 0; + + if ( (count = General.RemainingSecures( c_ParentHouse )+Secures) < Secures ) + Secures = count; + + if ( (count = General.RemainingLocks( c_ParentHouse )+Locks) < Locks ) + Locks = count; + } + + public bool ValidateLocSec() + { + if ( General.RemainingSecures( c_ParentHouse )+Secures < Secures ) + return false; + + if ( General.RemainingLocks( c_ParentHouse )+Locks < Locks ) + return false; + + return true; + } + + public override void ConvertItems( bool keep ) + { + if ( House == null || c_ParentHouse == null || c_RentalMaster == null ) + return; + + foreach( BaseDoor door in new ArrayList( c_ParentHouse.Doors ) ) + if ( door.Map == House.Map && House.Region.Contains( door.Location ) ) + ConvertDoor( door ); + + foreach( SecureInfo info in new ArrayList( c_ParentHouse.Secures ) ) + if ( info.Item.Map == House.Map && House.Region.Contains( info.Item.Location ) ) + c_ParentHouse.Release( c_RentalMaster, info.Item ); + + foreach( Item item in new ArrayList( c_ParentHouse.LockDowns ) ) + if ( item.Map == House.Map && House.Region.Contains( item.Location ) ) + c_ParentHouse.Release( c_RentalMaster, item ); + } + + public override void UnconvertDoors( ) + { + if ( House == null || c_ParentHouse == null ) + return; + + foreach( BaseDoor door in new ArrayList( House.Doors ) ) + House.Doors.Remove( door ); + } + + protected override void OnRentPaid() + { + if ( c_RentalMaster == null || c_RentalClient == null ) + return; + + if ( Free ) + return; + + c_RentalMaster.BankBox.DropItem( new Gold( Price ) ); + c_RentalMaster.SendMessage( "The bank has transfered your rent from {0}.", c_RentalClient.Name ); + } + + public override void ClearHouse() + { + if ( !Deleted ) + Delete(); + + base.ClearHouse(); + } + + public override void OnDoubleClick( Mobile m ) + { + ValidateOwnership(); + + if ( Deleted ) + return; + + if ( c_RentalMaster == null ) + c_RentalMaster = m; + + BaseHouse house = BaseHouse.FindHouseAt( m ); + + if ( c_ParentHouse == null ) + c_ParentHouse = house; + + if ( house == null || ( house != c_ParentHouse && house != House ) ) + { + m.SendMessage( "You must be in the home to view this contract." ); + return; + } + + if ( m == c_RentalMaster + && !c_Completed + && house is TownHouse + && ((TownHouse)house).ForSaleSign.PriceType != "Sale" ) + { + c_ParentHouse = null; + m.SendMessage( "You can only rent property you own." ); + return; + } + + if ( m == c_RentalMaster && !c_Completed && General.EntireHouseContracted( c_ParentHouse ) ) + { + m.SendMessage( "This entire house already has a rental contract." ); + return; + } + + if ( c_Completed ) + new ContractConfirmGump( m, this ); + else if ( m == c_RentalMaster ) + new ContractSetupGump( m, this ); + else + m.SendMessage( "This rental contract has not yet been completed." ); + } + + public override void GetProperties( ObjectPropertyList list ) + { + if ( c_RentalClient != null ) + list.Add( "a house rental contract with " + c_RentalClient.Name ); + else if ( c_Completed ) + list.Add( "a completed house rental contract" ); + else + list.Add( "an uncompleted house rental contract" ); + } + + public override void Delete() + { + if ( c_ParentHouse == null ) + { + base.Delete(); + return; + } + + if ( !Owned && !c_ParentHouse.IsFriend( c_RentalClient ) ) + { + if ( c_RentalClient != null && c_RentalMaster != null ) + { + c_RentalMaster.SendMessage( "{0} has ended your rental agreement. Because you revoked their access, their last payment will be refunded.", c_RentalMaster.Name ); + c_RentalClient.SendMessage( "You have ended your rental agreement with {0}. Because your access was revoked, your last payment is refunded.", c_RentalClient.Name ); + } + + DepositTo( c_RentalClient ); + } + else if ( Owned ) + { + if ( c_RentalClient != null && c_RentalMaster != null ) + { + c_RentalClient.SendMessage( "{0} has ended your rental agreement. Since they broke the contract, your are refunded the last payment.", c_RentalMaster.Name ); + c_RentalMaster.SendMessage( "You have ended your rental agreement with {0}. They will be refunded their last payment.", c_RentalClient.Name ); + } + + DepositTo( c_RentalClient ); + + /* Fixed for Rental Loop bug */ + //PackUpHouse(); + DeleteTest(); + } + else + { + if ( c_RentalClient != null && c_RentalMaster != null ) + { + c_RentalMaster.SendMessage( "{0} has ended your rental agreement.", c_RentalClient.Name ); + c_RentalClient.SendMessage( "You have ended your rental agreement with {0}.", c_RentalMaster.Name ); + } + + DepositTo( c_RentalMaster ); + } + + ClearRentTimer(); + base.Delete(); + } + + public RentalContract( Serial serial ) : base( serial ) + { + RecurRent = true; + } + + public override void Serialize( GenericWriter writer ) + { + base.Serialize( writer ); + + writer.Write( (int) 1 ); // version + + // Version 1 + + writer.Write( c_EntireHouse ); + + writer.Write( c_RentalMaster ); + writer.Write( c_RentalClient ); + writer.Write( c_ParentHouse ); + writer.Write( c_Completed ); + } + + public override void Deserialize( GenericReader reader ) + { + base.Deserialize( reader ); + + int version = reader.ReadInt(); + + if ( version >= 1 ) + c_EntireHouse = reader.ReadBool(); + + c_RentalMaster = reader.ReadMobile(); + c_RentalClient = reader.ReadMobile(); + c_ParentHouse = reader.ReadItem() as BaseHouse; + c_Completed = reader.ReadBool(); + } + } +} \ No newline at end of file diff --git a/Scripts/Items/Houses/Monopoly/Items/RentalContractCopy.cs b/Scripts/Items/Houses/Monopoly/Items/RentalContractCopy.cs new file mode 100644 index 0000000..f8dccb4 --- /dev/null +++ b/Scripts/Items/Houses/Monopoly/Items/RentalContractCopy.cs @@ -0,0 +1,47 @@ +using System; +using Server; +using Server.Items; + +namespace Knives.TownHouses +{ + public class RentalContractCopy : Item + { + private RentalContract c_Contract; + + public RentalContractCopy( RentalContract contract ) + { + Name = "rental contract copy"; + ItemID = 0x14F0; + c_Contract = contract; + } + + public override void OnDoubleClick( Mobile m ) + { + if ( c_Contract == null || c_Contract.Deleted ) + { + Delete(); + return; + } + + c_Contract.OnDoubleClick( m ); + } + + public RentalContractCopy( Serial serial ) : base( serial ) + { + } + + public override void Serialize( GenericWriter writer ) + { + base.Serialize( writer ); + + writer.Write( (int) 1 ); // version + } + + public override void Deserialize( GenericReader reader ) + { + base.Deserialize( reader ); + + int version = reader.ReadInt(); + } + } +} \ No newline at end of file diff --git a/Scripts/Items/Houses/Monopoly/Items/RentalLicense.cs b/Scripts/Items/Houses/Monopoly/Items/RentalLicense.cs new file mode 100644 index 0000000..ede2fa7 --- /dev/null +++ b/Scripts/Items/Houses/Monopoly/Items/RentalLicense.cs @@ -0,0 +1,53 @@ +using System; +using Server; +using Server.Items; + +namespace Knives.TownHouses +{ + public class RentalLicense : Item + { + private Mobile c_Owner; + + public Mobile Owner{ get{ return c_Owner; } set{ c_Owner = value; InvalidateProperties(); } } + + public RentalLicense() : base( 0x14F0 ) + { + } + + public override void GetProperties( ObjectPropertyList list ) + { + if ( c_Owner != null ) + list.Add( "a renter's license belonging to " + c_Owner.Name ); + else + list.Add( "a renter's license" ); + } + + public override void OnDoubleClick( Mobile m ) + { + if ( c_Owner == null ) + c_Owner = m; + } + + public RentalLicense( Serial serial ) : base( serial ) + { + } + + public override void Serialize( GenericWriter writer ) + { + base.Serialize( writer ); + + writer.Write( (int) 0 ); // version + + writer.Write( c_Owner ); + } + + public override void Deserialize( GenericReader reader ) + { + base.Deserialize( reader ); + + int version = reader.ReadInt(); + + c_Owner = reader.ReadMobile(); + } + } +} \ No newline at end of file diff --git a/Scripts/Items/Houses/Monopoly/Items/SignHammer.cs b/Scripts/Items/Houses/Monopoly/Items/SignHammer.cs new file mode 100644 index 0000000..dc1b053 --- /dev/null +++ b/Scripts/Items/Houses/Monopoly/Items/SignHammer.cs @@ -0,0 +1,299 @@ +using System; +using System.Collections; +using Server; +using Server.Items; +using Server.Multis; +using Server.Targeting; + +namespace Knives.TownHouses +{ + public enum HammerJob{ Flip, Swap } + + public class SignHammer : Item + { + private static Hashtable s_Table = new Hashtable(); + private static ArrayList s_List = new ArrayList(); + + public static void Initialize() + { + // Signs + s_Table[0xB95] = 0xB96; + s_Table[0xB96] = 0xB95; + s_Table[0xBA3] = 0xBA4; + s_Table[0xBA4] = 0xBA3; + s_Table[0xBA5] = 0xBA6; + s_Table[0xBA6] = 0xBA5; + s_Table[0xBA7] = 0xBA8; + s_Table[0xBA8] = 0xBA7; + s_Table[0xBA9] = 0xBAA; + s_Table[0xBAA] = 0xBA9; + s_Table[0xBAB] = 0xBAC; + s_Table[0xBAC] = 0xBAB; + s_Table[0xBAD] = 0xBAE; + s_Table[0xBAE] = 0xBAD; + s_Table[0xBAF] = 0xBB0; + s_Table[0xBB0] = 0xBAF; + s_Table[0xBB1] = 0xBB2; + s_Table[0xBB2] = 0xBB1; + s_Table[0xBB3] = 0xBB4; + s_Table[0xBB4] = 0xBB3; + s_Table[0xBB5] = 0xBB6; + s_Table[0xBB6] = 0xBB5; + s_Table[0xBB7] = 0xBB8; + s_Table[0xBB8] = 0xBB7; + s_Table[0xBB9] = 0xBBA; + s_Table[0xBBA] = 0xBB9; + s_Table[0xBBB] = 0xBBC; + s_Table[0xBBC] = 0xBBB; + s_Table[0xBBD] = 0xBBE; + s_Table[0xBBE] = 0xBBD; + s_Table[0xBBF] = 0xBC0; + s_Table[0xBC0] = 0xBBF; + s_Table[0xBC1] = 0xBC2; + s_Table[0xBC2] = 0xBC1; + s_Table[0xBC3] = 0xBC4; + s_Table[0xBC4] = 0xBC3; + s_Table[0xBC5] = 0xBC6; + s_Table[0xBC6] = 0xBC5; + s_Table[0xBC7] = 0xBC8; + s_Table[0xBC8] = 0xBC7; + s_Table[0xBC9] = 0xBCA; + s_Table[0xBCA] = 0xBC9; + s_Table[0xBCB] = 0xBCC; + s_Table[0xBCC] = 0xBCB; + s_Table[0xBCD] = 0xBCE; + s_Table[0xBCE] = 0xBCD; + s_Table[0xBCF] = 0xBD0; + s_Table[0xBD0] = 0xBCF; + s_Table[0xBD1] = 0xBD2; + s_Table[0xBD2] = 0xBD1; + s_Table[0xBD3] = 0xBD4; + s_Table[0xBD4] = 0xBD3; + s_Table[0xBD5] = 0xBD6; + s_Table[0xBD6] = 0xBD5; + s_Table[0xBD7] = 0xBD8; + s_Table[0xBD8] = 0xBD7; + s_Table[0xBD9] = 0xBDA; + s_Table[0xBDA] = 0xBD9; + s_Table[0xBDB] = 0xBDC; + s_Table[0xBDC] = 0xBDB; + s_Table[0xBDD] = 0xBDE; + s_Table[0xBDE] = 0xBDD; + s_Table[0xBDF] = 0xBE0; + s_Table[0xBE0] = 0xBDF; + s_Table[0xBE1] = 0xBE2; + s_Table[0xBE2] = 0xBE1; + s_Table[0xBE3] = 0xBE4; + s_Table[0xBE4] = 0xBE3; + s_Table[0xBE5] = 0xBE6; + s_Table[0xBE6] = 0xBE5; + s_Table[0xBE7] = 0xBE8; + s_Table[0xBE8] = 0xBE7; + s_Table[0xBE9] = 0xBEA; + s_Table[0xBEA] = 0xBE9; + s_Table[0xBEB] = 0xBEC; + s_Table[0xBEC] = 0xBEB; + s_Table[0xBED] = 0xBEE; + s_Table[0xBEE] = 0xBED; + s_Table[0xBEF] = 0xBF0; + s_Table[0xBF0] = 0xBEF; + s_Table[0xBF1] = 0xBF2; + s_Table[0xBF2] = 0xBF1; + s_Table[0xBF3] = 0xBF4; + s_Table[0xBF4] = 0xBF3; + s_Table[0xBF5] = 0xBF6; + s_Table[0xBF6] = 0xBF5; + s_Table[0xBF7] = 0xBF8; + s_Table[0xBF8] = 0xBF7; + s_Table[0xBF9] = 0xBFA; + s_Table[0xBFA] = 0xBF9; + s_Table[0xBFB] = 0xBFC; + s_Table[0xBFC] = 0xBFB; + s_Table[0xBFD] = 0xBFE; + s_Table[0xBFE] = 0xBFD; + s_Table[0xBFF] = 0xC00; + s_Table[0xC00] = 0xBFF; + s_Table[0xC01] = 0xC02; + s_Table[0xC02] = 0xC01; + s_Table[0xC03] = 0xC04; + s_Table[0xC04] = 0xC03; + s_Table[0xC05] = 0xC06; + s_Table[0xC06] = 0xC05; + s_Table[0xC07] = 0xC08; + s_Table[0xC08] = 0xC07; + s_Table[0xC09] = 0xC0A; + s_Table[0xC0A] = 0xC09; + s_Table[0xC0B] = 0xC0C; + s_Table[0xC0C] = 0xC0B; + s_Table[0xC0D] = 0xC0E; + s_Table[0xC0E] = 0xC0D; + + // Hangers + s_Table[0xB97] = 0xB98; + s_Table[0xB98] = 0xB97; + s_Table[0xB99] = 0xB9A; + s_Table[0xB9A] = 0xB99; + s_Table[0xB9B] = 0xB9C; + s_Table[0xB9C] = 0xB9B; + s_Table[0xB9D] = 0xB9E; + s_Table[0xB9E] = 0xB9D; + s_Table[0xB9F] = 0xBA0; + s_Table[0xBA0] = 0xB9F; + s_Table[0xBA1] = 0xBA2; + s_Table[0xBA2] = 0xBA1; + + // Hangers for swapping + s_List.Add(0xB97); + s_List.Add(0xB98); + s_List.Add(0xB99); + s_List.Add(0xB9A); + s_List.Add(0xB9B); + s_List.Add(0xB9C); + s_List.Add(0xB9D); + s_List.Add(0xB9E); + s_List.Add(0xB9F); + s_List.Add(0xBA0); + s_List.Add(0xBA1); + s_List.Add(0xBA2); + } + + private HammerJob c_Job; + + public HammerJob Job { get { return c_Job; } set { c_Job = value; } } + + [Constructable] + public SignHammer() + : base(0x13E3) + { + Name = "Sign Hammer"; + } + + public int GetFlipFor(int id) + { + return (s_Table[id] == null ? id : (int)s_Table[id]); + } + + public int GetNextSign(int id) + { + if (!s_List.Contains(id)) + return id; + + int idx = s_List.IndexOf(id); + + if (idx + 2 < s_List.Count) + return (int)s_List[idx + 2]; + + if (idx % 2 == 0) + return (int)s_List[0]; + + return (int)s_List[1]; + } + + public override void OnDoubleClick(Mobile m) + { + if (RootParent != m) + { + m.SendMessage("That item must be in your backpack to use."); + return; + } + + BaseHouse house = BaseHouse.FindHouseAt(m); + + if (m.AccessLevel == AccessLevel.Player && (house == null || house.Owner != m)) + { + m.SendMessage("You have to be inside your house to use this."); + return; + } + + m.BeginTarget(3, false, TargetFlags.None, new TargetCallback(OnTarget)); + } + + protected void OnTarget(Mobile m, object obj) + { + Item item = obj as Item; + + if (item == null) + { + m.SendMessage("You cannot change that with this."); + return; + } + + if (item == this) + { + new SignHammerGump(m, this); + return; + } + + if (c_Job == HammerJob.Flip) + { + int id = GetFlipFor(item.ItemID); + + if (id == item.ItemID) + m.SendMessage("You cannot change that with this."); + else + item.ItemID = id; + } + else + { + int id = GetNextSign(item.ItemID); + + if (id == item.ItemID) + m.SendMessage("You cannot change that with this."); + else + item.ItemID = id; + } + } + + public SignHammer(Serial serial) + : base(serial) + { + } + + public override void Serialize(GenericWriter writer) + { + base.Serialize(writer); + + writer.Write((int)0); // version + } + + public override void Deserialize(GenericReader reader) + { + base.Deserialize(reader); + + int version = reader.ReadInt(); + } + } + + public class SignHammerGump : GumpPlusLight + { + private SignHammer c_Hammer; + + public SignHammerGump( Mobile m, SignHammer hammer ) : base( m, 100, 100 ) + { + c_Hammer = hammer; + + NewGump(); + } + + protected override void BuildGump() + { + AddBackground(0, 0, 200, 200, 2600); + + AddButton(50, 45, 2152, 2154, "Swap", new GumpCallback(Swap)); + AddHtml( 90, 50, 70, "Swap Hanger"); + + AddButton( 50, 95, 2152, 2154, "Flip", new GumpCallback( Flip ) ); + AddHtml( 90, 100, 70, "Flip Sign or Hanger"); + } + + private void Swap() + { + c_Hammer.Job = HammerJob.Swap; + } + + private void Flip() + { + c_Hammer.Job = HammerJob.Flip; + } + } +} \ No newline at end of file diff --git a/Scripts/Items/Houses/Monopoly/Items/TownHouse.cs b/Scripts/Items/Houses/Monopoly/Items/TownHouse.cs new file mode 100644 index 0000000..8c0ec7e --- /dev/null +++ b/Scripts/Items/Houses/Monopoly/Items/TownHouse.cs @@ -0,0 +1,259 @@ +using System; +using System.Collections; +using Server; +using Server.Items; +using Server.Multis; +using Server.Targeting; + +namespace Knives.TownHouses +{ + public class TownHouse : VersionHouse + { + private static ArrayList s_TownHouses = new ArrayList(); + public static ArrayList AllTownHouses{ get{ return s_TownHouses; } } + + private TownHouseSign c_Sign; + private Item c_Hanger; + private ArrayList c_Sectors = new ArrayList(); + + public TownHouseSign ForSaleSign { get { return c_Sign; } } + + public Item Hanger + { + get + { + if ( c_Hanger == null ) + { + c_Hanger = new Item( 0xB98 ); + c_Hanger.Movable = false; + c_Hanger.Location = Sign.Location; + c_Hanger.Map = Sign.Map; + } + + return c_Hanger; + } + set{ c_Hanger = value; } + } + + public TownHouse( Mobile m, TownHouseSign sign, int locks, int secures ) : base( 0x1DD6 | 0x4000, m, locks, secures ) + { + c_Sign = sign; + + SetSign( 0, 0, 0 ); + + s_TownHouses.Add( this ); + } + + public void InitSectorDefinition() + { + if (c_Sign == null || c_Sign.Blocks.Count == 0) + return; + + int minX = ((Rectangle2D)c_Sign.Blocks[0]).Start.X; + int minY = ((Rectangle2D)c_Sign.Blocks[0]).Start.Y; + int maxX = ((Rectangle2D)c_Sign.Blocks[0]).End.X; + int maxY = ((Rectangle2D)c_Sign.Blocks[0]).End.Y; + + foreach( Rectangle2D rect in c_Sign.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; + } + + foreach (Sector sector in c_Sectors) + sector.OnMultiLeave(this); + + c_Sectors.Clear(); + for (int x = minX; x < maxX; ++x) + for (int y = minY; y < maxY; ++y) + if(!c_Sectors.Contains(Map.GetSector(new Point2D(x, y)))) + c_Sectors.Add(Map.GetSector(new Point2D(x, y))); + + foreach (Sector sector in c_Sectors) + sector.OnMultiEnter(this); + + Components.Resize(maxX - minX, maxY - minY); + Components.Add(0x520, Components.Width - 1, Components.Height - 1, -5); + } + + public override Rectangle2D[] Area + { + get + { + if (c_Sign == null) + return new Rectangle2D[100]; + + Rectangle2D[] rects = new Rectangle2D[c_Sign.Blocks.Count]; + + for (int i = 0; i < c_Sign.Blocks.Count && i < rects.Length; ++i) + rects[i] = (Rectangle2D)c_Sign.Blocks[i]; + + return rects; + } + } + + public override bool IsInside( Point3D p, int height ) + { + if (c_Sign == null) + return false; + + if ( Map == null || Region == null ) + { + Delete(); + return false; + } + + Sector sector = null; + + try + { + if (c_Sign is RentalContract && Region.Contains(p)) + return true; + + sector = Map.GetSector(p); + + foreach (BaseMulti m in sector.Multis) + { + if (m != this + && m is TownHouse + && ((TownHouse)m).ForSaleSign is RentalContract + && ((TownHouse)m).IsInside(p, height)) + return false; + } + + return Region.Contains(p); + } + catch(Exception e) + { + Errors.Report("Error occured in IsInside(). More information on the console."); + Console.WriteLine("Info:{0}, {1}, {2}", Map, sector, Region, sector != null ? "" + sector.Multis : "**"); + Console.WriteLine(e.Source); + Console.WriteLine(e.Message); + Console.WriteLine(e.StackTrace); + return false; + } + } + + public override int GetNewVendorSystemMaxVendors() + { + return 50; + } + + public override int GetAosMaxSecures() + { + return MaxSecures; + } + + public override int GetAosMaxLockdowns() + { + return MaxLockDowns; + } + + public override void OnMapChange() + { + base.OnMapChange(); + + if ( c_Hanger != null ) + c_Hanger.Map = Map; + } + + public override void OnLocationChange( Point3D oldLocation ) + { + base.OnLocationChange( oldLocation ); + + if ( c_Hanger != null ) + c_Hanger.Location = Sign.Location; + } + + public override void OnSpeech( SpeechEventArgs e ) + { + if ( e.Mobile != Owner || !IsInside( e.Mobile ) ) + return; + + if (e.Speech.ToLower() == "check house rent") + c_Sign.CheckRentTimer(); + + Timer.DelayCall(TimeSpan.Zero, new TimerStateCallback(AfterSpeech), e.Mobile); + } + + private void AfterSpeech(object o) + { + if (!(o is Mobile)) + return; + + if (((Mobile)o).Target is HouseBanTarget && ForSaleSign != null && ForSaleSign.NoBanning) + { + ((Mobile)o).Target.Cancel((Mobile)o, TargetCancelType.Canceled); + ((Mobile)o).SendMessage(0x161, "You cannot ban people from this house."); + } + } + + public override void OnDelete() + { + if (c_Hanger != null) + c_Hanger.Delete(); + + foreach (Item item in Sign.GetItemsInRange(0)) + if (item != Sign) + item.Visible = true; + + c_Sign.ClearHouse(); + Doors.Clear(); + + s_TownHouses.Remove(this); + + base.OnDelete(); + } + + public TownHouse(Serial serial) + : base(serial) + { + s_TownHouses.Add(this); + } + + public override void Serialize( GenericWriter writer ) + { + base.Serialize( writer ); + + writer.Write( 3 ); + + // Version 2 + + writer.Write( c_Hanger ); + + // Version 1 + + writer.Write( c_Sign ); + } + + public override void Deserialize( GenericReader reader ) + { + base.Deserialize( reader ); + + int version = reader.ReadInt(); + + if ( version >= 2 ) + c_Hanger = reader.ReadItem(); + + c_Sign = (TownHouseSign)reader.ReadItem(); + + if (version <= 2) + { + int count = reader.ReadInt(); + for (int i = 0; i < count; ++i) + reader.ReadRect2D(); + } + + if( Price == 0 ) + Price = 1; + + ItemID = 0x1DD6 | 0x4000; + } + } +} \ No newline at end of file diff --git a/Scripts/Items/Houses/Monopoly/Items/TownHouseSign.cs b/Scripts/Items/Houses/Monopoly/Items/TownHouseSign.cs new file mode 100644 index 0000000..4a5fb8f --- /dev/null +++ b/Scripts/Items/Houses/Monopoly/Items/TownHouseSign.cs @@ -0,0 +1,1334 @@ +using System; +using System.Collections; +using Server; +using Server.Multis; +using Server.Items; +using Server.Mobiles; + +namespace Knives.TownHouses +{ + public enum Intu{ Neither, No, Yes } + + [Flipable( 0xC0B, 0xC0C )] + public class TownHouseSign : Item + { + private static ArrayList s_TownHouseSigns = new ArrayList(); + public static ArrayList 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_Relock, c_KeepItems, c_LeaveItems, c_RentToOwn, c_Free, c_ForcePrivate, c_ForcePublic, c_NoTrade, c_NoBanning; + private string c_Skill; + private double c_SkillReq; + private ArrayList c_Blocks, c_DecoreItemInfos, c_PreviewItems; + private TownHouse c_House; + private Timer c_DemolishTimer, c_RentTimer, c_PreviewTimer; + private DateTime c_DemolishTime, c_RentTime; + private TimeSpan c_RentByTime, c_OriginalRentTime; + private Intu c_Murderers; + + public Point3D BanLoc + { + get{ return c_BanLoc; } + set + { + c_BanLoc = value; + InvalidateProperties(); + if ( Owned ) + c_House.Region.GoLocation = value; + } + } + + public Point3D SignLoc + { + get{ return c_SignLoc; } + set + { + c_SignLoc = value; + InvalidateProperties(); + + if ( Owned ) + { + c_House.Sign.Location = value; + c_House.Hanger.Location = value; + } + } + } + + public int Locks + { + get{ return c_Locks; } + set + { + c_Locks = value; + InvalidateProperties(); + if ( Owned ) + c_House.MaxLockDowns = value; + } + } + + public int Secures + { + get{ return c_Secures; } + set + { + c_Secures = value; + InvalidateProperties(); + if ( Owned ) + c_House.MaxSecures = value; + } + } + + public int Price + { + get{ return c_Price; } + set + { + c_Price = value; + InvalidateProperties(); + } + } + + public int MinZ + { + get{ return c_MinZ; } + set + { + if ( value > c_MaxZ ) + c_MaxZ = value+1; + + c_MinZ = value; + if (Owned) + RUOVersion.UpdateRegion(this); + } + } + + public int MaxZ + { + get{ return c_MaxZ; } + set + { + if ( value < c_MinZ ) + value = c_MinZ; + + c_MaxZ = value; + if (Owned) + RUOVersion.UpdateRegion(this); + } + } + + public int MinTotalSkill + { + get{ return c_MinTotalSkill; } + set + { + if ( value > c_MaxTotalSkill ) + value = c_MaxTotalSkill; + + c_MinTotalSkill = value; + ValidateOwnership(); + InvalidateProperties(); + } + } + + public int MaxTotalSkill + { + get{ return c_MaxTotalSkill; } + set + { + if ( value < c_MinTotalSkill ) + value = c_MinTotalSkill; + + c_MaxTotalSkill = value; + ValidateOwnership(); + InvalidateProperties(); + } + } + + public bool YoungOnly + { + get{ return c_YoungOnly; } + set + { + c_YoungOnly = value; + + if ( c_YoungOnly ) + c_Murderers = Intu.Neither; + + ValidateOwnership(); + InvalidateProperties(); + } + } + + public TimeSpan RentByTime + { + get{ return c_RentByTime; } + set + { + c_RentByTime = value; + c_OriginalRentTime = value; + + if ( value == TimeSpan.Zero ) + ClearRentTimer(); + else + { + ClearRentTimer(); + BeginRentTimer( value ); + } + + InvalidateProperties(); + } + } + + public bool RecurRent + { + get{ return c_RecurRent; } + set + { + c_RecurRent = value; + + if ( !value ) + c_RentToOwn = value; + + InvalidateProperties(); + } + } + + public bool KeepItems + { + get{ return c_KeepItems; } + set + { + c_LeaveItems = false; + c_KeepItems = value; + InvalidateProperties(); + } + } + + public bool Free + { + get{ return c_Free; } + set + { + c_Free = value; + c_Price = 1; + InvalidateProperties(); + } + } + + public Intu Murderers + { + get{ return c_Murderers; } + set + { + c_Murderers = value; + + ValidateOwnership(); + InvalidateProperties(); + } + } + + public bool ForcePrivate + { + get { return c_ForcePrivate; } + set + { + c_ForcePrivate = value; + + if (value) + { + c_ForcePublic = false; + + if (c_House != null) + c_House.Public = false; + } + } + } + + public bool ForcePublic + { + get { return c_ForcePublic; } + set + { + c_ForcePublic = value; + + if (value) + { + c_ForcePrivate = false; + + if (c_House != null) + c_House.Public = true; + } + } + } + + public bool NoBanning + { + get { return c_NoBanning; } + set + { + c_NoBanning = value; + + if (value && c_House != null) + c_House.Bans.Clear(); + } + } + + public ArrayList Blocks { get { return c_Blocks; } set { c_Blocks = value; } } + public string Skill { get { return c_Skill; } set { c_Skill = value; ValidateOwnership(); InvalidateProperties(); } } + public double SkillReq { get { return c_SkillReq; } set { c_SkillReq = value; ValidateOwnership(); InvalidateProperties(); } } + public bool LeaveItems{ get{ return c_LeaveItems; } set{ c_LeaveItems = value; InvalidateProperties(); } } + public bool RentToOwn{ get{ return c_RentToOwn; } set{ c_RentToOwn = value; InvalidateProperties(); } } + public bool Relock { get { return c_Relock; } set { c_Relock = value; } } + public bool NoTrade { get { return c_NoTrade; } set { c_NoTrade = value; } } + public int ItemsPrice { get { return c_ItemsPrice; } set { c_ItemsPrice = value; InvalidateProperties(); } } + public TownHouse House{ get{ return c_House; } set{ c_House = value; } } + public Timer DemolishTimer{ get{ return c_DemolishTimer; } } + public DateTime DemolishTime{ get{ return c_DemolishTime; } } + + public bool Owned{ get{ return c_House != null && !c_House.Deleted; } } + 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 ); } } + + 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"; + } + } + + 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; + + c_BanLoc = Point3D.Zero; + c_SignLoc = Point3D.Zero; + c_Skill = ""; + c_Blocks = new ArrayList(); + c_DecoreItemInfos = new ArrayList(); + c_PreviewItems = new ArrayList(); + c_DemolishTime = DateTime.Now; + c_RentTime = DateTime.Now; + c_RentByTime = TimeSpan.Zero; + c_RecurRent = true; + + c_MinZ = short.MinValue; + c_MaxZ = short.MaxValue; + + s_TownHouseSigns.Add( this ); + } + + private void SearchForHouse() + { + foreach( TownHouse house in TownHouse.AllTownHouses ) + if (house.ForSaleSign == this ) + c_House = house; + } + + public void UpdateBlocks() + { + if ( !Owned ) + return; + + if (c_Blocks.Count == 0) + UnconvertDoors(); + + RUOVersion.UpdateRegion(this); + ConvertItems(false); + c_House.InitSectorDefinition(); + } + + public void ShowAreaPreview( Mobile m ) + { + ClearPreview(); + + Point2D point = Point2D.Zero; + ArrayList blocks = new ArrayList(); + + foreach( Rectangle2D rect in c_Blocks ) + for( int x = rect.Start.X; x < rect.End.X; ++x ) + for( int 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; + } + + Item item = null; + int avgz = 0; + foreach( Point2D p in blocks ) + { + avgz = Map.GetAverageZ(p.X, p.Y); + + item = new Item( 0x1766 ); + item.Name = "Area Preview"; + item.Movable = false; + item.Location = new Point3D( p.X, p.Y, (avgz <= m.Z ? m.Z+2 : avgz+2 ) ); + item.Map = Map; + + c_PreviewItems.Add( item ); + } + + c_PreviewTimer = Timer.DelayCall( TimeSpan.FromSeconds( 100 ), new TimerCallback( ClearPreview ) ); + } + + public void ShowSignPreview() + { + ClearPreview(); + + Item sign = new Item( 0xBD2 ); + sign.Name = "Sign Preview"; + sign.Movable = false; + sign.Location = SignLoc; + sign.Map = Map; + + c_PreviewItems.Add( sign ); + + sign = new Item( 0xB9C ); + sign.Name = "Sign Preview"; + sign.Movable = false; + sign.Location = SignLoc; + sign.Map = Map; + + c_PreviewItems.Add( sign ); + + c_PreviewTimer = Timer.DelayCall( TimeSpan.FromSeconds( 100 ), new TimerCallback( ClearPreview ) ); + } + + public void ShowBanPreview() + { + ClearPreview(); + + Item ban = new Item( 0x17EE ); + ban.Name = "Ban Loc Preview"; + ban.Movable = false; + ban.Location = BanLoc; + ban.Map = Map; + + c_PreviewItems.Add( ban ); + + c_PreviewTimer = Timer.DelayCall( TimeSpan.FromSeconds( 100 ), new TimerCallback( ClearPreview ) ); + } + + public void ShowFloorsPreview(Mobile m) + { + ClearPreview(); + + Item item = new Item(0x7BD); + item.Name = "Bottom Floor Preview"; + item.Movable = false; + item.Location = m.Location; + item.Z = c_MinZ; + item.Map = Map; + + c_PreviewItems.Add(item); + + item = new Item(0x7BD); + item.Name = "Top Floor Preview"; + item.Movable = false; + item.Location = m.Location; + item.Z = c_MaxZ; + item.Map = Map; + + c_PreviewItems.Add(item); + + c_PreviewTimer = Timer.DelayCall(TimeSpan.FromSeconds(100), new TimerCallback(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; + } + + int price = c_Price + (sellitems ? c_ItemsPrice : 0); + + if (c_Free) + price = 0; + + if (m.AccessLevel == AccessLevel.Player && !Server.Mobiles.Banker.Withdraw(m, price)) + { + m.SendMessage("You cannot afford this house."); + return; + } + + if (m.AccessLevel == AccessLevel.Player) + m.SendLocalizedMessage(1060398, price.ToString()); // ~1_AMOUNT~ gold has been withdrawn from your bank box. + + Visible = false; + + int minX = ((Rectangle2D)c_Blocks[0]).Start.X; + int minY = ((Rectangle2D)c_Blocks[0]).Start.Y; + int maxX = ((Rectangle2D)c_Blocks[0]).End.X; + int maxY = ((Rectangle2D)c_Blocks[0]).End.Y; + + foreach (Rectangle2D rect in c_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; + } + + c_House = new TownHouse(m, this, c_Locks, c_Secures); + + c_House.Components.Resize( maxX-minX, maxY-minY ); + c_House.Components.Add( 0x520, c_House.Components.Width-1, c_House.Components.Height-1, -5 ); + + c_House.Location = new Point3D(minX, minY, Map.GetAverageZ(minX, minY)); + c_House.Map = Map; + c_House.Region.GoLocation = c_BanLoc; + c_House.Sign.Location = c_SignLoc; + c_House.Hanger = new Item(0xB9C); + c_House.Hanger.Location = c_SignLoc; + c_House.Hanger.Map = Map; + c_House.Hanger.Movable = false; + + if (c_ForcePublic) + c_House.Public = true; + + c_House.Price = (RentByTime == TimeSpan.FromDays(0) ? c_Price : 1); + + RUOVersion.UpdateRegion(this); + + if (c_House.Price == 0) + c_House.Price = 1; + + if (c_RentByTime != TimeSpan.Zero) + BeginRentTimer(c_RentByTime); + + c_RTOPayments = 1; + + HideOtherSigns(); + + c_DecoreItemInfos = new ArrayList(); + + ConvertItems(sellitems); + } + catch(Exception e) + { + Errors.Report(String.Format("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( Item item in c_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 ( c_House == null ) + return; + + ArrayList items = new ArrayList(); + foreach(Rectangle2D rect in c_Blocks) + foreach (Item item in Map.GetItemsInBounds(rect)) + if (c_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 == c_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; + c_House.LockDown(c_House.Owner, item, false); + } + } + } + } + + protected void ConvertDoor( BaseDoor door ) + { + if ( !Owned ) + return; + + if ( door is Server.Gumps.ISecurable ) + { + door.Locked = false; + c_House.Doors.Add( door ); + return; + } + + door.Open = false; + + GenericHouseDoor newdoor = new GenericHouseDoor( (DoorFacing)0, door.ClosedID, door.OpenedSound, door.ClosedSound ); + newdoor.Offset = door.Offset; + newdoor.ClosedID = door.ClosedID; + newdoor.OpenedID = door.OpenedID; + newdoor.Location = door.Location; + newdoor.Map = door.Map; + + door.Delete(); + + foreach( Item inneritem in newdoor.GetItemsInRange( 1 ) ) + if ( inneritem is BaseDoor && inneritem != newdoor && inneritem.Z == newdoor.Z ) + { + ((BaseDoor)inneritem).Link = newdoor; + newdoor.Link = (BaseDoor)inneritem; + } + + c_House.Doors.Add(newdoor); + } + + public virtual void UnconvertDoors() + { + if ( c_House == null ) + return; + + BaseDoor newdoor = null; + + foreach (BaseDoor door in new ArrayList(c_House.Doors)) + { + door.Open = false; + + if ( c_Relock ) + door.Locked = true; + + newdoor = new StrongWoodDoor( (DoorFacing)0 ); + newdoor.ItemID = door.ItemID; + newdoor.ClosedID = door.ClosedID; + newdoor.OpenedID = door.OpenedID; + newdoor.OpenedSound = door.OpenedSound; + newdoor.ClosedSound = door.ClosedSound; + newdoor.Offset = door.Offset; + newdoor.Location = door.Location; + newdoor.Map = door.Map; + + door.Delete(); + + foreach( Item inneritem in newdoor.GetItemsInRange( 1 ) ) + if ( inneritem is BaseDoor && inneritem != newdoor && inneritem.Z == newdoor.Z ) + { + ( (BaseDoor)inneritem ).Link = newdoor; + newdoor.Link = (BaseDoor)inneritem; + } + + c_House.Doors.Remove( door ); + } + } + + public void RecreateItems() + { + Item item = null; + foreach( DecoreItemInfo info in c_DecoreItemInfos ) + { + item = null; + + if ( info.TypeString.ToLower().IndexOf( "static" ) != -1 ) + 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; + } + } + + public virtual void ClearHouse() + { + UnconvertDoors(); + ClearDemolishTimer(); + ClearRentTimer(); + PackUpItems(); + RecreateItems(); + c_House = null; + Visible = true; + + if ( c_RentToOwn ) + c_RentByTime = c_OriginalRentTime; + } + + public virtual void ValidateOwnership() + { + if ( !Owned ) + return; + + if ( c_House.Owner == null ) + { + c_House.Delete(); + return; + } + + if ( c_House.Owner.AccessLevel != AccessLevel.Player ) + return; + + if ( !CanBuyHouse( c_House.Owner ) && c_DemolishTimer == null ) + BeginDemolishTimer(); + else + ClearDemolishTimer(); + } + + public int CalcVolume() + { + int floors = 1; + if ( c_MaxZ - c_MinZ < 100 ) + floors = 1 + Math.Abs( (c_MaxZ - c_MinZ)/20 ); + + Point3D point = Point3D.Zero; + ArrayList blocks = new ArrayList(); + + foreach( Rectangle2D rect in c_Blocks ) + for( int x = rect.Start.X; x < rect.End.X; ++x ) + for( int y = rect.Start.Y; y < rect.End.Y; ++y ) + for( int 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.Now) + BeginDemolishTimer(c_DemolishTime - DateTime.Now); + 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.Now; + + if ( !c_House.Deleted && Owned ) + c_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.Now + time; + c_DemolishTimer = Timer.DelayCall( time, new TimerCallback( PackUpHouse ) ); + + DemolishAlert(); + } + + protected virtual void DemolishAlert() + { + c_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.Now).Hours, (c_DemolishTime-DateTime.Now).Minutes, (c_DemolishTime-DateTime.Now).Seconds ); + } + + protected void PackUpHouse() + { + if ( !Owned || c_House.Deleted ) + return; + + PackUpItems(); + + c_House.Owner.BankBox.DropItem( new BankCheck( c_House.Price ) ); + + try + { + c_House.Delete(); + } + catch + { + Errors.Report("The infamous SVN bug has occured."); + } + + } + + /* Added for fixing Rental Loop Crash bug */ + protected void DeleteTest() + { + if ( !Owned || c_House.Deleted ) + return; + + PackUpItems(); + c_House.Owner.BankBox.DropItem( new BankCheck( c_House.Price ) ); + } + + protected void PackUpItems() + { + if ( c_House == null ) + return; + + Container bag = new Bag(); + bag.Name = "Town House Belongings"; + + foreach( Item item in new ArrayList( c_House.LockDowns ) ) + { + item.IsLockedDown = false; + item.Movable = true; + c_House.LockDowns.Remove( item ); + bag.DropItem( item ); + } + + foreach( SecureInfo info in new ArrayList( c_House.Secures ) ) + { + info.Item.IsLockedDown = false; + info.Item.IsSecure = false; + info.Item.Movable = true; + info.Item.SetLastMoved(); + c_House.Secures.Remove( info ); + bag.DropItem( info.Item ); + } + + foreach (Rectangle2D rect in c_Blocks) + { + ArrayList l = new ArrayList(); + foreach (Item item in Map.GetItemsInBounds(rect)) + l.Add(item); + + foreach (Item item in l) + { + if (item is HouseSign + || item is BaseDoor + || item is BaseMulti + || item is BaseAddon + || item is AddonComponent + || !item.Visible + || item.IsLockedDown + || item.IsSecure + || !item.Movable + || item.Map != c_House.Map + || !c_House.Region.Contains(item.Location)) + continue; + + bag.DropItem(item); + } + } + + if ( bag.Items.Count == 0 ) + { + bag.Delete(); + return; + } + + c_House.Owner.BankBox.DropItem( bag ); + } + + #endregion + + #region Rent + + public void ClearRentTimer() + { + if ( c_RentTimer != null ) + { + c_RentTimer.Stop(); + c_RentTimer = null; + } + + c_RentTime = DateTime.Now; + } + + private void BeginRentTimer() + { + BeginRentTimer( TimeSpan.FromDays( 1 ) ); + } + + private void BeginRentTimer( TimeSpan time ) + { + if ( !Owned ) + return; + + c_RentTimer = Timer.DelayCall( time, new TimerCallback( RentDue ) ); + c_RentTime = DateTime.Now + time; + } + + public void CheckRentTimer() + { + if ( c_RentTimer == null || !Owned ) + return; + + c_House.Owner.SendMessage( "This rent cycle ends in {0} days, {1}:{2}:{3}.", (c_RentTime-DateTime.Now).Days, (c_RentTime-DateTime.Now).Hours, (c_RentTime-DateTime.Now).Minutes, (c_RentTime-DateTime.Now).Seconds ); + } + + private void RentDue() + { + if ( !Owned || c_House.Owner == null ) + return; + + if ( !c_RecurRent ) + { + c_House.Owner.SendMessage( "Your town house rental contract has expired, and the bank has once again taken possession." ); + PackUpHouse(); + return; + } + + if ( !c_Free && c_House.Owner.AccessLevel == AccessLevel.Player && !Server.Mobiles.Banker.Withdraw( c_House.Owner, c_Price ) ) + { + c_House.Owner.SendMessage( "Since you can not afford the rent, the bank has reclaimed your town house." ); + PackUpHouse(); + return; + } + + if ( !c_Free ) + c_House.Owner.SendMessage( "The bank has withdrawn {0} gold rent for your town house.", c_Price ); + + OnRentPaid(); + + if ( c_RentToOwn ) + { + c_RTOPayments++; + + bool complete = false; + + if ( c_RentByTime == TimeSpan.FromDays( 1 ) && c_RTOPayments >= 60 ) + { + complete = true; + c_House.Price = c_Price*60; + } + + if ( c_RentByTime == TimeSpan.FromDays( 7 ) && c_RTOPayments >= 9 ) + { + complete = true; + c_House.Price = c_Price*9; + } + + if ( c_RentByTime == TimeSpan.FromDays( 30 ) && c_RTOPayments >= 2 ) + { + complete = true; + c_House.Price = c_Price*2; + } + + if ( complete ) + { + c_House.Owner.SendMessage( "You now own your rental home." ); + c_RentByTime = TimeSpan.FromDays( 0 ); + 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 + { + SkillName 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 ) + new TownHouseSetupGump( m, this ); + else if ( !Visible ) + return; + else if ( CanBuyHouse( m ) && !BaseHouse.HasAccountHouse( m ) ) + new TownHouseConfirmGump( m, this ); + else + m.SendMessage( "You cannot purchase this house." ); + } + + public override void Delete() + { + if ( c_House == null || c_House.Deleted ) + base.Delete(); + else + PublicOverheadMessage( Server.Network.MessageType.Regular, 0x0, true, "You cannot delete this while the home is owned." ); + + if ( this.Deleted ) + s_TownHouseSigns.Remove( this ); + } + + public override void GetProperties( ObjectPropertyList list ) + { + base.GetProperties( list ); + + string cost = String.Format("{0:n0}", c_Price); + string cost_items = String.Format("{0:n0}", c_ItemsPrice); + string locks = String.Format("{0:n0}", c_Locks); + string secures = String.Format("{0:n0}", c_Secures); + + if ( c_Free ) + list.Add( 1060658, "Price\tFree" ); + else if ( c_RentByTime == TimeSpan.Zero ) + list.Add( 1060658, "Price\t{0}{1}", cost, c_KeepItems ? " (+" + cost_items + " for the items)" : "" ); + else if ( c_RecurRent ) + list.Add( 1060658, "{0}\t{1}\r{2}", PriceType + (c_RentToOwn ? " Rent-to-Own" : " Recurring"), cost, c_KeepItems ? " (+" + cost_items + " for the items)" : "" ); + else + list.Add( 1060658, "One {0}\t{1}{2}", PriceTypeShort, cost, c_KeepItems ? " (+" + cost_items + " for the items)" : "" ); + + list.Add( 1060659, "Lockdowns\t{0}", locks ); + list.Add( 1060660, "Secures\t{0}", 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( 13 ); + + // Version 13 + + writer.Write(c_ForcePrivate); + writer.Write(c_ForcePublic); + writer.Write(c_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( c_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( c_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( c_Blocks.Count ); + foreach( Rectangle2D rect in c_Blocks ) + writer.Write( rect ); + } + + public override void Deserialize( GenericReader reader ) + { + base.Deserialize( reader ); + + int version = reader.ReadInt(); + + if (version >= 13) + { + c_ForcePrivate = reader.ReadBool(); + c_ForcePublic = reader.ReadBool(); + c_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 ) + { + int decorecount = reader.ReadInt(); + DecoreItemInfo info; + for( int i = 0; i < decorecount; ++i ) + { + info = new DecoreItemInfo(); + info.Load( reader ); + c_DecoreItemInfos.Add( info ); + } + + c_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 ) + c_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(); + + c_Blocks = new ArrayList(); + int count = reader.ReadInt(); + for ( int i = 0; i < count; ++i ) + c_Blocks.Add( reader.ReadRect2D() ); + + if ( c_RentTime > DateTime.Now ) + BeginRentTimer( c_RentTime-DateTime.Now ); + + Timer.DelayCall(TimeSpan.Zero, new TimerCallback(StartTimers)); + + ClearPreview(); + + s_TownHouseSigns.Add( this ); + } + } +} diff --git a/Scripts/Items/Houses/Monopoly/Misc/CommandInfo.cs b/Scripts/Items/Houses/Monopoly/Misc/CommandInfo.cs new file mode 100644 index 0000000..93a59ac --- /dev/null +++ b/Scripts/Items/Houses/Monopoly/Misc/CommandInfo.cs @@ -0,0 +1,36 @@ +using System; +using Server; + +namespace Knives.TownHouses +{ + public delegate void TownHouseCommandHandler(CommandInfo info); + + public class CommandInfo + { + private Mobile c_Mobile; + private string c_Command; + private string c_ArgString; + private string[] c_Arguments; + + public Mobile Mobile { get { return c_Mobile; } } + public string Command { get { return c_Command; } } + public string ArgString { get { return c_ArgString; } } + public string[] Arguments { get { return c_Arguments; } } + + public CommandInfo(Mobile m, string com, string args, string[] arglist) + { + c_Mobile = m; + c_Command = com; + c_ArgString = args; + c_Arguments = arglist; + } + + public string GetString(int num) + { + if (c_Arguments.Length > num) + return c_Arguments[num]; + + return ""; + } + } +} \ No newline at end of file diff --git a/Scripts/Items/Houses/Monopoly/Misc/DecoreItemInfo.cs b/Scripts/Items/Houses/Monopoly/Misc/DecoreItemInfo.cs new file mode 100644 index 0000000..b5aae3c --- /dev/null +++ b/Scripts/Items/Houses/Monopoly/Misc/DecoreItemInfo.cs @@ -0,0 +1,64 @@ +using System; +using Server; + +namespace Knives.TownHouses +{ + public class DecoreItemInfo + { + private string c_TypeString; + private string c_Name; + private int c_ItemID; + private int c_Hue; + private Point3D c_Location; + private Map c_Map; + + public string TypeString{ get{ return c_TypeString; } } + public string Name{ get{ return c_Name; } } + public int ItemID{ get{ return c_ItemID; } } + public int Hue{ get{ return c_Hue; } } + public Point3D Location{ get{ return c_Location; } } + public Map Map{ get{ return c_Map; } } + + public DecoreItemInfo() + { + } + + public DecoreItemInfo( string typestring, string name, int itemid, int hue, Point3D loc, Map map ) + { + c_TypeString = typestring; + c_ItemID = itemid; + c_Location = loc; + c_Map = map; + } + + public void Save( GenericWriter writer ) + { + writer.Write( (int)1 ); // Version + + // Version 1 + writer.Write( c_Hue ); + writer.Write( c_Name ); + + writer.Write( c_TypeString ); + writer.Write( c_ItemID ); + writer.Write( c_Location ); + writer.Write( c_Map ); + } + + public void Load( GenericReader reader ) + { + int version = reader.ReadInt(); + + if ( version >= 1 ) + { + c_Hue = reader.ReadInt(); + c_Name = reader.ReadString(); + } + + c_TypeString = reader.ReadString(); + c_ItemID = reader.ReadInt(); + c_Location = reader.ReadPoint3D(); + c_Map = reader.ReadMap(); + } + } +} \ No newline at end of file diff --git a/Scripts/Items/Houses/Monopoly/Misc/General.cs b/Scripts/Items/Houses/Monopoly/Misc/General.cs new file mode 100644 index 0000000..cd17bf2 --- /dev/null +++ b/Scripts/Items/Houses/Monopoly/Misc/General.cs @@ -0,0 +1,217 @@ +// Check PackUpHouse() for that crash on item delete. It causes a crash in RemoveMulti (Core) + +using System; +using System.Collections; +using Server; +using Server.Multis; + +namespace Knives.TownHouses +{ + public class General + { + public static string Version{ get { return "2.01"; } } + + // This setting determines the suggested gold value for a single square of a home + // which then derives price, lockdowns and secures. + public static int SuggestionFactor { get{ return 600; } } + + // This setting determines if players need License in order to rent out their property + public static bool RequireRenterLicense{ get{ return false; } } + + public static void Configure() + { + EventSink.WorldSave += new WorldSaveEventHandler( OnSave ); + } + + public static void Initialize() + { + EventSink.Login += new LoginEventHandler( OnLogin ); + EventSink.Speech += new SpeechEventHandler( HandleSpeech ); + EventSink.ServerStarted += new ServerStartedEventHandler( OnStarted ); + } + + private static void OnStarted() + { + foreach (TownHouse house in TownHouse.AllTownHouses) + { + house.InitSectorDefinition(); + RUOVersion.UpdateRegion(house.ForSaleSign); + } + } + + public static void OnSave( WorldSaveEventArgs e ) + { + foreach( TownHouseSign sign in new ArrayList( TownHouseSign.AllSigns ) ) + sign.ValidateOwnership(); + + foreach( TownHouse house in new ArrayList( TownHouse.AllTownHouses ) ) + if ( house.Deleted ) + { + TownHouse.AllTownHouses.Remove( house ); + continue; + } + } + + private static void OnLogin( LoginEventArgs e ) + { + foreach( BaseHouse house in BaseHouse.GetHouses( e.Mobile ) ) + if ( house is TownHouse ) + ((TownHouse)house).ForSaleSign.CheckDemolishTimer(); + } + + private static void HandleSpeech( SpeechEventArgs e ) + { + ArrayList houses = new ArrayList(BaseHouse.GetHouses( e.Mobile )); + + if ( houses == null ) + return; + + foreach( BaseHouse house in houses ) + { + if (!RUOVersion.RegionContains(house.Region, e.Mobile)) + continue; + + if ( house is TownHouse ) + house.OnSpeech( e ); + + if ( house.Owner == e.Mobile + && e.Speech.ToLower() == "create rental contract" + && CanRent( e.Mobile, house, true ) ) + { + e.Mobile.AddToBackpack( new RentalContract() ); + e.Mobile.SendMessage( "A rental contract has been placed in your bag." ); + } + + if ( house.Owner == e.Mobile + && e.Speech.ToLower() == "check storage" ) + { + int count = 0; + + e.Mobile.SendMessage( "You have {0} lockdowns and {1} secures available.", RemainingSecures( house ), RemainingLocks( house ) ); + + if ( (count = AllRentalLocks( house )) != 0 ) + e.Mobile.SendMessage( "Current rentals are using {0} of your lockdowns.", count ); + if ( (count = AllRentalSecures( house )) != 0 ) + e.Mobile.SendMessage( "Current rentals are using {0} of your secures.", count ); + } + } + } + + private static bool CanRent( Mobile m, BaseHouse house, bool say ) + { + if ( house is TownHouse && ((TownHouse)house).ForSaleSign.PriceType != "Sale" ) + { + if ( say ) + m.SendMessage( "You must own your property to rent it." ); + + return false; + } + + if ( RequireRenterLicense ) + { + RentalLicense lic = m.Backpack.FindItemByType( typeof( RentalLicense ) ) as RentalLicense; + + if ( lic != null && lic.Owner == null ) + lic.Owner = m; + + if ( lic == null || lic.Owner != m ) + { + if ( say ) + m.SendMessage( "You must have a renter's license to rent your property." ); + + return false; + } + } + + if ( EntireHouseContracted( house ) ) + { + if ( say ) + m.SendMessage( "This entire house already has a rental contract." ); + + return false; + } + + if ( RemainingSecures( house ) < 0 || RemainingLocks( house ) < 0 ) + { + if ( say ) + m.SendMessage( "You don't have the storage available to rent property." ); + + return false; + } + + return true; + } + + #region Rental Info + + public static bool EntireHouseContracted( BaseHouse house ) + { + foreach( Item item in TownHouseSign.AllSigns ) + if ( item is RentalContract && house == ((RentalContract)item).ParentHouse ) + if ( ((RentalContract)item).EntireHouse ) + return true; + + return false; + } + + public static bool HasContract( BaseHouse house ) + { + foreach( Item item in TownHouseSign.AllSigns ) + if ( item is RentalContract && house == ((RentalContract)item).ParentHouse ) + return true; + + return false; + } + + public static bool HasOtherContract( BaseHouse house, RentalContract contract ) + { + foreach( Item item in TownHouseSign.AllSigns ) + if ( item is RentalContract && item != contract && house == ((RentalContract)item).ParentHouse ) + return true; + + return false; + } + + public static int RemainingSecures( BaseHouse house ) + { + if ( house == null ) + return 0; + + int a, b, c, d; + + return (Core.AOS ? house.GetAosMaxSecures() - house.GetAosCurSecures( out a, out b, out c, out d ) : house.MaxSecures - house.SecureCount) - AllRentalSecures( house ); + } + + public static int RemainingLocks( BaseHouse house ) + { + if ( house == null ) + return 0; + + return (Core.AOS ? house.GetAosMaxLockdowns() - house.GetAosCurLockdowns() : house.MaxLockDowns - house.LockDownCount) - AllRentalLocks( house ); + } + + public static int AllRentalSecures( BaseHouse house ) + { + int count = 0; + + foreach( TownHouseSign sign in TownHouseSign.AllSigns ) + if ( sign is RentalContract && ((RentalContract)sign).ParentHouse == house ) + count+=sign.Secures; + + return count; + } + + public static int AllRentalLocks( BaseHouse house ) + { + int count = 0; + + foreach( TownHouseSign sign in TownHouseSign.AllSigns ) + if ( sign is RentalContract && ((RentalContract)sign).ParentHouse == house ) + count+=sign.Locks; + + return count; + } + + #endregion + } +} \ No newline at end of file diff --git a/Scripts/Items/Houses/Monopoly/Misc/GumpResponse.cs b/Scripts/Items/Houses/Monopoly/Misc/GumpResponse.cs new file mode 100644 index 0000000..3ed1e97 --- /dev/null +++ b/Scripts/Items/Houses/Monopoly/Misc/GumpResponse.cs @@ -0,0 +1,167 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using Server; +using Server.Network; +using Server.Gumps; + +namespace Knives.TownHouses +{ + public class GumpResponse + { + public static void Initialize() + { + Timer.DelayCall(TimeSpan.Zero, new TimerCallback(AfterInit)); + } + + private static void AfterInit() + { + PacketHandlers.Register(0xB1, 0, true, new OnPacketReceive(DisplayGumpResponse)); + } + + public static void DisplayGumpResponse(NetState state, PacketReader pvSrc) + { + int serial = pvSrc.ReadInt32(); + int typeID = pvSrc.ReadInt32(); + int buttonID = pvSrc.ReadInt32(); + + /* Fixed for SVN */ + //List gumps = state.Gumps; + List gumps = ((List)state.Gumps); + + for (int i = 0; i < gumps.Count; ++i) + { + Gump gump = gumps[i]; + + if (gump.Serial == serial && gump.TypeID == typeID) + { + int switchCount = pvSrc.ReadInt32(); + + if (switchCount < 0) + { + Console.WriteLine("Client: {0}: Invalid gump response, disconnecting...", state); + state.Dispose(); + return; + } + + int[] switches = new int[switchCount]; + + for (int j = 0; j < switches.Length; ++j) + switches[j] = pvSrc.ReadInt32(); + + int textCount = pvSrc.ReadInt32(); + + if (textCount < 0) + { + Console.WriteLine("Client: {0}: Invalid gump response, disconnecting...", state); + state.Dispose(); + return; + } + + TextRelay[] textEntries = new TextRelay[textCount]; + + for (int j = 0; j < textEntries.Length; ++j) + { + int entryID = pvSrc.ReadUInt16(); + int textLength = pvSrc.ReadUInt16(); + + if (textLength > 239) + return; + + string text = pvSrc.ReadUnicodeStringSafe(textLength); + textEntries[j] = new TextRelay(entryID, text); + } + + state.RemoveGump(i); + + if (!CheckResponse(gump, state.Mobile, buttonID)) + return; + + gump.OnResponse(state, new RelayInfo(buttonID, switches, textEntries)); + + return; + } + } + } + + private static bool CheckResponse(Gump gump, Mobile m, int id) + { + if (m == null || !m.Player) + return true; + + TownHouse th = null; + + ArrayList list = new ArrayList(); + foreach (Item item in m.GetItemsInRange(20)) + if (item is TownHouse) + list.Add(item); + + foreach (TownHouse t in list) + if (t.Owner == m) + { + th = t; + break; + } + + if (th == null || th.ForSaleSign == null) + return true; + + if (gump is HouseGumpAOS) + { + int val = id - 1; + + if (val < 0) + return true; + + int type = val % 15; + int index = val / 15; + + if (th.ForSaleSign.ForcePublic && type == 3 && index == 12 && th.Public) + { + m.SendMessage("This house cannot be private."); + m.SendGump(gump); + return false; + } + + if (th.ForSaleSign.ForcePrivate && type == 3 && index == 13 && !th.Public) + { + m.SendMessage("This house cannot be public."); + m.SendGump(gump); + return false; + } + + if (th.ForSaleSign.NoTrade && type == 6 && index == 1) + { + m.SendMessage("This house cannot be traded."); + m.SendGump(gump); + return false; + } + } + else if (gump is HouseGump) + { + if (th.ForSaleSign.ForcePublic && id == 17 && th.Public) + { + m.SendMessage("This house cannot be private."); + m.SendGump(gump); + return false; + } + + if (th.ForSaleSign.ForcePrivate && id == 17 && !th.Public) + { + m.SendMessage("This house cannot be public."); + m.SendGump(gump); + return false; + } + + if (th.ForSaleSign.NoTrade && id == 14) + { + m.SendMessage("This house cannot be traded."); + m.SendGump(gump); + return false; + } + } + + return true; + } + } +} \ No newline at end of file diff --git a/Scripts/Items/Houses/Monopoly/RUOVersion.cs b/Scripts/Items/Houses/Monopoly/RUOVersion.cs new file mode 100644 index 0000000..92fda88 --- /dev/null +++ b/Scripts/Items/Houses/Monopoly/RUOVersion.cs @@ -0,0 +1,137 @@ +/* + * The two lines following this entry specify what RunUO version you are running. + * In order to switch to RunUO 1.0 Final, remove the '//' in front of that setting + * and add '//' in front of '#define RunUO_2_RC1'. Warning: If you comment both + * out, many commands in this system will not work. Enjoy! + */ + +#define RunUO_2_RC1 +//#define RunUO_1_Final + +using System; +using System.Collections; +using Server; +using Server.Multis; +using Server.Network; + +#if (RunUO_2_RC1) + using Server.Commands; +#endif + +namespace Knives.TownHouses +{ + public class RUOVersion + { + private static Hashtable s_Commands = new Hashtable(); + + public static void AddCommand(string com, AccessLevel acc, TownHouseCommandHandler cch) + { + s_Commands[com.ToLower()] = cch; + + #if(RunUO_1_Final) + Server.Commands.Register(com, acc, new CommandEventHandler(OnCommand)); + #elif(RunUO_2_RC1) + Server.Commands.CommandSystem.Register(com, acc, new CommandEventHandler(OnCommand)); + #endif + } + + public static void OnCommand(CommandEventArgs e) + { + if (s_Commands[e.Command.ToLower()] == null) + return; + + ((TownHouseCommandHandler)s_Commands[e.Command.ToLower()])(new CommandInfo(e.Mobile, e.Command, e.ArgString, e.Arguments)); + } + + public static void UpdateRegion(TownHouseSign sign) + { + if (sign.House == null) + return; + + #if(RunUO_1_Final) + sign.House.Region.Coords = new ArrayList(sign.Blocks); + sign.House.Region.MinZ = sign.MinZ; + sign.House.Region.MaxZ = sign.MaxZ; + sign.House.Region.Unregister(); + sign.House.Region.Register(); + sign.House.Region.GoLocation = sign.BanLoc; + #elif(RunUO_2_RC1) + sign.House.UpdateRegion(); + + Rectangle3D rect = new Rectangle3D(Point3D.Zero, Point3D.Zero); + + for (int i = 0; i < sign.House.Region.Area.Length; ++i) + { + rect = sign.House.Region.Area[i]; + rect = new Rectangle3D(new Point3D(rect.Start.X - sign.House.X, rect.Start.Y - sign.House.Y, sign.MinZ), new Point3D(rect.End.X - sign.House.X, rect.End.Y - sign.House.Y, sign.MaxZ)); + sign.House.Region.Area[i] = rect; + } + + sign.House.Region.Unregister(); + sign.House.Region.Register(); + sign.House.Region.GoLocation = sign.BanLoc; + + #endif + } + + public static bool RegionContains(Region region, Mobile m) + { + #if(RunUO_1_Final) + return region.Mobiles.Contains(m); + #elif(RunUO_2_RC1) + return region.GetMobiles().Contains(m); + #endif + } + + public static Rectangle3D[] RegionArea(Region region) + { + #if(RunUO_1_Final) + + Rectangle3D[] rects = new Rectangle3D[region.Coords.Count]; + Rectangle2D rect = new Rectangle2D(Point2D.Zero, Point2D.Zero); + + for (int i = 0; i < rects.Length && i < region.Coords.Count; ++i) + { + rect = (Rectangle2D)region.Coords[i]; + rects[i] = new Rectangle3D(new Point3D(rect.Start.X, rect.Start.Y, region.MinZ), new Point3D(rect.End.X, rect.End.Y, region.MaxZ)); + } + + return rects; + + #elif(RunUO_2_RC1) + return region.Area; + #endif + } + } + + public class VersionHouse : BaseHouse + { + public VersionHouse(int id, Mobile m, int locks, int secures) + : base(id, m, locks, secures) + { + } + + public override Rectangle2D[] Area { get { return new Rectangle2D[5]; } } + + #if(RunUO_2_RC1) + + public override Point3D BaseBanLocation { get { return Point3D.Zero; } } + + #endif + + public VersionHouse(Serial serial) + : base(serial) + { + } + + public override void Serialize(GenericWriter writer) + { + base.Serialize(writer); + } + + public override void Deserialize(GenericReader reader) + { + base.Deserialize(reader); + } + } +} \ No newline at end of file diff --git a/Scripts/Items/Houses/StaticHouse.cs b/Scripts/Items/Houses/StaticHouse.cs new file mode 100644 index 0000000..f8bf0c7 --- /dev/null +++ b/Scripts/Items/Houses/StaticHouse.cs @@ -0,0 +1,106 @@ +using System; +using Server; +using Server.Multis; + +namespace Server.Custom.StaticHousing +{ + public class StaticHouse : BaseHouse + { + private Rectangle2D m_CustomArea; + private int m_MinZ; + private int m_MaxZ; + private int m_CustomLockdowns; + private int m_CustomSecures; + + public override Rectangle2D[] Area + { + get + { + return new Rectangle2D[] { new Rectangle2D(0, 0, m_CustomArea.Width, m_CustomArea.Height) }; + } + } + + public override Point3D BaseBanLocation + { + get + { + if (Sign != null) + return new Point3D(Sign.X, Sign.Y + 1, Sign.Z); + + return Point3D.Zero; + } + } + + public override double BonusStorageScalar { get { return 1.0; } } + + public StaticHouse(Mobile owner, Rectangle2D area, int minZ, int maxZ, int locks, int secures, int price) + : base(0xA28, owner, locks, secures) + { + RestrictDecay = true; + + m_CustomArea = area; + m_MinZ = minZ; + m_MaxZ = maxZ; + + m_CustomLockdowns = locks; + m_CustomSecures = secures; + + MaxLockDowns = locks; + MaxSecures = secures; + + Price = price; + + Components.Resize(area.Width, area.Height); + Components.Add(0x520, area.Width - 1, area.Height - 1, -5); + + SetSign(0, 0, 0); + } + + public StaticHouse(Serial serial) : base(serial) + { + } + + public override int GetAosMaxLockdowns() { return m_CustomLockdowns; } + public override int GetAosMaxSecures() { return m_CustomSecures; } + + public override bool IsInside(Point3D p, int height) + { + if (Deleted) return false; + + if (!m_CustomArea.Contains(new Point2D(p.X, p.Y))) + return false; + + if (p.Z >= m_MinZ && (p.Z + height) <= m_MaxZ) + return true; + + return false; + } + + public override void Serialize(GenericWriter writer) + { + base.Serialize(writer); + writer.Write((int)0); + + writer.Write(m_CustomArea); + writer.Write(m_MinZ); + writer.Write(m_MaxZ); + writer.Write(m_CustomLockdowns); + writer.Write(m_CustomSecures); + } + + public override void Deserialize(GenericReader reader) + { + base.Deserialize(reader); + int version = reader.ReadInt(); + + m_CustomArea = reader.ReadRect2D(); + m_MinZ = reader.ReadInt(); + m_MaxZ = reader.ReadInt(); + m_CustomLockdowns = reader.ReadInt(); + m_CustomSecures = reader.ReadInt(); + + Components.Resize(m_CustomArea.Width, m_CustomArea.Height); + Components.Add(0x520, m_CustomArea.Width - 1, m_CustomArea.Height - 1, -5); + } + } +} diff --git a/Scripts/Items/Houses/StaticHouseSign.cs b/Scripts/Items/Houses/StaticHouseSign.cs new file mode 100644 index 0000000..6a635f4 --- /dev/null +++ b/Scripts/Items/Houses/StaticHouseSign.cs @@ -0,0 +1,147 @@ +using System; +using Server; +using Server.Mobiles; +using Server.Gumps; +using Server.Network; + +namespace Server.Custom.StaticHousing +{ + public class StaticHouseSign : Item + { + private Rectangle2D m_HouseArea; + private int m_MinZ; + private int m_MaxZ; + private int m_Price; + private int m_CustomLockdowns; + private int m_CustomSecures; + + public Rectangle2D HouseArea { get { return m_HouseArea; } } + public int MinZ { get { return m_MinZ; } } + public int MaxZ { get { return m_MaxZ; } } + public int Price { get { return m_Price; } } + public int CustomLockdowns { get { return m_CustomLockdowns; } } + public int CustomSecures { get { return m_CustomSecures; } } + + [Constructable] + public StaticHouseSign(int itemID, Rectangle2D area, int minZ, int maxZ, int price, int locks, int secures) : base(itemID) + { + Name = "A Vacant House For Sale"; + Movable = false; + + m_HouseArea = area; + m_MinZ = minZ; + m_MaxZ = maxZ; + m_Price = price; + m_CustomLockdowns = locks; + m_CustomSecures = secures; + } + + public StaticHouseSign(Serial serial) : base(serial) + { + } + + public override void GetProperties(ObjectPropertyList list) + { + base.GetProperties(list); + list.Add(1060658, "Price\t{0} Gold", m_Price); + list.Add(1060659, "Lockdowns\t{0}", m_CustomLockdowns); + list.Add(1060660, "Secures\t{0}", m_CustomSecures); + } + + public override void OnDoubleClick(Mobile from) + { + if (!from.InRange(GetWorldLocation(), 3)) + { + from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that. + return; + } + + if (from is PlayerMobile) + { + from.SendGump(new StaticPurchaseGump((PlayerMobile)from, this)); + } + } + + public void Purchase(PlayerMobile pm) + { + if (Deleted) return; + + if (Banker.Withdraw(pm, m_Price)) + { + StaticHouse newHouse = new StaticHouse(pm, m_HouseArea, m_MinZ, m_MaxZ, m_CustomLockdowns, m_CustomSecures, m_Price); + + Point3D houseLoc = new Point3D(m_HouseArea.Start.X, m_HouseArea.Start.Y, m_MinZ); + newHouse.MoveToWorld(houseLoc, this.Map); + + if (newHouse.Sign != null) + newHouse.Sign.Location = this.Location; + + newHouse.BanLocation = new Point3D(this.X, this.Y + 1, this.Z); + + pm.PlaySound(0x249); + pm.SendMessage(68, $"You have purchased this home for {m_Price} gold."); + + this.Delete(); + } + else + { + pm.SendMessage(33, $"You need {m_Price} gold in your bank to purchase this home."); + } + } + + public override void Serialize(GenericWriter writer) + { + base.Serialize(writer); + writer.Write((int)0); + writer.Write(m_HouseArea); + writer.Write(m_MinZ); + writer.Write(m_MaxZ); + writer.Write(m_Price); + writer.Write(m_CustomLockdowns); + writer.Write(m_CustomSecures); + } + + public override void Deserialize(GenericReader reader) + { + base.Deserialize(reader); + int version = reader.ReadInt(); + m_HouseArea = reader.ReadRect2D(); + m_MinZ = reader.ReadInt(); + m_MaxZ = reader.ReadInt(); + m_Price = reader.ReadInt(); + m_CustomLockdowns = reader.ReadInt(); + m_CustomSecures = reader.ReadInt(); + } + + private class StaticPurchaseGump : Gump + { + private PlayerMobile m_Player; + private StaticHouseSign m_Sign; + + public StaticPurchaseGump(PlayerMobile pm, StaticHouseSign sign) : base(200, 200) + { + m_Player = pm; + m_Sign = sign; + + AddPage(0); + AddBackground(0, 0, 300, 150, 9270); + AddHtml(0, 15, 300, 20, "
Purchase Property?
", false, false); + AddHtml(20, 50, 260, 40, $"This will deduct {sign.Price} gold from your bank box.", false, false); + + AddButton(40, 100, 4005, 4007, 1, GumpButtonType.Reply, 0); + AddHtml(75, 100, 100, 20, "Confirm", false, false); + + AddButton(160, 100, 4005, 4007, 0, GumpButtonType.Reply, 0); + AddHtml(195, 100, 100, 20, "Cancel", false, false); + } + + public override void OnResponse(NetState sender, RelayInfo info) + { + if (info.ButtonID == 1 && m_Sign != null && !m_Sign.Deleted) + { + m_Sign.Purchase(m_Player); + } + } + } + } +} diff --git a/Scripts/TaskManager.cs b/Scripts/TaskManager.cs index d4ef335..f3e2797 100644 --- a/Scripts/TaskManager.cs +++ b/Scripts/TaskManager.cs @@ -1,7 +1,9 @@ using System; +using System.IO; using System.Collections.Generic; using Server; using Server.Items; +using Server.Custom.StaticHousing; namespace Server.Scripts.Custom { @@ -9,9 +11,6 @@ namespace Server.Scripts.Custom { public static void Initialize() { - // Timer.DelayCall parameters: (Initial Delay, Interval between runs, Method to call) - // We give the server 1 minute to finish booting up before running the first sweep, - // then it runs exactly every 1 hour after that. Timer.DelayCall(TimeSpan.FromMinutes(1), TimeSpan.FromHours(1), new TimerCallback(ExecuteTasks)); Console.WriteLine("TasksManager: Hourly automated tasks initialized."); @@ -25,20 +24,98 @@ namespace Server.Scripts.Custom { ClearSpawnedTraps(); } + CheckStaticHouses(); + } - // FUTURE TASKS: - // Just add new methods here as your server grows! - // Example: ClearAbandonedTents(); - // Example: AnnounceHourlyLottery(); + private static void CheckStaticHouses() + { + string filePath = Path.Combine(Core.BaseDirectory, "Data", "Config", "statichouses.cfg"); + + if (!File.Exists(filePath)) + { + Console.WriteLine("TasksManager: Error - Data/Config/statichouses.cfg not found!"); + return; + } + + int count = 0; + + using (StreamReader ip = new StreamReader(filePath)) + { + string line; + while ((line = ip.ReadLine()) != null) + { + line = line.Trim(); + if (line.Length == 0 || line.StartsWith("#")) continue; + + string[] split = line.Split(new char[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries); + + if (split.Length >= 13) + { + try + { + Map map = Map.Parse(split[0]); + Point3D signLoc = new Point3D(int.Parse(split[1]), int.Parse(split[2]), int.Parse(split[3])); + + Point2D start = new Point2D(int.Parse(split[4]), int.Parse(split[5])); + Point2D end = new Point2D(start.X + int.Parse(split[6]), start.Y + int.Parse(split[7])); + Rectangle2D area = new Rectangle2D(start, end); + + int minZ = int.Parse(split[8]); + int maxZ = int.Parse(split[9]); + int price = int.Parse(split[10]); + int locks = int.Parse(split[11]); + int secures = int.Parse(split[12]); + + int itemID = 0xC0B; + if (split.Length >= 14) + { + if (split[13].StartsWith("0x", StringComparison.OrdinalIgnoreCase)) + itemID = Convert.ToInt32(split[13], 16); + else + itemID = int.Parse(split[13]); + } + + if (map != null && !CheckForExistingHouse(map, signLoc)) + { + StaticHouseSign sign = new StaticHouseSign(itemID, area, minZ, maxZ, price, locks, secures); + sign.MoveToWorld(signLoc, map); + count++; + } + } + catch (Exception ex) + { + Console.WriteLine($"Error parsing statichouses.cfg line: {line}\n{ex.Message}"); + } + } + } + } + + if (count > 0) + Console.WriteLine($"TasksManager: Respawned {count} missing Static House signs."); + } + + private static bool CheckForExistingHouse(Map map, Point3D loc) + { + bool exists = false; + IPooledEnumerable eable = map.GetItemsInRange(loc, 0); + + foreach (Item item in eable) + { + if (item is StaticHouseSign || item is Server.Multis.HouseSign) + { + exists = true; + break; + } + } + + eable.Free(); + return exists; } private static void ClearSpawnedTraps() { - // We must put them in a list first. If we delete them while actively - // searching the World.Items dictionary, it will cause a crash. List trapsToDelete = new List(); - // Scan the entire world for any item that acts as a floor trap foreach (Item item in World.Items.Values) { if (item is BaseTrap) @@ -47,7 +124,6 @@ namespace Server.Scripts.Custom } } - // Loop through our safe list and delete them all foreach (Item trap in trapsToDelete) { trap.Delete();