using System; using System.Collections.Generic; using Dalamud.Plugin; using Dalamud.Plugin.Ipc; using Dalamud.Plugin.Services; namespace QuestionableCompanion.Services; public class QuestionableIPC : IDisposable { private readonly IDalamudPluginInterface pluginInterface; private readonly IPluginLog log; private ICallGateSubscriber? importQuestPrioritySubscriber; private ICallGateSubscriber? getCurrentQuestIdSubscriber; private ICallGateSubscriber? getCurrentStepDataSubscriber; private ICallGateSubscriber? isRunningSubscriber; private ICallGateSubscriber? getCurrentTaskSubscriber; private ICallGateSubscriber? isQuestCompleteSubscriber; private ICallGateSubscriber? isReadyToAcceptQuestSubscriber; private ICallGateSubscriber? addQuestPrioritySubscriber; private ICallGateSubscriber? clearQuestPrioritySubscriber; private ICallGateSubscriber>? getCurrentlyActiveEventQuestsSubscriber; private ICallGateSubscriber? getAlliedSocietyRemainingAllowancesSubscriber; private ICallGateSubscriber>? getAlliedSocietyAvailableQuestIdsSubscriber; private ICallGateSubscriber>? getAlliedSocietyAllAvailableQuestCountsSubscriber; private ICallGateSubscriber? getAlliedSocietyIsMaxRankSubscriber; private ICallGateSubscriber? getAlliedSocietyCurrentRankSubscriber; private ICallGateSubscriber>? getAlliedSocietiesWithAvailableQuestsSubscriber; private ICallGateSubscriber? addAlliedSocietyOptimalQuestsSubscriber; private ICallGateSubscriber>? getAlliedSocietyOptimalQuestsSubscriber; private ICallGateSubscriber? getAlliedSocietyTimeUntilResetSubscriber; private ICallGateSubscriber? getStopConditionsEnabledSubscriber; private ICallGateSubscriber>? getStopQuestListSubscriber; private ICallGateSubscriber? getLevelStopConditionSubscriber; private ICallGateSubscriber? getSequenceStopConditionSubscriber; private ICallGateSubscriber? getQuestSequenceStopConditionSubscriber; private ICallGateSubscriber? removeQuestSequenceStopConditionSubscriber; private ICallGateSubscriber>? getAllQuestSequenceStopConditionsSubscriber; private ICallGateSubscriber? getDefaultDutyModeSubscriber; private ICallGateSubscriber? setDefaultDutyModeSubscriber; private bool subscribersInitialized; private DateTime lastAvailabilityCheck = DateTime.MinValue; private const int AvailabilityCheckCooldownSeconds = 5; public bool IsAvailable { get; private set; } public QuestionableIPC(IDalamudPluginInterface pluginInterface, IPluginLog log) { this.pluginInterface = pluginInterface; this.log = log; InitializeIPC(); } private void InitializeIPC() { try { getCurrentQuestIdSubscriber = pluginInterface.GetIpcSubscriber("Questionable.GetCurrentQuestId"); getCurrentStepDataSubscriber = pluginInterface.GetIpcSubscriber("Questionable.GetCurrentStepData"); isRunningSubscriber = pluginInterface.GetIpcSubscriber("Questionable.IsRunning"); importQuestPrioritySubscriber = pluginInterface.GetIpcSubscriber("Questionable.ImportQuestPriority"); getCurrentTaskSubscriber = pluginInterface.GetIpcSubscriber("Questionable.GetCurrentTask"); isQuestCompleteSubscriber = pluginInterface.GetIpcSubscriber("Questionable.IsQuestComplete"); isReadyToAcceptQuestSubscriber = pluginInterface.GetIpcSubscriber("Questionable.IsReadyToAcceptQuest"); addQuestPrioritySubscriber = pluginInterface.GetIpcSubscriber("Questionable.AddQuestPriority"); clearQuestPrioritySubscriber = pluginInterface.GetIpcSubscriber("Questionable.ClearQuestPriority"); getCurrentlyActiveEventQuestsSubscriber = pluginInterface.GetIpcSubscriber>("Questionable.GetCurrentlyActiveEventQuests"); getAlliedSocietyRemainingAllowancesSubscriber = pluginInterface.GetIpcSubscriber("Questionable.AlliedSociety.GetRemainingAllowances"); getAlliedSocietyAvailableQuestIdsSubscriber = pluginInterface.GetIpcSubscriber>("Questionable.AlliedSociety.GetAvailableQuestIds"); getAlliedSocietyAllAvailableQuestCountsSubscriber = pluginInterface.GetIpcSubscriber>("Questionable.AlliedSociety.GetAllAvailableQuestCounts"); getAlliedSocietyIsMaxRankSubscriber = pluginInterface.GetIpcSubscriber("Questionable.AlliedSociety.IsMaxRank"); getAlliedSocietyCurrentRankSubscriber = pluginInterface.GetIpcSubscriber("Questionable.AlliedSociety.GetCurrentRank"); getAlliedSocietiesWithAvailableQuestsSubscriber = pluginInterface.GetIpcSubscriber>("Questionable.AlliedSociety.GetSocietiesWithAvailableQuests"); addAlliedSocietyOptimalQuestsSubscriber = pluginInterface.GetIpcSubscriber("Questionable.AlliedSociety.AddOptimalQuests"); getAlliedSocietyOptimalQuestsSubscriber = pluginInterface.GetIpcSubscriber>("Questionable.AlliedSociety.GetOptimalQuests"); getAlliedSocietyTimeUntilResetSubscriber = pluginInterface.GetIpcSubscriber("Questionable.AlliedSociety.GetTimeUntilReset"); getStopConditionsEnabledSubscriber = pluginInterface.GetIpcSubscriber("Questionable.GetStopConditionsEnabled"); getStopQuestListSubscriber = pluginInterface.GetIpcSubscriber>("Questionable.GetStopQuestList"); getLevelStopConditionSubscriber = pluginInterface.GetIpcSubscriber("Questionable.GetLevelStopCondition"); getSequenceStopConditionSubscriber = pluginInterface.GetIpcSubscriber("Questionable.GetSequenceStopCondition"); getQuestSequenceStopConditionSubscriber = pluginInterface.GetIpcSubscriber("Questionable.GetQuestSequenceStopCondition"); removeQuestSequenceStopConditionSubscriber = pluginInterface.GetIpcSubscriber("Questionable.RemoveQuestSequenceStopCondition"); getAllQuestSequenceStopConditionsSubscriber = pluginInterface.GetIpcSubscriber>("Questionable.GetAllQuestSequenceStopConditions"); getDefaultDutyModeSubscriber = pluginInterface.GetIpcSubscriber("Questionable.GetDefaultDutyMode"); setDefaultDutyModeSubscriber = pluginInterface.GetIpcSubscriber("Questionable.SetDefaultDutyMode"); subscribersInitialized = true; log.Debug("[QuestionableIPC] IPC subscribers initialized (lazy-loading enabled)"); } catch (Exception ex) { IsAvailable = false; subscribersInitialized = false; log.Error("[QuestionableIPC] Failed to initialize subscribers: " + ex.Message); } } private bool TryEnsureAvailable() { if (IsAvailable) { return true; } if (!subscribersInitialized) { log.Warning("[QuestionableIPC] Subscribers not initialized!"); return false; } DateTime now = DateTime.Now; if ((now - lastAvailabilityCheck).TotalSeconds < 5.0) { return false; } lastAvailabilityCheck = now; try { if (isRunningSubscriber == null) { log.Error("[QuestionableIPC] isRunningSubscriber is NULL!"); return false; } isRunningSubscriber.InvokeFunc(); if (!IsAvailable) { IsAvailable = true; } return true; } catch (Exception ex) { log.Error("[QuestionableIPC] Failed to connect to Questionable:"); log.Error("[QuestionableIPC] Exception Type: " + ex.GetType().Name); log.Error("[QuestionableIPC] Message: " + ex.Message); log.Error("[QuestionableIPC] Stack Trace: " + ex.StackTrace); IsAvailable = false; return false; } } public bool ForceCheckAvailability() { try { if (!subscribersInitialized) { log.Error("[QuestionableIPC] Subscribers not initialized!"); return false; } if (isRunningSubscriber == null) { log.Error("[QuestionableIPC] isRunningSubscriber is NULL!"); return false; } log.Information("[QuestionableIPC] Force checking Questionable availability..."); log.Information("[QuestionableIPC] Attempting to call Questionable.IsRunning..."); bool testRunning = isRunningSubscriber.InvokeFunc(); log.Information($"[QuestionableIPC] SUCCESS! Questionable.IsRunning returned: {testRunning}"); IsAvailable = true; lastAvailabilityCheck = DateTime.Now; return true; } catch (Exception ex) { log.Error("[QuestionableIPC] Failed to connect to Questionable:"); log.Error("[QuestionableIPC] Exception Type: " + ex.GetType().Name); log.Error("[QuestionableIPC] Message: " + ex.Message); log.Error("[QuestionableIPC] Stack Trace: " + ex.StackTrace); IsAvailable = false; return false; } } public bool TryEnsureAvailableSilent() { if (IsAvailable) { return true; } if (!subscribersInitialized) { return false; } lastAvailabilityCheck = DateTime.MinValue; try { if (isRunningSubscriber == null) { return false; } isRunningSubscriber.InvokeFunc(); if (!IsAvailable) { IsAvailable = true; } return true; } catch { IsAvailable = false; return false; } } public string? GetCurrentQuestId() { TryEnsureAvailable(); if (!IsAvailable || getCurrentQuestIdSubscriber == null) { return null; } try { return getCurrentQuestIdSubscriber.InvokeFunc(); } catch (Exception ex) { log.Debug("[QuestionableIPC] GetCurrentQuestId failed: " + ex.Message); return null; } } public StepData? GetCurrentStepData() { TryEnsureAvailable(); if (!IsAvailable || getCurrentStepDataSubscriber == null) { return null; } try { return getCurrentStepDataSubscriber.InvokeFunc(); } catch (Exception ex) { log.Debug("[QuestionableIPC] GetCurrentStepData failed: " + ex.Message); return null; } } public byte? GetCurrentSequence() { TryEnsureAvailable(); if (!IsAvailable || getCurrentStepDataSubscriber == null) { return null; } try { return getCurrentStepDataSubscriber.InvokeFunc()?.Sequence; } catch (Exception ex) { log.Debug("[QuestionableIPC] GetCurrentSequence failed: " + ex.Message); return null; } } public bool IsRunning() { TryEnsureAvailable(); if (isRunningSubscriber == null) { return false; } try { bool result = isRunningSubscriber.InvokeFunc(); if (!IsAvailable) { IsAvailable = true; log.Information("[QuestionableIPC] Questionable is now available"); } return result; } catch (Exception ex) { if (IsAvailable) { IsAvailable = false; log.Warning("[QuestionableIPC] Questionable is no longer available: " + ex.Message); } log.Debug("[QuestionableIPC] IsRunning failed: " + ex.Message); return false; } } public object? GetCurrentTask() { TryEnsureAvailable(); if (getCurrentTaskSubscriber == null) { return null; } try { object? result = getCurrentTaskSubscriber.InvokeFunc(); if (!IsAvailable) { IsAvailable = true; log.Information("[QuestionableIPC] Questionable is now available"); } return result; } catch (Exception ex) { if (IsAvailable) { IsAvailable = false; log.Warning("[QuestionableIPC] Questionable is no longer available: " + ex.Message); } log.Debug("[QuestionableIPC] GetCurrentTask failed: " + ex.Message); return null; } } public bool Start() { log.Warning("[QuestionableIPC] Start() called - NOT AVAILABLE VIA IPC!"); log.Warning("[QuestionableIPC] Use /qst start command instead"); return false; } public bool Stop() { log.Warning("[QuestionableIPC] Stop() called - NOT AVAILABLE VIA IPC!"); log.Warning("[QuestionableIPC] Use /qst stop command instead"); return false; } public bool ImportQuestPriority(string base64QuestData) { TryEnsureAvailable(); if (!IsAvailable || importQuestPrioritySubscriber == null) { return false; } try { bool result = importQuestPrioritySubscriber.InvokeFunc(base64QuestData); log.Information($"[QuestionableIPC] Imported priority quest: {result}"); return result; } catch (Exception ex) { log.Error("[QuestionableIPC] ImportQuestPriority failed: " + ex.Message); return false; } } public bool AddQuestPriority(string questId) { TryEnsureAvailable(); if (!IsAvailable || addQuestPrioritySubscriber == null) { return false; } try { bool result = addQuestPrioritySubscriber.InvokeFunc(questId); log.Debug($"[QuestionableIPC] Added quest {questId} to priority: {result}"); return result; } catch (Exception ex) { log.Error("[QuestionableIPC] AddQuestPriority failed: " + ex.Message); return false; } } public bool ClearQuestPriority() { TryEnsureAvailable(); if (!IsAvailable || clearQuestPrioritySubscriber == null) { return false; } try { bool result = clearQuestPrioritySubscriber.InvokeFunc(); log.Debug($"[QuestionableIPC] Cleared quest priority: {result}"); return result; } catch (Exception ex) { log.Error("[QuestionableIPC] ClearQuestPriority failed: " + ex.Message); return false; } } public bool IsQuestComplete(string questId) { TryEnsureAvailable(); if (!IsAvailable || isQuestCompleteSubscriber == null) { return false; } try { bool result = isQuestCompleteSubscriber.InvokeFunc(questId); log.Debug($"[QuestionableIPC] Quest {questId} complete: {result}"); return result; } catch (Exception ex) { log.Error("[QuestionableIPC] IsQuestComplete failed: " + ex.Message); return false; } } public bool IsReadyToAcceptQuest(string questId) { TryEnsureAvailable(); if (!IsAvailable || isReadyToAcceptQuestSubscriber == null) { return false; } try { bool result = isReadyToAcceptQuestSubscriber.InvokeFunc(questId); log.Debug($"[QuestionableIPC] Quest {questId} ready to accept: {result}"); return result; } catch (Exception ex) { log.Error("[QuestionableIPC] IsReadyToAcceptQuest failed: " + ex.Message); return false; } } public bool AddQuestsToQueue(List questIds) { TryEnsureAvailable(); if (!IsAvailable) { log.Warning("[QuestionableIPC] Cannot add quests to queue - Questionable not available"); return false; } if (questIds == null || questIds.Count == 0) { return true; } try { log.Information($"[QuestionableIPC] Adding {questIds.Count} quests to priority queue"); foreach (string questId in questIds) { if (!string.IsNullOrEmpty(questId)) { try { bool? result = addQuestPrioritySubscriber?.InvokeFunc(questId); log.Debug($"[QuestionableIPC] Added quest {questId} to queue: {result}"); } catch (Exception ex) { log.Warning("[QuestionableIPC] Failed to add quest " + questId + " to queue: " + ex.Message); } } } log.Information("[QuestionableIPC] All quests added to priority queue"); return true; } catch (Exception ex2) { log.Error("[QuestionableIPC] Error adding quests to queue: " + ex2.Message); return false; } } public List GetCurrentlyActiveEventQuests() { TryEnsureAvailable(); if (!IsAvailable || getCurrentlyActiveEventQuestsSubscriber == null) { log.Warning("[QuestionableIPC] Cannot get active event quests - Questionable not available"); return new List(); } try { List eventQuests = getCurrentlyActiveEventQuestsSubscriber.InvokeFunc(); log.Debug($"[QuestionableIPC] Retrieved {eventQuests?.Count ?? 0} active event quests"); return eventQuests ?? new List(); } catch (Exception ex) { log.Error("[QuestionableIPC] Error getting active event quests: " + ex.Message); return new List(); } } public int GetAlliedSocietyRemainingAllowances() { TryEnsureAvailable(); if (!IsAvailable || getAlliedSocietyRemainingAllowancesSubscriber == null) { log.Debug("[AlliedSociety] Cannot get remaining allowances - Questionable not available"); return 12; } try { int result = getAlliedSocietyRemainingAllowancesSubscriber.InvokeFunc(); log.Debug($"[AlliedSociety] Remaining allowances: {result}"); return result; } catch (Exception ex) { log.Error("[AlliedSociety] Error getting remaining allowances: " + ex.Message); return 12; } } public List GetAlliedSocietyAvailableQuestIds(byte societyId) { TryEnsureAvailable(); if (!IsAvailable || getAlliedSocietyAvailableQuestIdsSubscriber == null) { log.Debug($"[AlliedSociety] Cannot get quest IDs for society {societyId} - Questionable not available"); return new List(); } try { List result = getAlliedSocietyAvailableQuestIdsSubscriber.InvokeFunc(societyId); log.Debug($"[AlliedSociety] Society {societyId} has {result?.Count ?? 0} available quests"); return result ?? new List(); } catch (Exception ex) { log.Error($"[AlliedSociety] Error getting quest IDs for society {societyId}: {ex.Message}"); return new List(); } } public Dictionary GetAlliedSocietyAllAvailableQuestCounts() { TryEnsureAvailable(); if (!IsAvailable || getAlliedSocietyAllAvailableQuestCountsSubscriber == null) { log.Debug("[AlliedSociety] Cannot get quest counts - Questionable not available"); return new Dictionary(); } try { Dictionary result = getAlliedSocietyAllAvailableQuestCountsSubscriber.InvokeFunc(); log.Debug($"[AlliedSociety] Found {result?.Count ?? 0} societies with available quests"); return result ?? new Dictionary(); } catch (Exception ex) { log.Error("[AlliedSociety] Error getting quest counts: " + ex.Message); return new Dictionary(); } } public bool GetAlliedSocietyIsMaxRank(byte societyId) { TryEnsureAvailable(); if (!IsAvailable || getAlliedSocietyIsMaxRankSubscriber == null) { log.Debug($"[AlliedSociety] Cannot check max rank for society {societyId} - Questionable not available"); return false; } try { bool result = getAlliedSocietyIsMaxRankSubscriber.InvokeFunc(societyId); log.Debug($"[AlliedSociety] Society {societyId} max rank: {result}"); return result; } catch (Exception ex) { log.Error($"[AlliedSociety] Error checking max rank for society {societyId}: {ex.Message}"); return false; } } public int GetAlliedSocietyCurrentRank(byte societyId) { TryEnsureAvailable(); if (!IsAvailable || getAlliedSocietyCurrentRankSubscriber == null) { log.Debug($"[AlliedSociety] Cannot get rank for society {societyId} - Questionable not available"); return -1; } try { int result = getAlliedSocietyCurrentRankSubscriber.InvokeFunc(societyId); log.Debug($"[AlliedSociety] Society {societyId} current rank: {result}"); return result; } catch (Exception ex) { log.Error($"[AlliedSociety] Error getting rank for society {societyId}: {ex.Message}"); return -1; } } public List GetAlliedSocietiesWithAvailableQuests() { TryEnsureAvailable(); if (!IsAvailable || getAlliedSocietiesWithAvailableQuestsSubscriber == null) { log.Debug("[AlliedSociety] Cannot get societies with quests - Questionable not available"); return new List(); } try { List result = getAlliedSocietiesWithAvailableQuestsSubscriber.InvokeFunc(); log.Debug($"[AlliedSociety] Found {result?.Count ?? 0} societies with available quests"); return result ?? new List(); } catch (Exception ex) { log.Error("[AlliedSociety] Error getting societies with quests: " + ex.Message); return new List(); } } public int AddAlliedSocietyOptimalQuests(byte societyId) { TryEnsureAvailable(); if (!IsAvailable || addAlliedSocietyOptimalQuestsSubscriber == null) { log.Debug($"[AlliedSociety] Cannot add optimal quests for society {societyId} - Questionable not available"); return 0; } try { int result = addAlliedSocietyOptimalQuestsSubscriber.InvokeFunc(societyId); log.Information($"[AlliedSociety] Added {result} optimal quests for society {societyId}"); return result; } catch (Exception ex) { log.Error($"[AlliedSociety] Error adding optimal quests for society {societyId}: {ex.Message}"); return 0; } } public List GetAlliedSocietyOptimalQuests(byte societyId) { TryEnsureAvailable(); if (!IsAvailable || getAlliedSocietyOptimalQuestsSubscriber == null) { log.Debug($"[AlliedSociety] Cannot get optimal quests for society {societyId} - Questionable not available"); return new List(); } try { List result = getAlliedSocietyOptimalQuestsSubscriber.InvokeFunc(societyId); log.Debug($"[AlliedSociety] Found {result?.Count ?? 0} optimal quests for society {societyId}"); return result ?? new List(); } catch (Exception ex) { log.Error($"[AlliedSociety] Error getting optimal quests for society {societyId}: {ex.Message}"); return new List(); } } public TimeSpan GetAlliedSocietyTimeUntilReset() { TryEnsureAvailable(); if (!IsAvailable || getAlliedSocietyTimeUntilResetSubscriber == null) { log.Debug("[AlliedSociety] Cannot get time until reset - Questionable not available"); return TimeSpan.Zero; } try { TimeSpan timeSpan = TimeSpan.FromTicks(getAlliedSocietyTimeUntilResetSubscriber.InvokeFunc()); log.Debug($"[AlliedSociety] Time until reset: {timeSpan}"); return timeSpan; } catch (Exception ex) { log.Error("[AlliedSociety] Error getting time until reset: " + ex.Message); return TimeSpan.Zero; } } public bool GetStopConditionsEnabled() { TryEnsureAvailable(); if (!IsAvailable || getStopConditionsEnabledSubscriber == null) { log.Debug("[StopCondition] Cannot get stop conditions enabled - Questionable not available"); return false; } try { bool result = getStopConditionsEnabledSubscriber.InvokeFunc(); log.Debug($"[StopCondition] Stop conditions enabled: {result}"); return result; } catch (Exception ex) { log.Error("[StopCondition] Error getting stop conditions enabled: " + ex.Message); return false; } } public List GetStopQuestList() { TryEnsureAvailable(); if (!IsAvailable || getStopQuestListSubscriber == null) { return new List(); } try { List result = getStopQuestListSubscriber.InvokeFunc(); log.Debug($"[StopCondition] Found {result?.Count ?? 0} stop quests"); return result ?? new List(); } catch (Exception ex) { log.Error("[StopCondition] Error getting stop quest list: " + ex.Message); return new List(); } } public StopConditionData? GetLevelStopCondition() { TryEnsureAvailable(); if (!IsAvailable || getLevelStopConditionSubscriber == null) { log.Debug("[StopCondition] Cannot get level stop condition - Questionable not available"); return null; } try { return getLevelStopConditionSubscriber.InvokeFunc(); } catch (Exception ex) { log.Error("[StopCondition] Error getting level stop condition: " + ex.Message); return null; } } public StopConditionData? GetSequenceStopCondition() { TryEnsureAvailable(); if (!IsAvailable || getSequenceStopConditionSubscriber == null) { log.Debug("[StopCondition] Cannot get sequence stop condition - Questionable not available"); return null; } try { StopConditionData result = getSequenceStopConditionSubscriber.InvokeFunc(); log.Debug($"[StopCondition] Sequence stop condition - Enabled: {result?.Enabled}, Target: {result?.TargetValue}"); return result; } catch (Exception ex) { log.Error("[StopCondition] Error getting sequence stop condition: " + ex.Message); return null; } } public object? GetQuestSequenceStopCondition(string questId, uint sequence, int step) { TryEnsureAvailable(); if (!IsAvailable || getQuestSequenceStopConditionSubscriber == null) { log.Warning("[StopCondition] Cannot get quest sequence stop condition - Questionable not available"); return null; } try { object result = getQuestSequenceStopConditionSubscriber.InvokeFunc(questId, sequence, step); if (result == null) { log.Information($"[StopCondition] No quest sequence stop condition found for {questId} at {sequence}-{step}"); } else { log.Information($"[StopCondition] Quest sequence stop condition for {questId} at {sequence}-{step}: {result}"); } return result; } catch (Exception ex) { log.Error("[StopCondition] Error getting quest sequence stop condition: " + ex.Message); return null; } } public bool RemoveQuestSequenceStopCondition(string questId) { TryEnsureAvailable(); if (!IsAvailable || removeQuestSequenceStopConditionSubscriber == null) { log.Warning("[StopCondition] Cannot remove quest sequence stop condition - Questionable not available"); return false; } try { bool num = removeQuestSequenceStopConditionSubscriber.InvokeFunc(questId); if (num) { log.Information("[StopCondition] ✓ Removed quest sequence stop condition for " + questId); } else { log.Warning("[StopCondition] ✗ No quest sequence stop condition to remove for " + questId + " (or removal failed)"); } return num; } catch (Exception ex) { log.Error("[StopCondition] Error removing quest sequence stop condition: " + ex.Message); return false; } } public Dictionary GetAllQuestSequenceStopConditions() { TryEnsureAvailable(); if (!IsAvailable || getAllQuestSequenceStopConditionsSubscriber == null) { return new Dictionary(); } try { Dictionary result = getAllQuestSequenceStopConditionsSubscriber.InvokeFunc(); if (result == null || result.Count == 0) { log.Information("[StopCondition] No quest sequence stop conditions configured (empty or null result)"); return new Dictionary(); } log.Information($"[StopCondition] Found {result.Count} quest sequence stop condition(s)"); return result; } catch (Exception ex) { log.Error("[StopCondition] Error getting all quest sequence stop conditions: " + ex.Message); return new Dictionary(); } } public int GetDefaultDutyMode() { TryEnsureAvailable(); if (!IsAvailable || getDefaultDutyModeSubscriber == null) { log.Debug("[QuestionableIPC] Cannot get default duty mode - Questionable not available"); return 0; } try { int result = getDefaultDutyModeSubscriber.InvokeFunc(); log.Debug($"[QuestionableIPC] Default Duty Mode: {result}"); return result; } catch (Exception ex) { log.Error("[QuestionableIPC] GetDefaultDutyMode failed: " + ex.Message); return 0; } } public bool SetDefaultDutyMode(int dutyMode) { TryEnsureAvailable(); if (!IsAvailable || setDefaultDutyModeSubscriber == null) { log.Debug("[QuestionableIPC] Cannot set default duty mode - Questionable not available"); return false; } try { bool result = setDefaultDutyModeSubscriber.InvokeFunc(dutyMode); log.Information($"[QuestionableIPC] Set Default Duty Mode to {dutyMode}: {result}"); return result; } catch (Exception ex) { log.Error("[QuestionableIPC] SetDefaultDutyMode failed: " + ex.Message); return false; } } public bool ValidateFeatureCompatibility() { if (!IsAvailable) { return false; } try { if (getAllQuestSequenceStopConditionsSubscriber == null) { return false; } if (getLevelStopConditionSubscriber == null) { return false; } if (getAlliedSocietyOptimalQuestsSubscriber == null) { return false; } if (getDefaultDutyModeSubscriber == null) { return false; } try { getAllQuestSequenceStopConditionsSubscriber.InvokeFunc(); } catch { return false; } return true; } catch { return false; } } public void Dispose() { IsAvailable = false; } }