qstcompanion v1.0.1

This commit is contained in:
alydev 2025-12-04 04:39:08 +10:00
parent 3e10cbbbf2
commit 44c67ab71b
79 changed files with 21148 additions and 0 deletions

View file

@ -0,0 +1,171 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using Dalamud.Bindings.ImGui;
using Dalamud.Interface;
using Dalamud.Interface.Windowing;
using QuestionableCompanion.Helpers;
using QuestionableCompanion.Models;
using QuestionableCompanion.Services;
namespace QuestionableCompanion.Windows;
public class AlliedSocietyPriorityWindow : Window, IDisposable
{
private readonly Configuration configuration;
private readonly AlliedSocietyDatabase database;
private List<AlliedSocietyPriority> editingPriorities = new List<AlliedSocietyPriority>();
private int? draggedIndex;
private const string DragDropId = "ALLIED_SOCIETY_PRIORITY";
private readonly Dictionary<byte, string> societyNames = new Dictionary<byte, string>
{
{ 1, "Amalj'aa" },
{ 2, "Sylphs" },
{ 3, "Kobolds" },
{ 4, "Sahagin" },
{ 5, "Ixal" },
{ 6, "Vanu Vanu" },
{ 7, "Vath" },
{ 8, "Moogles" },
{ 9, "Kojin" },
{ 10, "Ananta" },
{ 11, "Namazu" },
{ 12, "Pixies" },
{ 13, "Qitari" },
{ 14, "Dwarves" },
{ 15, "Arkasodara" },
{ 16, "Omicrons" },
{ 17, "Loporrits" },
{ 18, "Pelupelu" },
{ 19, "Mamool Ja" },
{ 20, "Yok Huy" }
};
public AlliedSocietyPriorityWindow(Configuration configuration, AlliedSocietyDatabase database)
: base("Allied Society Priority Configuration", ImGuiWindowFlags.NoCollapse)
{
this.configuration = configuration;
this.database = database;
base.Size = new Vector2(400f, 600f);
base.SizeCondition = ImGuiCond.FirstUseEver;
}
public void Dispose()
{
}
public override void OnOpen()
{
if (configuration.AlliedSociety.RotationConfig.Priorities.Count == 0)
{
configuration.AlliedSociety.RotationConfig.InitializeDefaults();
database.SaveToConfig();
}
editingPriorities = (from p in configuration.AlliedSociety.RotationConfig.Priorities
orderby p.Order
select new AlliedSocietyPriority
{
SocietyId = p.SocietyId,
Enabled = p.Enabled,
Order = p.Order
}).ToList();
}
public override void Draw()
{
ImGui.TextWrapped("Drag societies to reorder priorities. Uncheck to disable specific societies.");
ImGui.Separator();
float availableHeight = ImGui.GetWindowSize().Y - 120f;
ImGui.BeginChild("PriorityList", new Vector2(0f, availableHeight), border: true);
for (int i = 0; i < editingPriorities.Count; i++)
{
AlliedSocietyPriority priority = editingPriorities[i];
string name = (societyNames.ContainsKey(priority.SocietyId) ? societyNames[priority.SocietyId] : $"Unknown ({priority.SocietyId})");
ImGui.PushID(i);
if (draggedIndex == i)
{
uint highlightColor = ImGui.ColorConvertFloat4ToU32(new Vector4(0f, 0.7f, 0f, 0.3f));
Vector2 cursorPos = ImGui.GetCursorScreenPos();
Vector2 itemSize = new Vector2(ImGui.GetContentRegionAvail().X, ImGui.GetFrameHeight());
ImGui.GetWindowDrawList().AddRectFilled(cursorPos, cursorPos + itemSize, highlightColor);
}
ImGui.PushFont(UiBuilder.IconFont);
ImU8String label = new ImU8String(6, 1);
label.AppendFormatted(FontAwesomeIcon.ArrowsUpDownLeftRight.ToIconString());
label.AppendLiteral("##drag");
ImGui.Button(label);
ImGui.PopFont();
if (ImGui.IsItemHovered())
{
ImGui.SetMouseCursor(ImGuiMouseCursor.ResizeAll);
}
if (ImGui.BeginDragDropSource())
{
draggedIndex = i;
ImGuiDragDrop.SetDragDropPayload("ALLIED_SOCIETY_PRIORITY", i);
ImGui.Text(name);
ImGui.EndDragDropSource();
}
else if (draggedIndex == i && !ImGui.IsMouseDown(ImGuiMouseButton.Left))
{
draggedIndex = null;
}
if (ImGui.BeginDragDropTarget())
{
if (ImGuiDragDrop.AcceptDragDropPayload<int>("ALLIED_SOCIETY_PRIORITY", out var sourceIndex) && sourceIndex != i)
{
AlliedSocietyPriority item = editingPriorities[sourceIndex];
editingPriorities.RemoveAt(sourceIndex);
editingPriorities.Insert(i, item);
UpdateOrders();
draggedIndex = i;
}
ImGui.EndDragDropTarget();
}
ImGui.SameLine();
bool enabled = priority.Enabled;
ImU8String label2 = new ImU8String(9, 0);
label2.AppendLiteral("##enabled");
if (ImGui.Checkbox(label2, ref enabled))
{
priority.Enabled = enabled;
}
ImGui.SameLine();
ImGui.Text(name);
ImGui.PopID();
}
ImGui.EndChild();
ImGui.Separator();
if (ImGui.Button("Save"))
{
Save();
base.IsOpen = false;
}
ImGui.SameLine();
if (ImGui.Button("Cancel"))
{
base.IsOpen = false;
}
}
private void UpdateOrders()
{
for (int i = 0; i < editingPriorities.Count; i++)
{
editingPriorities[i].Order = i;
}
}
private void Save()
{
UpdateOrders();
configuration.AlliedSociety.RotationConfig.Priorities = editingPriorities;
database.SaveToConfig();
}
}

