#W# Added Crafting Queue and Crafting skill list.

This commit is contained in:
WarrentyExpired 2026-08-07 19:25:55 -04:00
parent 7ba1dd7245
commit 791f82b4d0
7 changed files with 911 additions and 5 deletions

View file

@ -96,6 +96,16 @@ namespace Server.Engines.Craft
}
// ****************************************
// --- CraftItemSkillListGump Button ---
AddButton( 410, 342, 4005, 4007, GetButtonID( 6, 9 ), GumpButtonType.Reply, 0 );
AddHtml( 445, 345, 80, 18, "<BASEFONT COLOR=#FFFFFF>SKILLS</BASEFONT>", false, false );
// -------------------------------------------------------
// --- Crafting Queue Button ---
AddButton( 410, 362, 4005, 4007, GetButtonID( 6, 10 ), GumpButtonType.Reply, 0 );
AddHtml( 445, 365, 80, 18, "<BASEFONT COLOR=#FFFFFF>QUEUE</BASEFONT>", false, false );
// -------------------------------------------------------
// Enhance option
if ( craftSystem.CanEnhance )
{
@ -607,13 +617,24 @@ namespace Server.Engines.Craft
if ( system.CanEnhance )
Enhance.BeginTarget( m_From, system, m_Tool );
break;
}
case 9: // Skill List
{
m_From.SendGump( new CraftGump( m_From, system, m_Tool, null, m_Page ) );
m_From.SendGump( new CraftItemSkillListGump( m_From, system, m_Tool ) );
break;
}
case 10: // Crafting Queue
{
m_From.SendGump( new CraftQueueGump( m_From, system, m_Tool ) );
break;
}
}
break;
}
}
}
}
}
}

View file

@ -74,7 +74,10 @@ namespace Server.Engines.Craft
AddButton( 270, 387, 4005, 4007, 1, GumpButtonType.Reply, 0 );
AddHtmlLocalized( 305, 390, 150, 18, 1044151, LabelColor, false, false ); // MAKE NOW
}
// --- Add to queue ---
AddButton( 385, 387, 4005, 4007, 2, GumpButtonType.Reply, 0 );
AddHtml( 415, 390, 150, 18, "<BASEFONT COLOR=#FFFFFF>ADD TO QUEUE</BASEFONT>", false, false );
// ---------------------------------------------
if ( craftItem.NameNumber > 0 )
AddHtmlLocalized( 330, 40, 180, 18, craftItem.NameNumber, LabelColor, false, false );
else
@ -256,6 +259,24 @@ namespace Server.Engines.Craft
CraftGump craftGump = new CraftGump( m_From, m_CraftSystem, m_Tool, null );
m_From.SendGump( craftGump );
}
// Add to Queue Button
else if ( info.ButtonID == 2 )
{
Type typeRes = null;
CraftContext context = m_CraftSystem.GetContext( m_From );
if ( context != null )
{
CraftSubResCol res = ( m_CraftItem.UseSubRes2 ? m_CraftSystem.CraftSubRes2 : m_CraftSystem.CraftSubRes );
int resIndex = ( m_CraftItem.UseSubRes2 ? context.LastResourceIndex2 : context.LastResourceIndex );
if ( resIndex > -1 )
typeRes = res.GetAt( resIndex ).ItemType;
}
m_From.SendGump( new QueueAmountGump( m_From, m_CraftSystem, m_CraftItem, typeRes, m_Tool ) );
//m_From.SendMessage( 0x35, "How many would you like to add to the queue?" );
//m_From.Prompt = new QueuePrompt( m_From, m_CraftSystem, m_CraftItem, typeRes, m_Tool );
}
else // Make Button
{
int num = m_CraftSystem.CanCraft( m_From, m_Tool, m_CraftItem.ItemType );
@ -284,4 +305,42 @@ namespace Server.Engines.Craft
}
}
}
}
public class QueuePrompt : Server.Prompts.Prompt
{
private Mobile m_From;
private CraftSystem m_System;
private CraftItem m_Item;
private Type m_ResType;
private BaseTool m_Tool;
public QueuePrompt( Mobile from, CraftSystem system, CraftItem item, Type resType, BaseTool tool )
{
m_From = from;
m_System = system;
m_Item = item;
m_ResType = resType;
m_Tool = tool;
}
public override void OnResponse( Mobile from, string text )
{
int amount = 0;
// Try to parse the text into a number
if ( int.TryParse( text, out amount ) && amount > 0 )
{
CraftQueue queue = CraftQueueManager.GetQueue( from, m_System );
queue.Entries.Add( new CraftQueueEntry( m_Item, m_ResType, amount ) );
from.SendMessage( 0x35, "Added {0} of that item to your crafting queue.", amount );
}
else
{
from.SendMessage( 0x22, "Invalid amount. Must be a number greater than 0." );
}
// Send them back to the main menu so they can queue more items!
from.SendGump( new CraftGump( from, m_System, m_Tool, null ) );
}
}
}

