using System; using LLib.Gear; using LLib.Inventory; using Microsoft.Extensions.Logging; using Questionable.Model; using Questionable.Model.Questing; namespace Questionable.Controller.Steps.Interactions; internal static class UnequipItem { internal sealed class Factory : SimpleTaskFactory { public override ITask? CreateTask(Quest quest, QuestSequence sequence, QuestStep step) { if (step.InteractionType != EInteractionType.UnequipItem) { return null; } ArgumentNullException.ThrowIfNull(step.ItemId, "step.ItemId"); return new Task(step.ItemId.Value); } } internal sealed record Task(uint ItemId) : ITask { public override string ToString() { return $"Unequip({ItemId})"; } } internal sealed class DoUnequip(ILogger logger) : TaskExecutor() { private long _continueAt; private int _attempts; protected override bool Start() { int equippedItemSlot = InventoryHelper.GetEquippedItemSlot(base.Task.ItemId); if (equippedItemSlot < 0) { logger.LogDebug("Item {ItemId} is not equipped, skipping", base.Task.ItemId); return false; } if (!EEquipSlotCategoryExtensions.TryUnequipItem(equippedItemSlot)) { throw new TaskException($"Failed to unequip item {base.Task.ItemId} - armory chest may be full"); } _continueAt = Environment.TickCount64 + 1000; _attempts = 1; return true; } public override ETaskResult Update() { if (Environment.TickCount64 < _continueAt) { return ETaskResult.StillRunning; } if (!InventoryHelper.IsItemEquipped(base.Task.ItemId)) { return ETaskResult.TaskComplete; } _attempts++; if (_attempts > 3) { throw new TaskException($"Item {base.Task.ItemId} still equipped after {_attempts} attempts"); } int equippedItemSlot = InventoryHelper.GetEquippedItemSlot(base.Task.ItemId); if (equippedItemSlot >= 0) { EEquipSlotCategoryExtensions.TryUnequipItem(equippedItemSlot); } _continueAt = Environment.TickCount64 + 1000; return ETaskResult.StillRunning; } public override bool ShouldInterruptOnDamage() { return true; } } }