Fix 'move to target' for objects too far away to be targeted

pull/17/head
Liza 2024-08-19 11:26:55 +02:00
parent 5b47814ea6
commit 83e9541e76
Signed by: liza
GPG Key ID: 7199F8D727D55F67
4 changed files with 56 additions and 24 deletions

View File

@ -21,6 +21,9 @@ namespace Questionable.Controller;
internal sealed class CombatController : IDisposable internal sealed class CombatController : IDisposable
{ {
private const float MaxTargetRange = 55f;
private const float MaxNameplateRange = 50f;
private readonly List<ICombatModule> _combatModules; private readonly List<ICombatModule> _combatModules;
private readonly MovementController _movementController; private readonly MovementController _movementController;
private readonly ITargetManager _targetManager; private readonly ITargetManager _targetManager;
@ -83,7 +86,7 @@ internal sealed class CombatController : IDisposable
if (_currentFight == null) if (_currentFight == null)
return EStatus.Complete; return EStatus.Complete;
if (_movementController.IsPathfinding || _movementController.IsPathRunning) if (_movementController.IsPathfinding || _movementController.IsPathRunning || _movementController.MovementStartedAt > DateTime.Now.AddSeconds(-1))
return EStatus.Moving; return EStatus.Moving;
var target = _targetManager.Target; var target = _targetManager.Target;
@ -100,29 +103,16 @@ internal sealed class CombatController : IDisposable
else if (nextTarget != null) else if (nextTarget != null)
{ {
if (nextTargetPriority > currentTargetPriority) if (nextTargetPriority > currentTargetPriority)
{ SetTarget(nextTarget);
_logger.LogInformation("Changing next target to {TargetName} ({TargetId:X8})",
nextTarget.Name.ToString(), nextTarget.GameObjectId);
_targetManager.Target = nextTarget;
_currentFight.Module.SetTarget(nextTarget);
}
} }
else else
{ SetTarget(null);
_logger.LogInformation("Resetting next target");
_targetManager.Target = null;
}
} }
else else
{ {
var nextTarget = FindNextTarget(); var nextTarget = FindNextTarget();
if (nextTarget is { IsDead: false }) if (nextTarget is { IsDead: false })
{ SetTarget(nextTarget);
_logger.LogInformation("Setting next target to {TargetName} ({TargetId:X8})",
nextTarget.Name.ToString(), nextTarget.GameObjectId);
_targetManager.Target = nextTarget;
_currentFight.Module.SetTarget(nextTarget);
}
} }
if (_condition[ConditionFlag.InCombat]) if (_condition[ConditionFlag.InCombat])
@ -197,7 +187,7 @@ internal sealed class CombatController : IDisposable
.FirstOrDefault(); .FirstOrDefault();
} }
private unsafe int GetKillPriority(IGameObject gameObject) public unsafe int GetKillPriority(IGameObject gameObject)
{ {
if (gameObject is IBattleNpc battleNpc) if (gameObject is IBattleNpc battleNpc)
{ {
@ -257,7 +247,7 @@ internal sealed class CombatController : IDisposable
// for enemies that are very far away, their nameplate doesn't render but they're in the object table // for enemies that are very far away, their nameplate doesn't render but they're in the object table
if (_currentFight?.Data.SpawnType == EEnemySpawnType.OverworldEnemies && if (_currentFight?.Data.SpawnType == EEnemySpawnType.OverworldEnemies &&
Vector3.Distance(_clientState.LocalPlayer?.Position ?? Vector3.Zero, battleNpc.Position) > 45) Vector3.Distance(_clientState.LocalPlayer?.Position ?? Vector3.Zero, battleNpc.Position) > MaxNameplateRange)
return 25; return 25;
} }
else else
@ -288,6 +278,29 @@ internal sealed class CombatController : IDisposable
return 0; return 0;
} }
private void SetTarget(IGameObject? target)
{
if (target == null)
{
if (_targetManager.Target != null)
{
_logger.LogInformation("Clearing target");
_targetManager.Target = null;
}
}
else if (Vector3.Distance(_clientState.LocalPlayer!.Position, target.Position) > MaxTargetRange)
{
_logger.LogInformation("Moving to target, distance: {Distance:N2}", Vector3.Distance(_clientState.LocalPlayer!.Position, target.Position));
_currentFight!.Module.MoveToTarget(target);
}
else
{
_logger.LogInformation("Setting target to {TargetName} ({TargetId:X8})", target.Name.ToString(), target.GameObjectId);
_targetManager.Target = target;
_currentFight!.Module.MoveToTarget(target);
}
}
public void Stop(string label) public void Stop(string label)
{ {
using var scope = _logger.BeginScope(label); using var scope = _logger.BeginScope(label);

View File

@ -12,5 +12,5 @@ internal interface ICombatModule
void Update(IGameObject nextTarget); void Update(IGameObject nextTarget);
void SetTarget(IGameObject nextTarget); void MoveToTarget(IGameObject nextTarget);
} }