View file

@ -1064,7 +1064,7 @@ namespace Server.Engines.Craft
}
}
public void CompleteCraft( int quality, bool makersMark, Mobile from, CraftSystem craftSystem, Type typeRes, BaseTool tool, CustomCraft customCraft )
/*public void CompleteCraft( int quality, bool makersMark, Mobile from, CraftSystem craftSystem, Type typeRes, BaseTool tool, CustomCraft customCraft )
{
int badCraft = craftSystem.CanCraft( from, tool, m_Type );
@ -1292,6 +1292,260 @@ namespace Server.Engines.Craft
else if ( num > 0 )
from.SendLocalizedMessage( num );
}
}*/
public void CompleteCraft( int quality, bool makersMark, Mobile from, CraftSystem craftSystem, Type typeRes, BaseTool tool, CustomCraft customCraft )
{
int badCraft = craftSystem.CanCraft( from, tool, m_Type );
if ( badCraft > 0 )
{
if ( !CraftQueueManager.CheckQueue( from, craftSystem, tool, 1, false, badCraft ) )
{
if ( tool != null && !tool.Deleted && tool.UsesRemaining > 0 )
from.SendGump( new CraftGump( from, craftSystem, tool, badCraft ) );
else
from.SendLocalizedMessage( badCraft );
}
return;
}
int checkResHue = 0, checkMaxAmount = 0;
object checkMessage = null;
// Not enough resource to craft it
if ( !ConsumeRes( from, typeRes, craftSystem, ref checkResHue, ref checkMaxAmount, ConsumeType.None, ref checkMessage ) )
{
if ( !CraftQueueManager.CheckQueue( from, craftSystem, tool, 1, false, checkMessage ) )
{
if ( tool != null && !tool.Deleted && tool.UsesRemaining > 0 )
from.SendGump( new CraftGump( from, craftSystem, tool, checkMessage ) );
else if ( checkMessage is int && (int)checkMessage > 0 )
from.SendLocalizedMessage( (int)checkMessage );
else if ( checkMessage is string )
from.SendMessage( (string)checkMessage );
}
return;
}
else if ( !ConsumeAttributes( from, ref checkMessage, false ) )
{
if ( !CraftQueueManager.CheckQueue( from, craftSystem, tool, 1, false, checkMessage ) )
{
if ( tool != null && !tool.Deleted && tool.UsesRemaining > 0 )
from.SendGump( new CraftGump( from, craftSystem, tool, checkMessage ) );
else if ( checkMessage is int && (int)checkMessage > 0 )
from.SendLocalizedMessage( (int)checkMessage );
else if ( checkMessage is string )
from.SendMessage( (string)checkMessage );
}
return;
}
bool toolBroken = false;
int ignored = 1;
int endquality = 1;
bool allRequiredSkills = true;
if ( CheckSkills( from, typeRes, craftSystem, ref ignored, ref allRequiredSkills ) )
{
int resHue = 0;
int maxAmount = 0;
object message = null;
// Not enough resource to craft it
if ( !ConsumeRes( from, typeRes, craftSystem, ref resHue, ref maxAmount, ConsumeType.All, ref message ) )
{
if ( !CraftQueueManager.CheckQueue( from, craftSystem, tool, 1, false, message ) )
{
if ( tool != null && !tool.Deleted && tool.UsesRemaining > 0 )
from.SendGump( new CraftGump( from, craftSystem, tool, message ) );
else if ( message is int && (int)message > 0 )
from.SendLocalizedMessage( (int)message );
else if ( message is string )
from.SendMessage( (string)message );
}
return;
}
else if ( !ConsumeAttributes( from, ref message, true ) )
{
if ( !CraftQueueManager.CheckQueue( from, craftSystem, tool, 1, false, message ) )
{
if ( tool != null && !tool.Deleted && tool.UsesRemaining > 0 )
from.SendGump( new CraftGump( from, craftSystem, tool, message ) );
else if ( message is int && (int)message > 0 )
from.SendLocalizedMessage( (int)message );
else if ( message is string )
from.SendMessage( (string)message );
}
return;
}
tool.UsesRemaining--;
if ( craftSystem is DefBlacksmithy )
{
AncientSmithyHammer hammer = from.FindItemOnLayer( Layer.OneHanded ) as AncientSmithyHammer;
if ( hammer != null && hammer != tool )
{
hammer.UsesRemaining--;
if ( hammer.UsesRemaining < 1 )
hammer.Delete();
}
}
if ( tool.UsesRemaining < 1 && tool.BreakOnDepletion )
toolBroken = true;
if ( toolBroken )
tool.Delete();
int num = 0;
Item item;
if ( customCraft != null )
{
item = customCraft.CompleteCraft( out num );
}
else if ( typeof( MapItem ).IsAssignableFrom( ItemType ) && from.Map != Map.Trammel && from.Map != Map.Felucca )
{
item = new IndecipherableMap();
from.SendLocalizedMessage( 1070800 ); // The map you create becomes mysteriously indecipherable.
}
else
{
item = Activator.CreateInstance( ItemType ) as Item;
}
if ( item != null )
{
if( item is ICraftable )
endquality = ((ICraftable)item).OnCraft( quality, makersMark, from, craftSystem, typeRes, tool, this, resHue );
else if ( item.Hue == 0 )
item.Hue = resHue;
if ( maxAmount > 0 )
{
if ( !item.Stackable && item is IUsesRemaining )
((IUsesRemaining)item).UsesRemaining *= maxAmount;
else
item.Amount = maxAmount;
}
//from.AddToBackpack( item );
Container pack = from.Backpack;
SalvageBag craftBag = pack != null ? pack.FindItemByType( typeof( SalvageBag ) ) as SalvageBag : null;
if ( craftBag != null && craftBag.TryDropItem( from, item, false ) )
{
}
else
{
from.AddToBackpack( item );
}
if( from.AccessLevel > AccessLevel.Player )
CommandLogging.WriteLine( from, "Crafting {0} with craft system {1}", CommandLogging.Format( item ), craftSystem.GetType().Name );
}
if ( num == 0 )
num = craftSystem.PlayEndingEffect( from, false, true, toolBroken, endquality, makersMark, this );
bool queryFactionImbue = false;
int availableSilver = 0;
FactionItemDefinition def = null;
Faction faction = null;
if ( item is IFactionItem )
{
def = FactionItemDefinition.Identify( item );
if ( def != null )
{
faction = Faction.Find( from );
if ( faction != null )
{
Town town = Town.FromRegion( from.Region );
if ( town != null && town.Owner == faction )
{
Container pack = from.Backpack;
if ( pack != null )
{
availableSilver = pack.GetAmount( typeof( Silver ) );
if ( availableSilver >= def.SilverCost )
queryFactionImbue = Faction.IsNearType( from, def.VendorType, 12 );
}
}
}
}
}
if ( queryFactionImbue )
{
// Halt queue for Faction Imbuing decisions
CraftQueueManager.CheckQueue( from, craftSystem, tool, endquality, true, "Faction Imbue" );
from.SendGump( new FactionImbueGump( quality, item, from, craftSystem, tool, num, availableSilver, faction, def ) );
}
else if ( !CraftQueueManager.CheckQueue( from, craftSystem, tool, endquality, true, toolBroken ? (object) 1044038 : (object)null ) )
{
if ( tool != null && !tool.Deleted && tool.UsesRemaining > 0 )
from.SendGump( new CraftGump( from, craftSystem, tool, num ) );
else if ( num > 0 )
from.SendLocalizedMessage( num );
}
}
else if ( !allRequiredSkills )
{
if ( !CraftQueueManager.CheckQueue( from, craftSystem, tool, 1, false, 1044153 ) )
{
if ( tool != null && !tool.Deleted && tool.UsesRemaining > 0 )
from.SendGump( new CraftGump( from, craftSystem, tool, 1044153 ) );
else
from.SendLocalizedMessage( 1044153 ); // You don't have the required skills to attempt this item.
}
}
else
{
ConsumeType consumeType = ( UseAllRes ? ConsumeType.Half : ConsumeType.All );
int resHue = 0;
int maxAmount = 0;
object message = null;
if ( !ConsumeRes( from, typeRes, craftSystem, ref resHue, ref maxAmount, consumeType, ref message, true ) )
{
if ( !CraftQueueManager.CheckQueue( from, craftSystem, tool, 1, false, message ) )
{
if ( tool != null && !tool.Deleted && tool.UsesRemaining > 0 )
from.SendGump( new CraftGump( from, craftSystem, tool, message ) );
else if ( message is int && (int)message > 0 )
from.SendLocalizedMessage( (int)message );
else if ( message is string )
from.SendMessage( (string)message );
}
return;
}
tool.UsesRemaining--;
if ( tool.UsesRemaining < 1 && tool.BreakOnDepletion )
toolBroken = true;
if ( toolBroken )
tool.Delete();
int num = craftSystem.PlayEndingEffect( from, true, true, toolBroken, endquality, false, this );
if ( !CraftQueueManager.CheckQueue( from, craftSystem, tool, endquality, false, toolBroken ? (object)1044038 : (object)null ) )
{
if ( tool != null && !tool.Deleted && tool.UsesRemaining > 0 )
from.SendGump( new CraftGump( from, craftSystem, tool, num ) );
else if ( num > 0 )
from.SendLocalizedMessage( num );
}
}
}
private class InternalTimer : Timer

