punish v6.8.18.0

This commit is contained in:
alydev 2025-10-09 07:47:19 +10:00
commit cfb4dea47e
316 changed files with 554088 additions and 0 deletions

View file

@ -0,0 +1,50 @@
using Dalamud.Plugin;
using Dalamud.Plugin.Ipc;
using Dalamud.Plugin.Ipc.Exceptions;
using Microsoft.Extensions.Logging;
namespace Questionable.External;
internal sealed class ArtisanIpc
{
private readonly ILogger<ArtisanIpc> _logger;
private readonly ICallGateSubscriber<ushort, int, object> _craftItem;
private readonly ICallGateSubscriber<bool> _getEnduranceStatus;
public ArtisanIpc(IDalamudPluginInterface pluginInterface, ILogger<ArtisanIpc> logger)
{
_logger = logger;
_craftItem = pluginInterface.GetIpcSubscriber<ushort, int, object>("Artisan.CraftItem");
_getEnduranceStatus = pluginInterface.GetIpcSubscriber<bool>("Artisan.GetEnduranceStatus");
}
public bool CraftItem(ushort recipeId, int quantity)
{
try
{
_logger.LogInformation("Attempting to craft {Quantity} items with recipe {RecipeId} with Artisan", quantity, recipeId);
_craftItem.InvokeAction(recipeId, quantity);
return true;
}
catch (IpcError exception)
{
_logger.LogError(exception, "Unable to craft items");
return false;
}
}
public bool IsCrafting()
{
try
{
return _getEnduranceStatus.InvokeFunc();
}
catch (IpcError exception)
{
_logger.LogError(exception, "Unable to check for Artisan endurance status");
return false;
}
}
}

View file

@ -0,0 +1,138 @@
using System;
using Dalamud.Plugin;
using Dalamud.Plugin.Ipc;
using Dalamud.Plugin.Ipc.Exceptions;
using Microsoft.Extensions.Logging;
using Questionable.Controller.Steps;
using Questionable.Data;
using Questionable.Model.Questing;
namespace Questionable.External;
internal sealed class AutoDutyIpc
{
public enum DutyMode
{
Support = 1,
UnsyncRegular
}
private readonly Configuration _configuration;
private readonly TerritoryData _territoryData;
private readonly ILogger<AutoDutyIpc> _logger;
private readonly ICallGateSubscriber<uint, bool> _contentHasPath;
private readonly ICallGateSubscriber<string, string, object> _setConfig;
private readonly ICallGateSubscriber<uint, int, bool, object> _run;
private readonly ICallGateSubscriber<bool> _isStopped;
private readonly ICallGateSubscriber<object> _stop;
public AutoDutyIpc(IDalamudPluginInterface pluginInterface, Configuration configuration, TerritoryData territoryData, ILogger<AutoDutyIpc> logger)
{
_configuration = configuration;
_territoryData = territoryData;
_logger = logger;
_contentHasPath = pluginInterface.GetIpcSubscriber<uint, bool>("AutoDuty.ContentHasPath");
_setConfig = pluginInterface.GetIpcSubscriber<string, string, object>("AutoDuty.SetConfig");
_run = pluginInterface.GetIpcSubscriber<uint, int, bool, object>("AutoDuty.Run");
_isStopped = pluginInterface.GetIpcSubscriber<bool>("AutoDuty.IsStopped");
_stop = pluginInterface.GetIpcSubscriber<object>("AutoDuty.Stop");
}
public bool IsConfiguredToRunContent(DutyOptions? dutyOptions)
{
if (dutyOptions == null || dutyOptions.ContentFinderConditionId == 0)
{
return false;
}
if (!_configuration.Duties.RunInstancedContentWithAutoDuty)
{
return false;
}
if (_configuration.Duties.BlacklistedDutyCfcIds.Contains(dutyOptions.ContentFinderConditionId))
{
return false;
}
if (_configuration.Duties.WhitelistedDutyCfcIds.Contains(dutyOptions.ContentFinderConditionId) && _territoryData.TryGetContentFinderCondition(dutyOptions.ContentFinderConditionId, out TerritoryData.ContentFinderConditionData _))
{
return true;
}
if (dutyOptions.Enabled)
{
return HasPath(dutyOptions.ContentFinderConditionId);
}
return false;
}
public bool HasPath(uint cfcId)
{
if (!_territoryData.TryGetContentFinderCondition(cfcId, out TerritoryData.ContentFinderConditionData contentFinderConditionData))
{
return false;
}
try
{
return _contentHasPath.InvokeFunc(contentFinderConditionData.TerritoryId);
}
catch (IpcError ipcError)
{
_logger.LogWarning("Unable to query AutoDuty for path in territory {TerritoryType}: {Message}", contentFinderConditionData.TerritoryId, ipcError.Message);
return false;
}
}
public void StartInstance(uint cfcId, DutyMode dutyMode)
{
if (!_territoryData.TryGetContentFinderCondition(cfcId, out TerritoryData.ContentFinderConditionData contentFinderConditionData))
{
throw new TaskException($"Unknown ContentFinderConditionId {cfcId}");
}
try
{
_setConfig.InvokeAction("Unsynced", $"{dutyMode == DutyMode.UnsyncRegular}");
ICallGateSubscriber<string, string, object> setConfig = _setConfig;
setConfig.InvokeAction("dutyModeEnum", dutyMode switch
{
DutyMode.Support => "Support",
DutyMode.UnsyncRegular => "Regular",
_ => throw new ArgumentOutOfRangeException("dutyMode", dutyMode, null),
});
_run.InvokeAction(contentFinderConditionData.TerritoryId, 1, !_configuration.Advanced.DisableAutoDutyBareMode);
}
catch (IpcError ipcError)
{
throw new TaskException("Unable to run content with AutoDuty: " + ipcError.Message, ipcError);
}
}
public bool IsStopped()
{
try
{
return _isStopped.InvokeFunc();
}
catch (IpcError)
{
return true;
}
}
public void Stop()
{
try
{
_logger.LogInformation("Calling AutoDuty.Stop");
_stop.InvokeAction();
}
catch (IpcError ipcError)
{
throw new TaskException("Unable to stop AutoDuty: " + ipcError.Message, ipcError);
}
}
}

