From eb7d215ba35a83202e05e13fba6c140350a24bbd Mon Sep 17 00:00:00 2001 From: WarrentyExpired Date: Tue, 18 Aug 2026 18:53:37 -0400 Subject: [PATCH] #W# Added FarmController to spawn farms. Auto harvest crops on walking over. --- Scripts/Engines/FarmController.cs | 74 +++++++++++++++++++++++++++ Scripts/Items/Farming/FarmableCrop.cs | 38 ++++++++++++-- Scripts/Misc/ValidSettings.cs | 21 ++++++++ Scripts/Settings.cs | 2 + 4 files changed, 132 insertions(+), 3 deletions(-) create mode 100644 Scripts/Engines/FarmController.cs diff --git a/Scripts/Engines/FarmController.cs b/Scripts/Engines/FarmController.cs new file mode 100644 index 0000000..e7f981a --- /dev/null +++ b/Scripts/Engines/FarmController.cs @@ -0,0 +1,74 @@ +using System; +using System.Collections.Generic; +using Server; +using Server.Items; + +namespace Server.Items +{ + // The class is now static, meaning it exists globally and not as an Item + public static class FarmController + { + // Vegetable Plot Boundaries + private static Rectangle2D VeggieRect = new Rectangle2D(795, 771, 17, 15); + // Reagent Plot Boundaries + private static Rectangle2D ReagentRect = new Rectangle2D(820, 843, 23, 16); + + // Lists must be static now + private static List m_VeggieTypes = new List { typeof(FarmableCabbage), typeof(FarmableCarrot), typeof(FarmableCotton), typeof(FarmableFlax), typeof(FarmableLettuce), typeof(FarmableOnion), typeof(FarmablePumpkin), typeof(FarmableTurnip), typeof(FarmableWheat) }; + //private static List m_ReagentTypes = new List { typeof(FarmableBlackPearl), typeof(FarmableBloodmoss), typeof(FarmableGarlic), typeof(FarmableGinseng), typeof(FarmableMandrakeRoot), typeof(FarmableNightshade), typeof(FarmableSpidersSilk), typeof(FarmableSulfurousAsh) }; + + // The core looks for 'Initialize' on startup and runs it automatically + public static void Initialize() + { + double mySpawnVal = Server.ValidSettings.FarmSpawnTimer(); + TimeSpan spawnInterval = TimeSpan.FromMinutes(mySpawnVal); + + // Start the global background timer + Timer.DelayCall(spawnInterval, spawnInterval, SpawnTick); + } + + private static void SpawnTick() + { + // Spawn 2 vegetables and 2 reagents each tick if space allows + SpawnInArea(VeggieRect, m_VeggieTypes, 2); + //SpawnInArea(ReagentRect, m_ReagentTypes, 2); + } + + private static void SpawnInArea(Rectangle2D rect, List types, int count) + { + // Safety net for empty lists + if (types == null || types.Count == 0) + return; + + for (int i = 0; i < count; i++) + { + int x = Utility.Random(rect.X, rect.Width); + int y = Utility.Random(rect.Y, rect.Height); + Point3D loc = new Point3D(x, y, 0); + + bool occupied = false; + + // Get the items in range + IPooledEnumerable eable = Map.Felucca.GetItemsInRange(loc, 0); + + // If the loop runs even once, something is there + foreach (Item item in eable) + { + occupied = true; + break; + } + + // Free the pool to prevent memory leaks + eable.Free(); + + // If the spot is empty, spawn the crop + if (!occupied) + { + Type type = types[Utility.Random(types.Count)]; + Item crop = (Item)Activator.CreateInstance(type); + crop.MoveToWorld(loc, Map.Felucca); + } + } + } + } +} diff --git a/Scripts/Items/Farming/FarmableCrop.cs b/Scripts/Items/Farming/FarmableCrop.cs index d70199f..5b99a9e 100644 --- a/Scripts/Items/Farming/FarmableCrop.cs +++ b/Scripts/Items/Farming/FarmableCrop.cs @@ -16,7 +16,29 @@ namespace Server.Items { Movable = false; } + public override bool HandlesOnMovement { get { return true; } } + public override void OnMovement( Mobile m, Point3D oldLocation ) + { + if ( m_Picked || !m.Alive || !m.Player ) + return; + + int harvestRange = (int)Server.ValidSettings.HarvestRange(); + + if ( m.InRange( this.Location, harvestRange ) ) + { + Map map = this.Map; + Point3D loc = this.Location; + + if ( Parent != null || Movable || IsLockedDown || IsSecure || map == null || map == Map.Internal ) + return; + + if ( m.InLOS( this ) ) + { + OnPicked( m, loc, map ); + } + } + } public override void OnDoubleClick( Mobile from ) { Map map = this.Map; @@ -31,14 +53,24 @@ namespace Server.Items OnPicked( from, loc, map ); } - public virtual void OnPicked( Mobile from, Point3D loc, Map map ) + public virtual void OnPicked( Mobile from, Point3D loc, Map map ) { ItemID = GetPickedID(); Item spawn = GetCropObject(); if ( spawn != null ) - spawn.MoveToWorld( loc, map ); + { + if ( from.Backpack != null && from.Backpack.TryDropItem( from, spawn, false ) ) + { + from.SendMessage( 0x35, "You harvest the crop and place it in your backpack." ); + } + else + { + from.SendMessage( 0x22, "Your backpack is full, so the crop drops to the ground." ); + spawn.MoveToWorld( loc, map ); + } + } m_Picked = true; @@ -91,4 +123,4 @@ namespace Server.Items } } } -} \ No newline at end of file +} diff --git a/Scripts/Misc/ValidSettings.cs b/Scripts/Misc/ValidSettings.cs index 256ff08..8e57319 100644 --- a/Scripts/Misc/ValidSettings.cs +++ b/Scripts/Misc/ValidSettings.cs @@ -101,5 +101,26 @@ namespace Server return gold; } + public static double FarmSpawnTimer() + { + if ( Settings.S_FarmSpawnTimer < 1.0 ) + { + Settings.S_FarmSpawnTimer = 1.0; + } + return Settings.S_FarmSpawnTimer; + } + + public static int HarvestRange() + { + if ( Settings.S_HarvestRange > 3 ) + { + Settings.S_HarvestRange = 3; + } + else if ( Settings.S_HarvestRange < 1 ) + { + Settings.S_HarvestRange = 1; + } + return Settings.S_HarvestRange; + } } } diff --git a/Scripts/Settings.cs b/Scripts/Settings.cs index fad309f..4894c1e 100644 --- a/Scripts/Settings.cs +++ b/Scripts/Settings.cs @@ -20,5 +20,7 @@ namespace Server public static bool S_CanStealWhileHoldingThings = true; public static bool S_MonstersSurprise = true; public static bool S_DungeonTraps = true; + public static double S_FarmSpawnTimer = 15.0; + public static int S_HarvestRange = 2; } }