View file

@ -0,0 +1,564 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using Dalamud.Bindings.ImGui;
using Dalamud.Interface.Windowing;
using QuestionableCompanion.Services;
namespace QuestionableCompanion.Windows;
public class ConfigWindow : Window, IDisposable
{
private readonly Configuration configuration;
private readonly Plugin plugin;
public ConfigWindow(Plugin plugin)
: base("Questionable Companion Settings###QCSettings")
{
base.Size = new Vector2(600f, 400f);
base.SizeCondition = ImGuiCond.FirstUseEver;
this.plugin = plugin;
configuration = plugin.Configuration;
}
public void Dispose()
{
}
public override void PreDraw()
{
if (configuration.IsConfigWindowMovable)
{
base.Flags &= ~ImGuiWindowFlags.NoMove;
}
else
{
base.Flags |= ImGuiWindowFlags.NoMove;
}
}
public override void Draw()
{
ImGui.PushStyleColor(ImGuiCol.Text, new Vector4(1f, 0.8f, 0.2f, 1f));
ImGui.TextWrapped("Configuration Moved!");
ImGui.PopStyleColor();
ImGui.Spacing();
ImGui.Separator();
ImGui.Spacing();
ImGui.TextWrapped("The configuration interface has been moved to the new Main Window for a better user experience.");
ImGui.Spacing();
ImGui.TextWrapped("All settings are now available in the Main Window with improved organization and features:");
ImGui.Spacing();
ImGui.BulletText("Quest Rotation Management");
ImGui.BulletText("Event Quest Automation");
ImGui.BulletText("MSQ Progress Tracking");
ImGui.BulletText("DC Travel Configuration");
ImGui.BulletText("Advanced Settings");
ImGui.BulletText("And much more!");
ImGui.Spacing();
ImGui.Separator();
ImGui.Spacing();
if (ImGui.Button(size: new Vector2(ImGui.GetContentRegionAvail().X, 50f), label: "Open Main Window (Settings Tab)"))
{
plugin.ToggleMainUi();
base.IsOpen = false;
}
ImGui.Spacing();
ImGui.Spacing();
ImGui.PushStyleColor(ImGuiCol.Text, new Vector4(0.7f, 0.7f, 0.7f, 1f));
ImGui.TextWrapped("This legacy configuration window will be removed in a future update.");
ImGui.TextWrapped("Please use the Main Window for all configuration needs.");
ImGui.PopStyleColor();
}
private void DrawGeneralTab()
{
ImGui.Text("General Settings");
ImGui.Separator();
ImGui.Spacing();
bool autoStart = configuration.AutoStartOnLogin;
if (ImGui.Checkbox("Auto-start on login", ref autoStart))
{
configuration.AutoStartOnLogin = autoStart;
configuration.Save();
}
bool dryRun = configuration.EnableDryRun;
if (ImGui.Checkbox("Enable Dry Run Mode (simulate without executing)", ref dryRun))
{
configuration.EnableDryRun = dryRun;
configuration.Save();
}
bool restoreState = configuration.RestoreStateOnLoad;
if (ImGui.Checkbox("Restore state on plugin load", ref restoreState))
{
configuration.RestoreStateOnLoad = restoreState;
configuration.Save();
}
ImGui.Spacing();
ImGui.Text("Execution Settings");
ImGui.Separator();
ImGui.Spacing();
int maxRetries = configuration.MaxRetryAttempts;
if (ImGui.SliderInt("Max retry attempts", ref maxRetries, 1, 10))
{
configuration.MaxRetryAttempts = maxRetries;
configuration.Save();
}
int switchDelay = configuration.CharacterSwitchDelay;
if (ImGui.SliderInt("Character switch delay (seconds)", ref switchDelay, 3, 15))
{
configuration.CharacterSwitchDelay = switchDelay;
configuration.Save();
}
ImGui.Spacing();
ImGui.Text("Logging Settings");
ImGui.Separator();
ImGui.Spacing();
int maxLogs = configuration.MaxLogEntries;
if (ImGui.SliderInt("Max log entries", ref maxLogs, 50, 500))
{
configuration.MaxLogEntries = maxLogs;
configuration.Save();
}
bool showDebug = configuration.ShowDebugLogs;
if (ImGui.Checkbox("Show debug logs", ref showDebug))
{
configuration.ShowDebugLogs = showDebug;
configuration.Save();
}
bool logToFile = configuration.LogToFile;
if (ImGui.Checkbox("Log to file", ref logToFile))
{
configuration.LogToFile = logToFile;
configuration.Save();
}
ImGui.Spacing();
ImGui.Text("UI Settings");
ImGui.Separator();
ImGui.Spacing();
bool movable = configuration.IsConfigWindowMovable;
if (ImGui.Checkbox("Movable config window", ref movable))
{
configuration.IsConfigWindowMovable = movable;
configuration.Save();
}
}
private void DrawAdvancedFeaturesTab()
{
ImGui.TextColored(new Vector4(0.3f, 0.8f, 1f, 1f), "Submarine Management");
ImGui.Separator();
ImGui.Spacing();
bool enableSubmarineCheck = configuration.EnableSubmarineCheck;
if (ImGui.Checkbox("Enable Submarine Monitoring", ref enableSubmarineCheck))
{
configuration.EnableSubmarineCheck = enableSubmarineCheck;
configuration.Save();
}
if (ImGui.IsItemHovered())
{
ImGui.SetTooltip("Automatically monitor submarines and pause quest rotation when submarines are ready");
}
if (configuration.EnableSubmarineCheck)
{
ImGui.Indent();
int submarineCheckInterval = configuration.SubmarineCheckInterval;
if (ImGui.SliderInt("Check Interval (seconds)", ref submarineCheckInterval, 30, 300))
{
configuration.SubmarineCheckInterval = submarineCheckInterval;
configuration.Save();
}
int submarineReloginCooldown = configuration.SubmarineReloginCooldown;
if (ImGui.SliderInt("Cooldown after Relog (seconds)", ref submarineReloginCooldown, 60, 300))
{
configuration.SubmarineReloginCooldown = submarineReloginCooldown;
configuration.Save();
}
int submarineWaitTime = configuration.SubmarineWaitTime;
if (ImGui.SliderInt("Wait time before submarine (seconds)", ref submarineWaitTime, 10, 120))
{
configuration.SubmarineWaitTime = submarineWaitTime;
configuration.Save();
}
ImGui.Unindent();
}
ImGui.Spacing();
ImGui.Spacing();
ImGui.TextColored(new Vector4(0.3f, 0.8f, 1f, 1f), "Movement Monitor");
ImGui.Separator();
ImGui.Spacing();
bool enableMovementMonitor = configuration.EnableMovementMonitor;
if (ImGui.Checkbox("Enable Movement Monitor", ref enableMovementMonitor))
{
configuration.EnableMovementMonitor = enableMovementMonitor;
configuration.Save();
}
if (ImGui.IsItemHovered())
{
ImGui.SetTooltip("Automatically detect if player is stuck and send /qst reload");
}
if (configuration.EnableMovementMonitor)
{
ImGui.Indent();
int movementCheckInterval = configuration.MovementCheckInterval;
if (ImGui.SliderInt("Check Interval (seconds)##movement", ref movementCheckInterval, 3, 30))
{
configuration.MovementCheckInterval = movementCheckInterval;
configuration.Save();
}
int movementStuckThreshold = configuration.MovementStuckThreshold;
if (ImGui.SliderInt("Stuck Threshold (seconds)", ref movementStuckThreshold, 15, 120))
{
configuration.MovementStuckThreshold = movementStuckThreshold;
configuration.Save();
}
if (ImGui.IsItemHovered())
{
ImGui.SetTooltip("Time without movement before sending /qst reload");
}
ImGui.Unindent();
}
ImGui.Spacing();
ImGui.Spacing();
ImGui.TextColored(new Vector4(1f, 0.5f, 0.3f, 1f), "Combat Handling");
ImGui.Separator();
ImGui.Spacing();
bool enableCombatHandling = configuration.EnableCombatHandling;
if (ImGui.Checkbox("Enable Combat Handling", ref enableCombatHandling))
{
configuration.EnableCombatHandling = enableCombatHandling;
configuration.Save();
}
if (ImGui.IsItemHovered())
{
ImGui.SetTooltip("Automatically enable RSR/VBMAI/BMRAI when HP drops below threshold during combat");
}
if (configuration.EnableCombatHandling)
{
ImGui.Indent();
int combatHPThreshold = configuration.CombatHPThreshold;
if (ImGui.SliderInt("HP Threshold (%)", ref combatHPThreshold, 1, 99))
{
configuration.CombatHPThreshold = combatHPThreshold;
configuration.Save();
}
if (ImGui.IsItemHovered())
{
ImGui.SetTooltip("Enable combat automation when HP drops below this percentage\nCommands: /rsr manual, /vbmai on, /bmrai on");
}
ImGui.TextWrapped("When HP drops below threshold:");
ImGui.BulletText("/rsr manual");
ImGui.BulletText("/vbmai on");
ImGui.BulletText("/bmrai on");
ImGui.Spacing();
ImGui.TextWrapped("When combat ends:");
ImGui.BulletText("/rsr off");
ImGui.BulletText("/vbmai off");
ImGui.BulletText("/bmrai off");
ImGui.Unindent();
}
ImGui.Spacing();
ImGui.Spacing();
ImGui.TextColored(new Vector4(1f, 0.3f, 0.3f, 1f), "Death Handling");
ImGui.Separator();
ImGui.Spacing();
bool enableDeathHandling = configuration.EnableDeathHandling;
if (ImGui.Checkbox("Enable Death Handling", ref enableDeathHandling))
{
configuration.EnableDeathHandling = enableDeathHandling;
configuration.Save();
}
if (ImGui.IsItemHovered())
{
ImGui.SetTooltip("Automatically respawn when player dies");
}
if (configuration.EnableDeathHandling)
{
ImGui.Indent();
int deathRespawnDelay = configuration.DeathRespawnDelay;
if (ImGui.SliderInt("Teleport Delay (seconds)", ref deathRespawnDelay, 1, 30))
{
configuration.DeathRespawnDelay = deathRespawnDelay;
configuration.Save();
}
if (ImGui.IsItemHovered())
{
ImGui.SetTooltip("Time to wait after respawn before teleporting back to death location");
}
ImGui.Spacing();
ImGui.TextWrapped("On Death:");
ImGui.BulletText("Detect 0% HP");
ImGui.BulletText("Save position & territory");
ImGui.BulletText("Auto-click SelectYesNo (respawn)");
ImU8String text = new ImU8String(13, 1);
text.AppendLiteral("Wait ");
text.AppendFormatted(configuration.DeathRespawnDelay);
text.AppendLiteral(" seconds");
ImGui.BulletText(text);
ImGui.BulletText("Teleport back to death location");
ImGui.Unindent();
}
ImGui.Spacing();
ImGui.Spacing();
ImGui.TextColored(new Vector4(0.3f, 0.8f, 1f, 1f), "Logging Settings");
ImGui.Separator();
ImGui.Spacing();
bool logToDalamud = configuration.LogToDalamud;
if (ImGui.Checkbox("Log to Dalamud Log", ref logToDalamud))
{
configuration.LogToDalamud = logToDalamud;
configuration.Save();
}
if (ImGui.IsItemHovered())
{
ImGui.SetTooltip("Enable to also log to Dalamud log (can cause spam)");
}
ImGui.Spacing();
ImGui.Spacing();
ImGui.TextColored(new Vector4(0.3f, 0.8f, 1f, 1f), "Dungeon Automation");
ImGui.Separator();
ImGui.Spacing();
bool enableAutoDutyUnsynced = configuration.EnableAutoDutyUnsynced;
if (ImGui.Checkbox("Enable AutoDuty Unsynced", ref enableAutoDutyUnsynced))
{
configuration.EnableAutoDutyUnsynced = enableAutoDutyUnsynced;
configuration.Save();
plugin.GetDungeonAutomation()?.SetDutyModeBasedOnConfig();
}
if (ImGui.IsItemHovered())
{
ImGui.SetTooltip("Run dungeons unsynced for faster completion");
}
if (configuration.EnableAutoDutyUnsynced)
{
ImGui.Indent();
int autoDutyPartySize = configuration.AutoDutyPartySize;
if (ImGui.SliderInt("Party Size Check (members)", ref autoDutyPartySize, 1, 8))
{
configuration.AutoDutyPartySize = autoDutyPartySize;
configuration.Save();
}
if (ImGui.IsItemHovered())
{
ImGui.SetTooltip("Minimum party size required before starting dungeon");
}
int autoDutyMaxWaitForParty = configuration.AutoDutyMaxWaitForParty;
if (ImGui.SliderInt("Max Wait for Party (seconds)", ref autoDutyMaxWaitForParty, 10, 120))
{
configuration.AutoDutyMaxWaitForParty = autoDutyMaxWaitForParty;
configuration.Save();
}
int autoDutyReInviteInterval = configuration.AutoDutyReInviteInterval;
if (ImGui.SliderInt("Re-invite Interval (seconds)", ref autoDutyReInviteInterval, 5, 60))
{
configuration.AutoDutyReInviteInterval = autoDutyReInviteInterval;
configuration.Save();
}
ImGui.Unindent();
}
ImGui.Spacing();
ImGui.Spacing();
ImGui.TextColored(new Vector4(0.3f, 0.8f, 1f, 1f), "Quest Automation");
ImGui.Separator();
ImGui.Spacing();
bool enableQSTReloadTracking = configuration.EnableQSTReloadTracking;
if (ImGui.Checkbox("Enable QST Reload Tracking", ref enableQSTReloadTracking))
{
configuration.EnableQSTReloadTracking = enableQSTReloadTracking;
configuration.Save();
}
if (ImGui.IsItemHovered())
{
ImGui.SetTooltip("Track Questionable reloads and switch character if too many reloads occur");
}
if (configuration.EnableQSTReloadTracking)
{
ImGui.Indent();
int maxQSTReloadsBeforeSwitch = configuration.MaxQSTReloadsBeforeSwitch;
if (ImGui.SliderInt("Max Reloads before switch", ref maxQSTReloadsBeforeSwitch, 1, 20))
{
configuration.MaxQSTReloadsBeforeSwitch = maxQSTReloadsBeforeSwitch;
configuration.Save();
}
ImGui.Unindent();
}
ImGui.Spacing();
ImGui.Spacing();
ImGui.Spacing();
ImGui.TextColored(new Vector4(0.3f, 0.8f, 1f, 1f), "Character Management");
ImGui.Separator();
ImGui.Spacing();
bool enableMultiModeAfterRotation = configuration.EnableMultiModeAfterRotation;
if (ImGui.Checkbox("Enable Multi-Mode after Rotation", ref enableMultiModeAfterRotation))
{
configuration.EnableMultiModeAfterRotation = enableMultiModeAfterRotation;
configuration.Save();
}
if (ImGui.IsItemHovered())
{
ImGui.SetTooltip("Enable AutoRetainer Multi-Mode after completing character rotation");
}
bool returnToHomeworldOnStopQuest = configuration.ReturnToHomeworldOnStopQuest;
if (ImGui.Checkbox("Return to Homeworld on Stop Quest", ref returnToHomeworldOnStopQuest))
{
configuration.ReturnToHomeworldOnStopQuest = returnToHomeworldOnStopQuest;
configuration.Save();
}
if (ImGui.IsItemHovered())
{
ImGui.SetTooltip("Automatically return to homeworld when stop quest is completed");
}
ImGui.Spacing();
ImGui.Spacing();
ImGui.TextColored(new Vector4(0.3f, 0.8f, 1f, 1f), "Safe Wait Settings");
ImGui.Separator();
ImGui.Spacing();
bool enableSafeWaitBefore = configuration.EnableSafeWaitBeforeCharacterSwitch;
if (ImGui.Checkbox("Enable Safe Wait Before Character Switch", ref enableSafeWaitBefore))
{
configuration.EnableSafeWaitBeforeCharacterSwitch = enableSafeWaitBefore;
configuration.Save();
}
if (ImGui.IsItemHovered())
{
ImGui.SetTooltip("Wait for character to stabilize (movement, actions) before switching");
}
bool enableSafeWaitAfter = configuration.EnableSafeWaitAfterCharacterSwitch;
if (ImGui.Checkbox("Enable Safe Wait After Character Switch", ref enableSafeWaitAfter))
{
configuration.EnableSafeWaitAfterCharacterSwitch = enableSafeWaitAfter;
configuration.Save();
}
if (ImGui.IsItemHovered())
{
ImGui.SetTooltip("Wait for character to fully load after switching");
}
ImGui.Spacing();
ImGui.Spacing();
ImGui.TextColored(new Vector4(0.3f, 0.8f, 1f, 1f), "Quest Pre-Check");
ImGui.Separator();
ImGui.Spacing();
bool enableQuestPreCheck = configuration.EnableQuestPreCheck;
if (ImGui.Checkbox("Enable Quest Pre-Check", ref enableQuestPreCheck))
{
configuration.EnableQuestPreCheck = enableQuestPreCheck;
configuration.Save();
}
if (ImGui.IsItemHovered())
{
ImGui.SetTooltip("Check quest completion status before starting rotation to skip completed characters");
}
ImGui.TextWrapped("Quest Pre-Check scans all characters for completed quests before rotation starts, preventing unnecessary character switches.");
ImGui.Spacing();
ImGui.Spacing();
ImGui.TextColored(new Vector4(0.3f, 0.8f, 1f, 1f), "DC Travel World Selector");
ImGui.Separator();
ImGui.Spacing();
ImGui.TextWrapped("Configure world travel for Data Center travel quests. Requires Lifestream plugin.");
ImGui.Spacing();
string[] datacenters = configuration.WorldsByDatacenter.Keys.ToArray();
int currentDCIndex = Array.IndexOf(datacenters, configuration.SelectedDatacenter);
if (currentDCIndex < 0)
{
currentDCIndex = 0;
}
ImGui.Text("Select Datacenter:");
if (ImGui.Combo((ImU8String)"##DCSelector", ref currentDCIndex, (ReadOnlySpan<string>)datacenters, datacenters.Length))
{
configuration.SelectedDatacenter = datacenters[currentDCIndex];
if (configuration.WorldsByDatacenter.TryGetValue(configuration.SelectedDatacenter, out List<string> newWorlds) && newWorlds.Count > 0)
{
configuration.DCTravelWorld = newWorlds[0];
}
configuration.Save();
}
ImGui.Spacing();
if (configuration.WorldsByDatacenter.TryGetValue(configuration.SelectedDatacenter, out List<string> worlds))
{
string[] worldArray = worlds.ToArray();
int currentWorldIndex = Array.IndexOf(worldArray, configuration.DCTravelWorld);
if (currentWorldIndex < 0)
{
currentWorldIndex = 0;
}
ImGui.Text("Select Target World:");
if (ImGui.Combo((ImU8String)"##WorldSelector", ref currentWorldIndex, (ReadOnlySpan<string>)worldArray, worldArray.Length))
{
configuration.DCTravelWorld = worldArray[currentWorldIndex];
configuration.EnableDCTravel = !string.IsNullOrEmpty(configuration.DCTravelWorld);
configuration.Save();
}
ImGui.Spacing();
ImGui.Separator();
ImGui.Spacing();
ImGui.Spacing();
ImGui.Separator();
ImGui.Spacing();
LifestreamIPC lifestreamIPC = Plugin.Instance?.LifestreamIPC;
if (lifestreamIPC != null && !lifestreamIPC.IsAvailable)
{
lifestreamIPC.ForceCheckAvailability();
}
bool lifestreamAvailable = lifestreamIPC?.IsAvailable ?? false;
if (!lifestreamAvailable)
{
ImGui.BeginDisabled();
}
bool enableDCTravel = configuration.EnableDCTravel;
if (ImGui.Checkbox("Enable DC Travel", ref enableDCTravel))
{
configuration.EnableDCTravel = enableDCTravel;
configuration.Save();
}
if (!lifestreamAvailable)
{
ImGui.EndDisabled();
}
if (ImGui.IsItemHovered())
{
if (!lifestreamAvailable)
{
ImGui.SetTooltip("Lifestream plugin is required for DC Travel!\nPlease install and enable Lifestream to use this feature.");
}
else
{
ImGui.SetTooltip("Enable automatic DC travel when DC travel quests are detected");
}
}
if (!lifestreamAvailable)
{
ImGui.Spacing();
ImGui.TextColored(new Vector4(1f, 0.5f, 0f, 1f), "⚠\ufe0f Lifestream plugin not available!");
ImGui.TextWrapped("DC Travel requires Lifestream to be installed and enabled.");
}
ImGui.Spacing();
if (configuration.EnableDCTravel && !string.IsNullOrEmpty(configuration.DCTravelWorld))
{
Vector4 col = new Vector4(0.2f, 1f, 0.2f, 1f);
ImU8String text2 = new ImU8String(21, 1);
text2.AppendLiteral("✓ DC Travel ACTIVE → ");
text2.AppendFormatted(configuration.DCTravelWorld);
ImGui.TextColored(in col, text2);
ImU8String text3 = new ImU8String(100, 1);
text3.AppendLiteral("Character will travel to ");
text3.AppendFormatted(configuration.DCTravelWorld);
text3.AppendLiteral(" immediately after login, then return to homeworld before character switch.");
ImGui.TextWrapped(text3);
}
else if (!configuration.EnableDCTravel)
{
ImGui.TextColored(new Vector4(0.7f, 0.7f, 0.7f, 1f), "○ DC Travel disabled");
}
else
{
ImGui.TextColored(new Vector4(1f, 0.5f, 0f, 1f), "⚠ DC Travel enabled but no world selected!");
}
}
else
{
ImGui.TextColored(new Vector4(1f, 0.5f, 0f, 1f), "No worlds available for selected datacenter");
}
}
}