View file

@ -0,0 +1,42 @@
using Dalamud.Plugin;
using Dalamud.Plugin.Ipc;
using Dalamud.Plugin.Ipc.Exceptions;
using Microsoft.Extensions.Logging;
namespace Questionable.External;
internal sealed class AutomatonIpc
{
private readonly ILogger<AutomatonIpc> _logger;
private readonly ICallGateSubscriber<string, bool> _isTweakEnabled;
private bool _loggedIpcError;
public bool IsAutoSnipeEnabled
{
get
{
try
{
return _isTweakEnabled.InvokeFunc("AutoSnipeQuests");
}
catch (IpcError exception)
{
if (!_loggedIpcError)
{
_loggedIpcError = true;
_logger.LogWarning(exception, "Could not query automaton for tweak status, probably not installed");
}
return false;
}
}
}
public AutomatonIpc(IDalamudPluginInterface pluginInterface, ILogger<AutomatonIpc> logger)
{
_logger = logger;
_isTweakEnabled = pluginInterface.GetIpcSubscriber<string, bool>("Automaton.IsTweakEnabled");
logger.LogInformation("Automaton auto-snipe enabled: {IsTweakEnabled}", IsAutoSnipeEnabled);
}
}

View file

@ -0,0 +1,150 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using Dalamud.Plugin;
using Dalamud.Plugin.Ipc;
using Dalamud.Plugin.Ipc.Exceptions;
using Dalamud.Plugin.Services;
using Questionable.Data;
using Questionable.Model.Questing;
namespace Questionable.External;
internal sealed class BossModIpc
{
public enum EPreset
{
Overworld,
QuestBattle
}
private sealed class PresetDefinition
{
public string Name { get; }
public string Content { get; }
public PresetDefinition(string name, string fileName)
{
Name = name;
Content = LoadPreset(fileName);
base._002Ector();
}
private static string LoadPreset(string name)
{
using StreamReader streamReader = new StreamReader(typeof(BossModIpc).Assembly.GetManifestResourceStream("Questionable.Controller.CombatModules.BossModPreset." + name) ?? throw new InvalidOperationException("Preset " + name + " was not found"));
return streamReader.ReadToEnd();
}
}
private const string PluginName = "BossMod";
private static readonly ReadOnlyDictionary<EPreset, PresetDefinition> PresetDefinitions = new Dictionary<EPreset, PresetDefinition>
{
{
EPreset.Overworld,
new PresetDefinition("Questionable", "Overworld")
},
{
EPreset.QuestBattle,
new PresetDefinition("Questionable - Quest Battles", "QuestBattle")
}
}.AsReadOnly();
private readonly Configuration _configuration;
private readonly ICommandManager _commandManager;
private readonly TerritoryData _territoryData;
private readonly ICallGateSubscriber<string, string?> _getPreset;
private readonly ICallGateSubscriber<string, bool, bool> _createPreset;
private readonly ICallGateSubscriber<string, bool> _setPreset;
private readonly ICallGateSubscriber<bool> _clearPreset;
public BossModIpc(IDalamudPluginInterface pluginInterface, Configuration configuration, ICommandManager commandManager, TerritoryData territoryData)
{
_configuration = configuration;
_commandManager = commandManager;
_territoryData = territoryData;
_getPreset = pluginInterface.GetIpcSubscriber<string, string>("BossMod.Presets.Get");
_createPreset = pluginInterface.GetIpcSubscriber<string, bool, bool>("BossMod.Presets.Create");
_setPreset = pluginInterface.GetIpcSubscriber<string, bool>("BossMod.Presets.SetActive");
_clearPreset = pluginInterface.GetIpcSubscriber<bool>("BossMod.Presets.ClearActive");
}
public bool IsSupported()
{
try
{
return _getPreset.HasFunction;
}
catch (IpcError)
{
return false;
}
}
public void SetPreset(EPreset preset)
{
PresetDefinition presetDefinition = PresetDefinitions[preset];
if (_getPreset.InvokeFunc(presetDefinition.Name) == null)
{
_createPreset.InvokeFunc(presetDefinition.Content, arg2: true);
}
_setPreset.InvokeFunc(presetDefinition.Name);
}
public void ClearPreset()
{
_clearPreset.InvokeFunc();
}
public void EnableAi(bool passive)
{
_commandManager.ProcessCommand("/vbmai on");
_commandManager.ProcessCommand("/vbm cfg ZoneModuleConfig EnableQuestBattles true");
SetPreset((!passive) ? EPreset.QuestBattle : EPreset.Overworld);
}
public void DisableAi()
{
_commandManager.ProcessCommand("/vbmai off");
_commandManager.ProcessCommand("/vbm cfg ZoneModuleConfig EnableQuestBattles false");
ClearPreset();
}
public bool IsConfiguredToRunSoloInstance(ElementId questId, SinglePlayerDutyOptions? dutyOptions)
{
if (!IsSupported())
{
return false;
}
if (!_configuration.SinglePlayerDuties.RunSoloInstancesWithBossMod)
{
return false;
}
if (dutyOptions == null)
{
dutyOptions = new SinglePlayerDutyOptions();
}
if (!_territoryData.TryGetContentFinderConditionForSoloInstance(questId, dutyOptions.Index, out TerritoryData.ContentFinderConditionData contentFinderConditionData))
{
return false;
}
if (_configuration.SinglePlayerDuties.BlacklistedSinglePlayerDutyCfcIds.Contains(contentFinderConditionData.ContentFinderConditionId))
{
return false;
}
if (_configuration.SinglePlayerDuties.WhitelistedSinglePlayerDutyCfcIds.Contains(contentFinderConditionData.ContentFinderConditionId))
{
return true;
}
return dutyOptions.Enabled;
}
}

