1
0
Fork 0
forked from aly/qstbak
qstbak/Questionable/Questionable.Windows.QuestComponents/QuestSequenceComponent.cs
2025-11-17 11:31:27 +10:00

595 lines
25 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using Dalamud.Bindings.ImGui;
using Dalamud.Interface;
using Dalamud.Interface.Components;
using Dalamud.Interface.Utility.Raii;
using Dalamud.Plugin.Services;
using Lumina.Excel.Sheets;
using Microsoft.Extensions.Logging;
using Questionable.Controller;
using Questionable.Data;
using Questionable.Functions;
using Questionable.Model;
using Questionable.Model.Questing;
namespace Questionable.Windows.QuestComponents;
internal sealed class QuestSequenceComponent
{
private readonly QuestData _questData;
private readonly QuestRegistry _questRegistry;
private readonly QuestFunctions _questFunctions;
private readonly IDataManager _dataManager;
private readonly ILogger<QuestSequenceComponent> _logger;
private string _questLookupInput = string.Empty;
private ElementId? _lookedUpQuestId;
private int _hoveredSequenceId = -1;
public QuestSequenceComponent(QuestData questData, QuestRegistry questRegistry, QuestFunctions questFunctions, IDataManager dataManager, ILogger<QuestSequenceComponent> logger)
{
_questData = questData;
_questRegistry = questRegistry;
_questFunctions = questFunctions;
_dataManager = dataManager;
_logger = logger;
}
public static void DrawCustomHeader(ref bool isOpen)
{
Vector2 cursorScreenPos = ImGui.GetCursorScreenPos();
float x = ImGui.GetContentRegionAvail().X;
float num = ImGui.GetFrameHeightWithSpacing() + ImGui.GetStyle().ItemSpacing.Y * 1.5f;
ImDrawListPtr windowDrawList = ImGui.GetWindowDrawList();
windowDrawList.AddRectFilledMultiColor(cursorScreenPos, cursorScreenPos + new Vector2(x, num), ImGui.ColorConvertFloat4ToU32(new Vector4(0.22f, 0.2f, 0.28f, 0.85f)), ImGui.ColorConvertFloat4ToU32(new Vector4(0.18f, 0.16f, 0.24f, 0.85f)), ImGui.ColorConvertFloat4ToU32(new Vector4(0.18f, 0.16f, 0.24f, 0.85f)), ImGui.ColorConvertFloat4ToU32(new Vector4(0.22f, 0.2f, 0.28f, 0.85f)));
windowDrawList.AddLine(cursorScreenPos + new Vector2(0f, num), cursorScreenPos + new Vector2(x, num), ImGui.ColorConvertFloat4ToU32(new Vector4(0.7f, 0.6f, 0.9f, 0.5f)), 2f);
float textLineHeight = ImGui.GetTextLineHeight();
float num2 = (num - textLineHeight) * 0.5f;
ImGui.SetCursorPosY(ImGui.GetCursorPosY() + num2);
ImGui.SetCursorPosX(ImGui.GetCursorPosX() + 10f);
ImGui.TextColored(new Vector4(0.98f, 0.98f, 1f, 1f), "Quest Sequence Viewer");
ImGui.SameLine(x - 35f);
ImGui.SetCursorPosY(ImGui.GetCursorPosY() - num2 + ImGui.GetStyle().ItemSpacing.Y);
using (ImRaii.PushColor(ImGuiCol.Button, Vector4.Zero))
{
using (ImRaii.PushColor(ImGuiCol.ButtonHovered, new Vector4(0.8f, 0.3f, 0.3f, 0.4f)))
{
using (ImRaii.PushColor(ImGuiCol.ButtonActive, new Vector4(0.9f, 0.2f, 0.2f, 0.6f)))
{
if (ImGuiComponents.IconButton(FontAwesomeIcon.Times))
{
isOpen = false;
}
}
}
}
ImGui.SetCursorPosY(cursorScreenPos.Y + num - ImGui.GetCursorScreenPos().Y + ImGui.GetCursorPosY());
}
public static void DrawWindowBorder()
{
ImDrawListPtr windowDrawList = ImGui.GetWindowDrawList();
Vector2 windowPos = ImGui.GetWindowPos();
Vector2 windowSize = ImGui.GetWindowSize();
windowDrawList.AddRect(windowPos - new Vector2(1f, 1f), windowPos + windowSize + new Vector2(1f, 1f), ImGui.ColorConvertFloat4ToU32(new Vector4(0.7f, 0.6f, 0.9f, 0.15f)), 5f, ImDrawFlags.None, 3f);
windowDrawList.AddRect(windowPos, windowPos + windowSize, ImGui.ColorConvertFloat4ToU32(new Vector4(0.7f, 0.6f, 0.9f, 0.4f)), 4f, ImDrawFlags.None, 1.5f);
}
public void DrawCurrentQuestTab()
{
QuestReference currentQuest = _questFunctions.GetCurrentQuest();
(ElementId, byte) tuple = (currentQuest.CurrentQuest, currentQuest.Sequence);
if (tuple.Item1 != null)
{
DrawQuestSequences(tuple.Item1, tuple.Item2);
}
else
{
DrawEmptyState(FontAwesomeIcon.QuestionCircle, "No Active Quest", "Accept a quest to view its sequence information.", new Vector4(0.6f, 0.5f, 0.8f, 0.7f));
}
}
public void DrawQuestLookupTab()
{
Vector2 cursorScreenPos = ImGui.GetCursorScreenPos();
float y = ImGui.GetFrameHeightWithSpacing() + ImGui.GetStyle().ItemSpacing.Y * 3f;
float x = ImGui.GetContentRegionAvail().X;
ImDrawListPtr windowDrawList = ImGui.GetWindowDrawList();
windowDrawList.AddRectFilledMultiColor(cursorScreenPos, cursorScreenPos + new Vector2(x, y), ImGui.ColorConvertFloat4ToU32(new Vector4(0.12f, 0.1f, 0.16f, 0.6f)), ImGui.ColorConvertFloat4ToU32(new Vector4(0.1f, 0.08f, 0.14f, 0.6f)), ImGui.ColorConvertFloat4ToU32(new Vector4(0.1f, 0.08f, 0.14f, 0.6f)), ImGui.ColorConvertFloat4ToU32(new Vector4(0.12f, 0.1f, 0.16f, 0.6f)));
windowDrawList.AddRect(cursorScreenPos, cursorScreenPos + new Vector2(x, y), ImGui.ColorConvertFloat4ToU32(new Vector4(0.6f, 0.5f, 0.8f, 0.2f)), 4f, ImDrawFlags.None, 1f);
ImGui.SetCursorPosY(ImGui.GetCursorPosY() + ImGui.GetStyle().ItemSpacing.Y * 1.5f);
ImGui.SetCursorPosX(ImGui.GetCursorPosX() + 10f);
using (ImRaii.PushFont(UiBuilder.IconFont))
{
ImGui.TextColored(new Vector4(0.7f, 0.6f, 0.9f, 1f), FontAwesomeIcon.Search.ToIconString());
}
ImGui.SameLine();
float x2 = ImGui.GetStyle().ItemSpacing.X;
float num = 10f;
float num2 = 10f;
float num3 = ImGui.CalcTextSize("Search").X + ImGui.CalcTextSize(FontAwesomeIcon.Search.ToIconString()).X + ImGui.GetStyle().FramePadding.X * 4f + x2;
ImGui.SetNextItemWidth(x - num3 - x2 * 3f - num - num2);
using (ImRaii.PushColor(ImGuiCol.FrameBg, new Vector4(0.08f, 0.06f, 0.12f, 0.8f)))
{
using (ImRaii.PushColor(ImGuiCol.FrameBgHovered, new Vector4(0.12f, 0.1f, 0.18f, 0.9f)))
{
using (ImRaii.PushColor(ImGuiCol.FrameBgActive, new Vector4(0.15f, 0.13f, 0.22f, 1f)))
{
bool flag = ImGui.InputTextWithHint("##QuestLookup", "Enter quest ID...", ref _questLookupInput, 10, ImGuiInputTextFlags.EnterReturnsTrue);
ImGui.SameLine();
using (ImRaii.PushColor(ImGuiCol.Button, new Vector4(0.25f, 0.22f, 0.32f, 0.8f)))
{
using (ImRaii.PushColor(ImGuiCol.ButtonHovered, new Vector4(0.35f, 0.3f, 0.45f, 0.9f)))
{
using (ImRaii.PushColor(ImGuiCol.ButtonActive, new Vector4(0.4f, 0.35f, 0.5f, 1f)))
{
bool flag2 = ImGuiComponents.IconButtonWithText(FontAwesomeIcon.Search, "Search");
if (flag || flag2)
{
if (ushort.TryParse(_questLookupInput, out var result))
{
_lookedUpQuestId = new QuestId(result);
}
else
{
_lookedUpQuestId = null;
}
}
}
}
}
}
}
}
ImGui.SetCursorPosY(ImGui.GetCursorPosY() + ImGui.GetStyle().ItemSpacing.Y * 1.5f);
ImGui.Spacing();
ImGui.Spacing();
if (_lookedUpQuestId != null)
{
DrawQuestSequences(_lookedUpQuestId, null);
}
else
{
DrawEmptyState(FontAwesomeIcon.Search, "Enter a Quest ID", "Use the search box above to look up any quest by its ID.", new Vector4(0.6f, 0.5f, 0.8f, 0.7f));
}
}
private static void DrawEmptyState(FontAwesomeIcon icon, string title, string message, Vector4 iconColor)
{
float y = ImGui.GetContentRegionAvail().Y;
float x = ImGui.GetContentRegionAvail().X;
ImGui.SetCursorPosY(ImGui.GetCursorPosY() + y * 0.25f);
Vector2 cursorScreenPos = ImGui.GetCursorScreenPos();
ImGui.PushFont(UiBuilder.IconFont);
string text = icon.ToIconString();
Vector2 vector = ImGui.CalcTextSize(text);
vector *= 2.5f;
ImDrawListPtr windowDrawList = ImGui.GetWindowDrawList();
Vector2 vector2 = new Vector2(x * 0.5f, 0f) + cursorScreenPos + new Vector2(0f, vector.Y * 0.5f);
for (int num = 3; num > 0; num--)
{
Vector4 col = new Vector4(iconColor.X, iconColor.Y, iconColor.Z, iconColor.W * 0.1f * (float)num);
ImGui.SetCursorScreenPos(vector2 - vector * 0.5f - new Vector2(num * 2, num * 2));
ImGui.TextColored(in col, text);
}
ImGui.SetCursorScreenPos(vector2 - vector * 0.5f);
ImGui.TextColored(in iconColor, text);
ImGui.PopFont();
ImGui.SetCursorPosY(ImGui.GetCursorPosY() + vector.Y * 0.5f + 20f);
Vector2 vector3 = ImGui.CalcTextSize(title);
Vector2 vector4 = new Vector2((x - vector3.X) * 0.5f, 0f) + ImGui.GetCursorScreenPos();
windowDrawList.AddText(vector4 + new Vector2(1f, 1f), ImGui.ColorConvertFloat4ToU32(new Vector4(0f, 0f, 0f, 0.5f)), title);
ImGui.SetCursorPosX((x - vector3.X) * 0.5f);
ImGui.TextColored(new Vector4(0.95f, 0.95f, 1f, 1f), title);
ImGui.Spacing();
ImGui.Spacing();
ImGui.SetCursorPosX((x - ImGui.CalcTextSize(message).X) * 0.5f);
ImGui.TextColored(new Vector4(0.7f, 0.7f, 0.8f, 1f), message);
}
private void DrawQuestSequences(ElementId questElementId, byte? currentSequence)
{
if (!(questElementId is QuestId questId))
{
DrawErrorState("Invalid Quest ID Type", "This viewer only supports regular quest IDs.");
return;
}
if (!_questData.TryGetQuestInfo(questElementId, out IQuestInfo questInfo))
{
DrawErrorState($"Quest {questId.Value} Not Found", "This quest ID does not exist in the game data.");
return;
}
Vector2 cursorScreenPos = ImGui.GetCursorScreenPos();
float num = ImGui.GetFrameHeightWithSpacing() * 1.8f;
float x = ImGui.GetContentRegionAvail().X;
ImDrawListPtr windowDrawList = ImGui.GetWindowDrawList();
windowDrawList.AddRectFilledMultiColor(cursorScreenPos, cursorScreenPos + new Vector2(x, num), ImGui.ColorConvertFloat4ToU32(new Vector4(0.12f, 0.1f, 0.16f, 0.7f)), ImGui.ColorConvertFloat4ToU32(new Vector4(0.1f, 0.08f, 0.14f, 0.7f)), ImGui.ColorConvertFloat4ToU32(new Vector4(0.1f, 0.08f, 0.14f, 0.7f)), ImGui.ColorConvertFloat4ToU32(new Vector4(0.12f, 0.1f, 0.16f, 0.7f)));
windowDrawList.AddRect(cursorScreenPos, cursorScreenPos + new Vector2(x, num), ImGui.ColorConvertFloat4ToU32(new Vector4(0.6f, 0.5f, 0.8f, 0.25f)), 4f, ImDrawFlags.None, 1f);
float textLineHeight = ImGui.GetTextLineHeight();
float num2 = (num - textLineHeight) * 0.5f;
ImGui.SetCursorPosY(ImGui.GetCursorPosY() + num2);
ImGui.SetCursorPosX(ImGui.GetCursorPosX() + 10f);
ImGui.PushFont(UiBuilder.IconFont);
ImGui.TextColored(new Vector4(0.7f, 0.6f, 0.9f, 1f), FontAwesomeIcon.Book.ToIconString());
ImGui.PopFont();
ImGui.SameLine();
ImGui.TextColored(new Vector4(0.98f, 0.98f, 1f, 1f), questInfo.Name);
ImGui.SameLine();
Vector4 col = new Vector4(0.7f, 0.7f, 0.8f, 1f);
ImU8String text = new ImU8String(6, 1);
text.AppendLiteral("(ID: ");
text.AppendFormatted(questId.Value);
text.AppendLiteral(")");
ImGui.TextColored(in col, text);
if (currentSequence.HasValue)
{
ImGui.SameLine();
ImGui.TextColored(new Vector4(0.5f, 0.5f, 0.6f, 1f), "—");
ImGui.SameLine();
float num3 = (float)ImGui.GetTime();
float num4 = 0.85f + MathF.Sin(num3 * 3f) * 0.15f;
col = new Vector4(0.5f * num4, 1f * num4, 0.6f * num4, 1f);
text = new ImU8String(17, 1);
text.AppendLiteral("Active: Sequence ");
text.AppendFormatted(currentSequence.Value);
ImGui.TextColored(in col, text);
}
ImGui.SetCursorPosY(cursorScreenPos.Y + num - ImGui.GetCursorScreenPos().Y + ImGui.GetCursorPosY());
ImGui.Spacing();
try
{
Lumina.Excel.Sheets.Quest? quest = _dataManager.GetExcelSheet<Lumina.Excel.Sheets.Quest>()?.GetRowOrDefault((uint)(questId.Value + 65536));
if (!quest.HasValue)
{
DrawErrorState("Quest Not Found in Game Data", "Unable to load quest information from Lumina.");
return;
}
List<int> list = (from result in quest.Value.TodoParams.Where((Lumina.Excel.Sheets.Quest.TodoParamsStruct todoParamsStruct) => todoParamsStruct.ToDoCompleteSeq > 0 && todoParamsStruct.ToDoCompleteSeq < byte.MaxValue).Select((Func<Lumina.Excel.Sheets.Quest.TodoParamsStruct, int>)((Lumina.Excel.Sheets.Quest.TodoParamsStruct todoParamsStruct) => todoParamsStruct.ToDoCompleteSeq)).Distinct()
orderby result
select result).ToList();
if (list.Count == 0)
{
DrawErrorState("No Sequence Data Available", "This quest may not have traditional sequences.");
return;
}
int num5 = list.Max();
int num6 = num5 + 1;
Questionable.Model.Quest quest2;
bool flag = _questRegistry.TryGetQuest(questElementId, out quest2);
HashSet<int> hashSet = new HashSet<int>();
Dictionary<int, (int, string)> dictionary = new Dictionary<int, (int, string)>();
bool flag2 = false;
if (flag && quest2 != null && quest2.Root.QuestSequence.Count > 0)
{
foreach (QuestSequence item in quest2.Root.QuestSequence)
{
if (item.Sequence == byte.MaxValue)
{
flag2 = true;
dictionary[255] = (item.Steps.Count, item.Comment);
}
else
{
hashSet.Add(item.Sequence);
dictionary[item.Sequence] = (item.Steps.Count, item.Comment);
}
}
}
int num7 = hashSet.Count + (flag2 ? 1 : 0);
int num8 = num6 + 1;
float num9 = (flag ? ((float)num7 / (float)num8 * 100f) : 0f);
Vector4 coverageColor = ((num9 >= 100f) ? new Vector4(0.5f, 1f, 0.6f, 1f) : ((num9 >= 50f) ? new Vector4(1f, 0.9f, 0.5f, 1f) : ((num9 < 1f) ? new Vector4(0.6f, 0.5f, 0.8f, 0.7f) : new Vector4(1f, 0.5f, 0.5f, 1f))));
DrawSummaryCards(num6, num5, flag, num9, coverageColor, num7, num8);
ImGui.Spacing();
ImGui.Spacing();
DrawSequenceGrid(num5, currentSequence, hashSet, dictionary, flag2);
}
catch (Exception ex)
{
DrawErrorState("Error Loading Quest Data", ex.Message + "\nCheck logs for details.");
_logger.LogWarning(ex, "Failed to read quest sequence data from Lumina for {QuestId}", questId);
}
}
private static void DrawErrorState(string title, string message)
{
float y = ImGui.GetContentRegionAvail().Y;
float x = ImGui.GetContentRegionAvail().X;
ImGui.SetCursorPosY(ImGui.GetCursorPosY() + y * 0.25f);
float num = (float)ImGui.GetTime();
float num2 = 0.7f + MathF.Sin(num * 2f) * 0.3f;
ImGui.PushFont(UiBuilder.IconFont);
string text = FontAwesomeIcon.ExclamationTriangle.ToIconString();
Vector2 vector = ImGui.CalcTextSize(text);
ImGui.SetCursorPosX((x - (vector * 2f).X) * 0.5f);
ImGui.TextColored(new Vector4(1f * num2, 0.4f * num2, 0.4f * num2, 1f), text);
ImGui.PopFont();
ImGui.Spacing();
ImGui.Spacing();
ImGui.SetCursorPosX((x - ImGui.CalcTextSize(title).X) * 0.5f);
ImGui.TextColored(new Vector4(1f, 0.5f, 0.5f, 1f), title);
ImGui.Spacing();
ImGui.SetCursorPosX((x - ImGui.CalcTextSize(message).X) * 0.5f);
ImGui.TextColored(new Vector4(0.7f, 0.7f, 0.8f, 1f), message);
}
private static void DrawSummaryCards(int totalSequences, int maxSeq, bool hasQuestPath, float coverage, Vector4 coverageColor, int implementedCount, int expectedCount)
{
using ImRaii.IEndObject endObject = ImRaii.Table("SummaryCards", 2, ImGuiTableFlags.None);
if (!endObject)
{
return;
}
ImGui.TableSetupColumn("GameData", ImGuiTableColumnFlags.WidthStretch, 0.4f);
ImGui.TableSetupColumn("QuestPath", ImGuiTableColumnFlags.WidthStretch, 0.6f);
ImGui.TableNextRow();
ImGui.TableNextColumn();
DrawCard(80f, new Vector4(0.6f, 0.85f, 1f, 1f), FontAwesomeIcon.Gamepad, "Expected Sequences", delegate
{
ImGui.Spacing();
ImGui.Indent(10f);
Vector4 col = new Vector4(0.9f, 0.9f, 0.98f, 1f);
ImU8String text = new ImU8String(6, 0);
text.AppendLiteral("Count:");
ImGui.TextColored(in col, text);
ImGui.SameLine();
col = new Vector4(0.7f, 0.9f, 1f, 1f);
text = new ImU8String(0, 1);
text.AppendFormatted(totalSequences);
ImGui.TextColored(in col, text);
ImGui.Spacing();
col = new Vector4(0.9f, 0.9f, 0.98f, 1f);
text = new ImU8String(6, 0);
text.AppendLiteral("Range:");
ImGui.TextColored(in col, text);
ImGui.SameLine();
col = new Vector4(0.7f, 0.9f, 1f, 1f);
text = new ImU8String(9, 1);
text.AppendLiteral("0 → ");
text.AppendFormatted(maxSeq);
text.AppendLiteral(", 255");
ImGui.TextColored(in col, text);
ImGui.Unindent(10f);
});
ImGui.TableNextColumn();
DrawCard(80f, new Vector4(0.5f, 1f, 0.6f, 1f), FontAwesomeIcon.Code, "Implementation Status", delegate
{
if (hasQuestPath)
{
ImGui.Indent(10f);
ImGui.TextColored(new Vector4(0.9f, 0.9f, 0.98f, 1f), "Progress:");
ImGui.SameLine();
ref Vector4 col = ref coverageColor;
ImU8String text = new ImU8String(0, 1);
text.AppendFormatted(implementedCount);
ImGui.TextColored(in col, text);
ImGui.SameLine();
ImGui.TextColored(new Vector4(0.7f, 0.7f, 0.8f, 1f), "/");
ImGui.SameLine();
Vector4 col2 = new Vector4(0.9f, 0.9f, 0.98f, 1f);
text = new ImU8String(0, 1);
text.AppendFormatted(expectedCount);
ImGui.TextColored(in col2, text);
ImGui.SameLine();
ref Vector4 col3 = ref coverageColor;
text = new ImU8String(3, 1);
text.AppendLiteral("(");
text.AppendFormatted(coverage, "F0");
text.AppendLiteral("%)");
ImGui.TextColored(in col3, text);
ImGui.Spacing();
Vector2 cursorScreenPos = ImGui.GetCursorScreenPos();
float x = ImGui.GetContentRegionAvail().X - 10f;
using (ImRaii.PushColor(ImGuiCol.PlotHistogram, coverageColor))
{
using (ImRaii.PushColor(ImGuiCol.FrameBg, new Vector4(0.08f, 0.06f, 0.12f, 0.8f)))
{
ImGui.ProgressBar(coverage / 100f, new Vector2(x, 16f), "");
}
}
ImGui.GetWindowDrawList().AddRect(cursorScreenPos, cursorScreenPos + new Vector2(x, 16f), ImGui.ColorConvertFloat4ToU32(new Vector4(0.6f, 0.5f, 0.8f, 0.3f)), 2f);
ImGui.Unindent(10f);
}
else
{
ImGui.Spacing();
ImGui.Indent(10f);
ImGui.PushFont(UiBuilder.IconFont);
ImGui.TextColored(new Vector4(0.6f, 0.5f, 0.8f, 0.8f), FontAwesomeIcon.Ban.ToIconString());
ImGui.PopFont();
ImGui.SameLine();
ImGui.TextColored(new Vector4(0.6f, 0.5f, 0.8f, 0.8f), "Not Implemented");
ImGui.Spacing();
ImGui.TextColored(new Vector4(0.7f, 0.7f, 0.8f, 1f), "No quest path data available");
ImGui.Unindent(10f);
}
});
}
private static void DrawCard(float height, Vector4 accentColor, FontAwesomeIcon icon, string title, System.Action content)
{
Vector2 cursorScreenPos = ImGui.GetCursorScreenPos();
float x = ImGui.GetContentRegionAvail().X;
ImDrawListPtr windowDrawList = ImGui.GetWindowDrawList();
windowDrawList.AddRectFilledMultiColor(cursorScreenPos, cursorScreenPos + new Vector2(x, height), ImGui.ColorConvertFloat4ToU32(new Vector4(0.12f, 0.1f, 0.16f, 0.7f)), ImGui.ColorConvertFloat4ToU32(new Vector4(0.1f, 0.08f, 0.14f, 0.7f)), ImGui.ColorConvertFloat4ToU32(new Vector4(0.1f, 0.08f, 0.14f, 0.7f)), ImGui.ColorConvertFloat4ToU32(new Vector4(0.12f, 0.1f, 0.16f, 0.7f)));
windowDrawList.AddRect(cursorScreenPos, cursorScreenPos + new Vector2(x, height), ImGui.ColorConvertFloat4ToU32(new Vector4(0.6f, 0.5f, 0.8f, 0.2f)), 4f, ImDrawFlags.None, 1f);
windowDrawList.AddLine(cursorScreenPos, cursorScreenPos + new Vector2(x, 0f), ImGui.ColorConvertFloat4ToU32(accentColor), 3f);
float num = cursorScreenPos.Y + 10f;
ImGui.SetCursorScreenPos(new Vector2(cursorScreenPos.X + 10f, num));
ImGui.PushFont(UiBuilder.IconFont);
ImGui.TextColored(in accentColor, icon.ToIconString());
ImGui.PopFont();
ImGui.SameLine();
ImGui.TextColored(new Vector4(0.98f, 0.98f, 1f, 1f), title);
ImGui.SetCursorScreenPos(new Vector2(cursorScreenPos.X + 10f, num + 24f));
content();
ImGui.SetCursorScreenPos(new Vector2(cursorScreenPos.X, cursorScreenPos.Y + height + 4f));
}
private void DrawSequenceGrid(int maxSeq, byte? currentSequence, HashSet<int> implementedSequences, Dictionary<int, (int StepCount, string? Comment)> sequenceDetails, bool hasEndSequence)
{
int val = maxSeq + 2;
float x = ImGui.GetContentRegionAvail().X;
int val2 = Math.Max(4, Math.Min(8, (int)(x / 100f)));
val2 = Math.Min(val2, val);
float y = ImGui.GetContentRegionAvail().Y;
using (ImRaii.PushColor(ImGuiCol.ChildBg, new Vector4(0.08f, 0.06f, 0.12f, 0.6f)))
{
using (ImRaii.PushColor(ImGuiCol.Border, new Vector4(0.6f, 0.5f, 0.8f, 0.2f)))
{
using ImRaii.IEndObject endObject = ImRaii.Child("SequenceGrid", new Vector2(-1f, y), border: true, ImGuiWindowFlags.None);
if (!ImRaii.IEndObject.op_True(endObject))
{
return;
}
using (ImRaii.PushColor(ImGuiCol.TableBorderStrong, new Vector4(0.6f, 0.5f, 0.8f, 0.2f)))
{
using (ImRaii.PushColor(ImGuiCol.TableBorderLight, new Vector4(0.6f, 0.5f, 0.8f, 0.15f)))
{
using ImRaii.IEndObject endObject2 = ImRaii.Table("SequenceGridTable", val2, ImGuiTableFlags.Borders | ImGuiTableFlags.SizingStretchSame);
if (!ImRaii.IEndObject.op_True(endObject2))
{
return;
}
int num = 0;
for (int i = 0; i <= maxSeq; i++)
{
if (num % val2 == 0)
{
ImGui.TableNextRow();
}
ImGui.TableNextColumn();
DrawSequenceCell(i, currentSequence, implementedSequences, sequenceDetails);
num++;
}
if (num % val2 == 0)
{
ImGui.TableNextRow();
}
ImGui.TableNextColumn();
DrawSequenceCell(255, currentSequence, implementedSequences, sequenceDetails, hasEndSequence);
for (num++; num % val2 != 0; num++)
{
ImGui.TableNextColumn();
}
}
}
}
}
}
private void DrawSequenceCell(int sequenceId, byte? currentSequence, HashSet<int> implementedSequences, Dictionary<int, (int StepCount, string? Comment)> sequenceDetails, bool? forcedImplemented = null)
{
bool flag = currentSequence.HasValue && sequenceId == currentSequence.Value;
bool flag2 = forcedImplemented ?? implementedSequences.Contains(sequenceId);
bool flag3 = _hoveredSequenceId == sequenceId;
string text = ((sequenceId == 255) ? "255" : $"{sequenceId}");
Vector4 input;
Vector4 input2;
if (flag)
{
input = (flag3 ? new Vector4(0.18f, 0.55f, 0.25f, 0.8f) : new Vector4(0.15f, 0.48f, 0.22f, 0.7f));
input2 = new Vector4(0.5f, 1f, 0.6f, flag3 ? 0.8f : 0.5f);
}
else if (flag2)
{
input = (flag3 ? new Vector4(0.14f, 0.38f, 0.18f, 0.6f) : new Vector4(0.12f, 0.34f, 0.16f, 0.5f));
input2 = new Vector4(0.5f, 1f, 0.6f, flag3 ? 0.5f : 0.25f);
}
else
{
input = (flag3 ? new Vector4(0.5f, 0.18f, 0.18f, 0.6f) : new Vector4(0.45f, 0.15f, 0.15f, 0.5f));
input2 = new Vector4(1f, 0.5f, 0.5f, flag3 ? 0.6f : 0.3f);
}
Vector2 cursorScreenPos = ImGui.GetCursorScreenPos();
Vector2 vector = new Vector2(ImGui.GetContentRegionAvail().X, 75f);
ImDrawListPtr windowDrawList = ImGui.GetWindowDrawList();
windowDrawList.AddRectFilled(cursorScreenPos, cursorScreenPos + vector, ImGui.ColorConvertFloat4ToU32(input), 3f);
if (flag3)
{
windowDrawList.AddRect(cursorScreenPos - new Vector2(1f, 1f), cursorScreenPos + vector + new Vector2(1f, 1f), ImGui.ColorConvertFloat4ToU32(new Vector4(input2.X, input2.Y, input2.Z, input2.W * 0.3f)), 3f, ImDrawFlags.None, 3f);
}
windowDrawList.AddRect(cursorScreenPos, cursorScreenPos + vector, ImGui.ColorConvertFloat4ToU32(input2), 3f, ImDrawFlags.None, flag3 ? 2f : 1.5f);
float x = vector.X;
Vector2 vector2 = ImGui.CalcTextSize(text);
Vector4 input3 = (flag ? new Vector4(0.98f, 0.98f, 1f, 1f) : new Vector4(0.9f, 0.9f, 0.98f, 1f));
float y = cursorScreenPos.Y + (vector.Y - vector2.Y) * 0.5f;
windowDrawList.AddText(new Vector2(cursorScreenPos.X + (x - vector2.X) * 0.5f, y), ImGui.ColorConvertFloat4ToU32(input3), text);
ImGui.SetCursorScreenPos(cursorScreenPos);
ImU8String strId = new ImU8String(5, 1);
strId.AppendLiteral("##Seq");
strId.AppendFormatted(sequenceId);
ImGui.InvisibleButton(strId, vector);
if (ImGui.IsItemHovered())
{
_hoveredSequenceId = sequenceId;
using (ImRaii.Tooltip())
{
using (ImRaii.PushColor(ImGuiCol.Text, new Vector4(0.98f, 0.98f, 1f, 1f)))
{
strId = new ImU8String(9, 1);
strId.AppendLiteral("Sequence ");
strId.AppendFormatted(sequenceId);
ImGui.Text(strId);
}
ImGui.Separator();
if (flag2 && sequenceDetails.TryGetValue(sequenceId, out (int, string) value))
{
ImGui.PushFont(UiBuilder.IconFont);
ImGui.TextColored(new Vector4(0.5f, 1f, 0.6f, 1f), FontAwesomeIcon.CheckCircle.ToIconString());
ImGui.PopFont();
ImGui.SameLine();
ImGui.TextColored(new Vector4(0.5f, 1f, 0.6f, 1f), "Implemented");
ImGui.Spacing();
Vector4 col = new Vector4(0.9f, 0.9f, 0.98f, 1f);
strId = new ImU8String(6, 0);
strId.AppendLiteral("Steps:");
ImGui.TextColored(in col, strId);
ImGui.SameLine();
col = new Vector4(0.7f, 0.9f, 1f, 1f);
strId = new ImU8String(0, 1);
strId.AppendFormatted(value.Item1);
ImGui.TextColored(in col, strId);
if (!string.IsNullOrEmpty(value.Item2))
{
ImGui.Separator();
ImGui.PushTextWrapPos(250f);
ImGui.TextColored(new Vector4(0.7f, 0.7f, 0.8f, 1f), value.Item2);
ImGui.PopTextWrapPos();
}
}
else if (!flag2)
{
ImGui.PushFont(UiBuilder.IconFont);
ImGui.TextColored(new Vector4(1f, 0.5f, 0.5f, 1f), FontAwesomeIcon.TimesCircle.ToIconString());
ImGui.PopFont();
ImGui.SameLine();
ImGui.TextColored(new Vector4(1f, 0.5f, 0.5f, 1f), "Not Implemented");
ImGui.Spacing();
ImGui.PushTextWrapPos(250f);
ImGui.TextColored(new Vector4(0.7f, 0.7f, 0.8f, 1f), "This sequence is missing from the quest path.");
ImGui.PopTextWrapPos();
}
if (flag)
{
ImGui.Separator();
ImGui.TextColored(new Vector4(1f, 0.85f, 0.5f, 1f), "► Currently Active");
}
}
}
else if (_hoveredSequenceId == sequenceId)
{
_hoveredSequenceId = -1;
}
ImGui.SetCursorScreenPos(cursorScreenPos + new Vector2(0f, vector.Y));
}
}