View File

@ -77,7 +77,7 @@ internal sealed class RotationSolverRebornModule : ICombatModule, IDisposable
} }
} }
public void SetTarget(IGameObject gameObject) public void MoveToTarget(IGameObject gameObject)
{ {
var player = _clientState.LocalPlayer; var player = _clientState.LocalPlayer;
if (player == null) if (player == null)
@ -114,7 +114,7 @@ internal sealed class RotationSolverRebornModule : ICombatModule, IDisposable
if (DateTime.Now > _lastDistanceCheck.AddSeconds(10)) if (DateTime.Now > _lastDistanceCheck.AddSeconds(10))
{ {
SetTarget(gameObject); MoveToTarget(gameObject);
_lastDistanceCheck = DateTime.Now; _lastDistanceCheck = DateTime.Now;
} }
} }

View File

@ -1,4 +1,5 @@
using System.Diagnostics.CodeAnalysis; using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization; using System.Globalization;
using System.Numerics; using System.Numerics;
using Dalamud.Game.ClientState.Conditions; using Dalamud.Game.ClientState.Conditions;
@ -19,10 +20,12 @@ internal sealed class DebugOverlay : Window
private readonly IClientState _clientState; private readonly IClientState _clientState;
private readonly ICondition _condition; private readonly ICondition _condition;
private readonly AetheryteData _aetheryteData; private readonly AetheryteData _aetheryteData;
private readonly IObjectTable _objectTable;
private readonly CombatController _combatController;
private readonly Configuration _configuration; private readonly Configuration _configuration;
public DebugOverlay(QuestController questController, QuestRegistry questRegistry, IGameGui gameGui, public DebugOverlay(QuestController questController, QuestRegistry questRegistry, IGameGui gameGui,
IClientState clientState, ICondition condition, AetheryteData aetheryteData, Configuration configuration) IClientState clientState, ICondition condition, AetheryteData aetheryteData, IObjectTable objectTable, CombatController combatController, Configuration configuration)
: base("Questionable Debug Overlay###QuestionableDebugOverlay", : base("Questionable Debug Overlay###QuestionableDebugOverlay",
ImGuiWindowFlags.NoTitleBar | ImGuiWindowFlags.NoScrollbar | ImGuiWindowFlags.NoBackground | ImGuiWindowFlags.NoTitleBar | ImGuiWindowFlags.NoScrollbar | ImGuiWindowFlags.NoBackground |
ImGuiWindowFlags.NoInputs | ImGuiWindowFlags.NoSavedSettings, true) ImGuiWindowFlags.NoInputs | ImGuiWindowFlags.NoSavedSettings, true)
@ -33,6 +36,8 @@ internal sealed class DebugOverlay : Window
_clientState = clientState; _clientState = clientState;
_condition = condition; _condition = condition;
_aetheryteData = aetheryteData; _aetheryteData = aetheryteData;
_objectTable = objectTable;
_combatController = combatController;
_configuration = configuration; _configuration = configuration;
Position = Vector2.Zero; Position = Vector2.Zero;
@ -61,6 +66,7 @@ internal sealed class DebugOverlay : Window
DrawCurrentQuest(); DrawCurrentQuest();
DrawHighlightedQuest(); DrawHighlightedQuest();
DrawCombatTargets();
} }
private void DrawCurrentQuest() private void DrawCurrentQuest()
@ -119,6 +125,19 @@ internal sealed class DebugOverlay : Window
$"{counter}: {step.InteractionType}\n{position.ToString("G", CultureInfo.InvariantCulture)} [{(position - _clientState.LocalPlayer!.Position).Length():N2}]\n{step.Comment}"); $"{counter}: {step.InteractionType}\n{position.ToString("G", CultureInfo.InvariantCulture)} [{(position - _clientState.LocalPlayer!.Position).Length():N2}]\n{step.Comment}");
} }
[Conditional("false")]
private void DrawCombatTargets()
{
foreach (var x in _objectTable)
{
bool visible = _gameGui.WorldToScreen(x.Position, out Vector2 screenPos);
if (!visible)
continue;
ImGui.GetWindowDrawList() .AddText(screenPos + new Vector2(10, -8), 0xFFFFFFFF, $"{x.Name}/{x.GameObjectId:X}, {_combatController.GetKillPriority(x)}, {Vector3.Distance(x.Position, _clientState.LocalPlayer!.Position):N2}, {x.IsTargetable}");
}
}
private bool TryGetPosition(QuestStep step, [NotNullWhen(true)] out Vector3? position) private bool TryGetPosition(QuestStep step, [NotNullWhen(true)] out Vector3? position)
{ {
if (step.Position != null) if (step.Position != null)