139 lines
4.4 KiB
C#
139 lines
4.4 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using Dalamud.Plugin.Services;
|
|
using FFXIVClientStructs.FFXIV.Client.Game;
|
|
using FFXIVClientStructs.FFXIV.Client.UI.Agent;
|
|
using FFXIVClientStructs.FFXIV.Component.GUI;
|
|
using LLib.GameData;
|
|
using Lumina.Excel.Sheets;
|
|
using Microsoft.Extensions.Logging;
|
|
using Questionable.Controller.Steps.Common;
|
|
using Questionable.External;
|
|
using Questionable.Model;
|
|
using Questionable.Model.Questing;
|
|
|
|
namespace Questionable.Controller.Steps.Shared;
|
|
|
|
internal static class Craft
|
|
{
|
|
internal sealed class Factory : ITaskFactory
|
|
{
|
|
public IEnumerable<ITask> CreateAllTasks(Questionable.Model.Quest quest, QuestSequence sequence, QuestStep step)
|
|
{
|
|
if (step.InteractionType != EInteractionType.Craft)
|
|
{
|
|
return Array.Empty<ITask>();
|
|
}
|
|
ArgumentNullException.ThrowIfNull(step.ItemId, "step.ItemId");
|
|
ArgumentNullException.ThrowIfNull(step.ItemCount, "step.ItemCount");
|
|
return new global::_003C_003Ez__ReadOnlyArray<ITask>(new ITask[2]
|
|
{
|
|
new Questionable.Controller.Steps.Common.Mount.UnmountTask(),
|
|
new CraftTask(step.ItemId.Value, step.ItemCount.Value)
|
|
});
|
|
}
|
|
}
|
|
|
|
internal sealed record CraftTask(uint ItemId, int ItemCount) : ITask
|
|
{
|
|
public override string ToString()
|
|
{
|
|
return $"Craft {ItemCount}x {ItemId} (with Artisan)";
|
|
}
|
|
}
|
|
|
|
internal sealed class DoCraft(IDataManager dataManager, IClientState clientState, ArtisanIpc artisanIpc, ILogger<DoCraft> logger) : TaskExecutor<CraftTask>()
|
|
{
|
|
protected override bool Start()
|
|
{
|
|
if (HasRequestedItems())
|
|
{
|
|
logger.LogInformation("Already own {ItemCount}x {ItemId}", base.Task.ItemCount, base.Task.ItemId);
|
|
return false;
|
|
}
|
|
RecipeLookup? rowOrDefault = dataManager.GetExcelSheet<RecipeLookup>().GetRowOrDefault(base.Task.ItemId);
|
|
if (!rowOrDefault.HasValue)
|
|
{
|
|
throw new TaskException($"Item {base.Task.ItemId} is not craftable");
|
|
}
|
|
uint num = (EClassJob)clientState.LocalPlayer.ClassJob.RowId switch
|
|
{
|
|
EClassJob.Carpenter => rowOrDefault.Value.CRP.RowId,
|
|
EClassJob.Blacksmith => rowOrDefault.Value.BSM.RowId,
|
|
EClassJob.Armorer => rowOrDefault.Value.ARM.RowId,
|
|
EClassJob.Goldsmith => rowOrDefault.Value.GSM.RowId,
|
|
EClassJob.Leatherworker => rowOrDefault.Value.LTW.RowId,
|
|
EClassJob.Weaver => rowOrDefault.Value.WVR.RowId,
|
|
EClassJob.Alchemist => rowOrDefault.Value.ALC.RowId,
|
|
EClassJob.Culinarian => rowOrDefault.Value.CUL.RowId,
|
|
_ => 0u,
|
|
};
|
|
if (num == 0)
|
|
{
|
|
num = new uint[8]
|
|
{
|
|
rowOrDefault.Value.CRP.RowId,
|
|
rowOrDefault.Value.BSM.RowId,
|
|
rowOrDefault.Value.ARM.RowId,
|
|
rowOrDefault.Value.GSM.RowId,
|
|
rowOrDefault.Value.LTW.RowId,
|
|
rowOrDefault.Value.WVR.RowId,
|
|
rowOrDefault.Value.ALC.RowId,
|
|
rowOrDefault.Value.WVR.RowId
|
|
}.FirstOrDefault((uint x) => x != 0);
|
|
}
|
|
if (num == 0)
|
|
{
|
|
throw new TaskException($"Unable to determine recipe for item {base.Task.ItemId}");
|
|
}
|
|
int num2 = base.Task.ItemCount - GetOwnedItemCount();
|
|
logger.LogInformation("Starting craft for item {ItemId} with recipe {RecipeId} for {RemainingItemCount} items", base.Task.ItemId, num, num2);
|
|
if (!artisanIpc.CraftItem((ushort)num, num2))
|
|
{
|
|
throw new TaskException($"Failed to start Artisan craft for recipe {num}");
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public unsafe override ETaskResult Update()
|
|
{
|
|
if (HasRequestedItems() && !artisanIpc.IsCrafting())
|
|
{
|
|
AgentRecipeNote* ptr = AgentRecipeNote.Instance();
|
|
if (ptr != null && ptr->IsAgentActive())
|
|
{
|
|
uint addonId = ptr->GetAddonId();
|
|
if (addonId == 0)
|
|
{
|
|
return ETaskResult.StillRunning;
|
|
}
|
|
AtkUnitBase* addonById = AtkStage.Instance()->RaptureAtkUnitManager->GetAddonById((ushort)addonId);
|
|
if (addonById != null)
|
|
{
|
|
logger.LogInformation("Closing crafting window");
|
|
addonById->FireCallbackInt(-1);
|
|
return ETaskResult.TaskComplete;
|
|
}
|
|
}
|
|
}
|
|
return ETaskResult.StillRunning;
|
|
}
|
|
|
|
private bool HasRequestedItems()
|
|
{
|
|
return GetOwnedItemCount() >= base.Task.ItemCount;
|
|
}
|
|
|
|
private unsafe int GetOwnedItemCount()
|
|
{
|
|
InventoryManager* ptr = InventoryManager.Instance();
|
|
return ptr->GetInventoryItemCount(base.Task.ItemId, isHq: false, checkEquipped: false, checkArmory: true, 0) + ptr->GetInventoryItemCount(base.Task.ItemId, isHq: true, checkEquipped: false, checkArmory: true, 0);
|
|
}
|
|
|
|
public override bool ShouldInterruptOnDamage()
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
}
|