View file

@ -0,0 +1,162 @@
using System;
using System.Collections.Generic;
using Server.Gumps;
using Server.Network;
using Server.Items;
using System.Linq;
using Server.Mobiles;
namespace Server.Engines.Craft
{
public class CraftItemSkillListGump : Gump
{
private const int PAGE_BUTTON_OFFSET = 100;
private const int SHOW_ITEM_INFO_OFFSET = 10000;
private readonly Mobile m_From;
private readonly CraftSystem m_CraftSystem;
private readonly BaseTool m_Tool;
private readonly List<CraftItem> m_CraftItems;
private readonly int m_PageNumber;
public CraftItemSkillListGump(Mobile from, CraftSystem craftSystem, BaseTool tool, List<CraftItem> craftItems, int pageNumber) : base(572, 40)
{
m_From = from;
m_CraftSystem = craftSystem;
m_Tool = tool;
m_CraftItems = craftItems;
m_PageNumber = pageNumber;
const int HORIZONTAL_LINE = 2700;
const int BORDER_WIDTH = 2;
const int ITEM_HEIGHT = 30;
const int INFO_WINDOW_WIDTH = 300;
AddImageTiled(0, 0, INFO_WINDOW_WIDTH, 400, 2702);
const int LOCK_COLUMN_X = 5;
const int NAME_COLUMN_X = LOCK_COLUMN_X + 33;
const int SKILL_COLUMN_WIDTH = NAME_COLUMN_X + 30;
const int SKILL_COLUMN_X = INFO_WINDOW_WIDTH - SKILL_COLUMN_WIDTH;
const int ITEM_START_Y = 2 * ITEM_HEIGHT;
// Fixed: Replaced HtmlColors.OFFWHITE with standard UO 0x7FFF
TextDefinition.AddHtmlText(this, LOCK_COLUMN_X, 30, INFO_WINDOW_WIDTH, 20, "Craft these items for skill gains", false, false, 0x7FFF, 0x7FFF);
TextDefinition.AddHtmlText(this, SKILL_COLUMN_X, 10, SKILL_COLUMN_WIDTH, 40, "Max Skill", false, false, 0x7FFF, 0x7FFF);
const int ITEMS_PER_PAGE = 10;
var maxPages = (int)Math.Ceiling((double)m_CraftItems.Count / ITEMS_PER_PAGE);
int lineIndex = 0;
var toSkip = (pageNumber - 1) * ITEMS_PER_PAGE;
foreach (var craftItem in m_CraftItems.Skip(toSkip).Take(ITEMS_PER_PAGE))
{
for (int k = 0; k < craftItem.Skills.Count; k++)
{
CraftSkill skill = craftItem.Skills.GetAt(k);
if (skill.SkillToMake == craftSystem.MainSkill)
{
var y = ITEM_START_Y + (lineIndex * ITEM_HEIGHT);
// Add border above item
if (0 < lineIndex) // Skip the first
AddImageTiled(10, y - 7, INFO_WINDOW_WIDTH - 15, BORDER_WIDTH, HORIZONTAL_LINE);
// Fixed: Removed missing CliLocTable and used core TextDefinition
TextDefinition name = craftItem.NameString == null ? new TextDefinition(craftItem.NameNumber) : new TextDefinition(craftItem.NameString);
var hasRecipe = craftItem.Recipe == null || (from is PlayerMobile && ((PlayerMobile)from).HasRecipe( craftItem.Recipe ));
if (!hasRecipe)
{
AddImage(LOCK_COLUMN_X + 8, y + 3, 2092); // Lock icon
// Fixed: AddTooltip requires a cliloc integer, not a string!
AddTooltip(1073620); // "You have not learned this recipe."
}
else
{
AddButton(LOCK_COLUMN_X, y - 2, 4011, 4012, SHOW_ITEM_INFO_OFFSET + toSkip + lineIndex, GumpButtonType.Reply, 0); // Info icon
}
// Fixed: Replaced HtmlColors.OFFWHITE with standard UO 0x7FFF
TextDefinition.AddHtmlText(this, NAME_COLUMN_X, y, SKILL_COLUMN_X - 20, 20, name, false, false, 0x7FFF, 0x7FFF);
TextDefinition.AddHtmlText(this, SKILL_COLUMN_X, y, SKILL_COLUMN_WIDTH, 20, String.Format("{0:F1}", skill.MaxSkill), false, false, 0x7FFF, 0x7FFF);
lineIndex++;
break;
}
}
}
// Add page buttons
if (maxPages != 1)
{
AddButton(NAME_COLUMN_X, 365, 4014, 4015, PAGE_BUTTON_OFFSET + (pageNumber == 1 ? maxPages : pageNumber - 1), GumpButtonType.Reply, 0); // Previous
AddButton(SKILL_COLUMN_X, 365, 4005, 4006, PAGE_BUTTON_OFFSET + (pageNumber == maxPages ? 1 : pageNumber + 1), GumpButtonType.Reply, 0); // Next
}
}
public CraftItemSkillListGump(Mobile from, CraftSystem craftSystem, BaseTool tool) : this(from, craftSystem, tool, CreateItemList(from, craftSystem), 1)
{
}
public override void OnResponse(NetState sender, RelayInfo info)
{
if (info.ButtonID == 0) return;
if (SHOW_ITEM_INFO_OFFSET <= info.ButtonID)
{
var itemIndex = info.ButtonID - SHOW_ITEM_INFO_OFFSET;
var item = m_CraftItems[itemIndex];
sender.Mobile.SendGump(new CraftItemSkillListGump(m_From, m_CraftSystem, m_Tool, m_CraftItems, m_PageNumber));
var itemInfoGump = new CraftGumpItem(sender.Mobile, m_CraftSystem, item, m_Tool);
sender.Mobile.SendGump(itemInfoGump);
}
else if (PAGE_BUTTON_OFFSET <= info.ButtonID)
{
var pageNumber = info.ButtonID - PAGE_BUTTON_OFFSET;
sender.Mobile.SendGump(new CraftItemSkillListGump(m_From, m_CraftSystem, m_Tool, m_CraftItems, pageNumber));
}
}
public static List<CraftItem> CreateItemList(Mobile from, CraftSystem craftSystem)
{
var craftItems = new List<CraftItem>();
for (int i = 0; i < craftSystem.CraftGroups.Count; i++)
{
var group = craftSystem.CraftGroups.GetAt(i);
for (int j = 0; j < group.CraftItems.Count; j++)
{
var craftItem = group.CraftItems.GetAt(j);
bool hasSkills = true;
for (int k = 0; k < craftItem.Skills.Count; k++)
{
CraftSkill skill = craftItem.Skills.GetAt(k);
if (
from.Skills[skill.SkillToMake].Value < skill.MinSkill // Filter items you can't succeed on
|| skill.MaxSkill <= from.Skills[skill.SkillToMake].Value // Filter items you can longer gain from
)
{
hasSkills = false;
break;
}
}
if (hasSkills)
craftItems.Add(craftItem);
}
}
// Sort by max skill descending
return craftItems.OrderByDescending(craftItem =>
{
for (int k = 0; k < craftItem.Skills.Count; k++)
{
CraftSkill skill = craftItem.Skills.GetAt(k);
if (skill.SkillToMake == craftSystem.MainSkill) return skill.MaxSkill;
}
return 0;
}).ToList();
}
}
}

