using System; using Dalamud.Plugin.Services; using FFXIVClientStructs.FFXIV.Component.GUI; using FFXIVClientStructs.Interop; using LLib.GameUI; using Microsoft.Extensions.Logging; using Questionable.Controller.Utils; namespace Questionable.Controller.GameUi; internal sealed class QteController : IDisposable { private readonly Configuration _configuration; private readonly IGameGui _gameGui; private readonly IGameConfig _gameConfig; private readonly IFramework _framework; private readonly ILogger _logger; private long _throttler = Environment.TickCount64; private readonly Random _random = new Random(); private bool _hasDirectChat; private bool _directChatWasEnabled; public QteController(Configuration configuration, IGameGui gameGui, IGameConfig gameConfig, IFramework framework, ILogger logger) { _configuration = configuration; _gameGui = gameGui; _gameConfig = gameConfig; _framework = framework; _logger = logger; _framework.Update += OnUpdate; } private unsafe void OnUpdate(IFramework framework) { AtkUnitBase* addonPtr; if (!_configuration.General.AutoSolveQte) { EnableDirectChatIfNeeded(); } else if (_gameGui.TryGetAddonByName("QTE", out addonPtr) && LAddon.IsAddonReady(addonPtr) && addonPtr->IsVisible) { DisableDirectChatIfNeeded(); if (Environment.TickCount64 >= _throttler) { if (IsChatLogFocused()) { WindowsKeypress.SendKeypress(WindowsKeypress.LimitedKeys.Escape); } WindowsKeypress.SendKeypress(WindowsKeypress.LimitedKeys.A); _throttler = Environment.TickCount64 + _random.Next(25, 50); } } else { EnableDirectChatIfNeeded(); } } private unsafe bool IsChatLogFocused() { AtkStage* ptr = AtkStage.Instance(); if (ptr == null) { return false; } Span> entries = ptr->RaptureAtkUnitManager->AtkUnitManager.FocusedUnitsList.Entries; for (int i = 0; i < entries.Length; i++) { Pointer pointer = entries[i]; if (pointer.Value != null && pointer.Value->NameString == "ChatLog") { return true; } } return false; } private void EnableDirectChatIfNeeded() { if (_hasDirectChat) { _gameConfig.UiControl.Set("DirectChat", _directChatWasEnabled); _hasDirectChat = false; } } private void DisableDirectChatIfNeeded() { if (!_hasDirectChat && _gameConfig.UiControl.TryGetBool("DirectChat", out var value)) { _directChatWasEnabled = value; if (value) { _gameConfig.UiControl.Set("DirectChat", value: false); } _hasDirectChat = true; } } public void Dispose() { _framework.Update -= OnUpdate; EnableDirectChatIfNeeded(); } }