View file

@ -0,0 +1,45 @@
using System;
using Dalamud.Plugin;
using Dalamud.Plugin.Ipc;
using Microsoft.Extensions.Logging;
using Questionable.Model.Common;
namespace Questionable.External;
internal sealed class LifestreamIpc
{
private readonly ILogger<LifestreamIpc> _logger;
private readonly ICallGateSubscriber<uint, bool> _aethernetTeleportByPlaceNameId;
private readonly ICallGateSubscriber<uint, bool> _aethernetTeleportById;
private readonly ICallGateSubscriber<bool> _aethernetTeleportToFirmament;
public LifestreamIpc(IDalamudPluginInterface pluginInterface, ILogger<LifestreamIpc> logger)
{
_logger = logger;
_aethernetTeleportByPlaceNameId = pluginInterface.GetIpcSubscriber<uint, bool>("Lifestream.AethernetTeleportByPlaceNameId");
_aethernetTeleportById = pluginInterface.GetIpcSubscriber<uint, bool>("Lifestream.AethernetTeleportById");
_aethernetTeleportToFirmament = pluginInterface.GetIpcSubscriber<bool>("Lifestream.AethernetTeleportToFirmament");
}
public bool Teleport(EAetheryteLocation aetheryteLocation)
{
_logger.LogInformation("Teleporting to '{Name}'", aetheryteLocation);
return aetheryteLocation switch
{
EAetheryteLocation.IshgardFirmament => _aethernetTeleportToFirmament.InvokeFunc(),
EAetheryteLocation.FirmamentMendicantsCourt => _aethernetTeleportByPlaceNameId.InvokeFunc(3436u),
EAetheryteLocation.FirmamentMattock => _aethernetTeleportByPlaceNameId.InvokeFunc(3473u),
EAetheryteLocation.FirmamentNewNest => _aethernetTeleportByPlaceNameId.InvokeFunc(3475u),
EAetheryteLocation.FirmanentSaintRoellesDais => _aethernetTeleportByPlaceNameId.InvokeFunc(3474u),
EAetheryteLocation.FirmamentFeatherfall => _aethernetTeleportByPlaceNameId.InvokeFunc(3525u),
EAetheryteLocation.FirmamentHoarfrostHall => _aethernetTeleportByPlaceNameId.InvokeFunc(3528u),
EAetheryteLocation.FirmamentWesternRisensongQuarter => _aethernetTeleportByPlaceNameId.InvokeFunc(3646u),
EAetheryteLocation.FIrmamentEasternRisensongQuarter => _aethernetTeleportByPlaceNameId.InvokeFunc(3645u),
EAetheryteLocation.None => throw new ArgumentOutOfRangeException("aetheryteLocation"),
_ => _aethernetTeleportById.InvokeFunc((uint)aetheryteLocation),
};
}
}

View file

@ -0,0 +1,161 @@
using System.Collections.Generic;
using System.Numerics;
using System.Threading;
using System.Threading.Tasks;
using Dalamud.Plugin;
using Dalamud.Plugin.Ipc;
using Dalamud.Plugin.Ipc.Exceptions;
using Microsoft.Extensions.Logging;
namespace Questionable.External;
internal sealed class NavmeshIpc
{
private readonly ILogger<NavmeshIpc> _logger;
private readonly ICallGateSubscriber<bool> _isNavReady;
private readonly ICallGateSubscriber<Vector3, Vector3, bool, CancellationToken, Task<List<Vector3>>> _navPathfind;
private readonly ICallGateSubscriber<List<Vector3>, bool, object> _pathMoveTo;
private readonly ICallGateSubscriber<object> _pathStop;
private readonly ICallGateSubscriber<bool> _pathIsRunning;
private readonly ICallGateSubscriber<List<Vector3>> _pathListWaypoints;
private readonly ICallGateSubscriber<float, object> _pathSetTolerance;
private readonly ICallGateSubscriber<Vector3, bool, float, Vector3?> _queryPointOnFloor;
private readonly ICallGateSubscriber<float> _buildProgress;
public bool IsReady
{
get
{
try
{
return _isNavReady.InvokeFunc();
}
catch (IpcError)
{
return false;
}
}
}
public bool IsPathRunning
{
get
{
try
{
return _pathIsRunning.InvokeFunc();
}
catch (IpcError)
{
return false;
}
}
}
public NavmeshIpc(IDalamudPluginInterface pluginInterface, ILogger<NavmeshIpc> logger)
{
_logger = logger;
_isNavReady = pluginInterface.GetIpcSubscriber<bool>("vnavmesh.Nav.IsReady");
_navPathfind = pluginInterface.GetIpcSubscriber<Vector3, Vector3, bool, CancellationToken, Task<List<Vector3>>>("vnavmesh.Nav.PathfindCancelable");
_pathMoveTo = pluginInterface.GetIpcSubscriber<List<Vector3>, bool, object>("vnavmesh.Path.MoveTo");
_pathStop = pluginInterface.GetIpcSubscriber<object>("vnavmesh.Path.Stop");
_pathIsRunning = pluginInterface.GetIpcSubscriber<bool>("vnavmesh.Path.IsRunning");
_pathListWaypoints = pluginInterface.GetIpcSubscriber<List<Vector3>>("vnavmesh.Path.ListWaypoints");
_pathSetTolerance = pluginInterface.GetIpcSubscriber<float, object>("vnavmesh.Path.SetTolerance");
_queryPointOnFloor = pluginInterface.GetIpcSubscriber<Vector3, bool, float, Vector3?>("vnavmesh.Query.Mesh.PointOnFloor");
_buildProgress = pluginInterface.GetIpcSubscriber<float>("vnavmesh.Nav.BuildProgress");
}
public void Stop()
{
try
{
_pathStop.InvokeAction();
}
catch (IpcError exception)
{
_logger.LogWarning(exception, "Could not stop navigating via navmesh");
}
}
public Task<List<Vector3>> Pathfind(Vector3 localPlayerPosition, Vector3 targetPosition, bool fly, CancellationToken cancellationToken)
{
try
{
_pathSetTolerance.InvokeAction(0.25f);
return _navPathfind.InvokeFunc(localPlayerPosition, targetPosition, fly, cancellationToken);
}
catch (IpcError exception)
{
_logger.LogWarning(exception, "Could not pathfind via navmesh");
return Task.FromException<List<Vector3>>(exception);
}
}
public void MoveTo(List<Vector3> position, bool fly)
{
Stop();
try
{
_pathMoveTo.InvokeAction(position, fly);
}
catch (IpcError exception)
{
_logger.LogWarning(exception, "Could not move via navmesh");
}
}
public Vector3? GetPointOnFloor(Vector3 position, bool unlandable)
{
try
{
return _queryPointOnFloor.InvokeFunc(position, unlandable, 0.2f);
}
catch (IpcError)
{
return null;
}
}
public List<Vector3> GetWaypoints()
{
if (IsPathRunning)
{
try
{
return _pathListWaypoints.InvokeFunc();
}
catch (IpcError)
{
return new List<Vector3>();
}
}
return new List<Vector3>();
}
public int GetBuildProgress()
{
try
{
float num = _buildProgress.InvokeFunc();
if (num < 0f)
{
return 100;
}
return (int)(num * 100f);
}
catch (IpcError)
{
return 0;
}
}
}

