forked from aly/qstbak
qstcompanion v1.0.6
This commit is contained in:
parent
5e1e1decc5
commit
ada27cf05b
30 changed files with 3403 additions and 426 deletions
|
|
@ -2,6 +2,7 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Threading.Tasks;
|
||||
using Dalamud.Bindings.ImGui;
|
||||
using Dalamud.Interface;
|
||||
using Dalamud.Interface.Colors;
|
||||
|
|
@ -140,6 +141,8 @@ public class NewMainWindow : Window, IDisposable
|
|||
|
||||
private DateTime lastEventQuestRefresh = DateTime.MinValue;
|
||||
|
||||
private string? newLANHelperIP;
|
||||
|
||||
private readonly Dictionary<string, List<string>> dataCenterWorlds = new Dictionary<string, List<string>>
|
||||
{
|
||||
{
|
||||
|
|
@ -533,6 +536,7 @@ public class NewMainWindow : Window, IDisposable
|
|||
DrawSidebarItem("Event Quest", 6, 0);
|
||||
DrawSidebarItem("MSQ Progression", 7, 0);
|
||||
DrawSidebarItem("Data Center Travel", 8, 0);
|
||||
DrawSidebarItem("Multiboxing", 12, 0);
|
||||
DrawSidebarItem("Settings", 9, 0);
|
||||
}
|
||||
else
|
||||
|
|
@ -616,7 +620,7 @@ public class NewMainWindow : Window, IDisposable
|
|||
uint rightColor = ImGui.ColorConvertFloat4ToU32(new Vector4(colorSecondary.X * 0.3f, colorSecondary.Y * 0.3f, colorSecondary.Z * 0.3f, 1f));
|
||||
drawList.AddRectFilledMultiColor(windowPos, windowPos + new Vector2(windowSize.X, height), leftColor, rightColor, rightColor, leftColor);
|
||||
Vector2 titlePos = windowPos + new Vector2(10f, 7f);
|
||||
drawList.AddText(titlePos, ImGui.ColorConvertFloat4ToU32(new Vector4(1f, 1f, 1f, 0.9f)), "Questionable Companion V.1.0.5");
|
||||
drawList.AddText(titlePos, ImGui.ColorConvertFloat4ToU32(new Vector4(1f, 1f, 1f, 0.9f)), "Questionable Companion V.1.0.6");
|
||||
Vector2 minimizeButtonPos = windowPos + new Vector2(windowSize.X - 60f, 3f);
|
||||
Vector2 minimizeButtonSize = new Vector2(24f, 24f);
|
||||
if (ImGui.IsMouseHoveringRect(minimizeButtonPos, minimizeButtonPos + minimizeButtonSize))
|
||||
|
|
@ -718,6 +722,9 @@ public class NewMainWindow : Window, IDisposable
|
|||
case 11:
|
||||
DrawWarningTab();
|
||||
break;
|
||||
case 12:
|
||||
DrawMultiboxingTab();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -776,9 +783,9 @@ public class NewMainWindow : Window, IDisposable
|
|||
{
|
||||
selectedDataCenter = config.DCTravelDataCenter;
|
||||
}
|
||||
if (string.IsNullOrEmpty(selectedWorld) && !string.IsNullOrEmpty(config.DCTravelTargetWorld))
|
||||
if (string.IsNullOrEmpty(selectedWorld) && !string.IsNullOrEmpty(config.DCTravelWorld))
|
||||
{
|
||||
selectedWorld = config.DCTravelTargetWorld;
|
||||
selectedWorld = config.DCTravelWorld;
|
||||
}
|
||||
if (string.IsNullOrEmpty(selectedDataCenter))
|
||||
{
|
||||
|
|
@ -921,7 +928,7 @@ public class NewMainWindow : Window, IDisposable
|
|||
ImGui.TextUnformatted(text2);
|
||||
ImGui.SameLine();
|
||||
ImGui.PushStyleColor(ImGuiCol.Text, colorPrimary);
|
||||
ImGui.TextUnformatted((config.DCTravelTargetWorld.Length > 0) ? config.DCTravelTargetWorld : "Not Set");
|
||||
ImGui.TextUnformatted((config.DCTravelWorld.Length > 0) ? config.DCTravelWorld : "Not Set");
|
||||
ImGui.PopStyleColor();
|
||||
ImU8String text3 = new ImU8String(8, 0);
|
||||
text3.AppendLiteral("Status: ");
|
||||
|
|
@ -946,7 +953,7 @@ public class NewMainWindow : Window, IDisposable
|
|||
if (ImGui.Button("Apply", new Vector2(120f, 30f)))
|
||||
{
|
||||
config.DCTravelDataCenter = selectedDataCenter;
|
||||
config.DCTravelTargetWorld = selectedWorld;
|
||||
config.DCTravelWorld = selectedWorld;
|
||||
config.Save();
|
||||
log.Information("[DCTravel] Configuration saved: " + selectedDataCenter + " -> " + selectedWorld);
|
||||
}
|
||||
|
|
@ -955,7 +962,7 @@ public class NewMainWindow : Window, IDisposable
|
|||
if (ImGui.Button("Cancel", new Vector2(120f, 30f)))
|
||||
{
|
||||
selectedDataCenter = config.DCTravelDataCenter;
|
||||
selectedWorld = config.DCTravelTargetWorld;
|
||||
selectedWorld = config.DCTravelWorld;
|
||||
if (string.IsNullOrEmpty(selectedDataCenter))
|
||||
{
|
||||
selectedDataCenter = dataCenterWorlds.Keys.First();
|
||||
|
|
@ -978,81 +985,18 @@ public class NewMainWindow : Window, IDisposable
|
|||
}
|
||||
}
|
||||
|
||||
private void DrawSettingsTabFull()
|
||||
private void DrawMultiboxingTab()
|
||||
{
|
||||
ImGui.PushStyleColor(ImGuiCol.Text, colorPrimary);
|
||||
ImGui.TextUnformatted("Plugin Settings");
|
||||
ImGui.TextUnformatted("Multiboxing Settings");
|
||||
ImGui.PopStyleColor();
|
||||
ImGuiHelpers.ScaledDummy(10f);
|
||||
using ImRaii.IEndObject child = ImRaii.Child("SettingsScrollArea", new Vector2(0f, 0f), border: false, ImGuiWindowFlags.None);
|
||||
using ImRaii.IEndObject child = ImRaii.Child("MultiboxingScrollArea", new Vector2(0f, 0f), border: false, ImGuiWindowFlags.None);
|
||||
if (!child.Success)
|
||||
{
|
||||
return;
|
||||
}
|
||||
Configuration config = plugin.Configuration;
|
||||
DrawSettingSection("Submarine Management", delegate
|
||||
{
|
||||
config.EnableSubmarineCheck = DrawSettingWithInfo("Enable Submarine Monitoring", config.EnableSubmarineCheck, "Automatically monitors submarines and pauses quest rotation when submarines are ready.\nPrevents quest progression while submarines need attention.\nImpact: Rotation will pause when submarines are detected.");
|
||||
if (ImGui.IsItemDeactivatedAfterEdit())
|
||||
{
|
||||
config.Save();
|
||||
}
|
||||
if (config.EnableSubmarineCheck)
|
||||
{
|
||||
ImGui.Indent();
|
||||
int v = config.SubmarineCheckInterval;
|
||||
if (ImGui.SliderInt("Check Interval (seconds)", ref v, 30, 300))
|
||||
{
|
||||
config.SubmarineCheckInterval = v;
|
||||
config.Save();
|
||||
}
|
||||
DrawInfoIcon("How often to check for submarine status.\nLower values = more frequent checks but higher CPU usage.");
|
||||
int v2 = config.SubmarineReloginCooldown;
|
||||
if (ImGui.SliderInt("Cooldown after Relog (seconds)", ref v2, 60, 300))
|
||||
{
|
||||
config.SubmarineReloginCooldown = v2;
|
||||
config.Save();
|
||||
}
|
||||
DrawInfoIcon("Time to wait after character switch before checking submarines again.");
|
||||
int v3 = config.SubmarineWaitTime;
|
||||
if (ImGui.SliderInt("Wait time before submarine (seconds)", ref v3, 10, 120))
|
||||
{
|
||||
config.SubmarineWaitTime = v3;
|
||||
config.Save();
|
||||
}
|
||||
DrawInfoIcon("Delay before starting submarine operations after detection.");
|
||||
ImGui.Unindent();
|
||||
}
|
||||
}, config.EnableSubmarineCheck);
|
||||
ImGuiHelpers.ScaledDummy(10f);
|
||||
DrawSettingSection("AutoRetainer Post Process Event Quests", delegate
|
||||
{
|
||||
config.RunEventQuestsOnARPostProcess = DrawSettingWithInfo("Run Event Quests on AR Post Process", config.RunEventQuestsOnARPostProcess, "AUTO-DETECTION: Automatically detects and runs active Event Quests when AutoRetainer completes a character.\nEvent Quests are detected via Questionable IPC (same as manual Event Quest tab).\nAll prerequisites will be automatically resolved and executed.\nAutoRetainer will wait until all Event Quests are completed before proceeding.\nImpact: Extends AR post-process time but ensures Event Quests are completed.");
|
||||
if (ImGui.IsItemDeactivatedAfterEdit())
|
||||
{
|
||||
config.Save();
|
||||
}
|
||||
if (config.RunEventQuestsOnARPostProcess)
|
||||
{
|
||||
ImGui.Indent();
|
||||
ImGui.PushStyleColor(ImGuiCol.Text, new Vector4(0.4f, 0.8f, 0.4f, 1f));
|
||||
ImGui.TextUnformatted("Auto-Detection Enabled");
|
||||
ImGui.PopStyleColor();
|
||||
ImGui.PushStyleColor(ImGuiCol.Text, colorSecondary);
|
||||
ImGui.TextWrapped("Event Quests will be automatically detected from Questionable when AR Post Process starts. No manual configuration needed - just enable this setting and the plugin will handle the rest!");
|
||||
ImGui.PopStyleColor();
|
||||
ImGuiHelpers.ScaledDummy(5f);
|
||||
int v = config.EventQuestPostProcessTimeoutMinutes;
|
||||
if (ImGui.SliderInt("Timeout (minutes)", ref v, 10, 60))
|
||||
{
|
||||
config.EventQuestPostProcessTimeoutMinutes = v;
|
||||
config.Save();
|
||||
}
|
||||
DrawInfoIcon("Maximum time to wait for Event Quests to complete.\nAfter timeout, AR will proceed with next character.");
|
||||
ImGui.Unindent();
|
||||
}
|
||||
}, config.RunEventQuestsOnARPostProcess);
|
||||
ImGuiHelpers.ScaledDummy(10f);
|
||||
DrawSettingSection("Dungeon Automation", delegate
|
||||
{
|
||||
bool enableAutoDutyUnsynced = config.EnableAutoDutyUnsynced;
|
||||
|
|
@ -1086,6 +1030,15 @@ public class NewMainWindow : Window, IDisposable
|
|||
config.Save();
|
||||
}
|
||||
DrawInfoIcon("How often to re-send party invites if members don't join.");
|
||||
ImGuiHelpers.ScaledDummy(5f);
|
||||
bool v4 = config.EnableARRPrimalCheck;
|
||||
if (ImGui.Checkbox("Check ARR Primals when hitting flag", ref v4))
|
||||
{
|
||||
config.EnableARRPrimalCheck = v4;
|
||||
config.Save();
|
||||
Plugin.Log.Information("[Multiboxing] ARR Primal Check: " + (v4 ? "ENABLED" : "DISABLED"));
|
||||
}
|
||||
DrawInfoIcon("Checks if ARR Hard Mode Primals (Ifrit/Garuda/Titan) are done.\nRequired for Quest 363 (Good Intentions).");
|
||||
ImGui.Unindent();
|
||||
}
|
||||
}, config.EnableAutoDutyUnsynced);
|
||||
|
|
@ -1116,6 +1069,7 @@ public class NewMainWindow : Window, IDisposable
|
|||
config.IsQuester = true;
|
||||
config.IsHighLevelHelper = false;
|
||||
config.Save();
|
||||
Plugin.Log.Information("[Multiboxing] Role changed to: Quester");
|
||||
}
|
||||
ImGui.SameLine();
|
||||
DrawInfoIcon("This client will quest and invite helpers for dungeons");
|
||||
|
|
@ -1126,11 +1080,168 @@ public class NewMainWindow : Window, IDisposable
|
|||
Plugin.Framework.RunOnFrameworkThread(delegate
|
||||
{
|
||||
Plugin.Instance?.GetHelperManager()?.AnnounceIfHelper();
|
||||
Plugin.Instance?.GetChauffeurMode()?.StartHelperStatusBroadcast();
|
||||
});
|
||||
config.Save();
|
||||
Plugin.Log.Information("[Multiboxing] Role changed to: High-Level Helper");
|
||||
}
|
||||
ImGui.SameLine();
|
||||
DrawInfoIcon("This client will help with dungeons.\nAutoDuty starts/stops automatically on duty enter/leave");
|
||||
if (config.IsHighLevelHelper)
|
||||
{
|
||||
ImGuiHelpers.ScaledDummy(5f);
|
||||
ImGui.Indent();
|
||||
bool v = config.AlwaysAutoAcceptInvites;
|
||||
if (ImGui.Checkbox("Always Auto-Accept Party Invites", ref v))
|
||||
{
|
||||
config.AlwaysAutoAcceptInvites = v;
|
||||
config.Save();
|
||||
}
|
||||
DrawInfoIcon("Continuously accept ALL party invites (useful for ManualInput mode without IPC)");
|
||||
ImGui.Unindent();
|
||||
}
|
||||
ImGuiHelpers.ScaledDummy(10f);
|
||||
ImGui.Separator();
|
||||
ImGuiHelpers.ScaledDummy(5f);
|
||||
ImGui.TextColored(in colorPrimary, "LAN Multi-PC Helper System");
|
||||
ImGui.TextWrapped("Connect helpers on different PCs in your HOME NETWORK.");
|
||||
ImGuiHelpers.ScaledDummy(3f);
|
||||
config.EnableLANHelpers = DrawSettingWithInfo("Enable LAN Helper System", config.EnableLANHelpers, "Connect to helpers on other PCs in YOUR home network.\nNOT accessible from internet! Only devices in your home can connect.");
|
||||
if (ImGui.IsItemDeactivatedAfterEdit())
|
||||
{
|
||||
config.Save();
|
||||
}
|
||||
if (config.EnableLANHelpers)
|
||||
{
|
||||
ImGui.Indent();
|
||||
if (config.IsHighLevelHelper)
|
||||
{
|
||||
bool flag = DrawSettingWithInfo("Start LAN Server on this PC", config.StartLANServer, "Enable so OTHER PCs in your home can connect to THIS PC.\nNOT exposed to internet! Only devices in your home can connect.");
|
||||
if (flag != config.StartLANServer)
|
||||
{
|
||||
config.StartLANServer = flag;
|
||||
config.Save();
|
||||
plugin.ToggleLANServer(flag);
|
||||
}
|
||||
}
|
||||
ImGuiHelpers.ScaledDummy(5f);
|
||||
ImGui.TextColored(in colorSecondary, "Server Port:");
|
||||
ImGui.SetNextItemWidth(150f);
|
||||
int data = config.LANServerPort;
|
||||
if (ImGui.InputInt("##LANPort", ref data) && data >= 1024 && data <= 65535)
|
||||
{
|
||||
config.LANServerPort = data;
|
||||
config.Save();
|
||||
}
|
||||
ImGui.SameLine();
|
||||
DrawInfoIcon("Port for local network communication (default: 47788).\nFirewall may need to allow this port.");
|
||||
ImGuiHelpers.ScaledDummy(5f);
|
||||
ImGui.TextColored(in colorSecondary, "Helper PC IP Addresses:");
|
||||
ImGui.TextWrapped("Add IPs of OTHER PCs in your home with helper characters:");
|
||||
ImGuiHelpers.ScaledDummy(3f);
|
||||
if (config.LANHelperIPs == null)
|
||||
{
|
||||
config.LANHelperIPs = new List<string>();
|
||||
}
|
||||
for (int num2 = 0; num2 < config.LANHelperIPs.Count; num2++)
|
||||
{
|
||||
ImU8String strId = new ImU8String(3, 1);
|
||||
strId.AppendLiteral("IP_");
|
||||
strId.AppendFormatted(num2);
|
||||
ImGui.PushID(strId);
|
||||
ImGui.BulletText(config.LANHelperIPs[num2]);
|
||||
ImGui.SameLine();
|
||||
if (ImGui.SmallButton("\ud83d\udd04 Reconnect"))
|
||||
{
|
||||
string ip = config.LANHelperIPs[num2];
|
||||
LANHelperClient lanClient = plugin.GetLANHelperClient();
|
||||
if (lanClient != null)
|
||||
{
|
||||
Task.Run(async delegate
|
||||
{
|
||||
Plugin.Log.Information("[UI] Manual reconnect to " + ip + "...");
|
||||
await lanClient.ConnectToHelperAsync(ip);
|
||||
});
|
||||
}
|
||||
}
|
||||
ImGui.SameLine();
|
||||
if (ImGui.SmallButton("Remove"))
|
||||
{
|
||||
config.LANHelperIPs.RemoveAt(num2);
|
||||
config.Save();
|
||||
num2--;
|
||||
}
|
||||
ImGui.PopID();
|
||||
}
|
||||
if (config.LANHelperIPs.Count == 0)
|
||||
{
|
||||
ImGui.TextColored(new Vector4(1f, 0.8f, 0.2f, 1f), "No IPs configured");
|
||||
ImGui.TextWrapped("Add IPs below (or use 127.0.0.1 for same-PC testing)");
|
||||
}
|
||||
ImGuiHelpers.ScaledDummy(3f);
|
||||
ImGui.TextColored(in colorSecondary, "Add new IP:");
|
||||
ImGui.SetNextItemWidth(200f);
|
||||
string buf = newLANHelperIP ?? "";
|
||||
if (ImGui.InputText("##NewIP", ref buf, 50))
|
||||
{
|
||||
newLANHelperIP = buf;
|
||||
}
|
||||
ImGui.SameLine();
|
||||
if (ImGui.Button("Add IP") && !string.IsNullOrWhiteSpace(newLANHelperIP))
|
||||
{
|
||||
string trimmedIP = newLANHelperIP.Trim();
|
||||
if (!config.LANHelperIPs.Contains(trimmedIP))
|
||||
{
|
||||
config.LANHelperIPs.Add(trimmedIP);
|
||||
config.Save();
|
||||
newLANHelperIP = "";
|
||||
LANHelperClient lanClient2 = plugin.GetLANHelperClient();
|
||||
if (lanClient2 != null)
|
||||
{
|
||||
Task.Run(async delegate
|
||||
{
|
||||
await lanClient2.ConnectToHelperAsync(trimmedIP);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
ImGui.SameLine();
|
||||
if (ImGui.SmallButton("Add Localhost") && !config.LANHelperIPs.Contains("127.0.0.1"))
|
||||
{
|
||||
config.LANHelperIPs.Add("127.0.0.1");
|
||||
config.Save();
|
||||
LANHelperClient lanClient3 = plugin.GetLANHelperClient();
|
||||
if (lanClient3 != null)
|
||||
{
|
||||
Task.Run(async delegate
|
||||
{
|
||||
await lanClient3.ConnectToHelperAsync("127.0.0.1");
|
||||
});
|
||||
}
|
||||
}
|
||||
ImGuiHelpers.ScaledDummy(3f);
|
||||
ImGui.TextColored(new Vector4(0.7f, 0.7f, 0.7f, 1f), "\ud83d\udca1 Tip: Run 'ipconfig' and use your IPv4-Adresse (like 192.168.x.x)");
|
||||
ImGuiHelpers.ScaledDummy(5f);
|
||||
ImGui.PushStyleColor(ImGuiCol.Text, new Vector4(0.4f, 0.8f, 0.4f, 1f));
|
||||
if (config.StartLANServer)
|
||||
{
|
||||
ImU8String text = new ImU8String(48, 1);
|
||||
text.AppendLiteral("✓ LAN Server enabled (LOCAL network only, port ");
|
||||
text.AppendFormatted(config.LANServerPort);
|
||||
text.AppendLiteral(")");
|
||||
ImGui.TextWrapped(text);
|
||||
}
|
||||
if (config.LANHelperIPs.Count > 0)
|
||||
{
|
||||
ImU8String text2 = new ImU8String(37, 1);
|
||||
text2.AppendLiteral("✓ Will connect to ");
|
||||
text2.AppendFormatted(config.LANHelperIPs.Count);
|
||||
text2.AppendLiteral(" local helper PC(s)");
|
||||
ImGui.TextWrapped(text2);
|
||||
}
|
||||
ImGui.PopStyleColor();
|
||||
ImGui.Unindent();
|
||||
}
|
||||
ImGuiHelpers.ScaledDummy(10f);
|
||||
if (config.IsQuester)
|
||||
{
|
||||
|
|
@ -1140,139 +1251,201 @@ public class NewMainWindow : Window, IDisposable
|
|||
ImGui.TextWrapped("Helpers are automatically discovered via IPC when they have 'I'm a High-Level Helper' enabled:");
|
||||
ImGuiHelpers.ScaledDummy(5f);
|
||||
List<(string, ushort)> availableHelpers = plugin.GetAvailableHelpers();
|
||||
if (availableHelpers.Count != 0)
|
||||
if (availableHelpers.Count == 0)
|
||||
{
|
||||
ImGui.TextColored(new Vector4(1f, 0.8f, 0.2f, 1f), "No helpers discovered yet");
|
||||
ImGui.TextWrapped("Make sure helper clients are running with 'I'm a High-Level Helper' enabled.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Vector4 col = new Vector4(0.2f, 1f, 0.2f, 1f);
|
||||
ImU8String text = new ImU8String(21, 1);
|
||||
text.AppendFormatted(availableHelpers.Count);
|
||||
text.AppendLiteral(" helper(s) available:");
|
||||
ImGui.TextColored(in col, text);
|
||||
ImGuiHelpers.ScaledDummy(5f);
|
||||
ImGui.TextUnformatted("Preferred Helper for Chauffeur:");
|
||||
ImU8String text3 = new ImU8String(20, 1);
|
||||
text3.AppendFormatted(availableHelpers.Count);
|
||||
text3.AppendLiteral(" helper(s) available");
|
||||
ImGui.TextColored(in col, text3);
|
||||
}
|
||||
ImGuiHelpers.ScaledDummy(5f);
|
||||
ImGui.Separator();
|
||||
ImGuiHelpers.ScaledDummy(5f);
|
||||
ImGui.TextColored(in colorPrimary, "Helper Selection Mode");
|
||||
ImGuiHelpers.ScaledDummy(3f);
|
||||
int helperSelection = (int)config.HelperSelection;
|
||||
if (ImGui.RadioButton("Auto", helperSelection == 0))
|
||||
{
|
||||
config.HelperSelection = HelperSelectionMode.Auto;
|
||||
config.PreferredHelper = "";
|
||||
config.ManualHelperName = "";
|
||||
config.Save();
|
||||
}
|
||||
ImGui.SameLine();
|
||||
DrawInfoIcon("First available helper via IPC");
|
||||
if (ImGui.RadioButton("Dropdown", helperSelection == 1))
|
||||
{
|
||||
config.HelperSelection = HelperSelectionMode.Dropdown;
|
||||
config.ManualHelperName = "";
|
||||
config.Save();
|
||||
}
|
||||
ImGui.SameLine();
|
||||
DrawInfoIcon("Select specific helper from list");
|
||||
if (config.HelperSelection == HelperSelectionMode.Dropdown && availableHelpers.Count > 0)
|
||||
{
|
||||
ImGui.Indent();
|
||||
ImGui.SetNextItemWidth(250f);
|
||||
List<string> list = new List<string> { "Auto (First Available)" };
|
||||
foreach (var item5 in availableHelpers)
|
||||
string text4 = (string.IsNullOrEmpty(config.PreferredHelper) ? "-- Select --" : config.PreferredHelper);
|
||||
if (ImGui.BeginCombo("##PreferredHelper", text4))
|
||||
{
|
||||
string item = item5.Item1;
|
||||
ushort item2 = item5.Item2;
|
||||
ExcelSheet<World> excelSheet = Plugin.DataManager.GetExcelSheet<World>();
|
||||
string text2 = "Unknown";
|
||||
if (excelSheet != null)
|
||||
foreach (var item5 in availableHelpers)
|
||||
{
|
||||
foreach (World current2 in excelSheet)
|
||||
string item = item5.Item1;
|
||||
ushort item2 = item5.Item2;
|
||||
ExcelSheet<World> excelSheet = Plugin.DataManager.GetExcelSheet<World>();
|
||||
string text5 = "Unknown";
|
||||
if (excelSheet != null)
|
||||
{
|
||||
if (current2.RowId == item2)
|
||||
foreach (World current2 in excelSheet)
|
||||
{
|
||||
text2 = current2.Name.ExtractText();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
list.Add(item + "@" + text2);
|
||||
}
|
||||
string text3 = (string.IsNullOrEmpty(config.PreferredHelper) ? "Auto (First Available)" : config.PreferredHelper);
|
||||
if (ImGui.BeginCombo("##PreferredHelper", text3))
|
||||
{
|
||||
foreach (string current3 in list)
|
||||
{
|
||||
bool flag = text3 == current3;
|
||||
if (ImGui.Selectable(current3, flag))
|
||||
{
|
||||
config.PreferredHelper = ((current3 == "Auto (First Available)") ? "" : current3);
|
||||
config.Save();
|
||||
}
|
||||
if (flag)
|
||||
{
|
||||
ImGui.SetItemDefaultFocus();
|
||||
}
|
||||
}
|
||||
ImGui.EndCombo();
|
||||
}
|
||||
ImGui.SameLine();
|
||||
DrawInfoIcon("Select which helper to use for Chauffeur Mode.\n'Auto' will use the first available helper.");
|
||||
if (!string.IsNullOrEmpty(config.PreferredHelper))
|
||||
{
|
||||
ImGuiHelpers.ScaledDummy(3f);
|
||||
string text4 = (Plugin.Instance?.GetChauffeurMode())?.GetHelperStatus(config.PreferredHelper);
|
||||
Vector4 col2;
|
||||
ImU8String text5;
|
||||
switch (text4)
|
||||
{
|
||||
case "Available":
|
||||
col = new Vector4(0.2f, 1f, 0.2f, 1f);
|
||||
goto IL_04f7;
|
||||
case "Transporting":
|
||||
col = new Vector4(1f, 0.8f, 0f, 1f);
|
||||
goto IL_04f7;
|
||||
case "InDungeon":
|
||||
col = new Vector4(1f, 0.3f, 0.3f, 1f);
|
||||
goto IL_04f7;
|
||||
default:
|
||||
col = colorSecondary;
|
||||
goto IL_04f7;
|
||||
case null:
|
||||
{
|
||||
ImGui.TextColored(in colorSecondary, "Helper Status: Unknown (waiting for update...)");
|
||||
break;
|
||||
}
|
||||
IL_04f7:
|
||||
col2 = col;
|
||||
text5 = new ImU8String(15, 1);
|
||||
text5.AppendLiteral("Helper Status: ");
|
||||
text5.AppendFormatted(text4);
|
||||
ImGui.TextColored(in col2, text5);
|
||||
break;
|
||||
}
|
||||
}
|
||||
ImGuiHelpers.ScaledDummy(5f);
|
||||
ImGui.TextUnformatted("Available Helpers:");
|
||||
ChauffeurModeService chauffeurModeService = Plugin.Instance?.GetChauffeurMode();
|
||||
{
|
||||
foreach (var item6 in availableHelpers)
|
||||
{
|
||||
string item3 = item6.Item1;
|
||||
ushort item4 = item6.Item2;
|
||||
ExcelSheet<World> excelSheet2 = Plugin.DataManager.GetExcelSheet<World>();
|
||||
string text6 = "Unknown";
|
||||
if (excelSheet2 != null)
|
||||
{
|
||||
foreach (World current5 in excelSheet2)
|
||||
{
|
||||
if (current5.RowId == item4)
|
||||
if (current2.RowId == item2)
|
||||
{
|
||||
text6 = current5.Name.ExtractText();
|
||||
text5 = current2.Name.ExtractText();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
string text7 = item3 + "@" + text6;
|
||||
string text8 = chauffeurModeService?.GetHelperStatus(text7);
|
||||
ImU8String text9 = new ImU8String(4, 1);
|
||||
text9.AppendLiteral(" • ");
|
||||
text9.AppendFormatted(text7);
|
||||
ImGui.TextUnformatted(text9);
|
||||
if (text8 != null)
|
||||
string text6 = item + "@" + text5;
|
||||
bool selected = config.PreferredHelper == text6;
|
||||
if (ImGui.Selectable(text6, selected))
|
||||
{
|
||||
ImGui.SameLine();
|
||||
Vector4 col3 = text8 switch
|
||||
{
|
||||
"Available" => new Vector4(0.2f, 1f, 0.2f, 1f),
|
||||
"Transporting" => new Vector4(1f, 0.8f, 0f, 1f),
|
||||
"InDungeon" => new Vector4(1f, 0.3f, 0.3f, 1f),
|
||||
_ => colorSecondary,
|
||||
};
|
||||
ImU8String text10 = new ImU8String(2, 1);
|
||||
text10.AppendLiteral("[");
|
||||
text10.AppendFormatted(text8);
|
||||
text10.AppendLiteral("]");
|
||||
ImGui.TextColored(in col3, text10);
|
||||
config.PreferredHelper = text6;
|
||||
config.Save();
|
||||
}
|
||||
}
|
||||
return;
|
||||
ImGui.EndCombo();
|
||||
}
|
||||
if (!string.IsNullOrEmpty(config.PreferredHelper))
|
||||
{
|
||||
string text7 = (Plugin.Instance?.GetChauffeurMode())?.GetHelperStatus(config.PreferredHelper);
|
||||
Vector4 col;
|
||||
Vector4 col2;
|
||||
ImU8String text8;
|
||||
switch (text7)
|
||||
{
|
||||
case "Available":
|
||||
col = new Vector4(0.2f, 1f, 0.2f, 1f);
|
||||
goto IL_0c39;
|
||||
case "Transporting":
|
||||
col = new Vector4(1f, 0.8f, 0f, 1f);
|
||||
goto IL_0c39;
|
||||
case "InDungeon":
|
||||
col = new Vector4(1f, 0.3f, 0.3f, 1f);
|
||||
goto IL_0c39;
|
||||
default:
|
||||
col = colorSecondary;
|
||||
goto IL_0c39;
|
||||
case null:
|
||||
break;
|
||||
IL_0c39:
|
||||
col2 = col;
|
||||
ImGui.SameLine();
|
||||
text8 = new ImU8String(2, 1);
|
||||
text8.AppendLiteral("[");
|
||||
text8.AppendFormatted(text7);
|
||||
text8.AppendLiteral("]");
|
||||
ImGui.TextColored(in col2, text8);
|
||||
break;
|
||||
}
|
||||
}
|
||||
ImGui.Unindent();
|
||||
}
|
||||
else if (config.HelperSelection == HelperSelectionMode.Dropdown && availableHelpers.Count == 0)
|
||||
{
|
||||
ImGui.Indent();
|
||||
ImGui.TextColored(new Vector4(1f, 0.8f, 0.2f, 1f), "⚠ No helpers available to select");
|
||||
ImGui.Unindent();
|
||||
}
|
||||
if (ImGui.RadioButton("Manual Input", helperSelection == 2))
|
||||
{
|
||||
config.HelperSelection = HelperSelectionMode.ManualInput;
|
||||
config.PreferredHelper = "";
|
||||
config.Save();
|
||||
}
|
||||
ImGui.SameLine();
|
||||
DrawInfoIcon("Manual entry (Dungeon invites only - NOT Chauffeur/Following!)");
|
||||
if (config.HelperSelection == HelperSelectionMode.ManualInput)
|
||||
{
|
||||
ImGui.Indent();
|
||||
ImGui.SetNextItemWidth(250f);
|
||||
string buf2 = config.ManualHelperName;
|
||||
if (ImGui.InputText("##ManualHelperInput", ref buf2, 100))
|
||||
{
|
||||
config.ManualHelperName = buf2;
|
||||
config.Save();
|
||||
}
|
||||
ImGui.SameLine();
|
||||
DrawInfoIcon("Format: CharacterName@WorldName");
|
||||
if (!string.IsNullOrEmpty(config.ManualHelperName))
|
||||
{
|
||||
if (config.ManualHelperName.Contains("@"))
|
||||
{
|
||||
ImGui.SameLine();
|
||||
ImGui.TextColored(new Vector4(0.2f, 1f, 0.2f, 1f), "✓");
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui.SameLine();
|
||||
ImGui.TextColored(new Vector4(1f, 0.5f, 0f, 1f), "⚠");
|
||||
}
|
||||
}
|
||||
ImGui.PushStyleColor(ImGuiCol.Text, new Vector4(1f, 0.8f, 0.2f, 1f));
|
||||
ImGui.TextWrapped("⚠ Cannot be used with Chauffeur/Following (requires IPC)");
|
||||
ImGui.PopStyleColor();
|
||||
ImGui.Unindent();
|
||||
}
|
||||
if (availableHelpers.Count > 0)
|
||||
{
|
||||
ImGuiHelpers.ScaledDummy(5f);
|
||||
ImGui.TextUnformatted("Available Helpers:");
|
||||
ChauffeurModeService chauffeurModeService = Plugin.Instance?.GetChauffeurMode();
|
||||
foreach (var item6 in availableHelpers)
|
||||
{
|
||||
string item3 = item6.Item1;
|
||||
ushort item4 = item6.Item2;
|
||||
ExcelSheet<World> excelSheet2 = Plugin.DataManager.GetExcelSheet<World>();
|
||||
string text9 = "Unknown";
|
||||
if (excelSheet2 != null)
|
||||
{
|
||||
foreach (World current4 in excelSheet2)
|
||||
{
|
||||
if (current4.RowId == item4)
|
||||
{
|
||||
text9 = current4.Name.ExtractText();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
string text10 = item3 + "@" + text9;
|
||||
string text11 = chauffeurModeService?.GetHelperStatus(text10);
|
||||
ImU8String text12 = new ImU8String(4, 1);
|
||||
text12.AppendLiteral(" • ");
|
||||
text12.AppendFormatted(text10);
|
||||
ImGui.TextUnformatted(text12);
|
||||
if (text11 != null)
|
||||
{
|
||||
ImGui.SameLine();
|
||||
Vector4 col3 = text11 switch
|
||||
{
|
||||
"Available" => new Vector4(0.2f, 1f, 0.2f, 1f),
|
||||
"Transporting" => new Vector4(1f, 0.8f, 0f, 1f),
|
||||
"InDungeon" => new Vector4(1f, 0.3f, 0.3f, 1f),
|
||||
_ => colorSecondary,
|
||||
};
|
||||
ImU8String text13 = new ImU8String(2, 1);
|
||||
text13.AppendLiteral("[");
|
||||
text13.AppendFormatted(text11);
|
||||
text13.AppendLiteral("]");
|
||||
ImGui.TextColored(in col3, text13);
|
||||
}
|
||||
}
|
||||
}
|
||||
ImGui.TextColored(new Vector4(1f, 0.8f, 0.2f, 1f), "No helpers discovered yet");
|
||||
ImGui.TextWrapped("Make sure helper clients are running with 'I'm a High-Level Helper' enabled.");
|
||||
}
|
||||
}, config.IsQuester || config.IsHighLevelHelper);
|
||||
ImGuiHelpers.ScaledDummy(10f);
|
||||
|
|
@ -1291,6 +1464,7 @@ public class NewMainWindow : Window, IDisposable
|
|||
{
|
||||
config.ChauffeurModeEnabled = v;
|
||||
config.Save();
|
||||
Plugin.Log.Information("[Multiboxing] Chauffeur Mode: " + (v ? "ENABLED" : "DISABLED"));
|
||||
}
|
||||
DrawInfoIcon("Enable automatic helper summoning for long-distance travel in non-flying zones");
|
||||
if (config.ChauffeurModeEnabled)
|
||||
|
|
@ -1488,6 +1662,7 @@ public class NewMainWindow : Window, IDisposable
|
|||
{
|
||||
config.EnableHelperFollowing = v;
|
||||
config.Save();
|
||||
Plugin.Log.Information("[Multiboxing] Helper Following (Quester): " + (v ? "ENABLED" : "DISABLED"));
|
||||
}
|
||||
if (string.IsNullOrEmpty(config.AssignedHelperForFollowing))
|
||||
{
|
||||
|
|
@ -1565,6 +1740,7 @@ public class NewMainWindow : Window, IDisposable
|
|||
{
|
||||
config.EnableHelperFollowing = v2;
|
||||
config.Save();
|
||||
Plugin.Log.Information("[Multiboxing] Helper Following (Helper): " + (v2 ? "ENABLED" : "DISABLED"));
|
||||
}
|
||||
if (string.IsNullOrEmpty(config.AssignedQuesterForFollowing))
|
||||
{
|
||||
|
|
@ -1617,6 +1793,82 @@ public class NewMainWindow : Window, IDisposable
|
|||
}
|
||||
}
|
||||
}, config.EnableHelperFollowing);
|
||||
}
|
||||
|
||||
private void DrawSettingsTabFull()
|
||||
{
|
||||
ImGui.PushStyleColor(ImGuiCol.Text, colorPrimary);
|
||||
ImGui.TextUnformatted("Plugin Settings");
|
||||
ImGui.PopStyleColor();
|
||||
ImGuiHelpers.ScaledDummy(10f);
|
||||
using ImRaii.IEndObject child = ImRaii.Child("SettingsScrollArea", new Vector2(0f, 0f), border: false, ImGuiWindowFlags.None);
|
||||
if (!child.Success)
|
||||
{
|
||||
return;
|
||||
}
|
||||
Configuration config = plugin.Configuration;
|
||||
DrawSettingSection("Submarine Management", delegate
|
||||
{
|
||||
config.EnableSubmarineCheck = DrawSettingWithInfo("Enable Submarine Monitoring", config.EnableSubmarineCheck, "Automatically monitors submarines and pauses quest rotation when submarines are ready.\nPrevents quest progression while submarines need attention.\nImpact: Rotation will pause when submarines are detected.");
|
||||
if (ImGui.IsItemDeactivatedAfterEdit())
|
||||
{
|
||||
config.Save();
|
||||
}
|
||||
if (config.EnableSubmarineCheck)
|
||||
{
|
||||
ImGui.Indent();
|
||||
int v = config.SubmarineCheckInterval;
|
||||
if (ImGui.SliderInt("Check Interval (seconds)##Submarine", ref v, 30, 300))
|
||||
{
|
||||
config.SubmarineCheckInterval = v;
|
||||
config.Save();
|
||||
}
|
||||
DrawInfoIcon("How often to check for submarine status.\nLower values = more frequent checks but higher CPU usage.");
|
||||
int v2 = config.SubmarineReloginCooldown;
|
||||
if (ImGui.SliderInt("Cooldown after Relog (seconds)", ref v2, 60, 300))
|
||||
{
|
||||
config.SubmarineReloginCooldown = v2;
|
||||
config.Save();
|
||||
}
|
||||
DrawInfoIcon("Time to wait after character switch before checking submarines again.");
|
||||
int v3 = config.SubmarineWaitTime;
|
||||
if (ImGui.SliderInt("Wait time before submarine (seconds)", ref v3, 10, 120))
|
||||
{
|
||||
config.SubmarineWaitTime = v3;
|
||||
config.Save();
|
||||
}
|
||||
DrawInfoIcon("Delay before starting submarine operations after detection.");
|
||||
ImGui.Unindent();
|
||||
}
|
||||
}, config.EnableSubmarineCheck);
|
||||
ImGuiHelpers.ScaledDummy(10f);
|
||||
DrawSettingSection("AutoRetainer Post Process Event Quests", delegate
|
||||
{
|
||||
config.RunEventQuestsOnARPostProcess = DrawSettingWithInfo("Run Event Quests on AR Post Process", config.RunEventQuestsOnARPostProcess, "AUTO-DETECTION: Automatically detects and runs active Event Quests when AutoRetainer completes a character.\nEvent Quests are detected via Questionable IPC (same as manual Event Quest tab).\nAll prerequisites will be automatically resolved and executed.\nAutoRetainer will wait until all Event Quests are completed before proceeding.\nImpact: Extends AR post-process time but ensures Event Quests are completed.");
|
||||
if (ImGui.IsItemDeactivatedAfterEdit())
|
||||
{
|
||||
config.Save();
|
||||
}
|
||||
if (config.RunEventQuestsOnARPostProcess)
|
||||
{
|
||||
ImGui.Indent();
|
||||
ImGui.PushStyleColor(ImGuiCol.Text, new Vector4(0.4f, 0.8f, 0.4f, 1f));
|
||||
ImGui.TextUnformatted("Auto-Detection Enabled");
|
||||
ImGui.PopStyleColor();
|
||||
ImGui.PushStyleColor(ImGuiCol.Text, colorSecondary);
|
||||
ImGui.TextWrapped("Event Quests will be automatically detected from Questionable when AR Post Process starts. No manual configuration needed - just enable this setting and the plugin will handle the rest!");
|
||||
ImGui.PopStyleColor();
|
||||
ImGuiHelpers.ScaledDummy(5f);
|
||||
int v = config.EventQuestPostProcessTimeoutMinutes;
|
||||
if (ImGui.SliderInt("Timeout (minutes)", ref v, 10, 60))
|
||||
{
|
||||
config.EventQuestPostProcessTimeoutMinutes = v;
|
||||
config.Save();
|
||||
}
|
||||
DrawInfoIcon("Maximum time to wait for Event Quests to complete.\nAfter timeout, AR will proceed with next character.");
|
||||
ImGui.Unindent();
|
||||
}
|
||||
}, config.RunEventQuestsOnARPostProcess);
|
||||
ImGuiHelpers.ScaledDummy(10f);
|
||||
DrawSettingSection("Movement Monitor", delegate
|
||||
{
|
||||
|
|
@ -2529,7 +2781,7 @@ public class NewMainWindow : Window, IDisposable
|
|||
|
||||
private void DrawMSQOverall(List<string> characters)
|
||||
{
|
||||
using ImRaii.IEndObject table = ImRaii.Table("MSQOverallTable", 4, ImGuiTableFlags.Borders | ImGuiTableFlags.RowBg | ImGuiTableFlags.ScrollY);
|
||||
using ImRaii.IEndObject table = ImRaii.Table("MSQOverallTable", 5, ImGuiTableFlags.Borders | ImGuiTableFlags.RowBg | ImGuiTableFlags.ScrollY);
|
||||
if (!table.Success)
|
||||
{
|
||||
return;
|
||||
|
|
@ -2538,10 +2790,12 @@ public class NewMainWindow : Window, IDisposable
|
|||
ImGui.TableSetupColumn("MSQ Progress", ImGuiTableColumnFlags.WidthFixed, 120f);
|
||||
ImGui.TableSetupColumn("Current MSQ", ImGuiTableColumnFlags.WidthStretch);
|
||||
ImGui.TableSetupColumn("Completion %", ImGuiTableColumnFlags.WidthFixed, 100f);
|
||||
ImGui.TableSetupColumn("Actions", ImGuiTableColumnFlags.WidthFixed, 70f);
|
||||
ImGui.TableSetupScrollFreeze(0, 1);
|
||||
ImGui.TableHeadersRow();
|
||||
foreach (string character in characters)
|
||||
for (int charIndex = 0; charIndex < characters.Count; charIndex++)
|
||||
{
|
||||
string character = characters[charIndex];
|
||||
if (!characterProgressCache.TryGetValue(character, out CharacterProgressInfo progressInfo))
|
||||
{
|
||||
GetCharacterProgress(character);
|
||||
|
|
@ -2569,6 +2823,27 @@ public class NewMainWindow : Window, IDisposable
|
|||
overlay.AppendFormatted(percentage, "F1");
|
||||
overlay.AppendLiteral("%");
|
||||
ImGui.ProgressBar(fraction, sizeArg, overlay);
|
||||
ImGui.TableNextColumn();
|
||||
using (ImRaii.PushId(charIndex))
|
||||
{
|
||||
ImGui.PushStyleColor(ImGuiCol.Button, colorAccent);
|
||||
ImGui.PushStyleColor(ImGuiCol.ButtonHovered, new Vector4(colorAccent.X * 1.2f, colorAccent.Y * 1.2f, colorAccent.Z * 1.2f, 1f));
|
||||
if (ImGui.Button("Reset"))
|
||||
{
|
||||
questRotationService.ClearCharacterQuestData(character);
|
||||
characterProgressCache.Remove(character);
|
||||
log.Information("[MSQProgression] Reset quest data for " + character);
|
||||
}
|
||||
ImGui.PopStyleColor(2);
|
||||
if (ImGui.IsItemHovered())
|
||||
{
|
||||
ImU8String tooltip = new ImU8String(85, 1);
|
||||
tooltip.AppendLiteral("Reset all quest completion data for ");
|
||||
tooltip.AppendFormatted(character);
|
||||
tooltip.AppendLiteral(".\nUse this if data was corrupted during rotation.");
|
||||
ImGui.SetTooltip(tooltip);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue