diff --git a/Scripts/Engines/Craft/Core/CraftGump.cs b/Scripts/Engines/Craft/Core/CraftGump.cs
index 3bda0cc..8acf7bb 100644
--- a/Scripts/Engines/Craft/Core/CraftGump.cs
+++ b/Scripts/Engines/Craft/Core/CraftGump.cs
@@ -72,6 +72,8 @@ namespace Server.Engines.Craft
AddButton( 270, 402, 4005, 4007, GetButtonID( 6, 2 ), GumpButtonType.Reply, 0 );
AddHtmlLocalized( 305, 405, 150, 18, 1044013, LabelColor, false, false ); // MAKE LAST
+ AddButton( 270, 382, 4005, 4007, GetButtonID( 6, 7 ), GumpButtonType.Reply, 0 );
+ AddHtml( 305, 385, 150, 18, "CRAFT QUEUE", false, false ); // Caft Queue
// Mark option
if ( craftSystem.MarkOption )
{
@@ -527,13 +529,17 @@ namespace Server.Engines.Craft
m_From.SendGump( new CraftGump( m_From, m_CraftSystem, m_Tool, null, m_Page ) );
+ break;
+ }
+ case 7:
+ {
+ m_From.SendGump( new CraftQueueGump( m_From, m_CraftSystem, m_Tool ) );
break;
}
}
-
break;
}
}
}
}
-}
\ No newline at end of file
+}
diff --git a/Scripts/Engines/Craft/Core/CraftGumpItem.cs b/Scripts/Engines/Craft/Core/CraftGumpItem.cs
index 8a54d9f..b108cbd 100644
--- a/Scripts/Engines/Craft/Core/CraftGumpItem.cs
+++ b/Scripts/Engines/Craft/Core/CraftGumpItem.cs
@@ -63,6 +63,10 @@ namespace Server.Engines.Craft
AddButton( 15, 387, 4014, 4016, 0, GumpButtonType.Reply, 0 );
AddHtmlLocalized( 50, 390, 150, 18, 1044150, LabelColor, false, false ); // BACK
+ // --- ADD TO QUEUE BUTTON ---
+ AddButton( 270, 367, 4005, 4007, 2, GumpButtonType.Reply, 0 );
+ AddHtml( 305, 370, 150, 18, "ADD TO QUEUE", false, false );
+
AddButton( 270, 387, 4005, 4007, 1, GumpButtonType.Reply, 0 );
AddHtmlLocalized( 305, 390, 150, 18, 1044151, LabelColor, false, false ); // MAKE NOW
@@ -213,6 +217,14 @@ namespace Server.Engines.Craft
CraftGump craftGump = new CraftGump( m_From, m_CraftSystem, m_Tool, null );
m_From.SendGump( craftGump );
}
+ else if ( info.ButtonID == 2 )
+ {
+ CraftQueue.AddEntry( m_From, m_CraftSystem, m_CraftItem, m_Tool );
+ m_From.SendMessage( "Item added to your crafting queue." );
+
+ // Refresh the gump so they can keep clicking it if they want
+ m_From.SendGump( new CraftGumpItem( m_From, m_CraftSystem, m_CraftItem, m_Tool ) );
+ }
else // Make Button
{
int num = m_CraftSystem.CanCraft( m_From, m_Tool, m_CraftItem.ItemType );
@@ -241,4 +253,4 @@ namespace Server.Engines.Craft
}
}
}
-}
\ No newline at end of file
+}
diff --git a/Scripts/Engines/Craft/Core/CraftItem.cs b/Scripts/Engines/Craft/Core/CraftItem.cs
index b967d71..6e08c27 100644
--- a/Scripts/Engines/Craft/Core/CraftItem.cs
+++ b/Scripts/Engines/Craft/Core/CraftItem.cs
@@ -920,6 +920,7 @@ namespace Server.Engines.Craft
// Not enough resource to craft it
if ( !ConsumeRes( from, typeRes, craftSystem, ref checkResHue, ref checkMaxAmount, ConsumeType.None, ref checkMessage ) )
{
+ CraftQueue.Pause( from, "Missing resources." );
if ( tool != null && !tool.Deleted && tool.UsesRemaining > 0 )
from.SendGump( new CraftGump( from, craftSystem, tool, checkMessage ) );
else if ( checkMessage is int && (int)checkMessage > 0 )
@@ -959,6 +960,7 @@ namespace Server.Engines.Craft
// Not enough resource to craft it
if ( !ConsumeRes( from, typeRes, craftSystem, ref resHue, ref maxAmount, ConsumeType.All, ref message ) )
{
+ CraftQueue.Pause( from, "Missing resources." );
if ( tool != null && !tool.Deleted && tool.UsesRemaining > 0 )
from.SendGump( new CraftGump( from, craftSystem, tool, message ) );
else if ( message is int && (int)message > 0 )
@@ -1026,6 +1028,8 @@ namespace Server.Engines.Craft
CommandLogging.WriteLine( from, "Crafting {0} with craft system {1}", CommandLogging.Format( item ), craftSystem.GetType().Name );
//from.PlaySound( 0x57 );
+ // --- QUEUE SUCCESS HOOK ---
+ CraftQueue.HandleResult( from, true, quality == 2 );
}
if ( num == 0 )
@@ -1075,6 +1079,9 @@ namespace Server.Engines.Craft
// SkillCheck failed.
int num = craftSystem.PlayEndingEffect( from, true, true, toolBroken, endquality, false, this );
+ // --- QUEUE FAIL HOOK ---
+ CraftQueue.HandleResult( from, false, false );
+
if ( tool != null && !tool.Deleted && tool.UsesRemaining > 0 )
from.SendGump( new CraftGump( from, craftSystem, tool, num ) );
else if ( num > 0 )
diff --git a/Scripts/Engines/Craft/Core/CraftQueue.cs b/Scripts/Engines/Craft/Core/CraftQueue.cs
new file mode 100644
index 0000000..b8f0ca6
--- /dev/null
+++ b/Scripts/Engines/Craft/Core/CraftQueue.cs
@@ -0,0 +1,188 @@
+using System;
+using System.Collections.Generic;
+using Server;
+using Server.Engines.Craft;
+using Server.Items;
+
+namespace Server.Engines.Craft
+{
+ public class CraftQueueEntry
+ {
+ public CraftSystem System { get; set; }
+ public CraftItem Item { get; set; }
+ public BaseTool Tool { get; set; }
+ public int Amount { get; set; }
+ public int Made { get; set; }
+ public int Failed { get; set; }
+ public int Exceptional { get; set; }
+
+ public CraftQueueEntry( CraftSystem system, CraftItem item, BaseTool tool )
+ {
+ System = system;
+ Item = item;
+ Tool = tool;
+ Amount = 1;
+ Made = 0;
+ Failed = 0;
+ Exceptional = 0;
+ }
+ }
+
+ public class CraftQueue
+ {
+ private static Dictionary m_Queues = new Dictionary();
+
+ public List Entries { get; set; }
+ public bool IsPaused { get; set; }
+
+ public CraftQueue()
+ {
+ Entries = new List();
+ IsPaused = true; // Now defaults to Paused so the first click says "START"
+ }
+
+ public static CraftQueue GetQueue( Mobile m )
+ {
+ if ( !m_Queues.ContainsKey( m ) )
+ m_Queues[m] = new CraftQueue();
+
+ return m_Queues[m];
+ }
+
+ public static void AddEntry( Mobile m, CraftSystem system, CraftItem item, BaseTool tool )
+ {
+ CraftQueue queue = GetQueue( m );
+ queue.Entries.Add( new CraftQueueEntry( system, item, tool ) );
+ }
+
+ public static void Pause( Mobile m, string reason )
+ {
+ CraftQueue queue = GetQueue( m );
+ if ( !queue.IsPaused )
+ {
+ queue.IsPaused = true;
+ m.SendMessage( 0x20, $"Crafting queue paused: {reason}" );
+ }
+ }
+
+ public static void HandleResult( Mobile from, bool success, bool exceptional )
+ {
+ CraftQueue queue = GetQueue( from );
+
+ if ( queue.IsPaused || queue.Entries.Count == 0 )
+ return;
+
+ // Find the first item that still needs crafting
+ CraftQueueEntry entry = null;
+ foreach ( var e in queue.Entries )
+ {
+ if ( e.Amount > 0 )
+ {
+ entry = e;
+ break;
+ }
+ }
+
+ if ( entry == null ) return;
+
+ // Tally the stats
+ if ( success )
+ {
+ entry.Made++;
+ if ( exceptional )
+ entry.Exceptional++;
+ }
+ else
+ {
+ entry.Failed++;
+ }
+
+ // Decrement the remaining amount
+ entry.Amount--;
+
+ // Fire the next craft automatically!
+ Timer.DelayCall( TimeSpan.FromSeconds( 1.5 ), new TimerStateCallback( ProcessQueue ), from );
+ }
+
+ public static void ProcessQueue( object state )
+ {
+ Mobile from = (Mobile)state;
+ CraftQueue queue = GetQueue( from );
+
+ if ( queue.IsPaused )
+ return;
+
+ // Find the active item
+ CraftQueueEntry entry = null;
+ foreach ( var e in queue.Entries )
+ {
+ if ( e.Amount > 0 )
+ {
+ entry = e;
+ break;
+ }
+ }
+
+ if ( entry == null )
+ {
+ from.SendMessage( 0x480, "Your crafting queue is complete!" );
+ queue.IsPaused = true; // Auto-pause for the next time they use it
+ return;
+ }
+
+ // Safety Check: Did the tool break?
+ if ( entry.Tool == null || entry.Tool.Deleted || entry.Tool.UsesRemaining <= 0 )
+ {
+ Type toolType = entry.Tool != null ? entry.Tool.GetType() : null;
+ BaseTool newTool = null;
+
+ // Search the player's backpack for a valid replacement tool
+ if ( toolType != null && from.Backpack != null )
+ {
+ Item[] tools = from.Backpack.FindItemsByType( toolType );
+ foreach ( Item t in tools )
+ {
+ BaseTool bt = t as BaseTool;
+ if ( bt != null && !bt.Deleted && bt.UsesRemaining > 0 )
+ {
+ newTool = bt;
+ break; // Found a valid spare!
+ }
+ }
+ }
+
+ if ( newTool != null )
+ {
+ // Swap the broken tool out for the spare and keep going!
+ entry.Tool = newTool;
+ from.SendMessage( 0x480, "A broken tool was replaced with a spare from your backpack." );
+ }
+ else
+ {
+ // No spares found. Pause so they can go get one.
+ Pause( from, "Tool broken. Please place a new one in your backpack and hit Start." );
+ return;
+ }
+ }
+
+ // Figure out what resource (wood, ingot type, etc) they had selected
+ CraftContext context = entry.System.GetContext( from );
+ Type typeRes = null;
+ if ( context != null )
+ {
+ CraftSubResCol res = entry.System.CraftSubRes;
+ int resIndex = context.LastResourceIndex;
+ if ( resIndex > -1 && resIndex < res.Count )
+ typeRes = res.GetAt( resIndex ).ItemType;
+ }
+
+ // Close existing gumps so the screen doesn't spam
+ from.CloseGump( typeof( CraftGump ) );
+ from.CloseGump( typeof( CraftQueueGump ) );
+ from.CloseGump( typeof( CraftGumpItem ) );
+
+ // Start the next craft!
+ entry.Item.Craft( from, entry.System, typeRes, entry.Tool );
+ }
+ }
+}
diff --git a/Scripts/Engines/Craft/Core/CraftQueueGump.cs b/Scripts/Engines/Craft/Core/CraftQueueGump.cs
new file mode 100644
index 0000000..aa30a58
--- /dev/null
+++ b/Scripts/Engines/Craft/Core/CraftQueueGump.cs
@@ -0,0 +1,149 @@
+using System;
+using Server;
+using Server.Gumps;
+using Server.Network;
+using Server.Items;
+
+namespace Server.Engines.Craft
+{
+ public class CraftQueueGump : Gump
+ {
+ private Mobile m_From;
+ private CraftSystem m_CraftSystem;
+ private BaseTool m_Tool;
+
+ private const int LabelHue = 0x480;
+ private const int LabelColor = 0x7FFF;
+
+ public CraftQueueGump( Mobile from, CraftSystem craftSystem, BaseTool tool ) : base( 40, 40 )
+ {
+ m_From = from;
+ m_CraftSystem = craftSystem;
+ m_Tool = tool;
+
+ from.CloseGump( typeof( CraftQueueGump ) );
+ from.CloseGump( typeof( CraftGump ) );
+
+ CraftQueue queue = CraftQueue.GetQueue( from );
+
+ AddPage( 0 );
+ AddBackground( 0, 0, 530, 437, 5054 );
+ AddImageTiled( 10, 10, 510, 22, 2624 );
+ AddAlphaRegion( 10, 10, 510, 417 );
+
+ AddHtml( 10, 12, 510, 20, "CRAFTING QUEUE MANAGER", false, false );
+
+ // Back Button
+ AddButton( 15, 402, 4014, 4016, 0, GumpButtonType.Reply, 0 );
+ AddHtmlLocalized( 50, 405, 150, 18, 1044150, LabelColor, false, false ); // BACK
+
+ // Play / Pause Button
+ string playPauseStr = queue.IsPaused ? "START QUEUE" : "PAUSE QUEUE";
+ AddButton( 200, 402, 4005, 4007, 1, GumpButtonType.Reply, 0 );
+ AddHtml( 235, 405, 150, 18, $"{playPauseStr}", false, false );
+
+ // Update Quantities Button
+ AddButton( 380, 402, 4005, 4007, 2, GumpButtonType.Reply, 0 );
+ AddHtml( 415, 405, 150, 18, "UPDATE QTY", false, false );
+
+ // Main List Background
+ AddImageTiled( 10, 40, 510, 350, 2624 );
+
+ // Column Headers
+ AddHtml( 50, 45, 150, 18, "Item Name", false, false );
+ AddHtml( 230, 45, 50, 18, "Target", false, false );
+ AddHtml( 310, 45, 200, 18, "Made / Fail / Exc", false, false );
+
+ // Loop through the queue entries (Displaying up to 10 for clean UI)
+ for ( int i = 0; i < queue.Entries.Count && i < 10; i++ )
+ {
+ CraftQueueEntry entry = queue.Entries[i];
+ int y = 70 + (i * 30);
+
+ // Remove Item Button (Little red X)
+ AddButton( 15, y, 4020, 4022, 10 + i, GumpButtonType.Reply, 0 );
+
+ // Item Name
+ if ( entry.Item.NameNumber > 0 )
+ AddHtmlLocalized( 50, y, 170, 18, entry.Item.NameNumber, LabelColor, false, false );
+ else
+ AddLabel( 50, y, LabelHue, entry.Item.NameString );
+
+ // Text Entry Box for Amount (Dark background)
+ if ( entry.Amount > 0 )
+ {
+ AddImageTiled( 230, y, 50, 20, 0xBBC );
+ AddTextEntry( 230, y, 50, 20, LabelHue, i, entry.Amount.ToString() );
+ }
+ else
+ {
+ // If the item finishes, show a green DONE label instead of the text box
+ AddLabel( 230, y, 68, "DONE" );
+ }
+
+ // Statistics
+ AddLabel( 310, y, LabelHue, $"{entry.Made} / {entry.Failed} / {entry.Exceptional}" );
+ }
+
+ if ( queue.Entries.Count == 0 )
+ {
+ AddHtml( 10, 100, 510, 20, "Your crafting queue is currently empty.", false, false );
+ }
+ }
+
+ public override void OnResponse( NetState sender, RelayInfo info )
+ {
+ Mobile from = sender.Mobile;
+ CraftQueue queue = CraftQueue.GetQueue( from );
+
+ // Always read and save any typed text amounts before processing buttons
+ for ( int i = 0; i < queue.Entries.Count && i < 10; i++ )
+ {
+ TextRelay relay = info.GetTextEntry( i );
+ if ( relay != null )
+ {
+ int amount;
+ if ( int.TryParse( relay.Text, out amount ) && amount >= 0 )
+ {
+ queue.Entries[i].Amount = amount;
+ }
+ }
+ }
+
+ if ( info.ButtonID == 0 ) // Back
+ {
+ from.SendGump( new CraftGump( from, m_CraftSystem, m_Tool, null ) );
+ }
+ else if ( info.ButtonID == 1 ) // Toggle Pause
+ {
+ queue.IsPaused = !queue.IsPaused;
+ from.SendGump( new CraftQueueGump( from, m_CraftSystem, m_Tool ) );
+
+ if ( !queue.IsPaused )
+ {
+ from.SendMessage( 0x480, "Crafting queue started." );
+ CraftQueue.ProcessQueue( from );
+ }
+ else
+ {
+ from.SendMessage( 0x20, "Crafting queue paused." );
+ }
+ }
+ else if ( info.ButtonID == 2 ) // Update Qty
+ {
+ from.SendMessage( 0x480, "Queue quantities updated." );
+ from.SendGump( new CraftQueueGump( from, m_CraftSystem, m_Tool ) );
+ }
+ else if ( info.ButtonID >= 10 ) // Remove item from queue
+ {
+ int index = info.ButtonID - 10;
+ if ( index >= 0 && index < queue.Entries.Count )
+ {
+ queue.Entries.RemoveAt( index );
+ from.SendMessage( 0x20, "Item removed from queue." );
+ }
+ from.SendGump( new CraftQueueGump( from, m_CraftSystem, m_Tool ) );
+ }
+ }
+ }
+}