diff --git a/Projects/UOContent/Items/Farming/FarmableCrop.cs b/Projects/UOContent/Items/Farming/FarmableCrop.cs index db07588cd..7144396be 100644 --- a/Projects/UOContent/Items/Farming/FarmableCrop.cs +++ b/Projects/UOContent/Items/Farming/FarmableCrop.cs @@ -14,6 +14,36 @@ public abstract partial class FarmableCrop : Item public abstract Item GetCropObject(); public abstract int GetPickedID(); + public override void AddNameProperties(IPropertyList list) + { + } + + public override bool HandlesOnMovement => true; + + public override void OnMovement(Mobile m, Point3D oldLocation) + { + if (m.Player && m.Alive && !_picked && m.InRange(this.Location, 2)) + { + Timer.DelayCall(TimeSpan.FromMilliseconds(100), () => + { + if (m.InRange(this.Location, 2) && !_picked) + { + OnPicked(m, Location, Map); + } + }); + } + base.OnMovement(m, oldLocation); + } + + public override bool OnMoveOver(Mobile from) + { + if (from != null && from.Alive && from.Player && !_picked) + { + OnPicked(from, this.Location, this.Map); + } + return base.OnMoveOver(from); + } + public override void OnDoubleClick(Mobile from) { var map = Map; @@ -40,7 +70,20 @@ public abstract partial class FarmableCrop : Item var spawn = GetCropObject(); - spawn?.MoveToWorld(loc, map); + //spawn?.MoveToWorld(loc, map); + if (spawn != null) + { + if (from.Backpack == null || !from.Backpack.CheckHold(from, spawn, true, true)) + { + spawn.MoveToWorld(loc, map); + from.SendMessage("Your backpack is full, the crop was placed on the ground."); + } + else + { + from.AddToBackpack(spawn); + from.PlaySound(0x13E); // Harvest sound + } + } _picked = true; @@ -59,11 +102,11 @@ public abstract partial class FarmableCrop : Item } [AfterDeserialization] - private void AfterDeserialization() + public void AfterDeserialization() { if (_picked) { - Unlink(); + //Unlink(); Delete(); } } diff --git a/Projects/UOContent/Items/Farming/FarmableFlax.cs b/Projects/UOContent/Items/Farming/FarmableFlax.cs index 5dd7fe755..a4bde23b4 100644 --- a/Projects/UOContent/Items/Farming/FarmableFlax.cs +++ b/Projects/UOContent/Items/Farming/FarmableFlax.cs @@ -6,11 +6,10 @@ namespace Server.Items; public partial class FarmableFlax : FarmableCrop { [Constructible] - public FarmableFlax() : base(GetCropID()) + public FarmableFlax() : base(6810) { } - - public static int GetCropID() => Utility.Random(6809, 3); + public static int GetCropID() => 6810; public override Item GetCropObject() => new Flax diff --git a/Projects/UOContent/Items/Resources/Tailor/Cotton.cs b/Projects/UOContent/Items/Resources/Tailor/Cotton.cs index 9d8ce0ef6..aab8e95c7 100644 --- a/Projects/UOContent/Items/Resources/Tailor/Cotton.cs +++ b/Projects/UOContent/Items/Resources/Tailor/Cotton.cs @@ -85,8 +85,17 @@ public partial class Cotton : Item, IDyable } else { - m_Cotton.Consume(); - wheel.BeginSpin(m_Cotton.OnSpun, from, m_Cotton.Hue); + int amountToProcess = m_Cotton.Amount; + int cottonHue = m_Cotton.Hue; + m_Cotton.Delete(); + wheel.BeginSpin((w, mobile, h) => + { + mobile.AddToBackpack(new SpoolOfThread(6 * amountToProcess) + { + Hue = h + }); + mobile.SendLocalizedMessage(1010577); // You put the spools of thread in your backpack. + }, from, cottonHue); } } } diff --git a/Projects/UOContent/Items/Resources/Tailor/Flax.cs b/Projects/UOContent/Items/Resources/Tailor/Flax.cs index 464778b14..d80337280 100644 --- a/Projects/UOContent/Items/Resources/Tailor/Flax.cs +++ b/Projects/UOContent/Items/Resources/Tailor/Flax.cs @@ -85,8 +85,17 @@ public partial class Flax : Item } else { - m_Flax.Consume(); - wheel.BeginSpin(m_Flax.OnSpun, from, m_Flax.Hue); + int amountToProcess = m_Flax.Amount; + int flaxHue = m_Flax.Hue; + m_Flax.Delete(); + wheel.BeginSpin((w, mobile, h) => + { + mobile.AddToBackpack(new SpoolOfThread(6 * amountToProcess) + { + Hue = h + }); + mobile.SendLocalizedMessage(1010577); // You put the spools of thread in your backpack. + }, from, flaxHue); } } } diff --git a/Projects/UOContent/Items/Resources/Tailor/Wool.cs b/Projects/UOContent/Items/Resources/Tailor/Wool.cs index 2ef0ddbf7..eb2f67163 100644 --- a/Projects/UOContent/Items/Resources/Tailor/Wool.cs +++ b/Projects/UOContent/Items/Resources/Tailor/Wool.cs @@ -14,6 +14,7 @@ public partial class Wool : Item, IDyable } public override double DefaultWeight => 4.0; + public virtual int YarnMultiplier => 3; public bool Dye(Mobile from, DyeTub sender) { @@ -81,8 +82,21 @@ public partial class Wool : Item, IDyable } else { - m_Wool.Consume(); - wheel.BeginSpin(m_Wool.OnSpun, from, m_Wool.Hue); + int amountToProcess = m_Wool.Amount; + int woolHue = m_Wool.Hue; + int multiplier = m_Wool.YarnMultiplier; + m_Wool.Delete(); + wheel.BeginSpin((w, mobile, h) => + { + int totalYarnEarned = multiplier * amountToProcess; + + mobile.AddToBackpack(new DarkYarn(totalYarnEarned) + { + Hue = h + }); + + mobile.SendLocalizedMessage(totalYarnEarned > 1 ? 1010576 : 1010574); + }, from, woolHue); } } else @@ -104,7 +118,7 @@ public partial class TaintedWool : Wool } public override double DefaultWeight => 4.0; - + public override int YarnMultiplier => 1; public override void OnSpun(ISpinningWheel wheel, Mobile from, int hue) { from.AddToBackpack(new DarkYarn diff --git a/Projects/UOContent/Items/Resources/Tailor/YarnsAndThreads.cs b/Projects/UOContent/Items/Resources/Tailor/YarnsAndThreads.cs index ea5265b6d..c4e86217d 100644 --- a/Projects/UOContent/Items/Resources/Tailor/YarnsAndThreads.cs +++ b/Projects/UOContent/Items/Resources/Tailor/YarnsAndThreads.cs @@ -65,26 +65,48 @@ public abstract partial class BaseClothMaterial : Item, IDyable { from.SendLocalizedMessage(1042001); // That must be in your pack for you to use it. } - else if (loom.Phase < 4) - { - m_Material.Consume(); - - if (targeted is Item item) - { - item.SendLocalizedMessageTo(from, 1010001 + loom.Phase++); - } - } else { - var create = new BoltOfCloth - { - Hue = m_Material.Hue - }; + // 1. Capture stack values and current loom state before deletion + int totalThreads = m_Material.Amount; + int currentPhase = loom.Phase; + int materialHue = m_Material.Hue; - m_Material.Consume(); - loom.Phase = 0; - from.SendLocalizedMessage(500368); // You create some cloth and put it in your backpack. - from.AddToBackpack(create); + // 2. Combine the loom's current contents with the incoming stack + int totalEffectiveThreads = currentPhase + totalThreads; + + // 3. Calculate bolts earned (5 threads per bolt) and the leftover phase remainder + int boltsToMake = totalEffectiveThreads / 5; + int newPhase = totalEffectiveThreads % 5; + + // 4. Safely delete the resource stack up front to prevent any anti-duping movement exploits + m_Material.Delete(); + + // 5. Commit the new leftover phase back to the loom structure + loom.Phase = newPhase; + + // 6. Award the bulk bolts of cloth if thresholds were met + if (boltsToMake > 0) + { + var create = new BoltOfCloth + { + Hue = materialHue, + Amount = boltsToMake + }; + + from.SendLocalizedMessage(500368); // You create some cloth and put it in your backpack. + from.AddToBackpack(create); + } + + // 7. If no bolts were finished but progress was added, send the proper progression message + if (boltsToMake == 0 && newPhase > 0) + { + if (targeted is Item item) + { + // Matches the original localization offsets (Phase 1 = 1010001, Phase 4 = 1010004) + item.SendLocalizedMessageTo(from, 1010000 + newPhase); + } + } } } else