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 ); } } }