View file

@ -0,0 +1,153 @@
using System;
using System.Collections.Generic;
using Server;
using Server.Engines.Craft;
using Server.Items;
namespace Server.Engines.Craft
{
public class CraftQueueEntry
{
public CraftItem CraftItem { get; set; }
public Type ResourceType { get; set; }
public int TargetAmount { get; set; }
public int AmountMade { get; set; }
public int AmountFailed { get; set; }
public int AmountExceptional { get; set; }
public bool IsCompleted { get; set; }
public CraftQueueEntry( CraftItem item, Type resType, int target )
{
CraftItem = item;
ResourceType = resType;
TargetAmount = target;
IsCompleted = false;
}
}
public class CraftQueue
{
public List<CraftQueueEntry> Entries { get; set; }
public bool IsPaused { get; set; }
public CraftQueue()
{
Entries = new List<CraftQueueEntry>();
IsPaused = true; // Always start paused so they can safely build the list
}
}
public static class CraftQueueManager
{
private static Dictionary<Mobile, Dictionary<CraftSystem, CraftQueue>> m_Data = new Dictionary<Mobile, Dictionary<CraftSystem, CraftQueue>>();
// Here is the GetQueue method that went missing!
public static CraftQueue GetQueue( Mobile m, CraftSystem system )
{
if ( !m_Data.ContainsKey( m ) )
m_Data[m] = new Dictionary<CraftSystem, CraftQueue>();
if ( !m_Data[m].ContainsKey( system ) )
m_Data[m][system] = new CraftQueue();
return m_Data[m][system];
}
public static bool CheckQueue( Mobile from, CraftSystem system, BaseTool tool, int endquality, bool success, object haltMessage )
{
CraftQueue queue = GetQueue( from, system );
if ( queue.IsPaused || queue.Entries.Count == 0 )
return false;
// --- AVATARS CONQUEST: Seamless Auto-Tool Replacement ---
if ( haltMessage is int && (int)haltMessage == 1044038 )
{
BaseTool replacement = from.Backpack != null ? from.Backpack.FindItemByType( tool.GetType() ) as BaseTool : null;
if ( replacement != null && !replacement.Deleted && replacement.UsesRemaining > 0 )
{
tool = replacement; // Swap to the new tool
haltMessage = null; // Erase the error message so the queue doesn't pause!
from.SendMessage( 0x35, "Your tool broke, but you automatically equipped a new one!" );
}
}
// 1. Tally stats for the item that just finished
CraftQueueEntry current = queue.Entries.Find( e => !e.IsCompleted );
if ( current != null )
{
if ( success )
{
current.AmountMade++; // <--- The ONLY place it counts up now!
if ( endquality == 2 )
current.AmountExceptional++;
if ( current.AmountMade >= current.TargetAmount )
{
current.IsCompleted = true;
from.SendMessage( 0x3E, "Queue task complete: " + current.CraftItem.NameString );
}
}
else
{
// If it wasn't a success and it isn't just a broken tool, count it as a failure
if ( haltMessage is int && (int)haltMessage == 1044038 )
{
// The item WAS successfully made, the tool just broke, so don't count a failure
}
else
{
current.AmountFailed++;
// Also check completion on failure if we want to stop after X attempts
if ( (current.AmountMade + current.AmountFailed) >= current.TargetAmount )
{
current.IsCompleted = true;
from.SendMessage( 0x3E, "Queue task complete (with failures): " + current.CraftItem.NameString );
}
}
}
}
if ( haltMessage != null )
{
queue.IsPaused = true;
from.SendMessage( 0x22, "Queue paused: Missing materials, tool broke, or skill too low." );
from.CloseGump( typeof( CraftQueueGump ) );
from.SendGump( new CraftQueueGump( from, system, tool ) );
return false;
}
// Refresh UI
from.CloseGump( typeof( CraftQueueGump ) );
from.SendGump( new CraftQueueGump( from, system, tool ) );
// 2. Logic to find the NEXT thing to craft
Timer.DelayCall( TimeSpan.FromSeconds( 1.0 ), delegate()
{
CraftQueue currentQueue = GetQueue( from, system );
// Find the next incomplete item
CraftQueueEntry next = currentQueue.Entries.Find( e => !e.IsCompleted );
if ( !currentQueue.IsPaused && next != null && from.NetState != null && tool != null && !tool.Deleted )
{
// Execute the craft call for the NEXT item
next.CraftItem.Craft( from, system, next.ResourceType, tool );
}
else if ( next == null ) // All entries completed
{
currentQueue.IsPaused = true;
from.SendMessage( 0x3E, "All crafting queue tasks are finished." );
from.CloseGump( typeof( CraftQueueGump ) );
from.SendGump( new CraftQueueGump( from, system, tool ) );
}
});
return true;
}
}
}