View file

@ -0,0 +1,34 @@
using Dalamud.Plugin;
using NotificationMasterAPI;
namespace Questionable.External;
internal sealed class NotificationMasterIpc
{
private readonly NotificationMasterApi _api;
public bool Enabled => _api.IsIPCReady();
public NotificationMasterIpc(IDalamudPluginInterface pluginInterface, Configuration configuration)
{
_003Cconfiguration_003EP = configuration;
_api = new NotificationMasterApi(pluginInterface);
base._002Ector();
}
public void Notify(string message)
{
Configuration.NotificationConfiguration notifications = _003Cconfiguration_003EP.Notifications;
if (notifications.Enabled)
{
if (notifications.ShowTrayMessage)
{
_api.DisplayTrayNotification("Questionable", message);
}
if (notifications.FlashTaskbar)
{
_api.FlashTaskbarIcon();
}
}
}
}

View file

@ -0,0 +1,132 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using Dalamud.Plugin;
using Dalamud.Plugin.Ipc;
using Dalamud.Plugin.Ipc.Exceptions;
using Dalamud.Plugin.Services;
using Microsoft.Extensions.Logging;
using Questionable.Controller;
using Questionable.Data;
namespace Questionable.External;
internal sealed class PandorasBoxIpc : IDisposable
{
private static readonly ImmutableHashSet<string> ConflictingFeatures = new HashSet<string> { "Auto-Meditation", "Auto-Motif (Out of Combat)", "Auto-Mount after Combat", "Auto-Mount after Gathering", "Auto-Peleton", "Auto-Spring in Sanctuaries", "Auto-select Turn-ins", "Auto-Sync FATEs", "Auto-interact with Gathering Nodes", "Pandora Quick Gather" }.ToImmutableHashSet();
private readonly IFramework _framework;
private readonly QuestController _questController;
private readonly TerritoryData _territoryData;
private readonly IClientState _clientState;
private readonly ILogger<PandorasBoxIpc> _logger;
private readonly ICallGateSubscriber<string, bool?> _getFeatureEnabled;
private readonly ICallGateSubscriber<string, bool, object?> _setFeatureEnabled;
private bool _loggedIpcError;
private HashSet<string>? _pausedFeatures;
public bool IsAutoActiveTimeManeuverEnabled
{
get
{
try
{
return _getFeatureEnabled.InvokeFunc("Auto Active Time Maneuver") == true;
}
catch (IpcError exception)
{
if (!_loggedIpcError)
{
_loggedIpcError = true;
_logger.LogWarning(exception, "Could not query pandora's box for feature status, probably not installed");
}
return false;
}
}
}
public PandorasBoxIpc(IDalamudPluginInterface pluginInterface, IFramework framework, QuestController questController, TerritoryData territoryData, IClientState clientState, ILogger<PandorasBoxIpc> logger)
{
_framework = framework;
_questController = questController;
_territoryData = territoryData;
_clientState = clientState;
_logger = logger;
_getFeatureEnabled = pluginInterface.GetIpcSubscriber<string, bool?>("PandorasBox.GetFeatureEnabled");
_setFeatureEnabled = pluginInterface.GetIpcSubscriber<string, bool, object>("PandorasBox.SetFeatureEnabled");
logger.LogInformation("Pandora's Box auto active time maneuver enabled: {IsAtmEnabled}", IsAutoActiveTimeManeuverEnabled);
_framework.Update += OnUpdate;
}
private void OnUpdate(IFramework framework)
{
if ((_questController.IsRunning || _questController.AutomationType != QuestController.EAutomationType.Manual) && !_territoryData.IsDutyInstance(_clientState.TerritoryType))
{
DisableConflictingFeatures();
}
else
{
RestoreConflictingFeatures();
}
}
public void Dispose()
{
_framework.Update -= OnUpdate;
RestoreConflictingFeatures();
}
private void DisableConflictingFeatures()
{
if (_pausedFeatures != null)
{
return;
}
_pausedFeatures = new HashSet<string>();
foreach (string conflictingFeature in ConflictingFeatures)
{
try
{
if (_getFeatureEnabled.InvokeFunc(conflictingFeature) == true)
{
_setFeatureEnabled.InvokeAction(conflictingFeature, arg2: false);
_pausedFeatures.Add(conflictingFeature);
_logger.LogInformation("Paused Pandora's Box feature: {Feature}", conflictingFeature);
}
}
catch (IpcError exception)
{
_logger.LogWarning(exception, "Failed to pause Pandora's Box feature: {Feature}", conflictingFeature);
}
}
}
private void RestoreConflictingFeatures()
{
if (_pausedFeatures == null)
{
return;
}
foreach (string pausedFeature in _pausedFeatures)
{
try
{
_setFeatureEnabled.InvokeAction(pausedFeature, arg2: true);
_logger.LogInformation("Restored Pandora's Box feature: {Feature}", pausedFeature);
}
catch (IpcError exception)
{
_logger.LogWarning(exception, "Failed to restore Pandora's Box feature: {Feature}", pausedFeature);
}
}
_pausedFeatures = null;
}
}