View file

@ -0,0 +1,161 @@
using System;
using System.Numerics;
using Dalamud.Bindings.ImGui;
using Dalamud.Interface.Windowing;
using QuestionableCompanion.Services;
namespace QuestionableCompanion.Windows;
public class DebugWindow : Window, IDisposable
{
private readonly Plugin plugin;
private readonly CombatDutyDetectionService? combatDutyDetection;
private readonly DeathHandlerService? deathHandler;
private readonly DungeonAutomationService? dungeonAutomation;
public DebugWindow(Plugin plugin, CombatDutyDetectionService? combatDutyDetection, DeathHandlerService? deathHandler, DungeonAutomationService? dungeonAutomation)
: base("QST Companion Debug###QSTDebug", ImGuiWindowFlags.NoCollapse)
{
this.plugin = plugin;
this.combatDutyDetection = combatDutyDetection;
this.deathHandler = deathHandler;
this.dungeonAutomation = dungeonAutomation;
base.Size = new Vector2(500f, 400f);
base.SizeCondition = ImGuiCond.FirstUseEver;
}
public void Dispose()
{
}
public override void Draw()
{
ImGui.TextColored(new Vector4(1f, 0.5f, 0f, 1f), " DEBUG MENU - FOR TESTING ONLY ");
ImGui.Separator();
ImGui.Spacing();
ImGui.TextColored(new Vector4(1f, 0.3f, 0.3f, 1f), "Combat Handling");
ImGui.Separator();
if (combatDutyDetection != null)
{
ImU8String text = new ImU8String(11, 1);
text.AppendLiteral("In Combat: ");
text.AppendFormatted(combatDutyDetection.IsInCombat);
ImGui.Text(text);
ImU8String text2 = new ImU8String(9, 1);
text2.AppendLiteral("In Duty: ");
text2.AppendFormatted(combatDutyDetection.IsInDuty);
ImGui.Text(text2);
ImU8String text3 = new ImU8String(15, 1);
text3.AppendLiteral("In Duty Queue: ");
text3.AppendFormatted(combatDutyDetection.IsInDutyQueue);
ImGui.Text(text3);
ImU8String text4 = new ImU8String(14, 1);
text4.AppendLiteral("Should Pause: ");
text4.AppendFormatted(combatDutyDetection.ShouldPauseAutomation);
ImGui.Text(text4);
ImGui.Spacing();
if (ImGui.Button("Test Combat Detection"))
{
combatDutyDetection.Update();
}
if (ImGui.IsItemHovered())
{
ImGui.SetTooltip("Manually trigger combat detection update");
}
ImGui.SameLine();
if (ImGui.Button("Reset Combat State"))
{
combatDutyDetection.Reset();
}
}
else
{
ImGui.TextColored(new Vector4(1f, 0f, 0f, 1f), "Combat Detection Service not available");
}
ImGui.Spacing();
ImGui.Spacing();
ImGui.TextColored(new Vector4(1f, 0.3f, 0.3f, 1f), "Death Handling");
ImGui.Separator();
if (deathHandler != null)
{
ImU8String text5 = new ImU8String(9, 1);
text5.AppendLiteral("Is Dead: ");
text5.AppendFormatted(deathHandler.IsDead);
ImGui.Text(text5);
ImU8String text6 = new ImU8String(19, 1);
text6.AppendLiteral("Time Since Death: ");
text6.AppendFormatted(deathHandler.TimeSinceDeath.TotalSeconds, "F1");
text6.AppendLiteral("s");
ImGui.Text(text6);
ImGui.Spacing();
if (ImGui.Button("Test Death Detection"))
{
deathHandler.Update();
}
if (ImGui.IsItemHovered())
{
ImGui.SetTooltip("Manually trigger death detection update");
}
ImGui.SameLine();
if (ImGui.Button("Reset Death State"))
{
deathHandler.Reset();
}
}
else
{
ImGui.TextColored(new Vector4(1f, 0f, 0f, 1f), "Death Handler Service not available");
}
ImGui.Spacing();
ImGui.Spacing();
ImGui.TextColored(new Vector4(1f, 0.3f, 0.3f, 1f), "Dungeon Automation");
ImGui.Separator();
if (dungeonAutomation != null)
{
ImU8String text7 = new ImU8String(19, 1);
text7.AppendLiteral("Waiting for Party: ");
text7.AppendFormatted(dungeonAutomation.IsWaitingForParty);
ImGui.Text(text7);
ImU8String text8 = new ImU8String(20, 1);
text8.AppendLiteral("Current Party Size: ");
text8.AppendFormatted(dungeonAutomation.CurrentPartySize);
ImGui.Text(text8);
ImGui.Spacing();
if (ImGui.Button("Test Party Invite"))
{
dungeonAutomation.StartDungeonAutomation();
}
if (ImGui.IsItemHovered())
{
ImGui.SetTooltip("Test BTB enable + invite + party wait");
}
ImGui.SameLine();
if (ImGui.Button("Test Party Disband"))
{
dungeonAutomation.DisbandParty();
}
if (ImGui.IsItemHovered())
{
ImGui.SetTooltip("Test party disband with /pcmd breakup");
}
ImGui.SameLine();
if (ImGui.Button("Reset Dungeon State"))
{
dungeonAutomation.Reset();
}
}
else
{
ImGui.TextColored(new Vector4(1f, 0f, 0f, 1f), "Dungeon Automation Service not available");
}
ImGui.Spacing();
ImGui.Spacing();
ImGui.Separator();
ImGui.TextColored(new Vector4(0.5f, 0.8f, 1f, 1f), "Info");
ImGui.Text("This debug menu allows testing of individual features.");
ImGui.Text("Use /qstcomp dbg to toggle this window.");
}
}

File diff suppressed because it is too large Load diff