View file

@ -0,0 +1,66 @@
using System;
using Server.Gumps;
using Server.Network;
using Server.Engines.Craft;
using Server.Items;
namespace Server.Engines.Craft
{
public class QueueAmountGump : Gump
{
private Mobile m_From;
private CraftSystem m_System;
private CraftItem m_Item;
private Type m_ResType;
private BaseTool m_Tool;
public QueueAmountGump( Mobile from, CraftSystem system, CraftItem item, Type resType, BaseTool tool ) : base( 200, 200 )
{
m_From = from;
m_System = system;
m_Item = item;
m_ResType = resType;
m_Tool = tool;
// Match the theme: 5054 background, 2624 tiles
AddBackground( 0, 0, 250, 160, 5054 );
AddImageTiled( 10, 10, 230, 22, 2624 );
AddAlphaRegion( 10, 10, 230, 140 );
AddHtml( 10, 12, 230, 20, "<CENTER><BASEFONT COLOR=#FFFFFF>AMOUNT TO QUEUE</BASEFONT></CENTER>", false, false );
// Input Box
AddImageTiled( 50, 50, 150, 25, 2624 );
AddTextEntry( 55, 52, 140, 20, 0x480, 1, "1" );
// Buttons
AddButton( 40, 110, 4005, 4007, 1, GumpButtonType.Reply, 0 ); // OK
AddLabel( 70, 113, 0x480, "ADD " );
AddButton( 150, 110, 4017, 4019, 0, GumpButtonType.Reply, 0 ); // CANCEL
AddLabel( 185, 113, 0x480, "CANCEL " );
}
public override void OnResponse( NetState sender, RelayInfo info )
{
if ( info.ButtonID == 1 )
{
TextRelay relay = info.GetTextEntry( 1 );
int amount = 0;
if ( relay != null && int.TryParse( relay.Text, out amount ) && amount > 0 )
{
CraftQueue queue = CraftQueueManager.GetQueue( m_From, m_System );
queue.Entries.Add( new CraftQueueEntry( m_Item, m_ResType, amount ) );
m_From.SendMessage( 0x35, "Added {0} of that item to your queue.", amount );
}
else
{
m_From.SendMessage( 0x22, "Invalid amount." );
}
}
// Always return to the craft gump
m_From.SendGump( new CraftGump( m_From, m_System, m_Tool, null ) );
}
}
}

