1
0
Fork 0

Polishing

master
Liza 2023-10-05 00:57:44 +02:00
parent 76d5db1542
commit c0106709ac
Signed by: liza
GPG Key ID: 7199F8D727D55F67
5 changed files with 165 additions and 21 deletions

View File

@ -1,5 +1,8 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
using Dalamud.Configuration;
using Workshoppa.GameData;
namespace Workshoppa;
@ -20,6 +23,55 @@ internal sealed class Configuration : IPluginConfiguration
{
public uint WorkshopItemId { get; set; }
public bool StartedCrafting { get; set; }
public bool FinishedCrafting { get; set; }
public uint PhasesComplete { get; set; } = 0;
public List<PhaseItem> ContributedItemsInCurrentPhase { get; set; } = new();
public bool UpdateFromCraftState(CraftState craftState)
{
bool changed = false;
if (PhasesComplete != craftState.StepsComplete)
{
PhasesComplete = craftState.StepsComplete;
changed = true;
}
if (ContributedItemsInCurrentPhase.Count != craftState.Items.Count)
{
ContributedItemsInCurrentPhase = craftState.Items.Select(x => new PhaseItem
{
ItemId = x.ItemId,
QuantityComplete = x.QuantityComplete,
}).ToList();
changed = true;
}
else
{
for (int i = 0; i < ContributedItemsInCurrentPhase.Count; ++i)
{
var contributedItem = ContributedItemsInCurrentPhase[i];
var craftItem = craftState.Items[i];
if (contributedItem.ItemId != craftItem.ItemId)
{
contributedItem.ItemId = craftItem.ItemId;
changed = true;
}
if (contributedItem.QuantityComplete != craftItem.QuantityComplete)
{
contributedItem.QuantityComplete = craftItem.QuantityComplete;
changed = true;
}
}
}
return changed;
}
}
internal sealed class PhaseItem
{
public uint ItemId { get; set; }
public uint QuantityComplete { get; set; }
}
}

View File

@ -14,4 +14,6 @@ public class CraftItem
public uint StepsTotal { get; set; }
public bool Finished { get; set; }
public uint CrafterMinimumLevel { get; set; }
public uint QuantityComplete => StepsComplete * ItemCountPerStep;
}

View File

