167 lines
4.4 KiB
C#
167 lines
4.4 KiB
C#
using System;
|
|
using System.Numerics;
|
|
using Dalamud.Plugin.Services;
|
|
|
|
namespace QuestionableCompanion.Services;
|
|
|
|
public class MovementMonitorService : IDisposable
|
|
{
|
|
private readonly IClientState clientState;
|
|
|
|
private readonly IPluginLog log;
|
|
|
|
private readonly ICommandManager commandManager;
|
|
|
|
private readonly IFramework framework;
|
|
|
|
private readonly Configuration config;
|
|
|
|
private ChauffeurModeService? chauffeurMode;
|
|
|
|
private Vector3 lastPosition = Vector3.Zero;
|
|
|
|
private DateTime lastMovementTime = DateTime.Now;
|
|
|
|
private DateTime lastCheckTime = DateTime.MinValue;
|
|
|
|
private bool isMonitoring;
|
|
|
|
private const float MovementThreshold = 0.1f;
|
|
|
|
public bool IsMonitoring => isMonitoring;
|
|
|
|
public MovementMonitorService(IClientState clientState, IPluginLog log, ICommandManager commandManager, IFramework framework, Configuration config)
|
|
{
|
|
this.clientState = clientState;
|
|
this.log = log;
|
|
this.commandManager = commandManager;
|
|
this.framework = framework;
|
|
this.config = config;
|
|
log.Information("[MovementMonitor] Service initialized");
|
|
}
|
|
|
|
public void SetChauffeurMode(ChauffeurModeService service)
|
|
{
|
|
chauffeurMode = service;
|
|
log.Information("[MovementMonitor] ChauffeurMode service linked for failsafe");
|
|
}
|
|
|
|
public void StartMonitoring()
|
|
{
|
|
if (!isMonitoring)
|
|
{
|
|
isMonitoring = true;
|
|
lastMovementTime = DateTime.Now;
|
|
lastCheckTime = DateTime.Now;
|
|
lastPosition = Vector3.Zero;
|
|
framework.Update += OnFrameworkUpdate;
|
|
log.Information("[MovementMonitor] Movement monitoring started");
|
|
}
|
|
}
|
|
|
|
public void StopMonitoring()
|
|
{
|
|
if (isMonitoring)
|
|
{
|
|
isMonitoring = false;
|
|
framework.Update -= OnFrameworkUpdate;
|
|
log.Information("[MovementMonitor] Movement monitoring stopped");
|
|
}
|
|
}
|
|
|
|
public void ResetMovementTimer()
|
|
{
|
|
lastMovementTime = DateTime.Now;
|
|
if (clientState.LocalPlayer != null)
|
|
{
|
|
lastPosition = clientState.LocalPlayer.Position;
|
|
}
|
|
}
|
|
|
|
private void OnFrameworkUpdate(IFramework framework)
|
|
{
|
|
if (!isMonitoring)
|
|
{
|
|
return;
|
|
}
|
|
DateTime now = DateTime.Now;
|
|
if ((now - lastCheckTime).TotalSeconds < (double)config.MovementCheckInterval)
|
|
{
|
|
return;
|
|
}
|
|
lastCheckTime = now;
|
|
if (clientState.LocalPlayer == null || !clientState.IsLoggedIn)
|
|
{
|
|
return;
|
|
}
|
|
try
|
|
{
|
|
Vector3 currentPosition = clientState.LocalPlayer.Position;
|
|
if (lastPosition == Vector3.Zero)
|
|
{
|
|
lastPosition = currentPosition;
|
|
lastMovementTime = now;
|
|
return;
|
|
}
|
|
if (Vector3.Distance(lastPosition, currentPosition) > 0.1f)
|
|
{
|
|
lastMovementTime = now;
|
|
lastPosition = currentPosition;
|
|
return;
|
|
}
|
|
double timeSinceMovement = (now - lastMovementTime).TotalSeconds;
|
|
if (!(timeSinceMovement >= (double)config.MovementStuckThreshold))
|
|
{
|
|
return;
|
|
}
|
|
log.Warning("[MovementMonitor] ========================================");
|
|
log.Warning("[MovementMonitor] === PLAYER STUCK DETECTED ===");
|
|
log.Warning("[MovementMonitor] ========================================");
|
|
log.Warning($"[MovementMonitor] No movement for {timeSinceMovement:F1} seconds");
|
|
log.Warning($"[MovementMonitor] Position: {currentPosition}");
|
|
if (chauffeurMode != null && (chauffeurMode.IsWaitingForHelper || chauffeurMode.IsTransportingQuester))
|
|
{
|
|
log.Warning("[MovementMonitor] FAILSAFE: Resetting Chauffeur Mode due to stuck detection!");
|
|
chauffeurMode.ResetChauffeurState();
|
|
}
|
|
log.Warning("[MovementMonitor] Sending /qst reload command...");
|
|
framework.RunOnTick(delegate
|
|
{
|
|
try
|
|
{
|
|
commandManager.ProcessCommand("/qst reload");
|
|
log.Information("[MovementMonitor] /qst reload command sent");
|
|
}
|
|
catch (Exception ex2)
|
|
{
|
|
log.Error("[MovementMonitor] Failed to send reload command: " + ex2.Message);
|
|
}
|
|
}, TimeSpan.FromMilliseconds(100L, 0L));
|
|
framework.RunOnTick(delegate
|
|
{
|
|
try
|
|
{
|
|
commandManager.ProcessCommand("/qst start");
|
|
log.Information("[MovementMonitor] /qst start command sent");
|
|
}
|
|
catch (Exception ex2)
|
|
{
|
|
log.Error("[MovementMonitor] Failed to send start command: " + ex2.Message);
|
|
}
|
|
}, TimeSpan.FromSeconds(1L));
|
|
lastMovementTime = now;
|
|
lastPosition = currentPosition;
|
|
log.Information("[MovementMonitor] Movement timer reset - monitoring continues...");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
log.Error("[MovementMonitor] Error checking movement: " + ex.Message);
|
|
}
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
StopMonitoring();
|
|
log.Information("[MovementMonitor] Service disposed");
|
|
}
|
|
}
|