View file

@ -0,0 +1,221 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using Dalamud.Plugin;
using Dalamud.Plugin.Ipc;
using Questionable.Controller;
using Questionable.Functions;
using Questionable.Model;
using Questionable.Model.Questing;
using Questionable.Windows;
using Questionable.Windows.QuestComponents;
namespace Questionable.External;
internal sealed class QuestionableIpc : IDisposable
{
public sealed class StepData
{
public required string QuestId { get; init; }
public required byte Sequence { get; init; }
public required int Step { get; init; }
public required string InteractionType { get; init; }
public required Vector3? Position { get; init; }
public required ushort TerritoryId { get; init; }
}
private const string IpcIsRunning = "Questionable.IsRunning";
private const string IpcGetCurrentQuestId = "Questionable.GetCurrentQuestId";
private const string IpcGetCurrentStepData = "Questionable.GetCurrentStepData";
private const string IpcGetCurrentlyActiveEventQuests = "Questionable.GetCurrentlyActiveEventQuests";
private const string IpcStartQuest = "Questionable.StartQuest";
private const string IpcStartSingleQuest = "Questionable.StartSingleQuest";
private const string IpcIsQuestLocked = "Questionable.IsQuestLocked";
private const string IpcImportQuestPriority = "Questionable.ImportQuestPriority";
private const string IpcClearQuestPriority = "Questionable.ClearQuestPriority";
private const string IpcAddQuestPriority = "Questionable.AddQuestPriority";
private const string IpcInsertQuestPriority = "Questionable.InsertQuestPriority";
private const string IpcExportQuestPriority = "Questionable.ExportQuestPriority";
private readonly QuestController _questController;
private readonly QuestRegistry _questRegistry;
private readonly QuestFunctions _questFunctions;
private readonly ICallGateProvider<bool> _isRunning;
private readonly ICallGateProvider<string?> _getCurrentQuestId;
private readonly ICallGateProvider<StepData?> _getCurrentStepData;
private readonly ICallGateProvider<List<string>> _getCurrentlyActiveEventQuests;
private readonly ICallGateProvider<string, bool> _startQuest;
private readonly ICallGateProvider<string, bool> _startSingleQuest;
private readonly ICallGateProvider<string, bool> _isQuestLocked;
private readonly ICallGateProvider<string, bool> _importQuestPriority;
private readonly ICallGateProvider<string, bool> _addQuestPriority;
private readonly ICallGateProvider<bool> _clearQuestPriority;
private readonly ICallGateProvider<int, string, bool> _insertQuestPriority;
private readonly ICallGateProvider<string> _exportQuestPriority;
public QuestionableIpc(QuestController questController, EventInfoComponent eventInfoComponent, QuestRegistry questRegistry, QuestFunctions questFunctions, PriorityWindow priorityWindow, IDalamudPluginInterface pluginInterface)
{
QuestionableIpc questionableIpc = this;
_questController = questController;
_questRegistry = questRegistry;
_questFunctions = questFunctions;
_isRunning = pluginInterface.GetIpcProvider<bool>("Questionable.IsRunning");
_isRunning.RegisterFunc(() => questController.AutomationType != QuestController.EAutomationType.Manual || questController.IsRunning);
_getCurrentQuestId = pluginInterface.GetIpcProvider<string>("Questionable.GetCurrentQuestId");
_getCurrentQuestId.RegisterFunc(() => questController.CurrentQuest?.Quest.Id.ToString());
_getCurrentStepData = pluginInterface.GetIpcProvider<StepData>("Questionable.GetCurrentStepData");
_getCurrentStepData.RegisterFunc(GetStepData);
_getCurrentlyActiveEventQuests = pluginInterface.GetIpcProvider<List<string>>("Questionable.GetCurrentlyActiveEventQuests");
_getCurrentlyActiveEventQuests.RegisterFunc(() => (from q in eventInfoComponent.GetCurrentlyActiveEventQuests()
select q.ToString()).ToList());
_startQuest = pluginInterface.GetIpcProvider<string, bool>("Questionable.StartQuest");
_startQuest.RegisterFunc((string questId) => questionableIpc.StartQuest(questId, single: false));
_startSingleQuest = pluginInterface.GetIpcProvider<string, bool>("Questionable.StartSingleQuest");
_startSingleQuest.RegisterFunc((string questId) => questionableIpc.StartQuest(questId, single: true));
_isQuestLocked = pluginInterface.GetIpcProvider<string, bool>("Questionable.IsQuestLocked");
_isQuestLocked.RegisterFunc(IsQuestLocked);
_importQuestPriority = pluginInterface.GetIpcProvider<string, bool>("Questionable.ImportQuestPriority");
_importQuestPriority.RegisterFunc(ImportQuestPriority);
_addQuestPriority = pluginInterface.GetIpcProvider<string, bool>("Questionable.AddQuestPriority");
_addQuestPriority.RegisterFunc(AddQuestPriority);
_clearQuestPriority = pluginInterface.GetIpcProvider<bool>("Questionable.ClearQuestPriority");
_clearQuestPriority.RegisterFunc(ClearQuestPriority);
_insertQuestPriority = pluginInterface.GetIpcProvider<int, string, bool>("Questionable.InsertQuestPriority");
_insertQuestPriority.RegisterFunc(InsertQuestPriority);
_exportQuestPriority = pluginInterface.GetIpcProvider<string>("Questionable.ExportQuestPriority");
_exportQuestPriority.RegisterFunc(priorityWindow.EncodeQuestPriority);
}
private bool StartQuest(string questId, bool single)
{
if (ElementId.TryFromString(questId, out ElementId elementId) && elementId != null && _questRegistry.TryGetQuest(elementId, out Quest quest))
{
_questController.SetNextQuest(quest);
if (single)
{
_questController.StartSingleQuest("IPCQuestSelection");
}
else
{
_questController.Start("IPCQuestSelection");
}
return true;
}
return false;
}
private StepData? GetStepData()
{
QuestController.QuestProgress currentQuest = _questController.CurrentQuest;
if (currentQuest == null)
{
return null;
}
string text = currentQuest.Quest.Id.ToString();
if (string.IsNullOrEmpty(text))
{
return null;
}
QuestStep questStep = currentQuest.Quest.FindSequence(currentQuest.Sequence)?.FindStep(currentQuest.Step);
if (questStep == null)
{
return null;
}
return new StepData
{
QuestId = text,
Sequence = currentQuest.Sequence,
Step = currentQuest.Step,
InteractionType = questStep.InteractionType.ToString(),
Position = questStep.Position,
TerritoryId = questStep.TerritoryId
};
}
private bool IsQuestLocked(string questId)
{
if (ElementId.TryFromString(questId, out ElementId elementId) && elementId != null && _questRegistry.TryGetQuest(elementId, out Quest _))
{
return _questFunctions.IsQuestLocked(elementId);
}
return true;
}
private bool ImportQuestPriority(string encodedQuestPriority)
{
List<ElementId> questElements = PriorityWindow.DecodeQuestPriority(encodedQuestPriority);
_questController.ImportQuestPriority(questElements);
return true;
}
private bool ClearQuestPriority()
{
_questController.ClearQuestPriority();
return true;
}
private bool AddQuestPriority(string questId)
{
if (ElementId.TryFromString(questId, out ElementId elementId) && elementId != null && _questRegistry.IsKnownQuest(elementId))
{
return _questController.AddQuestPriority(elementId);
}
return true;
}
private bool InsertQuestPriority(int index, string questId)
{
if (ElementId.TryFromString(questId, out ElementId elementId) && elementId != null && _questRegistry.IsKnownQuest(elementId))
{
return _questController.InsertQuestPriority(index, elementId);
}
return true;
}
public void Dispose()
{
_exportQuestPriority.UnregisterFunc();
_insertQuestPriority.UnregisterFunc();
_clearQuestPriority.UnregisterFunc();
_addQuestPriority.UnregisterFunc();
_importQuestPriority.UnregisterFunc();
_isQuestLocked.UnregisterFunc();
_startSingleQuest.UnregisterFunc();
_startQuest.UnregisterFunc();
_getCurrentlyActiveEventQuests.UnregisterFunc();
_getCurrentStepData.UnregisterFunc();
_getCurrentQuestId.UnregisterFunc();
_isRunning.UnregisterFunc();
}
}

