If you start moving while in combat (because mounting isn't possible), use mount as soon as you're out of combat

This commit is contained in:
Liza 2024-11-04 17:20:42 +01:00
parent cc8f326d7e
commit 6ef6dbfdb4
Signed by: liza
GPG Key ID: 7199F8D727D55F67
3 changed files with 71 additions and 19 deletions

View File

@ -35,21 +35,21 @@ internal static class Mount
private bool _mountTriggered; private bool _mountTriggered;
private DateTime _retryAt = DateTime.MinValue; private DateTime _retryAt = DateTime.MinValue;
protected override bool Start() public MountResult EvaluateMountState()
{ {
if (condition[ConditionFlag.Mounted]) if (condition[ConditionFlag.Mounted])
return false; return MountResult.DontMount;
if (!territoryData.CanUseMount(Task.TerritoryId)) if (!territoryData.CanUseMount(Task.TerritoryId))
{ {
logger.LogInformation("Can't use mount in current territory {Id}", Task.TerritoryId); logger.LogInformation("Can't use mount in current territory {Id}", Task.TerritoryId);
return false; return MountResult.DontMount;
} }
if (gameFunctions.HasStatusPreventingMount()) if (gameFunctions.HasStatusPreventingMount())
{ {
logger.LogInformation("Can't mount due to status preventing sprint or mount"); logger.LogInformation("Can't mount due to status preventing sprint or mount");
return false; return MountResult.DontMount;
} }
if (Task.MountIf == EMountIf.AwayFromPosition) if (Task.MountIf == EMountIf.AwayFromPosition)
@ -59,7 +59,7 @@ internal static class Mount
if (Task.TerritoryId == clientState.TerritoryType && distance < 30f && !Conditions.IsDiving) if (Task.TerritoryId == clientState.TerritoryType && distance < 30f && !Conditions.IsDiving)
{ {
logger.LogInformation("Not using mount, as we're close to the target"); logger.LogInformation("Not using mount, as we're close to the target");
return false; return MountResult.DontMount;
} }
logger.LogInformation( logger.LogInformation(
@ -72,12 +72,14 @@ internal static class Mount
if (!condition[ConditionFlag.InCombat]) if (!condition[ConditionFlag.InCombat])
{ {
_retryAt = DateTime.Now.AddSeconds(0.5); _retryAt = DateTime.Now.AddSeconds(0.5);
return true; return MountResult.Mount;
} }
else
return false; return MountResult.WhenOutOfCombat;
} }
protected override bool Start() => EvaluateMountState() == MountResult.Mount;
public override ETaskResult Update() public override ETaskResult Update()
{ {
if (_mountTriggered && !condition[ConditionFlag.Mounted] && DateTime.Now > _retryAt) if (_mountTriggered && !condition[ConditionFlag.Mounted] && DateTime.Now > _retryAt)
@ -108,6 +110,13 @@ internal static class Mount
} }
} }
internal enum MountResult
{
DontMount,
Mount,
WhenOutOfCombat,
}
internal sealed record UnmountTask : ITask internal sealed record UnmountTask : ITask
{ {
public bool ShouldRedoOnInterrupt() => true; public bool ShouldRedoOnInterrupt() => true;

View File

@ -87,19 +87,23 @@ internal static class MoveTo
private readonly GameFunctions _gameFunctions; private readonly GameFunctions _gameFunctions;
private readonly ILogger<MoveExecutor> _logger; private readonly ILogger<MoveExecutor> _logger;
private readonly IClientState _clientState; private readonly IClientState _clientState;
private readonly ICondition _condition;
private readonly Mount.MountExecutor _mountExecutor; private readonly Mount.MountExecutor _mountExecutor;
private readonly Mount.UnmountExecutor _unmountExecutor; private readonly Mount.UnmountExecutor _unmountExecutor;
private Action? _startAction; private Action? _startAction;
private Vector3 _destination; private Vector3 _destination;
private bool _canRestart; private bool _canRestart;
private ITaskExecutor? _nestedExecutor;
private (ITaskExecutor Executor, ITask Task, bool Triggered)? _nestedExecutor =
(new NoOpTaskExecutor(), new NoOpTask(), true);
public MoveExecutor( public MoveExecutor(
MovementController movementController, MovementController movementController,
GameFunctions gameFunctions, GameFunctions gameFunctions,
ILogger<MoveExecutor> logger, ILogger<MoveExecutor> logger,
IClientState clientState, IClientState clientState,
ICondition condition,
IDataManager dataManager, IDataManager dataManager,
Mount.MountExecutor mountExecutor, Mount.MountExecutor mountExecutor,
Mount.UnmountExecutor unmountExecutor) Mount.UnmountExecutor unmountExecutor)
@ -108,6 +112,7 @@ internal static class MoveTo
_gameFunctions = gameFunctions; _gameFunctions = gameFunctions;
_logger = logger; _logger = logger;
_clientState = clientState; _clientState = clientState;
_condition = condition;
_mountExecutor = mountExecutor; _mountExecutor = mountExecutor;
_unmountExecutor = unmountExecutor; _unmountExecutor = unmountExecutor;
_cannotExecuteAtThisTime = dataManager.GetString<LogMessage>(579, x => x.Text)!; _cannotExecuteAtThisTime = dataManager.GetString<LogMessage>(579, x => x.Text)!;
@ -161,16 +166,18 @@ internal static class MoveTo
var mountTask = new Mount.MountTask(Task.TerritoryId, Mount.EMountIf.Always); var mountTask = new Mount.MountTask(Task.TerritoryId, Mount.EMountIf.Always);
if (_mountExecutor.Start(mountTask)) if (_mountExecutor.Start(mountTask))
{ {
_nestedExecutor = _mountExecutor; _nestedExecutor = (_mountExecutor, mountTask, true);
return true; return true;
} }
else if (_mountExecutor.EvaluateMountState() == Mount.MountResult.WhenOutOfCombat)
_nestedExecutor = (_mountExecutor, mountTask, false);
} }
else if (Task.Mount == false) else if (Task.Mount == false)
{ {
var mountTask = new Mount.UnmountTask(); var mountTask = new Mount.UnmountTask();
if (_unmountExecutor.Start(mountTask)) if (_unmountExecutor.Start(mountTask))
{ {
_nestedExecutor = _unmountExecutor; _nestedExecutor = (_unmountExecutor, mountTask, true);
return true; return true;
} }
} }
@ -187,21 +194,43 @@ internal static class MoveTo
var mountTask = new Mount.MountTask(Task.TerritoryId, mountIf, _destination); var mountTask = new Mount.MountTask(Task.TerritoryId, mountIf, _destination);
if (_mountExecutor.Start(mountTask)) if (_mountExecutor.Start(mountTask))
{ {
_nestedExecutor = _mountExecutor; _nestedExecutor = (_mountExecutor, mountTask, true);
return true; return true;
} }
else if (_mountExecutor.EvaluateMountState() == Mount.MountResult.WhenOutOfCombat)
_nestedExecutor = (_mountExecutor, mountTask, false);
} }
} }
_nestedExecutor = new NoOpTaskExecutor(); if (_startAction != null && (_nestedExecutor == null || _nestedExecutor.Value.Triggered == false))
_startAction();
return true; return true;
} }
public override ETaskResult Update() public override ETaskResult Update()
{ {
if (_nestedExecutor != null) if (_nestedExecutor is { } nestedExecutor)
{ {
if (_nestedExecutor.Update() == ETaskResult.TaskComplete) if (nestedExecutor is { Triggered: false, Executor: Mount.MountExecutor mountExecutor })
{
if (!_condition[ConditionFlag.InCombat])
{
if (mountExecutor.EvaluateMountState() == Mount.MountResult.DontMount)
_nestedExecutor = (new NoOpTaskExecutor(), new NoOpTask(), true);
else
{
if (_movementController.IsPathfinding || _movementController.IsPathRunning)
_movementController.Stop();
if (nestedExecutor.Executor.Start(nestedExecutor.Task))
{
_nestedExecutor = nestedExecutor with { Triggered = true };
return ETaskResult.StillRunning;
}
}
}
}
else if (nestedExecutor.Executor.Update() == ETaskResult.TaskComplete)
{ {
_nestedExecutor = null; _nestedExecutor = null;
if (_startAction != null) if (_startAction != null)
@ -213,6 +242,7 @@ internal static class MoveTo
else else
return ETaskResult.TaskComplete; return ETaskResult.TaskComplete;
} }
return ETaskResult.StillRunning; return ETaskResult.StillRunning;
} }
@ -245,6 +275,17 @@ internal static class MoveTo
return ETaskResult.TaskComplete; return ETaskResult.TaskComplete;
} }
public override bool WasInterrupted()
{
if (Task.Fly && _condition[ConditionFlag.InCombat] && !_condition[ConditionFlag.Mounted] &&
_nestedExecutor is { Triggered: false, Executor: Mount.MountExecutor mountExecutor } &&
mountExecutor.EvaluateMountState() == Mount.MountResult.WhenOutOfCombat)
{
return true;
}
return base.WasInterrupted();
}
public bool OnErrorToast(SeString message) public bool OnErrorToast(SeString message)
{ {
@ -255,7 +296,9 @@ internal static class MoveTo
} }
} }
private sealed class NoOpTaskExecutor : TaskExecutor<ITask> private sealed record NoOpTask : ITask;
private sealed class NoOpTaskExecutor : TaskExecutor<NoOpTask>
{ {
protected override bool Start() => true; protected override bool Start() => true;
@ -306,7 +349,6 @@ internal static class MoveTo
GameFunctions gameFunctions, GameFunctions gameFunctions,
IClientState clientState) : TaskExecutor<WaitForNearDataId> IClientState clientState) : TaskExecutor<WaitForNearDataId>
{ {
protected override bool Start() => true; protected override bool Start() => true;
public override ETaskResult Update() public override ETaskResult Update()
@ -328,7 +370,8 @@ internal static class MoveTo
public override string ToString() => "Land"; public override string ToString() => "Land";
} }
internal sealed class LandExecutor(IClientState clientState, ICondition condition, ILogger<LandExecutor> logger) : TaskExecutor<LandTask> internal sealed class LandExecutor(IClientState clientState, ICondition condition, ILogger<LandExecutor> logger)
: TaskExecutor<LandTask>
{ {
private bool _landing; private bool _landing;
private DateTime _continueAt; private DateTime _continueAt;

View File

@ -23,7 +23,7 @@ internal abstract class TaskExecutor<T> : ITaskExecutor
public InteractionProgressContext? ProgressContext { get; set; } public InteractionProgressContext? ProgressContext { get; set; }
ITask ITaskExecutor.CurrentTask => Task; ITask ITaskExecutor.CurrentTask => Task;
public bool WasInterrupted() public virtual bool WasInterrupted()
{ {
if (ProgressContext is {} progressContext) if (ProgressContext is {} progressContext)
{ {