using System; using System.Collections.Generic; using System.Linq; using System.Numerics; using Dalamud.Bindings.ImGui; using Dalamud.Game.Text; using Dalamud.Interface; using Dalamud.Interface.Utility.Raii; using Dalamud.Plugin.Services; using FFXIVClientStructs.FFXIV.Client.Game; using Microsoft.Extensions.Logging; using Questionable.Controller; using Questionable.Data; using Questionable.Functions; using Questionable.Model; using Questionable.Model.Questing; using Questionable.Windows.QuestComponents; namespace Questionable.Windows.JournalComponents; internal sealed class AlliedSocietyJournalComponent { private static readonly string[] RankNames = new string[9] { "Neutral", "Recognized", "Friendly", "Trusted", "Respected", "Honored", "Sworn", "Bloodsworn", "Allied" }; private const int DefaultDailyQuestLimit = 3; private const int SharedDailyAllowanceLimit = 12; private readonly Dictionary _societyHeaderStates = new Dictionary(); private readonly AlliedSocietyQuestFunctions _alliedSocietyQuestFunctions; private readonly QuestData _questData; private readonly QuestRegistry _questRegistry; private readonly QuestJournalUtils _questJournalUtils; private readonly QuestTooltipComponent _questTooltipComponent; private readonly UiUtils _uiUtils; private readonly QuestController _questController; private readonly IChatGui _chatGui; private readonly ILogger _logger; private static readonly (string Name, EAlliedSociety[] Societies)[] ExpansionGroups = new(string, EAlliedSociety[])[6] { ("A Realm Reborn", new EAlliedSociety[5] { EAlliedSociety.Amaljaa, EAlliedSociety.Sylphs, EAlliedSociety.Kobolds, EAlliedSociety.Sahagin, EAlliedSociety.Ixal }), ("Heavensward", new EAlliedSociety[3] { EAlliedSociety.VanuVanu, EAlliedSociety.Vath, EAlliedSociety.Moogles }), ("Stormblood", new EAlliedSociety[3] { EAlliedSociety.Kojin, EAlliedSociety.Ananta, EAlliedSociety.Namazu }), ("Shadowbringers", new EAlliedSociety[3] { EAlliedSociety.Pixies, EAlliedSociety.Qitari, EAlliedSociety.Dwarves }), ("Endwalker", new EAlliedSociety[3] { EAlliedSociety.Arkasodara, EAlliedSociety.Omicrons, EAlliedSociety.Loporrits }), ("Dawntrail", new EAlliedSociety[3] { EAlliedSociety.Pelupelu, EAlliedSociety.MamoolJa, EAlliedSociety.YokHuy }) }; public AlliedSocietyJournalComponent(AlliedSocietyQuestFunctions alliedSocietyQuestFunctions, QuestData questData, QuestRegistry questRegistry, QuestJournalUtils questJournalUtils, QuestTooltipComponent questTooltipComponent, UiUtils uiUtils, QuestController questController, IChatGui chatGui, ILogger logger) { _alliedSocietyQuestFunctions = alliedSocietyQuestFunctions; _questData = questData; _questRegistry = questRegistry; _questJournalUtils = questJournalUtils; _questTooltipComponent = questTooltipComponent; _uiUtils = uiUtils; _questController = questController; _chatGui = chatGui; _logger = logger; } public void DrawAlliedSocietyQuests() { DrawDailyAllowanceBar(); ImGui.Separator(); ImGui.Spacing(); bool flag = false; (string, EAlliedSociety[])[] expansionGroups = ExpansionGroups; for (int i = 0; i < expansionGroups.Length; i++) { (string, EAlliedSociety[]) tuple = expansionGroups[i]; string item = tuple.Item1; EAlliedSociety[] item2 = tuple.Item2; List<(EAlliedSociety, List)> list = new List<(EAlliedSociety, List)>(); EAlliedSociety[] array = item2; foreach (EAlliedSociety eAlliedSociety in array) { List list2 = (from x in _alliedSocietyQuestFunctions.GetAvailableAlliedSocietyQuests(eAlliedSociety) select (QuestInfo)_questData.GetQuestInfo(x)).ToList(); if (list2.Count > 0) { list.Add((eAlliedSociety, list2)); } } if (list.Count == 0) { continue; } flag = true; UiThemeUtils.SubSectionHeader(item); ImGui.Spacing(); foreach (var (alliedSociety, quests) in list) { DrawSocietySection(alliedSociety, quests); } ImGui.Spacing(); } if (!flag) { ImGui.TextColored(in UiThemeUtils.DimTextColor, "No allied society quests available."); } } private unsafe void DrawDailyAllowanceBar() { QuestManager* ptr = QuestManager.Instance(); if (ptr != null) { byte b = (byte)ptr->GetBeastTribeAllowance(); int num = 12 - b; TimeSpan item = CalculateTimeUntilReset().TimeUntilReset; JournalUiShared.DrawAllowanceHeader(num, 12, "daily allowances", item, $"Shared across all allied societies\nUsed today: {num}"); } } internal static (DateTime ResetTime, TimeSpan TimeUntilReset) CalculateTimeUntilReset() { DateTime utcNow = DateTime.UtcNow; DateTime dateTime = new DateTime(utcNow.Year, utcNow.Month, utcNow.Day, 15, 0, 0, DateTimeKind.Utc); DateTime dateTime2 = ((utcNow >= dateTime) ? dateTime.AddDays(1.0) : dateTime); TimeSpan item = dateTime2 - utcNow; return (ResetTime: dateTime2.ToLocalTime(), TimeUntilReset: item); } private void DrawReputationStatus(EAlliedSociety alliedSociety) { (byte, ushort, ushort, bool, bool)? reputationStatus = _alliedSocietyQuestFunctions.GetReputationStatus(alliedSociety); if (!reputationStatus.HasValue) { return; } (byte, ushort, ushort, bool, bool) value = reputationStatus.Value; byte item = value.Item1; ushort item2 = value.Item2; ushort item3 = value.Item3; bool item4 = value.Item4; bool item5 = value.Item5; string value2 = ((item < RankNames.Length) ? RankNames[item] : $"Rank {item}"); if (item4) { ImU8String text = new ImU8String(0, 1); text.AppendFormatted(value2); ImGui.TextColored(in UiThemeUtils.StatusComplete, text); } else if (item5) { using (ImRaii.PushColor(ImGuiCol.Text, UiThemeUtils.StatusActive)) { using (ImRaii.PushFont(UiBuilder.IconFont)) { ImGui.Text(FontAwesomeIcon.ExclamationTriangle.ToIconString()); } ImGui.SameLine(0f, 4f); ImU8String text2 = new ImU8String(24, 3); text2.AppendFormatted(value2); text2.AppendLiteral(" - "); text2.AppendFormatted(item2); text2.AppendLiteral("/"); text2.AppendFormatted(item3); text2.AppendLiteral(" (rank up available)"); ImGui.TextUnformatted(text2); } } else { Vector4 col = ((((item3 > 0) ? ((float)(int)item2 / (float)(int)item3) : 0f) >= 0.8f) ? UiThemeUtils.StatusActive : UiThemeUtils.MutedTextColor); ImU8String text3 = new ImU8String(4, 3); text3.AppendFormatted(value2); text3.AppendLiteral(" - "); text3.AppendFormatted(item2); text3.AppendLiteral("/"); text3.AppendFormatted(item3); ImGui.TextColored(in col, text3); } ImGui.Spacing(); } private void DrawSocietySection(EAlliedSociety alliedSociety, List quests) { Quest quest; int num = quests.Count((QuestInfo q) => _questRegistry.TryGetQuest(q.QuestId, out quest) && !quest.Root.Disabled); string rightText = ((num > 0) ? $"{num} available" : "no paths available"); string text = $"AlliedSociety{alliedSociety}"; string label = alliedSociety.ToString(); bool open = _societyHeaderStates.GetValueOrDefault(text, defaultValue: false); UiThemeUtils.ThemedAccordion(text, label, rightText, ref open); _societyHeaderStates[text] = open; if (!open) { return; } using (ImRaii.PushIndent()) { DrawReputationStatus(alliedSociety); DrawAddToPriorityButtons(alliedSociety, quests); ImGui.Spacing(); DrawQuestList(alliedSociety, quests); } } private void DrawQuestList(EAlliedSociety alliedSociety, List quests) { int num = (((int)alliedSociety <= 4) ? 4 : ((alliedSociety != EAlliedSociety.Ixal) ? 9 : 8)); int num2 = num; int num3 = 0; byte rank = 1; while (rank <= num2) { List list = quests.Where((QuestInfo x) => x.AlliedSocietyRank == rank).ToList(); if (list.Count != 0) { ImGui.TextColored(in UiThemeUtils.MutedTextColor, RankNames[rank]); foreach (QuestInfo item in list) { UiThemeUtils.DrawAltRowBackground(num3++); DrawQuest(item); } } byte b = (byte)(rank + 1); rank = b; } } private void DrawAddToPriorityButtons(EAlliedSociety alliedSociety, List quests) { bool flag = (int)alliedSociety <= 5; int dailyLimit = (flag ? 12 : 3); int remainingAllowances = GetRemainingAllowances(); Quest quest; List list = (from q in quests where _questRegistry.TryGetQuest(q.QuestId, out quest) && !quest.Root.Disabled where !_questController.ManualPriorityQuests.Any((Quest pq) => pq.Id.Equals(q.QuestId)) orderby q.AlliedSocietyRank descending select q).ToList(); if (list.Count == 0) { DrawDisabledAddButton(); } else if (flag) { DrawArrSocietyButtons(alliedSociety, list, dailyLimit, remainingAllowances); } else { DrawStandardAddButton(alliedSociety, list, remainingAllowances); } } private unsafe int GetRemainingAllowances() { QuestManager* ptr = QuestManager.Instance(); if (ptr == null) { return 12; } return (int)ptr->GetBeastTribeAllowance(); } private static float IconTextButtonWidth(FontAwesomeIcon icon, string text) { Vector2 vector; using (ImRaii.PushFont(UiBuilder.IconFont)) { vector = ImGui.CalcTextSize(icon.ToIconString()); } return ImGui.GetStyle().FramePadding.X * 3f * 2f + vector.X + 6f + ImGui.CalcTextSize(text).X; } private static void DrawDisabledAddButton() { using (ImRaii.Disabled(disabled: true)) { UiThemeUtils.IconTextButton(FontAwesomeIcon.Plus, "Add to Priority", IconTextButtonWidth(FontAwesomeIcon.Plus, "Add to Priority")); } if (ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenDisabled)) { ImGui.SetTooltip("No quests available to add (may be disabled, already in priority, or not available)"); } } private void DrawArrSocietyButtons(EAlliedSociety alliedSociety, List availableQuests, int dailyLimit, int remainingAllowances) { int num = Math.Min(Math.Min(dailyLimit, remainingAllowances), availableQuests.Count); using (ImRaii.Disabled(remainingAllowances == 0)) { string text = num switch { 1 => "Add 1 Quest (Optimal)", 2 => "Add 2 Quests (Optimal)", 3 => "Add 3 Quests (Optimal)", _ => (num != remainingAllowances) ? $"Add {num} (Optimal)" : $"Add {num} (Today's Remaining)", }; if (UiThemeUtils.IconTextButton(FontAwesomeIcon.Plus, text, IconTextButtonWidth(FontAwesomeIcon.Plus, text))) { AddQuestsToPriority(alliedSociety, availableQuests.Take(num).ToList()); } } if (ImGui.IsItemHovered(ImGuiHoveredFlags.AllowWhenDisabled)) { DrawRecommendedButtonTooltip(num, remainingAllowances, dailyLimit, alliedSociety, availableQuests.Count); } ImGui.SameLine(); string text2 = $"Add All {availableQuests.Count} Available"; if (UiThemeUtils.IconTextButton(FontAwesomeIcon.ListOl, text2, IconTextButtonWidth(FontAwesomeIcon.ListOl, text2))) { AddQuestsToPriority(alliedSociety, availableQuests); } if (ImGui.IsItemHovered()) { DrawAddAllButtonTooltip(availableQuests.Count, remainingAllowances, dailyLimit, alliedSociety); } } private static void DrawRecommendedButtonTooltip(int questsToAddCount, int remainingAllowances, int dailyLimit, EAlliedSociety alliedSociety, int availableCount) { ImGui.BeginTooltip(); if (remainingAllowances == 0) { using (ImRaii.PushColor(ImGuiCol.Text, UiThemeUtils.StatusLocked)) { ImU8String text = new ImU8String(0, 1); text.AppendFormatted(SeIconChar.Cross.ToIconString()); ImGui.Text(text); ImGui.SameLine(); ImGui.TextUnformatted("No daily allowances remaining"); } ImU8String text2 = new ImU8String(44, 1); text2.AppendLiteral("You've used all "); text2.AppendFormatted(12); text2.AppendLiteral(" shared allowances for today"); ImGui.TextColored(in UiThemeUtils.MutedTextColor, text2); } else if (questsToAddCount == remainingAllowances && questsToAddCount < availableCount) { using (ImRaii.PushColor(ImGuiCol.Text, UiThemeUtils.StatusComplete)) { ImU8String text3 = new ImU8String(0, 1); text3.AppendFormatted(SeIconChar.QuestSync.ToIconString()); ImGui.Text(text3); ImGui.SameLine(); ImU8String text4 = new ImU8String(5, 2); text4.AppendLiteral("Add "); text4.AppendFormatted(questsToAddCount); text4.AppendLiteral(" "); text4.AppendFormatted((questsToAddCount == 1) ? "quest" : "quests"); ImGui.TextUnformatted(text4); } ImU8String text5 = new ImU8String(44, 2); text5.AppendLiteral("You can complete "); text5.AppendFormatted(remainingAllowances); text5.AppendLiteral(" more allied society "); text5.AppendFormatted((remainingAllowances == 1) ? "quest" : "quests"); text5.AppendLiteral(" today"); ImGui.TextColored(in UiThemeUtils.MutedTextColor, text5); ImGui.Spacing(); ImGui.TextColored(in UiThemeUtils.MutedTextColor, "Prioritises highest rank quests first"); } else if (questsToAddCount == dailyLimit) { using (ImRaii.PushColor(ImGuiCol.Text, UiThemeUtils.StatusComplete)) { ImU8String text6 = new ImU8String(0, 1); text6.AppendFormatted(SeIconChar.QuestSync.ToIconString()); ImGui.Text(text6); ImGui.SameLine(); ImU8String text7 = new ImU8String(11, 1); text7.AppendLiteral("Add "); text7.AppendFormatted(dailyLimit); text7.AppendLiteral(" quests"); ImGui.TextUnformatted(text7); } ImU8String text8 = new ImU8String(51, 2); text8.AppendLiteral("This will use "); text8.AppendFormatted(dailyLimit); text8.AppendLiteral(" of your "); text8.AppendFormatted(remainingAllowances); text8.AppendLiteral(" remaining shared allowances"); ImGui.TextColored(in UiThemeUtils.MutedTextColor, text8); ImGui.Spacing(); ImGui.TextColored(in UiThemeUtils.MutedTextColor, "Prioritises highest rank quests first"); } else if (questsToAddCount == availableCount) { using (ImRaii.PushColor(ImGuiCol.Text, UiThemeUtils.StatusComplete)) { ImU8String text9 = new ImU8String(0, 1); text9.AppendFormatted(SeIconChar.QuestSync.ToIconString()); ImGui.Text(text9); ImGui.SameLine(); ImU8String text10 = new ImU8String(20, 3); text10.AppendLiteral("Add all "); text10.AppendFormatted(questsToAddCount); text10.AppendLiteral(" available "); text10.AppendFormatted(alliedSociety); text10.AppendLiteral(" "); text10.AppendFormatted((questsToAddCount == 1) ? "quest" : "quests"); ImGui.TextUnformatted(text10); } ImU8String text11 = new ImU8String(37, 2); text11.AppendLiteral("Uses "); text11.AppendFormatted(questsToAddCount); text11.AppendLiteral(" of "); text11.AppendFormatted(remainingAllowances); text11.AppendLiteral(" shared allowances remaining"); ImGui.TextColored(in UiThemeUtils.MutedTextColor, text11); ImGui.Spacing(); ImGui.TextColored(in UiThemeUtils.MutedTextColor, "Prioritises highest rank quests first"); } else { using (ImRaii.PushColor(ImGuiCol.Text, UiThemeUtils.StatusActive)) { ImU8String text12 = new ImU8String(0, 1); text12.AppendFormatted(SeIconChar.BoxedLetterQ.ToIconString()); ImGui.Text(text12); ImGui.SameLine(); ImU8String text13 = new ImU8String(6, 3); text13.AppendLiteral("Add "); text13.AppendFormatted(questsToAddCount); text13.AppendLiteral(" "); text13.AppendFormatted(alliedSociety); text13.AppendLiteral(" "); text13.AppendFormatted((questsToAddCount == 1) ? "quest" : "quests"); ImGui.TextUnformatted(text13); } ImU8String text14 = new ImU8String(55, 2); text14.AppendLiteral("Limited by available quests ("); text14.AppendFormatted(availableCount); text14.AppendLiteral(") and shared allowances ("); text14.AppendFormatted(remainingAllowances); text14.AppendLiteral(")"); ImGui.TextColored(in UiThemeUtils.MutedTextColor, text14); ImGui.Spacing(); ImGui.TextColored(in UiThemeUtils.MutedTextColor, "Prioritises highest rank quests first"); } ImGui.EndTooltip(); } private static void DrawAddAllButtonTooltip(int availableCount, int remainingAllowances, int dailyLimit, EAlliedSociety alliedSociety) { ImGui.BeginTooltip(); if (availableCount > remainingAllowances) { using (ImRaii.PushColor(ImGuiCol.Text, UiThemeUtils.StatusActive)) { ImU8String text = new ImU8String(0, 1); text.AppendFormatted(SeIconChar.Cross.ToIconString()); ImGui.Text(text); ImGui.SameLine(); ImGui.TextUnformatted("Warning: Exceeds remaining allowances"); } ImGui.Spacing(); ImU8String text2 = new ImU8String(54, 1); text2.AppendLiteral("This adds all "); text2.AppendFormatted(availableCount); text2.AppendLiteral(" available quests to your priority list,"); ImGui.TextUnformatted(text2); ImU8String text3 = new ImU8String(37, 2); text3.AppendLiteral("but you only have "); text3.AppendFormatted(remainingAllowances); text3.AppendLiteral(" shared "); text3.AppendFormatted((remainingAllowances == 1) ? "allowance" : "allowances"); text3.AppendLiteral(" remaining."); ImGui.TextUnformatted(text3); ImGui.Spacing(); ImGui.TextColored(in UiThemeUtils.MutedTextColor, "The excess quests won't be completable until tomorrow."); } else if (availableCount > dailyLimit) { using (ImRaii.PushColor(ImGuiCol.Text, UiThemeUtils.StatusActive)) { ImU8String text4 = new ImU8String(0, 1); text4.AppendFormatted(SeIconChar.Cross.ToIconString()); ImGui.Text(text4); ImGui.SameLine(); ImGui.TextUnformatted("Warning: Exceeds daily optimal amount"); } ImGui.Spacing(); ImU8String text5 = new ImU8String(32, 1); text5.AppendLiteral("This adds all "); text5.AppendFormatted(availableCount); text5.AppendLiteral(" available quests,"); ImGui.TextUnformatted(text5); ImU8String text6 = new ImU8String(48, 1); text6.AppendLiteral("using more than the typical "); text6.AppendFormatted(3); text6.AppendLiteral(" quests per society."); ImGui.TextUnformatted(text6); ImGui.Spacing(); ImU8String text7 = new ImU8String(37, 1); text7.AppendLiteral("You have "); text7.AppendFormatted(remainingAllowances); text7.AppendLiteral(" shared allowances remaining"); ImGui.TextColored(in UiThemeUtils.StatusComplete, text7); ImGui.TextColored(in UiThemeUtils.MutedTextColor, "You may want to save allowances for other societies."); } else { using (ImRaii.PushColor(ImGuiCol.Text, UiThemeUtils.StatusComplete)) { ImU8String text8 = new ImU8String(0, 1); text8.AppendFormatted(SeIconChar.QuestSync.ToIconString()); ImGui.Text(text8); ImGui.SameLine(); ImU8String text9 = new ImU8String(20, 3); text9.AppendLiteral("Add all "); text9.AppendFormatted(availableCount); text9.AppendLiteral(" available "); text9.AppendFormatted(alliedSociety); text9.AppendLiteral(" "); text9.AppendFormatted((availableCount == 1) ? "quest" : "quests"); ImGui.TextUnformatted(text9); } ImGui.Spacing(); ImU8String text10 = new ImU8String(27, 2); text10.AppendLiteral("Uses "); text10.AppendFormatted(availableCount); text10.AppendLiteral(" of "); text10.AppendFormatted(remainingAllowances); text10.AppendLiteral(" shared allowances"); ImGui.TextColored(in UiThemeUtils.MutedTextColor, text10); ImGui.TextColored(in UiThemeUtils.MutedTextColor, "All can be completed today"); } ImGui.EndTooltip(); } private void DrawStandardAddButton(EAlliedSociety alliedSociety, List availableQuests, int remainingAllowances) { string text = availableQuests.Count switch { 1 => "Add 1 Quest", 2 => "Add 2 Quests", 3 => "Add 3 Quests", _ => $"Add All {availableQuests.Count} Quests", }; if (UiThemeUtils.IconTextButton(FontAwesomeIcon.Plus, text, IconTextButtonWidth(FontAwesomeIcon.Plus, text))) { AddQuestsToPriority(alliedSociety, availableQuests); } if (!ImGui.IsItemHovered()) { return; } ImGui.BeginTooltip(); ImU8String text2 = new ImU8String(18, 3); text2.AppendLiteral("Add "); text2.AppendFormatted(availableQuests.Count); text2.AppendLiteral(" "); text2.AppendFormatted(alliedSociety); text2.AppendLiteral(" "); text2.AppendFormatted((availableQuests.Count == 1) ? "quest" : "quests"); text2.AppendLiteral(" to priority"); ImGui.TextUnformatted(text2); ImGui.Spacing(); if (availableQuests.Count <= remainingAllowances) { using (ImRaii.PushColor(ImGuiCol.Text, UiThemeUtils.StatusComplete)) { ImU8String text3 = new ImU8String(0, 1); text3.AppendFormatted(SeIconChar.QuestSync.ToIconString()); ImGui.Text(text3); ImGui.SameLine(); ImU8String text4 = new ImU8String(17, 3); text4.AppendLiteral("Uses "); text4.AppendFormatted(availableQuests.Count); text4.AppendLiteral(" of "); text4.AppendFormatted(remainingAllowances); text4.AppendLiteral(" shared "); text4.AppendFormatted((remainingAllowances == 1) ? "allowance" : "allowances"); ImGui.TextUnformatted(text4); } ImGui.TextColored(in UiThemeUtils.MutedTextColor, "All can be completed today"); } else { using (ImRaii.PushColor(ImGuiCol.Text, UiThemeUtils.StatusActive)) { ImU8String text5 = new ImU8String(0, 1); text5.AppendFormatted(SeIconChar.Cross.ToIconString()); ImGui.Text(text5); ImGui.SameLine(); ImU8String text6 = new ImU8String(31, 1); text6.AppendLiteral("Exceeds remaining allowances ("); text6.AppendFormatted(remainingAllowances); text6.AppendLiteral(")"); ImGui.TextUnformatted(text6); } ImGui.TextColored(in UiThemeUtils.MutedTextColor, "Some quests won't be completable until tomorrow"); } ImGui.EndTooltip(); } private void AddQuestsToPriority(EAlliedSociety alliedSociety, List questsToAdd) { int num = 0; foreach (QuestInfo item in questsToAdd) { if (_questController.AddQuestPriority(item.QuestId)) { num++; } } if (num > 0) { string text = ((num == 1) ? "quest" : "quests"); _logger.LogInformation("Added {Count} {Society} {QuestWord} to priority list", num, alliedSociety, text); _chatGui.Print($"Added {num} {alliedSociety} {text} to priority list.", "Questionable", 576); } } private void DrawQuest(QuestInfo questInfo) { var (color, icon, value) = _uiUtils.GetQuestStyle(questInfo.QuestId); if (!_questRegistry.TryGetQuest(questInfo.QuestId, out Quest quest) || quest.Root.Disabled) { color = UiThemeUtils.StatusUnobtainable; } string text = $"{questInfo.Name} ({value}) [{questInfo.QuestId}]"; float x; using (ImRaii.PushFont(UiBuilder.IconFont)) { x = ImGui.CalcTextSize(icon.ToIconString()).X; } float maxWidth = ImGui.GetContentRegionAvail().X - x - ImGui.GetStyle().ItemSpacing.X; if (_uiUtils.ChecklistItem(UiThemeUtils.TruncateToWidth(text, maxWidth), color, icon)) { _questTooltipComponent.Draw(questInfo); } _questJournalUtils.ShowContextMenu(questInfo, quest, "AlliedSocietyJournalComponent"); } }