using FFXIVClientStructs.FFXIV.Client.Game; using FFXIVClientStructs.FFXIV.Client.UI.Agent; using FFXIVClientStructs.FFXIV.Component.GUI; using LLib.GameUI; using Microsoft.Extensions.Logging; using Questionable.Model; using Questionable.Model.Questing; namespace Questionable.Controller.Steps.Gathering; internal static class TurnInDelivery { internal sealed class Factory : SimpleTaskFactory { public override ITask? CreateTask(Quest quest, QuestSequence sequence, QuestStep step) { if (!(quest.Id is SatisfactionSupplyNpcId) || sequence.Sequence != 1) { return null; } return new Task(); } } internal sealed record Task : ITask { public override string ToString() { return "WeeklyDeliveryTurnIn"; } } internal sealed class SatisfactionSupplyTurnIn(ILogger logger) : TaskExecutor() { private ushort? _remainingAllowances; protected override bool Start() { return true; } public unsafe override ETaskResult Update() { AgentSatisfactionSupply* ptr = AgentSatisfactionSupply.Instance(); if (ptr == null || !ptr->IsAgentActive()) { if (_remainingAllowances.HasValue) { return ETaskResult.TaskComplete; } return ETaskResult.StillRunning; } uint addonId = ptr->GetAddonId(); if (addonId == 0) { if (_remainingAllowances.HasValue) { return ETaskResult.TaskComplete; } return ETaskResult.StillRunning; } AtkUnitBase* addonById = LAddon.GetAddonById(addonId); if (addonById == null || !LAddon.IsAddonReady(addonById)) { return ETaskResult.StillRunning; } ushort remainingAllowances = ptr->NpcData.RemainingAllowances; if (remainingAllowances == 0) { logger.LogInformation("No remaining weekly allowances"); addonById->FireCallbackInt(0); return ETaskResult.TaskComplete; } if (InventoryManager.Instance()->GetInventoryItemCount(ptr->Items[1].Id, isHq: false, checkEquipped: true, checkArmory: true, (short)ptr->Items[1].Collectability1) == 0) { logger.LogInformation("Inventory has no {ItemId}", ptr->Items[1].Id); addonById->FireCallbackInt(0); return ETaskResult.TaskComplete; } if (_remainingAllowances == remainingAllowances) { return ETaskResult.StillRunning; } logger.LogInformation("Attempting turn-in (remaining allowances: {RemainingAllowances})", remainingAllowances); _remainingAllowances = remainingAllowances; AtkValue* values = stackalloc AtkValue[2] { new AtkValue { Type = ValueType.Int, Int = 1 }, new AtkValue { Type = ValueType.Int, Int = 1 } }; addonById->FireCallback(2u, values); return ETaskResult.StillRunning; } public override bool ShouldInterruptOnDamage() { return false; } } }