View file

@ -0,0 +1,191 @@
using System;
using Server.Gumps;
using Server.Network;
using Server.Mobiles;
using Server.Items;
namespace Server.Engines.Craft
{
public class CraftQueueGump : Gump
{
private Mobile m_From;
private CraftSystem m_System;
private BaseTool m_Tool;
private CraftQueue m_Queue;
public CraftQueueGump( Mobile from, CraftSystem system, BaseTool tool ) : base( 40, 40 )
{
m_From = from;
m_System = system;
m_Tool = tool;
m_Queue = CraftQueueManager.GetQueue( from, system );
AddPage( 0 );
AddBackground( 0, 0, 600, 440, 5054 );
AddImageTiled( 10, 10, 580, 22, 2624 );
AddImageTiled( 10, 37, 580, 360, 2624 );
AddImageTiled( 10, 402, 580, 28, 2624 );
AddAlphaRegion( 10, 10, 580, 420 );
AddHtml( 10, 12, 580, 20, "<CENTER><BASEFONT COLOR=#FFFFFF>CRAFTING QUEUE</BASEFONT></CENTER>", false, false );
// Column Headers
AddHtml( 15, 40, 150, 20, "<BASEFONT COLOR=#FFFFFF>Item</BASEFONT>", false, false );
AddHtml( 165, 40, 100, 20, "<BASEFONT COLOR=#FFFFFF>Material</BASEFONT>", false, false );
AddHtml( 275, 40, 50, 20, "<BASEFONT COLOR=#FFFFFF>Target</BASEFONT>", false, false );
AddHtml( 335, 40, 50, 20, "<BASEFONT COLOR=#FFFFFF>Made</BASEFONT>", false, false );
AddHtml( 395, 40, 50, 20, "<BASEFONT COLOR=#FFFFFF>Fail</BASEFONT>", false, false );
AddHtml( 455, 40, 50, 20, "<BASEFONT COLOR=#FFFFFF>Exc</BASEFONT>", false, false );
AddHtml( 515, 40, 50, 20, "<BASEFONT COLOR=#FFFFFF>Remove</BASEFONT>", false, false );
int y = 60;
for ( int i = 0; i < m_Queue.Entries.Count; i++ )
{
CraftQueueEntry entry = m_Queue.Entries[i];
int statusHue = entry.IsCompleted ? 0x3E : 0x480;
if ( entry.CraftItem.NameNumber > 0 )
AddHtmlLocalized( 15, y, 140, 20, entry.CraftItem.NameNumber, 0x7FFF, false, false );
else
AddLabel( 15, y, statusHue, entry.CraftItem.NameString );
// --- MANUAL RESOURCE OVERRIDE ---
string resName = "Default";
if (entry.ResourceType != null)
{
resName = entry.ResourceType.Name;
}
else
{
// Clean up the system name
string systemName = m_System.GetType().Name.Replace("Def", "").Replace("Craft", "");
// Hardcode the base materials
if (systemName == "Blacksmithy")
resName = "Iron Ingot";
else if (systemName == "Carpentry" || systemName == "Bowcraft")
resName = "Board";
else if (systemName == "Tailoring")
{
bool requiresCloth = false;
// Look at the first ingredient required to make this item
if (entry.CraftItem.Resources.Count > 0)
{
Type reqType = entry.CraftItem.Resources.GetAt(0).ItemType;
if (reqType == typeof(Server.Items.Cloth) || reqType == typeof(Server.Items.UncutCloth))
{
requiresCloth = true;
}
}
if (requiresCloth)
resName = "Cloth";
else
resName = "Leather";
}
}
// Render as pure white (1152) using the standard AddLabel method
AddLabel(165, y, 1152, resName);
AddLabel( 275, y, 0x480, entry.TargetAmount.ToString() );
AddLabel( 335, y, 0x35, entry.AmountMade.ToString() );
AddLabel( 395, y, 0x22, entry.AmountFailed.ToString() );
AddLabel( 455, y, 0x3E, entry.AmountExceptional.ToString() );
AddButton( 525, y + 3, 4017, 4019, 100 + i, GumpButtonType.Reply, 0 );
y += 20;
if ( y > 380 ) break;
}
// Footer Buttons
AddButton( 15, 405, 4014, 4016, 0, GumpButtonType.Reply, 0 );
AddHtml( 50, 407, 100, 20, "<BASEFONT COLOR=#FFFFFF>BACK</BASEFONT>", false, false );
// Dynamic Play/Pause Button
AddButton( 250, 405, m_Queue.IsPaused ? 4005 : 4011, m_Queue.IsPaused ? 4007 : 4012, 1, GumpButtonType.Reply, 0 );
AddHtml( 285, 407, 100, 20, m_Queue.IsPaused ? "<BASEFONT COLOR=#00FF00>PLAY QUEUE</BASEFONT>" : "<BASEFONT COLOR=#FF0000>PAUSE QUEUE</BASEFONT>", false, false );
AddButton( 450, 405, 4017, 4019, 2, GumpButtonType.Reply, 0 );
AddHtml( 485, 407, 100, 20, "<BASEFONT COLOR=#FFFFFF>CLEAR ALL</BASEFONT>", false, false );
}
public override void OnResponse( NetState sender, RelayInfo info )
{
if ( info.ButtonID == 0 ) // Back
{
m_From.SendGump( new CraftGump( m_From, m_System, m_Tool, null ) );
}
else if ( info.ButtonID == 1 ) // Play/Pause Toggle
{
m_Queue.IsPaused = !m_Queue.IsPaused;
if ( !m_Queue.IsPaused && m_Queue.Entries.Count > 0 )
{
// --- AVATARS CONQUEST: Auto-Tool Replacement ---
if ( m_Tool == null || m_Tool.Deleted || m_Tool.UsesRemaining <= 0 )
{
// Try to find a replacement tool of the exact same type in their backpack
BaseTool replacement = m_From.Backpack != null ? m_From.Backpack.FindItemByType( m_Tool.GetType() ) as BaseTool : null;
if ( replacement != null && !replacement.Deleted && replacement.UsesRemaining > 0 )
{
m_Tool = replacement; // Swap the broken tool for the new one!
m_From.SendMessage( 0x35, "Equipped a new tool from your backpack." );
}
else
{
m_From.SendMessage( 0x22, "You do not have a working tool to continue crafting." );
m_Queue.IsPaused = true;
m_From.SendGump( new CraftQueueGump( m_From, m_System, m_Tool ) );
return;
}
}
// -----------------------------------------------
m_From.SendMessage( 0x35, "Crafting queue started." );
// Make sure we grab the next INCOMPLETE item, not just the top of the list
CraftQueueEntry next = m_Queue.Entries.Find( e => !e.IsCompleted );
if ( next != null )
{
next.CraftItem.Craft( m_From, m_System, next.ResourceType, m_Tool );
return; // Exit here so it doesn't reopen the gump
}
else
{
m_From.SendMessage( 0x3E, "Queue is already completely finished." );
m_Queue.IsPaused = true;
}
}
else if ( !m_Queue.IsPaused && m_Queue.Entries.Count == 0 )
{
m_From.SendMessage( 0x22, "Your queue is empty." );
m_Queue.IsPaused = true;
}
else
{
m_From.SendMessage( 0x22, "Crafting queue paused." );
}
m_From.SendGump( new CraftQueueGump( m_From, m_System, m_Tool ) );
}
else if ( info.ButtonID == 2 ) // Clear All
{
m_Queue.Entries.Clear();
m_From.SendGump( new CraftQueueGump( m_From, m_System, m_Tool ) );
}
else if ( info.ButtonID >= 100 ) // Remove specific item
{
int index = info.ButtonID - 100;
if ( index >= 0 && index < m_Queue.Entries.Count )
{
m_Queue.Entries.RemoveAt( index );
}
m_From.SendGump( new CraftQueueGump( m_From, m_System, m_Tool ) );
}
}
}
}