forked from liza/Workshoppa
643 lines
23 KiB
C#
643 lines
23 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Numerics;
|
|
using System.Text;
|
|
using System.Text.RegularExpressions;
|
|
using Dalamud.Interface;
|
|
using Dalamud.Interface.Colors;
|
|
using Dalamud.Interface.Components;
|
|
using Dalamud.Interface.Textures.TextureWraps;
|
|
using Dalamud.Plugin;
|
|
using Dalamud.Plugin.Services;
|
|
using FFXIVClientStructs.FFXIV.Client.Game;
|
|
using ImGuiNET;
|
|
using LLib;
|
|
using LLib.ImGui;
|
|
using Workshoppa.GameData;
|
|
|
|
namespace Workshoppa.Windows;
|
|
|
|
// FIXME The close button doesn't work near the workshop, either hide it or make it work
|
|
internal sealed class MainWindow : LWindow, IPersistableWindowConfig
|
|
{
|
|
private static readonly Regex CountAndName = new(@"^(\d{1,5})x?\s+(.*)$", RegexOptions.Compiled);
|
|
|
|
private readonly WorkshopPlugin _plugin;
|
|
private readonly IDalamudPluginInterface _pluginInterface;
|
|
private readonly IClientState _clientState;
|
|
private readonly Configuration _configuration;
|
|
private readonly WorkshopCache _workshopCache;
|
|
private readonly IconCache _iconCache;
|
|
private readonly IChatGui _chatGui;
|
|
private readonly RecipeTree _recipeTree;
|
|
private readonly IPluginLog _pluginLog;
|
|
|
|
private string _searchString = string.Empty;
|
|
private bool _checkInventory;
|
|
private string _newPresetName = string.Empty;
|
|
|
|
public MainWindow(WorkshopPlugin plugin, IDalamudPluginInterface pluginInterface, IClientState clientState,
|
|
Configuration configuration, WorkshopCache workshopCache, IconCache iconCache, IChatGui chatGui,
|
|
RecipeTree recipeTree, IPluginLog pluginLog)
|
|
: base("Workshoppa###WorkshoppaMainWindow")
|
|
{
|
|
_plugin = plugin;
|
|
_pluginInterface = pluginInterface;
|
|
_clientState = clientState;
|
|
_configuration = configuration;
|
|
_workshopCache = workshopCache;
|
|
_iconCache = iconCache;
|
|
_chatGui = chatGui;
|
|
_recipeTree = recipeTree;
|
|
_pluginLog = pluginLog;
|
|
|
|
Position = new Vector2(100, 100);
|
|
PositionCondition = ImGuiCond.FirstUseEver;
|
|
|
|
SizeConstraints = new WindowSizeConstraints
|
|
{
|
|
MinimumSize = new Vector2(350, 50),
|
|
MaximumSize = new Vector2(500, 9999),
|
|
};
|
|
|
|
Flags = ImGuiWindowFlags.AlwaysAutoResize | ImGuiWindowFlags.MenuBar;
|
|
AllowClickthrough = false;
|
|
}
|
|
|
|
public EOpenReason OpenReason { get; set; } = EOpenReason.None;
|
|
public bool NearFabricationStation { get; set; }
|
|
public ButtonState State { get; set; } = ButtonState.None;
|
|
|
|
private bool IsDiscipleOfHand =>
|
|
_clientState.LocalPlayer != null && _clientState.LocalPlayer.ClassJob.Id is >= 8 and <= 15;
|
|
|
|
public WindowConfig WindowConfig => _configuration.MainWindowConfig;
|
|
|
|
public override void Draw()
|
|
{
|
|
if (ImGui.BeginMenuBar())
|
|
{
|
|
ImGui.BeginDisabled(_plugin.CurrentStage != Stage.Stopped);
|
|
DrawPresetsMenu();
|
|
DrawClipboardMenu();
|
|
ImGui.EndDisabled();
|
|
|
|
ImGui.EndMenuBar();
|
|
}
|
|
|
|
var currentItem = _configuration.CurrentlyCraftedItem;
|
|
if (currentItem != null)
|
|
{
|
|
var currentCraft = _workshopCache.Crafts.Single(x => x.WorkshopItemId == currentItem.WorkshopItemId);
|
|
ImGui.Text($"Currently Crafting:");
|
|
|
|
IDalamudTextureWrap? icon = _iconCache.GetIcon(currentCraft.IconId);
|
|
if (icon != null)
|
|
{
|
|
ImGui.Image(icon.ImGuiHandle, new Vector2(ImGui.GetFrameHeight()));
|
|
ImGui.SameLine(0, ImGui.GetStyle().ItemInnerSpacing.X);
|
|
ImGui.SetCursorPosY(ImGui.GetCursorPosY() + (ImGui.GetFrameHeight() - ImGui.GetTextLineHeight()) / 2);
|
|
}
|
|
|
|
ImGui.TextUnformatted($"{currentCraft.Name}");
|
|
ImGui.Spacing();
|
|
|
|
if (_plugin.CurrentStage == Stage.Stopped)
|
|
{
|
|
if (ImGuiComponents.IconButtonWithText(FontAwesomeIcon.Search, "Check Inventory"))
|
|
_checkInventory = !_checkInventory;
|
|
|
|
ImGui.SameLine();
|
|
ImGui.BeginDisabled(!NearFabricationStation || !IsDiscipleOfHand);
|
|
if (currentItem.StartedCrafting)
|
|
{
|
|
if (ImGuiComponents.IconButtonWithText(FontAwesomeIcon.Play, "Resume"))
|
|
{
|
|
State = ButtonState.Resume;
|
|
_checkInventory = false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (ImGuiComponents.IconButtonWithText(FontAwesomeIcon.Play, "Start Crafting"))
|
|
{
|
|
State = ButtonState.Start;
|
|
_checkInventory = false;
|
|
}
|
|
}
|
|
|
|
ImGui.EndDisabled();
|
|
|
|
ImGui.SameLine();
|
|
|
|
bool keysHeld = ImGui.GetIO().KeyCtrl && ImGui.GetIO().KeyShift;
|
|
ImGui.BeginDisabled(!keysHeld);
|
|
if (ImGuiComponents.IconButtonWithText(FontAwesomeIcon.Times, "Cancel"))
|
|
{
|
|
State = ButtonState.Pause;
|
|
_configuration.CurrentlyCraftedItem = null;
|
|
|
|
Save();
|
|
}
|
|
|
|
ImGui.EndDisabled();
|
|
if (ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenDisabled) && !keysHeld)
|
|
ImGui.SetTooltip(
|
|
$"Hold CTRL+SHIFT to remove this as craft. You have to manually use the fabrication station to cancel or finish the workshop project before you can continue using the queue.");
|
|
|
|
ShowErrorConditions();
|
|
}
|
|
else
|
|
{
|
|
ImGui.BeginDisabled(_plugin.CurrentStage == Stage.RequestStop);
|
|
if (ImGuiComponents.IconButtonWithText(FontAwesomeIcon.Pause, "Pause"))
|
|
State = ButtonState.Pause;
|
|
|
|
ImGui.EndDisabled();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ImGui.Text("Currently Crafting: ---");
|
|
|
|
if (ImGuiComponents.IconButtonWithText(FontAwesomeIcon.Search, "Check Inventory"))
|
|
_checkInventory = !_checkInventory;
|
|
|
|
ImGui.SameLine();
|
|
ImGui.BeginDisabled(!NearFabricationStation || _configuration.ItemQueue.Sum(x => x.Quantity) == 0 ||
|
|
_plugin.CurrentStage != Stage.Stopped || !IsDiscipleOfHand);
|
|
if (ImGuiComponents.IconButtonWithText(FontAwesomeIcon.Play, "Start Crafting"))
|
|
{
|
|
State = ButtonState.Start;
|
|
_checkInventory = false;
|
|
}
|
|
|
|
ImGui.EndDisabled();
|
|
|
|
ShowErrorConditions();
|
|
}
|
|
|
|
if (_checkInventory)
|
|
{
|
|
ImGui.Separator();
|
|
CheckMaterial();
|
|
}
|
|
|
|
ImGui.Separator();
|
|
ImGui.Text("Queue:");
|
|
ImGui.BeginDisabled(_plugin.CurrentStage != Stage.Stopped);
|
|
Configuration.QueuedItem? itemToRemove = null;
|
|
for (int i = 0; i < _configuration.ItemQueue.Count; ++i)
|
|
{
|
|
ImGui.PushID($"ItemQueue{i}");
|
|
var item = _configuration.ItemQueue[i];
|
|
var craft = _workshopCache.Crafts.Single(x => x.WorkshopItemId == item.WorkshopItemId);
|
|
|
|
IDalamudTextureWrap? icon = _iconCache.GetIcon(craft.IconId);
|
|
if (icon != null)
|
|
{
|
|
ImGui.Image(icon.ImGuiHandle, new Vector2(ImGui.GetFrameHeight()));
|
|
ImGui.SameLine(0, ImGui.GetStyle().ItemInnerSpacing.X);
|
|
}
|
|
|
|
ImGui.SetNextItemWidth(Math.Max(100 * ImGui.GetIO().FontGlobalScale, 4 * (ImGui.GetFrameHeight() + ImGui.GetStyle().FramePadding.X)));
|
|
int quantity = item.Quantity;
|
|
if (ImGui.InputInt(craft.Name, ref quantity))
|
|
{
|
|
item.Quantity = Math.Max(0, quantity);
|
|
Save();
|
|
}
|
|
|
|
ImGui.OpenPopupOnItemClick($"###Context{i}");
|
|
if (ImGui.BeginPopupContextItem($"###Context{i}"))
|
|
{
|
|
if (ImGui.MenuItem($"Remove {craft.Name}"))
|
|
itemToRemove = item;
|
|
|
|
ImGui.EndPopup();
|
|
}
|
|
|
|
ImGui.PopID();
|
|
}
|
|
|
|
if (itemToRemove != null)
|
|
{
|
|
_configuration.ItemQueue.Remove(itemToRemove);
|
|
Save();
|
|
}
|
|
|
|
ImGui.SetNextItemWidth(ImGui.GetContentRegionAvail().X);
|
|
if (ImGui.BeginCombo("##CraftSelection", "Add Craft...", ImGuiComboFlags.HeightLarge))
|
|
{
|
|
ImGui.SetNextItemWidth(ImGui.GetContentRegionAvail().X);
|
|
ImGui.InputTextWithHint("", "Filter...", ref _searchString, 256);
|
|
|
|
foreach (var craft in _workshopCache.Crafts
|
|
.Where(x => x.Name.Contains(_searchString, StringComparison.OrdinalIgnoreCase))
|
|
.OrderBy(x => x.WorkshopItemId))
|
|
{
|
|
IDalamudTextureWrap? icon = _iconCache.GetIcon(craft.IconId);
|
|
Vector2 pos = ImGui.GetCursorPos();
|
|
Vector2 iconSize = new Vector2(ImGui.GetTextLineHeight() + ImGui.GetStyle().ItemSpacing.Y);
|
|
if (icon != null)
|
|
{
|
|
ImGui.SetCursorPos(pos + new Vector2(iconSize.X + ImGui.GetStyle().FramePadding.X, ImGui.GetStyle().ItemSpacing.Y / 2));
|
|
}
|
|
|
|
if (ImGui.Selectable($"{craft.Name}##SelectCraft{craft.WorkshopItemId}", false, ImGuiSelectableFlags.SpanAllColumns))
|
|
{
|
|
_configuration.ItemQueue.Add(new Configuration.QueuedItem
|
|
{
|
|
WorkshopItemId = craft.WorkshopItemId,
|
|
Quantity = 1,
|
|
});
|
|
Save();
|
|
}
|
|
|
|
if (icon != null)
|
|
{
|
|
ImGui.SameLine(0, 0);
|
|
ImGui.SetCursorPos(pos);
|
|
ImGui.Image(icon.ImGuiHandle, iconSize);
|
|
}
|
|
}
|
|
|
|
ImGui.EndCombo();
|
|
}
|
|
|
|
ImGui.EndDisabled();
|
|
|
|
ImGui.Separator();
|
|
ImGui.Text($"Debug (Stage): {_plugin.CurrentStage}");
|
|
}
|
|
|
|
private void DrawPresetsMenu()
|
|
{
|
|
if (ImGui.BeginMenu("Presets"))
|
|
{
|
|
if (_configuration.Presets.Count == 0)
|
|
{
|
|
ImGui.BeginDisabled();
|
|
ImGui.MenuItem("Import Queue from Preset");
|
|
ImGui.EndDisabled();
|
|
}
|
|
else if (ImGui.BeginMenu("Import Queue from Preset"))
|
|
{
|
|
if (_configuration.Presets.Count == 0)
|
|
ImGui.MenuItem("You have no presets.");
|
|
|
|
foreach (var preset in _configuration.Presets)
|
|
{
|
|
ImGui.PushID($"Preset{preset.Id}");
|
|
if (ImGui.MenuItem(preset.Name))
|
|
{
|
|
foreach (var item in preset.ItemQueue)
|
|
{
|
|
var queuedItem =
|
|
_configuration.ItemQueue.FirstOrDefault(x => x.WorkshopItemId == item.WorkshopItemId);
|
|
if (queuedItem != null)
|
|
queuedItem.Quantity += item.Quantity;
|
|
else
|
|
{
|
|
_configuration.ItemQueue.Add(new Configuration.QueuedItem
|
|
{
|
|
WorkshopItemId = item.WorkshopItemId,
|
|
Quantity = item.Quantity,
|
|
});
|
|
}
|
|
}
|
|
|
|
Save();
|
|
_chatGui.Print($"Imported {preset.ItemQueue.Count} items from preset.");
|
|
}
|
|
|
|
ImGui.PopID();
|
|
}
|
|
|
|
ImGui.EndMenu();
|
|
}
|
|
|
|
if (_configuration.ItemQueue.Count == 0)
|
|
{
|
|
ImGui.BeginDisabled();
|
|
ImGui.MenuItem("Export Queue to Preset");
|
|
ImGui.EndDisabled();
|
|
}
|
|
else if (ImGui.BeginMenu("Export Queue to Preset"))
|
|
{
|
|
ImGui.InputTextWithHint("", "Preset Name...", ref _newPresetName, 64);
|
|
|
|
ImGui.BeginDisabled(_configuration.Presets.Any(x =>
|
|
x.Name.Equals(_newPresetName, StringComparison.OrdinalIgnoreCase)));
|
|
if (ImGuiComponents.IconButtonWithText(FontAwesomeIcon.Save, "Save"))
|
|
{
|
|
_configuration.Presets.Add(new Configuration.Preset
|
|
{
|
|
Id = Guid.NewGuid(),
|
|
Name = _newPresetName,
|
|
ItemQueue = _configuration.ItemQueue.Select(x => new Configuration.QueuedItem
|
|
{
|
|
WorkshopItemId = x.WorkshopItemId,
|
|
Quantity = x.Quantity
|
|
}).ToList()
|
|
});
|
|
|
|
Save();
|
|
_chatGui.Print($"Saved queue as preset '{_newPresetName}'.");
|
|
|
|
_newPresetName = string.Empty;
|
|
}
|
|
|
|
ImGui.EndDisabled();
|
|
|
|
ImGui.EndMenu();
|
|
}
|
|
|
|
if (_configuration.Presets.Count == 0)
|
|
{
|
|
ImGui.BeginDisabled();
|
|
ImGui.MenuItem("Delete Preset");
|
|
ImGui.EndDisabled();
|
|
}
|
|
else if (ImGui.BeginMenu("Delete Preset"))
|
|
{
|
|
if (_configuration.Presets.Count == 0)
|
|
ImGui.MenuItem("You have no presets.");
|
|
|
|
Guid? presetToRemove = null;
|
|
foreach (var preset in _configuration.Presets)
|
|
{
|
|
ImGui.PushID($"Preset{preset.Id}");
|
|
if (ImGui.MenuItem(preset.Name))
|
|
{
|
|
presetToRemove = preset.Id;
|
|
}
|
|
|
|
ImGui.PopID();
|
|
}
|
|
|
|
if (presetToRemove != null)
|
|
{
|
|
var preset = _configuration.Presets.First(x => x.Id == presetToRemove);
|
|
_configuration.Presets.Remove(preset);
|
|
|
|
Save();
|
|
_chatGui.Print($"Deleted preset '{preset.Name}'.");
|
|
}
|
|
|
|
ImGui.EndMenu();
|
|
}
|
|
|
|
ImGui.EndMenu();
|
|
}
|
|
}
|
|
|
|
private void DrawClipboardMenu()
|
|
{
|
|
if (ImGui.BeginMenu("Clipboard"))
|
|
{
|
|
List<Configuration.QueuedItem> fromClipboardItems = new();
|
|
try
|
|
{
|
|
string? clipboardText = GetClipboardText();
|
|
if (!string.IsNullOrWhiteSpace(clipboardText))
|
|
{
|
|
foreach (var clipboardLine in clipboardText.ReplaceLineEndings().Split(Environment.NewLine))
|
|
{
|
|
var match = CountAndName.Match(clipboardLine);
|
|
if (!match.Success)
|
|
continue;
|
|
|
|
var craft = _workshopCache.Crafts.FirstOrDefault(x =>
|
|
x.Name.Equals(match.Groups[2].Value, StringComparison.OrdinalIgnoreCase));
|
|
if (craft != null && int.TryParse(match.Groups[1].Value, out int quantity))
|
|
{
|
|
fromClipboardItems.Add(new Configuration.QueuedItem
|
|
{
|
|
WorkshopItemId = craft.WorkshopItemId,
|
|
Quantity = quantity,
|
|
});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (Exception)
|
|
{
|
|
//_pluginLog.Warning(e, "Unable to extract clipboard text");
|
|
}
|
|
|
|
ImGui.BeginDisabled(fromClipboardItems.Count == 0);
|
|
if (ImGui.MenuItem("Import Queue from Clipboard"))
|
|
{
|
|
_pluginLog.Information($"Importing {fromClipboardItems.Count} items...");
|
|
int count = 0;
|
|
foreach (var item in fromClipboardItems)
|
|
{
|
|
var queuedItem =
|
|
_configuration.ItemQueue.FirstOrDefault(x => x.WorkshopItemId == item.WorkshopItemId);
|
|
if (queuedItem != null)
|
|
queuedItem.Quantity += item.Quantity;
|
|
else
|
|
{
|
|
_configuration.ItemQueue.Add(new Configuration.QueuedItem
|
|
{
|
|
WorkshopItemId = item.WorkshopItemId,
|
|
Quantity = item.Quantity,
|
|
});
|
|
}
|
|
|
|
++count;
|
|
}
|
|
|
|
Save();
|
|
_chatGui.Print($"Imported {count} items from clipboard.");
|
|
}
|
|
|
|
ImGui.EndDisabled();
|
|
|
|
ImGui.BeginDisabled(_configuration.ItemQueue.Count == 0);
|
|
if (ImGui.MenuItem("Export Queue to Clipboard"))
|
|
{
|
|
var toClipboardItems = _configuration.ItemQueue.Select(x =>
|
|
new
|
|
{
|
|
_workshopCache.Crafts.Single(y => x.WorkshopItemId == y.WorkshopItemId).Name,
|
|
x.Quantity
|
|
})
|
|
.Select(x => $"{x.Quantity}x {x.Name}");
|
|
ImGui.SetClipboardText(string.Join(Environment.NewLine, toClipboardItems));
|
|
|
|
_chatGui.Print("Copied queue content to clipboard.");
|
|
}
|
|
|
|
if (ImGui.MenuItem("Export Material List to Clipboard"))
|
|
{
|
|
var toClipboardItems = _recipeTree.ResolveRecipes(GetMaterialList()).Where(x => x.Type == Ingredient.EType.Craftable);
|
|
ImGui.SetClipboardText(string.Join(Environment.NewLine, toClipboardItems.Select(x => $"{x.TotalQuantity}x {x.Name}")));
|
|
|
|
_chatGui.Print("Copied material list to clipboard.");
|
|
}
|
|
|
|
if (ImGui.MenuItem("Export Gathered/Venture materials to Clipboard"))
|
|
{
|
|
var toClipboardItems = _recipeTree.ResolveRecipes(GetMaterialList()).Where(x => x.Type == Ingredient.EType.Gatherable);
|
|
ImGui.SetClipboardText(string.Join(Environment.NewLine, toClipboardItems.Select(x => $"{x.TotalQuantity}x {x.Name}")));
|
|
|
|
_chatGui.Print("Copied material list to clipboard.");
|
|
}
|
|
|
|
ImGui.EndDisabled();
|
|
|
|
ImGui.EndMenu();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// The default implementation for <see cref="ImGui.GetClipboardText"/> throws an NullReferenceException if the clipboard is empty, maybe also if it doesn't contain text.
|
|
/// </summary>
|
|
private unsafe string? GetClipboardText()
|
|
{
|
|
byte* ptr = ImGuiNative.igGetClipboardText();
|
|
if (ptr == null)
|
|
return null;
|
|
|
|
int byteCount = 0;
|
|
while (ptr[byteCount] != 0)
|
|
++byteCount;
|
|
return Encoding.UTF8.GetString(ptr, byteCount);
|
|
}
|
|
|
|
private void Save()
|
|
{
|
|
_pluginInterface.SavePluginConfig(_configuration);
|
|
}
|
|
|
|
public void Toggle(EOpenReason reason)
|
|
{
|
|
if (!IsOpen)
|
|
{
|
|
IsOpen = true;
|
|
OpenReason = reason;
|
|
}
|
|
else
|
|
IsOpen = false;
|
|
}
|
|
|
|
public override void OnClose()
|
|
{
|
|
OpenReason = EOpenReason.None;
|
|
}
|
|
|
|
private unsafe void CheckMaterial()
|
|
{
|
|
ImGui.Text("Items needed for all crafts in queue:");
|
|
var items = GetMaterialList();
|
|
|
|
ImGui.Indent(20);
|
|
InventoryManager* inventoryManager = InventoryManager.Instance();
|
|
foreach (var item in items)
|
|
{
|
|
int inInventory = inventoryManager->GetInventoryItemCount(item.ItemId, true, false, false) +
|
|
inventoryManager->GetInventoryItemCount(item.ItemId, false, false, false);
|
|
|
|
IDalamudTextureWrap? icon = _iconCache.GetIcon(item.IconId);
|
|
if (icon != null)
|
|
{
|
|
ImGui.Image(icon.ImGuiHandle, new Vector2(ImGui.GetFrameHeight()));
|
|
ImGui.SameLine(0, ImGui.GetStyle().ItemInnerSpacing.X);
|
|
ImGui.SetCursorPosY(ImGui.GetCursorPosY() + (ImGui.GetFrameHeight() - ImGui.GetTextLineHeight()) / 2);
|
|
|
|
icon.Dispose();
|
|
}
|
|
|
|
ImGui.TextColored(inInventory >= item.TotalQuantity ? ImGuiColors.HealerGreen : ImGuiColors.DalamudRed,
|
|
$"{item.Name} ({inInventory} / {item.TotalQuantity})");
|
|
}
|
|
|
|
ImGui.Unindent(20);
|
|
}
|
|
|
|
private List<Ingredient> GetMaterialList()
|
|
{
|
|
List<uint> workshopItemIds = _configuration.ItemQueue
|
|
.SelectMany(x => Enumerable.Range(0, x.Quantity).Select(_ => x.WorkshopItemId))
|
|
.ToList();
|
|
Dictionary<uint, int> completedForCurrentCraft = new();
|
|
var currentItem = _configuration.CurrentlyCraftedItem;
|
|
if (currentItem != null)
|
|
{
|
|
workshopItemIds.Add(currentItem.WorkshopItemId);
|
|
|
|
var craft = _workshopCache.Crafts.Single(x =>
|
|
x.WorkshopItemId == currentItem.WorkshopItemId);
|
|
for (int i = 0; i < currentItem.PhasesComplete; ++i)
|
|
{
|
|
foreach (var item in craft.Phases[i].Items)
|
|
AddMaterial(completedForCurrentCraft, item.ItemId, item.TotalQuantity);
|
|
}
|
|
|
|
if (currentItem.PhasesComplete < craft.Phases.Count)
|
|
{
|
|
foreach (var item in currentItem.ContributedItemsInCurrentPhase)
|
|
AddMaterial(completedForCurrentCraft, item.ItemId, (int)item.QuantityComplete);
|
|
}
|
|
}
|
|
|
|
return workshopItemIds.Select(x => _workshopCache.Crafts.Single(y => y.WorkshopItemId == x))
|
|
.SelectMany(x => x.Phases)
|
|
.SelectMany(x => x.Items)
|
|
.GroupBy(x => new { x.Name, x.ItemId, x.IconId })
|
|
.OrderBy(x => x.Key.Name)
|
|
.Select(x => new Ingredient
|
|
{
|
|
ItemId = x.Key.ItemId,
|
|
IconId = x.Key.IconId,
|
|
Name = x.Key.Name,
|
|
TotalQuantity = completedForCurrentCraft.TryGetValue(x.Key.ItemId, out var completed)
|
|
? x.Sum(y => y.TotalQuantity) - completed
|
|
: x.Sum(y => y.TotalQuantity),
|
|
Type = Ingredient.EType.Craftable,
|
|
})
|
|
.ToList();
|
|
}
|
|
|
|
private static void AddMaterial(Dictionary<uint, int> completedForCurrentCraft, uint itemId, int quantity)
|
|
{
|
|
if (completedForCurrentCraft.TryGetValue(itemId, out var existingQuantity))
|
|
completedForCurrentCraft[itemId] = quantity + existingQuantity;
|
|
else
|
|
completedForCurrentCraft[itemId] = quantity;
|
|
}
|
|
|
|
private void ShowErrorConditions()
|
|
{
|
|
if (!_plugin.WorkshopTerritories.Contains(_clientState.TerritoryType))
|
|
ImGui.TextColored(ImGuiColors.DalamudRed, "You are not in the Company Workshop.");
|
|
else if (!NearFabricationStation)
|
|
ImGui.TextColored(ImGuiColors.DalamudRed, "You are not near a Fabrication Station.");
|
|
|
|
if (!IsDiscipleOfHand)
|
|
ImGui.TextColored(ImGuiColors.DalamudRed, "You need to be a Disciple of the Hand to start crafting.");
|
|
}
|
|
|
|
public void SaveWindowConfig() => Save();
|
|
|
|
public enum ButtonState
|
|
{
|
|
None,
|
|
Start,
|
|
Resume,
|
|
Pause,
|
|
Stop,
|
|
}
|
|
|
|
public enum EOpenReason
|
|
{
|
|
None,
|
|
Command,
|
|
NearFabricationStation,
|
|
PluginInstaller,
|
|
}
|
|
}
|