View file

@ -0,0 +1,86 @@
using System;
using Dalamud.Plugin;
using Dalamud.Plugin.Ipc;
using Dalamud.Plugin.Services;
using Questionable.Controller;
namespace Questionable.External;
internal sealed class TextAdvanceIpc : IDisposable
{
public sealed class ExternalTerritoryConfig
{
public bool? EnableQuestAccept = true;
public bool? EnableQuestComplete = true;
public bool? EnableRewardPick = true;
public bool? EnableRequestHandin = true;
public bool? EnableCutsceneEsc = true;
public bool? EnableCutsceneSkipConfirm = true;
public bool? EnableTalkSkip = true;
public bool? EnableRequestFill = true;
public bool? EnableAutoInteract = false;
}
private bool _isExternalControlActivated;
private readonly QuestController _questController;
private readonly Configuration _configuration;
private readonly IFramework _framework;
private readonly ICallGateSubscriber<bool> _isInExternalControl;
private readonly ICallGateSubscriber<string, ExternalTerritoryConfig, bool> _enableExternalControl;
private readonly ICallGateSubscriber<string, bool> _disableExternalControl;
private readonly string _pluginName;
private readonly ExternalTerritoryConfig _externalTerritoryConfig = new ExternalTerritoryConfig();
public TextAdvanceIpc(IDalamudPluginInterface pluginInterface, IFramework framework, QuestController questController, Configuration configuration)
{
_framework = framework;
_questController = questController;
_configuration = configuration;
_isInExternalControl = pluginInterface.GetIpcSubscriber<bool>("TextAdvance.IsInExternalControl");
_enableExternalControl = pluginInterface.GetIpcSubscriber<string, ExternalTerritoryConfig, bool>("TextAdvance.EnableExternalControl");
_disableExternalControl = pluginInterface.GetIpcSubscriber<string, bool>("TextAdvance.DisableExternalControl");
_pluginName = pluginInterface.InternalName;
_framework.Update += OnUpdate;
}
public void Dispose()
{
_framework.Update -= OnUpdate;
if (_isExternalControlActivated)
{
_disableExternalControl.InvokeFunc(_pluginName);
}
}
private void OnUpdate(IFramework framework)
{
bool flag = _questController.IsRunning || _questController.AutomationType != QuestController.EAutomationType.Manual;
if (_configuration.General.ConfigureTextAdvance && flag)
{
if (!_isInExternalControl.InvokeFunc() && _enableExternalControl.InvokeFunc(_pluginName, _externalTerritoryConfig))
{
_isExternalControlActivated = true;
}
}
else if (_isExternalControlActivated && (_disableExternalControl.InvokeFunc(_pluginName) || !_isInExternalControl.InvokeFunc()))
{
_isExternalControlActivated = false;
}
}
}