@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using Dalamud.Interface;
@ -44,7 +45,7 @@ internal sealed class MainWindow : Window
Flags = ImGuiWindowFlags.AlwaysAutoResize | ImGuiWindowFlags.NoCollapse;
}
public bool NearFabricationStation { get; set; } = false;
public bool NearFabricationStation { get; set; }
public ButtonState State { get; set; } = ButtonState.None;
public bool IsDiscipleOfHand =>
@ -60,7 +61,7 @@ internal sealed class MainWindow : Window
if (_plugin.CurrentStage == Stage.Stopped)
{
if (ImGuiComponents.IconButtonWithText(FontAwesomeIcon.Search, "Check Material"))
if (ImGuiComponents.IconButtonWithText(FontAwesomeIcon.Search, "Check Inventory"))
ImGui.OpenPopup(nameof(CheckMaterial));
ImGui.SameLine();
@ -109,7 +110,7 @@ internal sealed class MainWindow : Window
{
ImGui.Text("Currently Crafting: ---");
if (ImGuiComponents.IconButtonWithText(FontAwesomeIcon.Search, "Check Material"))
if (ImGuiComponents.IconButtonWithText(FontAwesomeIcon.Search, "Check Inventory"))
ImGui.OpenPopup(nameof(CheckMaterial));
ImGui.SameLine();
@ -200,34 +201,67 @@ internal sealed class MainWindow : Window
private unsafe void CheckMaterial()
{
if (_configuration.CurrentlyCraftedItem != null)
ImGui.Text("Items needed for all crafts in queue (not including current in-progress craft):");
else
ImGui.Text("Items needed for all crafts in queue:");
var items = _configuration.ItemQueue
.SelectMany(x =>
Enumerable.Range(0, x.Quantity).Select(_ =>
_workshopCache.Crafts.Single(y => y.WorkshopItemId == x.WorkshopItemId)))
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);
}
}
var items = 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 })
.OrderBy(x => x.Key.Name);
.OrderBy(x => x.Key.Name)
.Select(x => new
{
x.Key.ItemId,
x.Key.Name,
TotalQuantity = completedForCurrentCraft.TryGetValue(x.Key.ItemId, out var completed)
? x.Sum(y => y.TotalQuantity) - completed
: x.Sum(y => y.TotalQuantity),
});
ImGui.Indent(20);
InventoryManager* inventoryManager = InventoryManager.Instance();
foreach (var item in items)
{
int inInventory = inventoryManager->GetInventoryItemCount(item.Key.ItemId, true, false, false) +
inventoryManager->GetInventoryItemCount(item.Key.ItemId, false, false, false);
int required = item.Sum(x => x.TotalQuantity);
ImGui.TextColored(inInventory >= required ? ImGuiColors.HealerGreen : ImGuiColors.DalamudRed,
$"{item.Key.Name} ({inInventory} / {required})");
int inInventory = inventoryManager->GetInventoryItemCount(item.ItemId, true, false, false) +
inventoryManager->GetInventoryItemCount(item.ItemId, false, false, false);
ImGui.TextColored(inInventory >= item.TotalQuantity ? ImGuiColors.HealerGreen : ImGuiColors.DalamudRed,
$"{item.Name} ({inInventory} / {item.TotalQuantity})");
}
ImGui.Unindent(20);
}
private 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;
}
public enum ButtonState
{
None,

View File

@ -10,6 +10,41 @@ partial class WorkshopPlugin
{
private uint? _contributingItemId;
/// <summary>
/// Check if delivery window is open when we clicked resume.
/// </summary>
private unsafe bool CheckContinueWithDelivery()
{
if (_configuration.CurrentlyCraftedItem != null)
{
AtkUnitBase* addonMaterialDelivery = GetMaterialDeliveryAddon();
if (addonMaterialDelivery == null)
return false;
_pluginLog.Warning("Material delivery window is open, although unexpected... checking current craft");
CraftState? craftState = ReadCraftState(addonMaterialDelivery);
if (craftState == null || craftState.ResultItem == 0)
{
_pluginLog.Error("Unable to read craft state");
_continueAt = DateTime.Now.AddSeconds(1);
return false;
}
var craft = _workshopCache.Crafts.SingleOrDefault(x => x.ResultItem == craftState.ResultItem);
if (craft == null || craft.WorkshopItemId != _configuration.CurrentlyCraftedItem.WorkshopItemId)
{
_pluginLog.Error("Unable to match currently crafted item with game state");
_continueAt = DateTime.Now.AddSeconds(1);
return false;
}
_pluginLog.Information("Delivering materials for current active craft, switching to delivery");
return true;
}
return false;
}
private void SelectCraftBranch()
{
if (SelectSelectString("contrib", 0, s => s.StartsWith("Contribute materials.")))
@ -20,6 +55,11 @@ partial class WorkshopPlugin
else if (SelectSelectString("advance", 0, s => s.StartsWith("Advance to the next phase of production.")))
{
_pluginLog.Information("Phase is complete");
_configuration.CurrentlyCraftedItem!.PhasesComplete++;
_configuration.CurrentlyCraftedItem!.ContributedItemsInCurrentPhase = new();
_pluginInterface.SavePluginConfig(_configuration);
CurrentStage = Stage.TargetFabricationStation;
_continueAt = DateTime.Now.AddSeconds(3);
}
@ -51,6 +91,12 @@ partial class WorkshopPlugin
return;
}
if (_configuration.CurrentlyCraftedItem!.UpdateFromCraftState(craftState))
{
_pluginLog.Information("Saving updated current craft information");
_pluginInterface.SavePluginConfig(_configuration);
}
for (int i = 0; i < craftState.Items.Count; ++i)
{
var item = craftState.Items[i];
@ -59,7 +105,8 @@ partial class WorkshopPlugin
if (!HasItemInSingleSlot(item.ItemId, item.ItemCountPerStep))
{
_pluginLog.Error($"Can't contribute item {item.ItemId} to craft, couldn't find {item.ItemCountPerStep}x in a single inventory slot");
_pluginLog.Error(
$"Can't contribute item {item.ItemId} to craft, couldn't find {item.ItemCountPerStep}x in a single inventory slot");
CurrentStage = Stage.RequestStop;
break;
}
@ -113,6 +160,11 @@ partial class WorkshopPlugin
}
else
{
_configuration.CurrentlyCraftedItem!.ContributedItemsInCurrentPhase
.Single(x => x.ItemId == item.ItemId)
.QuantityComplete = item.QuantityComplete;
_pluginInterface.SavePluginConfig(_configuration);
CurrentStage = Stage.ContributeMaterials;
_continueAt = DateTime.Now.AddSeconds(1);
}

View File

@ -107,6 +107,7 @@ public sealed partial class WorkshopPlugin : IDalamudPlugin
}
else if (_mainWindow.State is MainWindow.ButtonState.Start or MainWindow.ButtonState.Resume && CurrentStage == Stage.Stopped)
{
// TODO Error checking, we should ensure the player has the required job level for *all* crafting parts
_mainWindow.State = MainWindow.ButtonState.None;
CurrentStage = Stage.TakeItemFromQueue;
}
@ -117,6 +118,9 @@ public sealed partial class WorkshopPlugin : IDalamudPlugin
switch (CurrentStage)
{
case Stage.TakeItemFromQueue:
if (CheckContinueWithDelivery())
CurrentStage = Stage.ContributeMaterials;
else
TakeItemFromQueue();
break;