New experimental interrupt handler
This commit is contained in:
parent
f12b777d12
commit
3a763d625a
@ -49,9 +49,10 @@ internal sealed unsafe class GatheringController : MiniTaskController<GatheringC
|
||||
ILogger<GatheringController> logger,
|
||||
ICondition condition,
|
||||
IServiceProvider serviceProvider,
|
||||
InterruptHandler interruptHandler,
|
||||
IDataManager dataManager,
|
||||
IPluginLog pluginLog)
|
||||
: base(chatGui, condition, serviceProvider, dataManager, logger)
|
||||
: base(chatGui, condition, serviceProvider, interruptHandler, dataManager, logger)
|
||||
{
|
||||
_movementController = movementController;
|
||||
_gatheringPointRegistry = gatheringPointRegistry;
|
||||
|
165
Questionable/Controller/InterruptHandler.cs
Normal file
165
Questionable/Controller/InterruptHandler.cs
Normal file
@ -0,0 +1,165 @@
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Runtime.InteropServices;
|
||||
using Dalamud.Game;
|
||||
using Dalamud.Hooking;
|
||||
using Dalamud.Plugin.Services;
|
||||
using FFXIVClientStructs.FFXIV.Client.Game;
|
||||
using FFXIVClientStructs.FFXIV.Client.Game.Character;
|
||||
using FFXIVClientStructs.FFXIV.Common.Math;
|
||||
using JetBrains.Annotations;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Questionable.Data;
|
||||
|
||||
namespace Questionable.Controller;
|
||||
|
||||
internal sealed unsafe class InterruptHandler : IDisposable
|
||||
{
|
||||
private readonly Hook<ProcessActionEffect> _processActionEffectHook;
|
||||
private readonly IClientState _clientState;
|
||||
private readonly TerritoryData _territoryData;
|
||||
private readonly ILogger<InterruptHandler> _logger;
|
||||
|
||||
private delegate void ProcessActionEffect(uint sourceId, Character* sourceCharacter, Vector3* pos,
|
||||
EffectHeader* effectHeader, EffectEntry* effectArray, ulong* effectTail);
|
||||
|
||||
public InterruptHandler(IGameInteropProvider gameInteropProvider, IClientState clientState,
|
||||
TerritoryData territoryData, ILogger<InterruptHandler> logger)
|
||||
{
|
||||
_clientState = clientState;
|
||||
_territoryData = territoryData;
|
||||
_logger = logger;
|
||||
_processActionEffectHook =
|
||||
gameInteropProvider.HookFromSignature<ProcessActionEffect>(Signatures.ActionEffect,
|
||||
HandleProcessActionEffect);
|
||||
_processActionEffectHook.Enable();
|
||||
}
|
||||
|
||||
public event EventHandler? Interrupted;
|
||||
|
||||
private void HandleProcessActionEffect(uint sourceId, Character* sourceCharacter, Vector3* pos,
|
||||
EffectHeader* effectHeader, EffectEntry* effectArray, ulong* effectTail)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!_territoryData.IsDutyInstance(_clientState.TerritoryType))
|
||||
{
|
||||
for (int i = 0; i < effectHeader->TargetCount; i++)
|
||||
{
|
||||
uint targetId = (uint)(effectTail[i] & uint.MaxValue);
|
||||
EffectEntry* effect = effectArray + 8 * i;
|
||||
|
||||
if (targetId == _clientState.LocalPlayer?.GameObjectId &&
|
||||
effect->Type is EActionEffectType.Damage or EActionEffectType.BlockedDamage
|
||||
or EActionEffectType.ParriedDamage)
|
||||
{
|
||||
_logger.LogTrace("Damage action effect on self, from {SourceId} ({EffectType})", sourceId,
|
||||
effect->Type);
|
||||
Interrupted?.Invoke(this, EventArgs.Empty);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.LogWarning(e, "Unable to process action effect");
|
||||
}
|
||||
finally
|
||||
{
|
||||
_processActionEffectHook.Original(sourceId, sourceCharacter, pos, effectHeader, effectArray, effectTail);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_processActionEffectHook.Disable();
|
||||
_processActionEffectHook.Dispose();
|
||||
}
|
||||
|
||||
private static class Signatures
|
||||
{
|
||||
internal const string ActionEffect = "40 ?? 56 57 41 ?? 41 ?? 41 ?? 48 ?? ?? ?? ?? ?? ?? ?? 48";
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
private struct EffectEntry
|
||||
{
|
||||
[FieldOffset(0)] public EActionEffectType Type;
|
||||
[FieldOffset(1)] public byte Param0;
|
||||
[FieldOffset(2)] public byte Param1;
|
||||
[FieldOffset(3)] public byte Param2;
|
||||
[FieldOffset(4)] public byte Mult;
|
||||
[FieldOffset(5)] public byte Flags;
|
||||
[FieldOffset(6)] public ushort Value;
|
||||
|
||||
public byte AttackType => (byte)(Param1 & 0xF);
|
||||
public uint Damage => Mult == 0 ? Value : Value + ((uint)ushort.MaxValue + 1) * Mult;
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return
|
||||
$"Type: {Type}, p0: {Param0:D3}, p1: {Param1:D3}, p2: {Param2:D3} 0x{Param2:X2} '{Convert.ToString(Param2, 2).PadLeft(8, '0')}', mult: {Mult:D3}, flags: {Flags:D3} | {Convert.ToString(Flags, 2).PadLeft(8, '0')}, value: {Value:D6} ATTACK TYPE: {AttackType}";
|
||||
}
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
private struct EffectHeader
|
||||
{
|
||||
[FieldOffset(0)] public ulong AnimationTargetId;
|
||||
[FieldOffset(8)] public uint ActionID;
|
||||
[FieldOffset(12)] public uint GlobalEffectCounter;
|
||||
[FieldOffset(16)] public float AnimationLockTime;
|
||||
[FieldOffset(20)] public uint SomeTargetID;
|
||||
[FieldOffset(24)] public ushort SourceSequence;
|
||||
[FieldOffset(26)] public ushort Rotation;
|
||||
[FieldOffset(28)] public ushort AnimationId;
|
||||
[FieldOffset(30)] public byte Variation;
|
||||
[FieldOffset(31)] public ActionType ActionType;
|
||||
[FieldOffset(33)] public byte TargetCount;
|
||||
}
|
||||
|
||||
[UsedImplicitly(ImplicitUseTargetFlags.Members)]
|
||||
private enum EActionEffectType : byte
|
||||
{
|
||||
None = 0,
|
||||
Miss = 1,
|
||||
FullResist = 2,
|
||||
Damage = 3,
|
||||
Heal = 4,
|
||||
BlockedDamage = 5,
|
||||
ParriedDamage = 6,
|
||||
Invulnerable = 7,
|
||||
NoEffectText = 8,
|
||||
Unknown0 = 9,
|
||||
MpLoss = 10,
|
||||
MpGain = 11,
|
||||
TpLoss = 12,
|
||||
TpGain = 13,
|
||||
ApplyStatusEffectTarget = 14,
|
||||
ApplyStatusEffectSource = 15,
|
||||
RecoveredFromStatusEffect = 16,
|
||||
LoseStatusEffectTarget = 17,
|
||||
LoseStatusEffectSource = 18,
|
||||
StatusNoEffect = 20,
|
||||
ThreatPosition = 24,
|
||||
EnmityAmountUp = 25,
|
||||
EnmityAmountDown = 26,
|
||||
StartActionCombo = 27,
|
||||
ComboSucceed = 28,
|
||||
Retaliation = 29,
|
||||
Knockback = 32,
|
||||
Attract1 = 33, //Here is an issue bout knockback. some is 32 some is 33.
|
||||
Attract2 = 34,
|
||||
Mount = 40,
|
||||
FullResistStatus = 52,
|
||||
FullResistStatus2 = 55,
|
||||
VFX = 59,
|
||||
Gauge = 60,
|
||||
JobGauge = 61,
|
||||
SetModelState = 72,
|
||||
SetHP = 73,
|
||||
PartialInvulnerable = 74,
|
||||
Interrupt = 75,
|
||||
}
|
||||
}
|
@ -17,26 +17,29 @@ using Mount = Questionable.Controller.Steps.Common.Mount;
|
||||
|
||||
namespace Questionable.Controller;
|
||||
|
||||
internal abstract class MiniTaskController<T>
|
||||
internal abstract class MiniTaskController<T> : IDisposable
|
||||
{
|
||||
protected readonly TaskQueue _taskQueue = new();
|
||||
|
||||
private readonly IChatGui _chatGui;
|
||||
private readonly ICondition _condition;
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
private readonly InterruptHandler _interruptHandler;
|
||||
private readonly ILogger<T> _logger;
|
||||
|
||||
private readonly string _actionCanceledText;
|
||||
|
||||
protected MiniTaskController(IChatGui chatGui, ICondition condition, IServiceProvider serviceProvider,
|
||||
IDataManager dataManager, ILogger<T> logger)
|
||||
InterruptHandler interruptHandler, IDataManager dataManager, ILogger<T> logger)
|
||||
{
|
||||
_chatGui = chatGui;
|
||||
_logger = logger;
|
||||
_serviceProvider = serviceProvider;
|
||||
_interruptHandler = interruptHandler;
|
||||
_condition = condition;
|
||||
|
||||
_actionCanceledText = dataManager.GetString<LogMessage>(1314, x => x.Text)!;
|
||||
_interruptHandler.Interrupted += HandleInterruption;
|
||||
}
|
||||
|
||||
protected virtual void UpdateCurrentTask()
|
||||
@ -198,8 +201,21 @@ internal abstract class MiniTaskController<T>
|
||||
if (!isHandled)
|
||||
{
|
||||
if (GameFunctions.GameStringEquals(_actionCanceledText, message.TextValue) &&
|
||||
!_condition[ConditionFlag.InFlight])
|
||||
!_condition[ConditionFlag.InFlight] &&
|
||||
_taskQueue.CurrentTaskExecutor?.ShouldInterruptOnDamage() == true)
|
||||
InterruptQueueWithCombat();
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void HandleInterruption(object? sender, EventArgs e)
|
||||
{
|
||||
if (!_condition[ConditionFlag.InFlight] &&
|
||||
_taskQueue.CurrentTaskExecutor?.ShouldInterruptOnDamage() == true)
|
||||
InterruptQueueWithCombat();
|
||||
}
|
||||
|
||||
public virtual void Dispose()
|
||||
{
|
||||
_interruptHandler.Interrupted -= HandleInterruption;
|
||||
}
|
||||
}
|
||||
|
@ -75,8 +75,9 @@ internal sealed class QuestController : MiniTaskController<QuestController>, IDi
|
||||
YesAlreadyIpc yesAlreadyIpc,
|
||||
TaskCreator taskCreator,
|
||||
IServiceProvider serviceProvider,
|
||||
InterruptHandler interruptHandler,
|
||||
IDataManager dataManager)
|
||||
: base(chatGui, condition, serviceProvider, dataManager, logger)
|
||||
: base(chatGui, condition, serviceProvider, interruptHandler, dataManager, logger)
|
||||
{
|
||||
_clientState = clientState;
|
||||
_gameFunctions = gameFunctions;
|
||||
@ -801,11 +802,23 @@ internal sealed class QuestController : MiniTaskController<QuestController>, IDi
|
||||
_gatheringController.OnNormalToast(message);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
protected override void HandleInterruption(object? sender, EventArgs e)
|
||||
{
|
||||
if (!IsRunning)
|
||||
return;
|
||||
|
||||
if (AutomationType == EAutomationType.Manual)
|
||||
return;
|
||||
|
||||
base.HandleInterruption(sender, e);
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
_toastGui.ErrorToast -= OnErrorToast;
|
||||
_toastGui.Toast -= OnNormalToast;
|
||||
_condition.ConditionChange -= OnConditionChange;
|
||||
base.Dispose();
|
||||
}
|
||||
|
||||
public sealed record StepProgress(
|
||||
|
@ -110,6 +110,8 @@ internal static class Mount
|
||||
? ETaskResult.TaskComplete
|
||||
: ETaskResult.StillRunning;
|
||||
}
|
||||
|
||||
public override bool ShouldInterruptOnDamage() => false;
|
||||
}
|
||||
|
||||
internal enum MountResult
|
||||
@ -197,6 +199,8 @@ internal static class Mount
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override bool ShouldInterruptOnDamage() => false;
|
||||
}
|
||||
|
||||
public enum EMountIf
|
||||
|
@ -61,5 +61,7 @@ internal static class NextQuest
|
||||
}
|
||||
|
||||
public override ETaskResult Update() => ETaskResult.TaskComplete;
|
||||
|
||||
public override bool ShouldInterruptOnDamage() => false;
|
||||
}
|
||||
}
|
||||
|
@ -104,5 +104,7 @@ internal static class SendNotification
|
||||
}
|
||||
|
||||
public override ETaskResult Update() => ETaskResult.TaskComplete;
|
||||
|
||||
public override bool ShouldInterruptOnDamage() => false;
|
||||
}
|
||||
}
|
||||
|
@ -25,5 +25,7 @@ internal static class WaitCondition
|
||||
|
||||
return DateTime.Now >= _continueAt ? ETaskResult.TaskComplete : ETaskResult.StillRunning;
|
||||
}
|
||||
|
||||
public override bool ShouldInterruptOnDamage() => false;
|
||||
}
|
||||
}
|
||||
|
@ -236,6 +236,8 @@ internal static class DoGather
|
||||
EAction action = PickAction(minerAction, botanistAction);
|
||||
return ActionManager.Instance()->GetActionStatus(ActionType.Action, (uint)action) == 0;
|
||||
}
|
||||
|
||||
public override bool ShouldInterruptOnDamage() => false;
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper", "NotAccessedPositionalProperty.Local")]
|
||||
|
@ -198,6 +198,8 @@ internal static class DoGatherCollectable
|
||||
else
|
||||
return botanistAction;
|
||||
}
|
||||
|
||||
public override bool ShouldInterruptOnDamage() => false;
|
||||
}
|
||||
|
||||
[SuppressMessage("ReSharper", "NotAccessedPositionalProperty.Local")]
|
||||
|
@ -59,5 +59,6 @@ internal static class MoveToLandingLocation
|
||||
|
||||
public override ETaskResult Update() => moveExecutor.Update();
|
||||
public bool OnErrorToast(SeString message) => moveExecutor.OnErrorToast(message);
|
||||
public override bool ShouldInterruptOnDamage() => moveExecutor.ShouldInterruptOnDamage();
|
||||
}
|
||||
}
|
||||
|
@ -80,5 +80,8 @@ internal static class TurnInDelivery
|
||||
addon->FireCallback(2, pickGatheringItem);
|
||||
return ETaskResult.StillRunning;
|
||||
}
|
||||
|
||||
// not even sure if any turn-in npcs are NEAR mobs; but we also need to be on a gathering/crafting job
|
||||
public override bool ShouldInterruptOnDamage() => false;
|
||||
}
|
||||
}
|
||||
|
@ -124,6 +124,8 @@ internal static class Action
|
||||
|
||||
return ETaskResult.TaskComplete;
|
||||
}
|
||||
|
||||
public override bool ShouldInterruptOnDamage() => false;
|
||||
}
|
||||
|
||||
internal sealed record UseMudraOnObject(uint DataId, EAction Action) : ITask
|
||||
@ -187,5 +189,7 @@ internal static class Action
|
||||
logger.LogError("Unable to find relevant combo for {Action}", Task.Action);
|
||||
return ETaskResult.TaskComplete;
|
||||
}
|
||||
|
||||
public override bool ShouldInterruptOnDamage() => false;
|
||||
}
|
||||
}
|
||||
|
@ -65,5 +65,7 @@ internal static class AetherCurrent
|
||||
gameFunctions.IsAetherCurrentUnlocked(Task.AetherCurrentId)
|
||||
? ETaskResult.TaskComplete
|
||||
: ETaskResult.StillRunning;
|
||||
|
||||
public override bool ShouldInterruptOnDamage() => true;
|
||||
}
|
||||
}
|
||||
|
@ -53,5 +53,7 @@ internal static class AethernetShard
|
||||
aetheryteFunctions.IsAetheryteUnlocked(Task.AetheryteLocation)
|
||||
? ETaskResult.TaskComplete
|
||||
: ETaskResult.StillRunning;
|
||||
|
||||
public override bool ShouldInterruptOnDamage() => true;
|
||||
}
|
||||
}
|
||||
|
@ -52,5 +52,7 @@ internal static class Aetheryte
|
||||
aetheryteFunctions.IsAetheryteUnlocked(Task.AetheryteLocation)
|
||||
? ETaskResult.TaskComplete
|
||||
: ETaskResult.StillRunning;
|
||||
|
||||
public override bool ShouldInterruptOnDamage() => true;
|
||||
}
|
||||
}
|
||||
|
@ -190,5 +190,7 @@ internal static class Combat
|
||||
return ETaskResult.TaskComplete;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool ShouldInterruptOnDamage() => false;
|
||||
}
|
||||
}
|
||||
|
@ -71,6 +71,8 @@ internal static class Dive
|
||||
return base.Update();
|
||||
}
|
||||
|
||||
public override bool ShouldInterruptOnDamage() => false;
|
||||
|
||||
protected override ETaskResult UpdateInternal()
|
||||
{
|
||||
if (condition[ConditionFlag.Diving])
|
||||
|
@ -93,6 +93,8 @@ internal static class Duty
|
||||
? ETaskResult.TaskComplete
|
||||
: ETaskResult.StillRunning;
|
||||
}
|
||||
|
||||
public override bool ShouldInterruptOnDamage() => false;
|
||||
}
|
||||
|
||||
internal sealed record WaitAutoDutyTask(uint ContentFinderConditionId) : ITask
|
||||
@ -117,6 +119,8 @@ internal static class Duty
|
||||
? ETaskResult.TaskComplete
|
||||
: ETaskResult.StillRunning;
|
||||
}
|
||||
|
||||
public override bool ShouldInterruptOnDamage() => false;
|
||||
}
|
||||
|
||||
internal sealed record OpenDutyFinderTask(uint ContentFinderConditionId) : ITask
|
||||
@ -138,5 +142,7 @@ internal static class Duty
|
||||
}
|
||||
|
||||
public override ETaskResult Update() => ETaskResult.TaskComplete;
|
||||
|
||||
public override bool ShouldInterruptOnDamage() => false;
|
||||
}
|
||||
}
|
||||
|
@ -51,6 +51,8 @@ internal static class Emote
|
||||
chatFunctions.UseEmote(Task.DataId, Task.Emote);
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool ShouldInterruptOnDamage() => true;
|
||||
}
|
||||
|
||||
internal sealed record UseOnSelf(EEmote Emote) : ITask
|
||||
@ -65,5 +67,7 @@ internal static class Emote
|
||||
chatFunctions.UseEmote(Task.Emote);
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool ShouldInterruptOnDamage() => true;
|
||||
}
|
||||
}
|
||||
|
@ -183,5 +183,7 @@ internal static class EquipItem
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override bool ShouldInterruptOnDamage() => true;
|
||||
}
|
||||
}
|
||||
|
@ -98,5 +98,7 @@ internal static class EquipRecommended
|
||||
|
||||
return ETaskResult.TaskComplete;
|
||||
}
|
||||
|
||||
public override bool ShouldInterruptOnDamage() => true;
|
||||
}
|
||||
}
|
||||
|
@ -228,6 +228,8 @@ internal static class Interact
|
||||
}
|
||||
}
|
||||
|
||||
public override bool ShouldInterruptOnDamage() => true;
|
||||
|
||||
private enum EInteractionState
|
||||
{
|
||||
None,
|
||||
|
@ -80,6 +80,8 @@ internal static class Jump
|
||||
|
||||
return ETaskResult.TaskComplete;
|
||||
}
|
||||
|
||||
public override bool ShouldInterruptOnDamage() => true;
|
||||
}
|
||||
|
||||
internal sealed class DoSingleJump(
|
||||
|
@ -48,5 +48,7 @@ internal static class Say
|
||||
chatFunctions.ExecuteCommand($"/say {Task.ChatMessage}");
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool ShouldInterruptOnDamage() => true;
|
||||
}
|
||||
}
|
||||
|
@ -43,5 +43,7 @@ internal static class StatusOff
|
||||
{
|
||||
return gameFunctions.HasStatus(Task.Status) ? ETaskResult.StillRunning : ETaskResult.TaskComplete;
|
||||
}
|
||||
|
||||
public override bool ShouldInterruptOnDamage() => false;
|
||||
}
|
||||
}
|
||||
|
@ -205,6 +205,8 @@ internal static class UseItem
|
||||
else
|
||||
return TimeSpan.FromSeconds(5);
|
||||
}
|
||||
|
||||
public override bool ShouldInterruptOnDamage() => true;
|
||||
}
|
||||
|
||||
internal sealed record UseOnGround(
|
||||
|
@ -50,6 +50,8 @@ internal static class InitiateLeve
|
||||
|
||||
return ETaskResult.TaskComplete;
|
||||
}
|
||||
|
||||
public override bool ShouldInterruptOnDamage() => false;
|
||||
}
|
||||
|
||||
internal sealed record OpenJournal(ElementId ElementId) : ITask
|
||||
@ -85,6 +87,8 @@ internal static class InitiateLeve
|
||||
|
||||
return ETaskResult.StillRunning;
|
||||
}
|
||||
|
||||
public override bool ShouldInterruptOnDamage() => false;
|
||||
}
|
||||
|
||||
internal sealed record Initiate(ElementId ElementId) : ITask
|
||||
@ -111,6 +115,8 @@ internal static class InitiateLeve
|
||||
|
||||
return ETaskResult.StillRunning;
|
||||
}
|
||||
|
||||
public override bool ShouldInterruptOnDamage() => false;
|
||||
}
|
||||
|
||||
internal sealed class SelectDifficulty : ITask
|
||||
@ -138,5 +144,7 @@ internal static class InitiateLeve
|
||||
|
||||
return ETaskResult.StillRunning;
|
||||
}
|
||||
|
||||
public override bool ShouldInterruptOnDamage() => false;
|
||||
}
|
||||
}
|
||||
|
@ -269,5 +269,7 @@ internal static class AethernetShortcut
|
||||
|
||||
return ETaskResult.TaskComplete;
|
||||
}
|
||||
|
||||
public override bool ShouldInterruptOnDamage() => true;
|
||||
}
|
||||
}
|
||||
|
@ -221,6 +221,8 @@ internal static class AetheryteShortcut
|
||||
}
|
||||
|
||||
public override bool WasInterrupted() => condition[ConditionFlag.InCombat] || base.WasInterrupted();
|
||||
|
||||
public override bool ShouldInterruptOnDamage() => true;
|
||||
}
|
||||
|
||||
internal sealed record MoveAwayFromAetheryte(EAetheryteLocation TargetAetheryte) : ITask
|
||||
@ -264,5 +266,7 @@ internal static class AetheryteShortcut
|
||||
}
|
||||
|
||||
public override ETaskResult Update() => moveExecutor.Update();
|
||||
|
||||
public override bool ShouldInterruptOnDamage() => true;
|
||||
}
|
||||
}
|
||||
|
@ -133,5 +133,8 @@ internal static class Craft
|
||||
return inventoryManager->GetInventoryItemCount(Task.ItemId, isHq: false, checkEquipped: false)
|
||||
+ inventoryManager->GetInventoryItemCount(Task.ItemId, isHq: true, checkEquipped: false);
|
||||
}
|
||||
|
||||
// we're on a crafting class, so combat doesn't make much sense (we also can't change classes in combat...)
|
||||
public override bool ShouldInterruptOnDamage() => false;
|
||||
}
|
||||
}
|
||||
|
@ -100,6 +100,8 @@ internal static class Gather
|
||||
minCollectability: (short)itemToGather.Collectability) >=
|
||||
itemToGather.ItemCount;
|
||||
}
|
||||
|
||||
public override bool ShouldInterruptOnDamage() => false;
|
||||
}
|
||||
|
||||
internal sealed record GatheringTask(
|
||||
@ -140,6 +142,9 @@ internal static class Gather
|
||||
gatheringController.OnErrorToast(ref message, ref isHandled);
|
||||
return isHandled;
|
||||
}
|
||||
|
||||
// we're on a gathering class, so combat doesn't make much sense (we also can't change classes in combat...)
|
||||
public override bool ShouldInterruptOnDamage() => false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -154,5 +159,7 @@ internal static class Gather
|
||||
{
|
||||
protected override bool Start() => true;
|
||||
public override ETaskResult Update() => ETaskResult.TaskComplete;
|
||||
|
||||
public override bool ShouldInterruptOnDamage() => false;
|
||||
}
|
||||
}
|
||||
|
@ -286,6 +286,8 @@ internal static class MoveTo
|
||||
return base.WasInterrupted();
|
||||
}
|
||||
|
||||
public override bool ShouldInterruptOnDamage() => false;
|
||||
|
||||
public bool OnErrorToast(SeString message)
|
||||
{
|
||||
if (GameFunctions.GameStringEquals(_cannotExecuteAtThisTime, message.TextValue))
|
||||
@ -302,6 +304,8 @@ internal static class MoveTo
|
||||
protected override bool Start() => true;
|
||||
|
||||
public override ETaskResult Update() => ETaskResult.TaskComplete;
|
||||
|
||||
public override bool ShouldInterruptOnDamage() => false;
|
||||
}
|
||||
|
||||
internal sealed record MoveTask(
|
||||
@ -361,6 +365,8 @@ internal static class MoveTo
|
||||
|
||||
return ETaskResult.TaskComplete;
|
||||
}
|
||||
|
||||
public override bool ShouldInterruptOnDamage() => false;
|
||||
}
|
||||
|
||||
internal sealed class LandTask : ITask
|
||||
@ -421,5 +427,7 @@ internal static class MoveTo
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public override bool ShouldInterruptOnDamage() => false;
|
||||
}
|
||||
}
|
||||
|
@ -74,5 +74,7 @@ internal static class RedeemRewardItems
|
||||
|
||||
return DateTime.Now <= _continueAt ? ETaskResult.StillRunning : ETaskResult.TaskComplete;
|
||||
}
|
||||
|
||||
public override bool ShouldInterruptOnDamage() => true;
|
||||
}
|
||||
}
|
||||
|
@ -315,5 +315,7 @@ internal static class SkipCondition
|
||||
}
|
||||
|
||||
public override ETaskResult Update() => ETaskResult.SkipRemainingTasksForStep;
|
||||
|
||||
public override bool ShouldInterruptOnDamage() => false;
|
||||
}
|
||||
}
|
||||
|
@ -31,5 +31,7 @@ internal static class StepDisabled
|
||||
logger.LogInformation("Skipping step, as it is disabled");
|
||||
return ETaskResult.SkipRemainingTasksForStep;
|
||||
}
|
||||
|
||||
public override bool ShouldInterruptOnDamage() => false;
|
||||
}
|
||||
}
|
||||
|
@ -52,5 +52,8 @@ internal static class SwitchClassJob
|
||||
}
|
||||
|
||||
protected override ETaskResult UpdateInternal() => ETaskResult.TaskComplete;
|
||||
|
||||
// can we even take damage while switching jobs? we should be out of combat...
|
||||
public override bool ShouldInterruptOnDamage() => false;
|
||||
}
|
||||
}
|
||||
|
@ -157,6 +157,8 @@ internal static class WaitAtEnd
|
||||
Delay = Task.Delay;
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool ShouldInterruptOnDamage() => false;
|
||||
}
|
||||
|
||||
internal sealed class WaitNextStepOrSequence : ITask
|
||||
@ -169,6 +171,8 @@ internal static class WaitAtEnd
|
||||
protected override bool Start() => true;
|
||||
|
||||
public override ETaskResult Update() => ETaskResult.StillRunning;
|
||||
|
||||
public override bool ShouldInterruptOnDamage() => false;
|
||||
}
|
||||
|
||||
internal sealed record WaitForCompletionFlags(QuestId Quest, QuestStep Step) : ITask
|
||||
@ -190,6 +194,8 @@ internal static class WaitAtEnd
|
||||
? ETaskResult.TaskComplete
|
||||
: ETaskResult.StillRunning;
|
||||
}
|
||||
|
||||
public override bool ShouldInterruptOnDamage() => false;
|
||||
}
|
||||
|
||||
internal sealed record WaitObjectAtPosition(
|
||||
@ -209,6 +215,8 @@ internal static class WaitAtEnd
|
||||
gameFunctions.IsObjectAtPosition(Task.DataId, Task.Destination, Task.Distance)
|
||||
? ETaskResult.TaskComplete
|
||||
: ETaskResult.StillRunning;
|
||||
|
||||
public override bool ShouldInterruptOnDamage() => false;
|
||||
}
|
||||
|
||||
internal sealed record WaitQuestAccepted(ElementId ElementId) : ITask
|
||||
@ -226,6 +234,8 @@ internal static class WaitAtEnd
|
||||
? ETaskResult.TaskComplete
|
||||
: ETaskResult.StillRunning;
|
||||
}
|
||||
|
||||
public override bool ShouldInterruptOnDamage() => false;
|
||||
}
|
||||
|
||||
internal sealed record WaitQuestCompleted(ElementId ElementId) : ITask
|
||||
@ -241,6 +251,8 @@ internal static class WaitAtEnd
|
||||
{
|
||||
return questFunctions.IsQuestComplete(Task.ElementId) ? ETaskResult.TaskComplete : ETaskResult.StillRunning;
|
||||
}
|
||||
|
||||
public override bool ShouldInterruptOnDamage() => false;
|
||||
}
|
||||
|
||||
internal sealed record NextStep(ElementId ElementId, int Sequence) : ILastTask
|
||||
@ -253,6 +265,8 @@ internal static class WaitAtEnd
|
||||
protected override bool Start() => true;
|
||||
|
||||
public override ETaskResult Update() => ETaskResult.NextStep;
|
||||
|
||||
public override bool ShouldInterruptOnDamage() => false;
|
||||
}
|
||||
|
||||
internal sealed class EndAutomation : ILastTask
|
||||
@ -268,5 +282,7 @@ internal static class WaitAtEnd
|
||||
protected override bool Start() => true;
|
||||
|
||||
public override ETaskResult Update() => ETaskResult.End;
|
||||
|
||||
public override bool ShouldInterruptOnDamage() => false;
|
||||
}
|
||||
}
|
||||
|
@ -31,6 +31,7 @@ internal static class WaitAtStart
|
||||
Delay = Task.Delay;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool ShouldInterruptOnDamage() => false;
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,8 @@ internal interface ITaskExecutor
|
||||
|
||||
bool Start(ITask task);
|
||||
|
||||
bool ShouldInterruptOnDamage();
|
||||
|
||||
bool WasInterrupted();
|
||||
|
||||
ETaskResult Update();
|
||||
@ -56,4 +58,6 @@ internal abstract class TaskExecutor<T> : ITaskExecutor
|
||||
}
|
||||
|
||||
public abstract ETaskResult Update();
|
||||
|
||||
public abstract bool ShouldInterruptOnDamage();
|
||||
}
|
||||
|
@ -247,6 +247,7 @@ public sealed class QuestionablePlugin : IDalamudPlugin
|
||||
serviceCollection.AddSingleton<GatheringController>();
|
||||
serviceCollection.AddSingleton<ContextMenuController>();
|
||||
serviceCollection.AddSingleton<ShopController>();
|
||||
serviceCollection.AddSingleton<InterruptHandler>();
|
||||
|
||||
serviceCollection.AddSingleton<CraftworksSupplyController>();
|
||||
serviceCollection.AddSingleton<CreditsController>();
|
||||
|
Loading…
Reference in New Issue
Block a user