609 lines
19 KiB
C#
609 lines
19 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text.RegularExpressions;
|
|
using Dalamud.Game.ClientState.Conditions;
|
|
using Dalamud.Plugin.Services;
|
|
using FFXIVClientStructs.FFXIV.Client.Game;
|
|
using Newtonsoft.Json.Linq;
|
|
|
|
namespace QuestionableCompanion.Services;
|
|
|
|
public class EventQuestExecutionService : IDisposable
|
|
{
|
|
private readonly AutoRetainerIPC autoRetainerIpc;
|
|
|
|
private readonly QuestionableIPC questionableIPC;
|
|
|
|
private readonly IPluginLog log;
|
|
|
|
private readonly IFramework framework;
|
|
|
|
private readonly ICommandManager commandManager;
|
|
|
|
private readonly ICondition condition;
|
|
|
|
private readonly Configuration configuration;
|
|
|
|
private readonly EventQuestResolver eventQuestResolver;
|
|
|
|
private EventQuestState currentState = new EventQuestState();
|
|
|
|
private Dictionary<string, List<string>> eventQuestCompletionByCharacter = new Dictionary<string, List<string>>();
|
|
|
|
private DateTime lastCheckTime = DateTime.MinValue;
|
|
|
|
private const double CheckIntervalMs = 250.0;
|
|
|
|
private bool isRotationActive;
|
|
|
|
private string? lastTerritoryWaitDetected;
|
|
|
|
private DateTime lastTerritoryTeleportTime = DateTime.MinValue;
|
|
|
|
private Action? onDataChanged;
|
|
|
|
public bool IsRotationActive => isRotationActive;
|
|
|
|
public EventQuestExecutionService(AutoRetainerIPC autoRetainerIpc, QuestionableIPC questionableIPC, IPluginLog log, IFramework framework, ICommandManager commandManager, ICondition condition, Configuration configuration, IDataManager dataManager, Action? onDataChanged = null)
|
|
{
|
|
this.autoRetainerIpc = autoRetainerIpc;
|
|
this.questionableIPC = questionableIPC;
|
|
this.log = log;
|
|
this.framework = framework;
|
|
this.commandManager = commandManager;
|
|
this.condition = condition;
|
|
this.configuration = configuration;
|
|
this.onDataChanged = onDataChanged;
|
|
eventQuestResolver = new EventQuestResolver(dataManager, log);
|
|
framework.Update += OnFrameworkUpdate;
|
|
log.Information("[EventQuest] Service initialized");
|
|
}
|
|
|
|
public bool StartEventQuestRotation(string eventQuestId, List<string> characters)
|
|
{
|
|
if (characters == null || characters.Count == 0)
|
|
{
|
|
log.Error("[EventQuest] Cannot start rotation: No characters selected");
|
|
return false;
|
|
}
|
|
if (string.IsNullOrEmpty(eventQuestId))
|
|
{
|
|
log.Error("[EventQuest] Cannot start rotation: Event Quest ID is empty");
|
|
return false;
|
|
}
|
|
List<string> dependencies = eventQuestResolver.ResolveEventQuestDependencies(eventQuestId);
|
|
List<string> remainingChars = new List<string>();
|
|
List<string> completedChars = new List<string>();
|
|
foreach (string character in characters)
|
|
{
|
|
if (HasCharacterCompletedEventQuest(eventQuestId, character))
|
|
{
|
|
completedChars.Add(character);
|
|
log.Debug("[EventQuest] " + character + " already completed event quest " + eventQuestId);
|
|
}
|
|
else
|
|
{
|
|
remainingChars.Add(character);
|
|
log.Debug("[EventQuest] " + character + " needs to complete event quest " + eventQuestId);
|
|
}
|
|
}
|
|
if (remainingChars.Count == 0)
|
|
{
|
|
log.Information("[EventQuest] All characters have already completed event quest " + eventQuestId);
|
|
return false;
|
|
}
|
|
string currentLoggedInChar = autoRetainerIpc.GetCurrentCharacter();
|
|
bool isAlreadyLoggedIn = !string.IsNullOrEmpty(currentLoggedInChar) && remainingChars.Contains(currentLoggedInChar);
|
|
currentState = new EventQuestState
|
|
{
|
|
EventQuestId = eventQuestId,
|
|
EventQuestName = eventQuestResolver.GetQuestName(eventQuestId),
|
|
SelectedCharacters = new List<string>(characters),
|
|
RemainingCharacters = remainingChars,
|
|
CompletedCharacters = completedChars,
|
|
DependencyQuests = dependencies,
|
|
Phase = ((!isAlreadyLoggedIn) ? EventQuestPhase.InitializingFirstCharacter : EventQuestPhase.CheckingQuestCompletion),
|
|
CurrentCharacter = (isAlreadyLoggedIn ? currentLoggedInChar : ""),
|
|
PhaseStartTime = DateTime.Now,
|
|
RotationStartTime = DateTime.Now
|
|
};
|
|
isRotationActive = true;
|
|
log.Information("[EventQuest] ═══ Starting Event Quest Rotation ═══");
|
|
log.Information($"[EventQuest] Event Quest: {currentState.EventQuestName} ({eventQuestId})");
|
|
log.Information($"[EventQuest] Total Characters: {characters.Count}");
|
|
log.Information($"[EventQuest] Remaining: {remainingChars.Count} | Completed: {completedChars.Count}");
|
|
log.Information($"[EventQuest] Dependencies to resolve: {dependencies.Count}");
|
|
if (dependencies.Count > 0)
|
|
{
|
|
log.Information("[EventQuest] Prerequisites: " + string.Join(", ", dependencies.Select((string id) => eventQuestResolver.GetQuestName(id))));
|
|
}
|
|
if (isAlreadyLoggedIn)
|
|
{
|
|
log.Information("[EventQuest] User already logged in as " + currentLoggedInChar + " - starting immediately");
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public EventQuestState GetCurrentState()
|
|
{
|
|
return currentState;
|
|
}
|
|
|
|
public void LoadEventQuestCompletionData(Dictionary<string, List<string>> data)
|
|
{
|
|
if (data != null && data.Count > 0)
|
|
{
|
|
eventQuestCompletionByCharacter = new Dictionary<string, List<string>>(data);
|
|
log.Information($"[EventQuest] Loaded completion data for {data.Count} event quests");
|
|
}
|
|
}
|
|
|
|
public Dictionary<string, List<string>> GetEventQuestCompletionData()
|
|
{
|
|
return new Dictionary<string, List<string>>(eventQuestCompletionByCharacter);
|
|
}
|
|
|
|
public void AbortRotation()
|
|
{
|
|
log.Information("[EventQuest] Aborting Event Quest rotation");
|
|
currentState = new EventQuestState
|
|
{
|
|
Phase = EventQuestPhase.Idle
|
|
};
|
|
isRotationActive = false;
|
|
}
|
|
|
|
private void MarkEventQuestCompleted(string eventQuestId, string characterName)
|
|
{
|
|
if (!eventQuestCompletionByCharacter.ContainsKey(eventQuestId))
|
|
{
|
|
eventQuestCompletionByCharacter[eventQuestId] = new List<string>();
|
|
}
|
|
if (!eventQuestCompletionByCharacter[eventQuestId].Contains(characterName))
|
|
{
|
|
eventQuestCompletionByCharacter[eventQuestId].Add(characterName);
|
|
log.Debug("[EventQuest] Marked " + characterName + " as completed event quest " + eventQuestId);
|
|
onDataChanged?.Invoke();
|
|
}
|
|
}
|
|
|
|
private bool HasCharacterCompletedEventQuest(string eventQuestId, string characterName)
|
|
{
|
|
if (eventQuestCompletionByCharacter.TryGetValue(eventQuestId, out List<string> characters))
|
|
{
|
|
return characters.Contains(characterName);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private void OnFrameworkUpdate(IFramework framework)
|
|
{
|
|
if (!isRotationActive)
|
|
{
|
|
return;
|
|
}
|
|
DateTime now = DateTime.Now;
|
|
if (!((now - lastCheckTime).TotalMilliseconds < 250.0))
|
|
{
|
|
lastCheckTime = now;
|
|
CheckForTerritoryWait();
|
|
switch (currentState.Phase)
|
|
{
|
|
case EventQuestPhase.InitializingFirstCharacter:
|
|
HandleInitializingFirstCharacter();
|
|
break;
|
|
case EventQuestPhase.WaitingForCharacterLogin:
|
|
HandleWaitingForCharacterLogin();
|
|
break;
|
|
case EventQuestPhase.CheckingQuestCompletion:
|
|
HandleCheckingQuestCompletion();
|
|
break;
|
|
case EventQuestPhase.ResolvingDependencies:
|
|
HandleResolvingDependencies();
|
|
break;
|
|
case EventQuestPhase.ExecutingDependencies:
|
|
HandleExecutingDependencies();
|
|
break;
|
|
case EventQuestPhase.WaitingForQuestStart:
|
|
case EventQuestPhase.QuestActive:
|
|
HandleQuestMonitoring();
|
|
break;
|
|
case EventQuestPhase.WaitingBeforeCharacterSwitch:
|
|
HandleWaitingBeforeCharacterSwitch();
|
|
break;
|
|
case EventQuestPhase.Completed:
|
|
HandleCompleted();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void CheckForTerritoryWait()
|
|
{
|
|
if (!questionableIPC.IsRunning())
|
|
{
|
|
return;
|
|
}
|
|
object task = questionableIPC.GetCurrentTask();
|
|
if (task == null)
|
|
{
|
|
return;
|
|
}
|
|
try
|
|
{
|
|
if (!(task is JObject jObject))
|
|
{
|
|
return;
|
|
}
|
|
JToken taskNameToken = jObject["TaskName"];
|
|
if (taskNameToken == null)
|
|
{
|
|
return;
|
|
}
|
|
string taskName = taskNameToken.ToString();
|
|
if (string.IsNullOrEmpty(taskName))
|
|
{
|
|
return;
|
|
}
|
|
Match waitTerritoryMatch = new Regex("Wait\\(territory:\\s*(.+?)\\s*\\((\\d+)\\)\\)").Match(taskName);
|
|
if (!waitTerritoryMatch.Success)
|
|
{
|
|
return;
|
|
}
|
|
string territoryName = waitTerritoryMatch.Groups[1].Value.Trim();
|
|
uint territoryId = uint.Parse(waitTerritoryMatch.Groups[2].Value);
|
|
string territoryKey = $"{territoryName}_{territoryId}";
|
|
double timeSinceLastTeleport = (DateTime.Now - lastTerritoryTeleportTime).TotalSeconds;
|
|
if (lastTerritoryWaitDetected == territoryKey && timeSinceLastTeleport < 60.0)
|
|
{
|
|
return;
|
|
}
|
|
log.Information($"[EventQuest] Wait(territory) detected: {territoryName} (ID: {territoryId})");
|
|
log.Information("[EventQuest] Auto-teleporting via Lifestream...");
|
|
lastTerritoryWaitDetected = territoryKey;
|
|
lastTerritoryTeleportTime = DateTime.Now;
|
|
framework.RunOnFrameworkThread(delegate
|
|
{
|
|
try
|
|
{
|
|
string text = "/li " + territoryName;
|
|
commandManager.ProcessCommand(text);
|
|
log.Information("[EventQuest] Sent teleport command: " + text);
|
|
}
|
|
catch (Exception ex2)
|
|
{
|
|
log.Error("[EventQuest] Failed to teleport to " + territoryName + ": " + ex2.Message);
|
|
}
|
|
});
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
log.Error("[EventQuest] Error checking Wait(territory) task: " + ex.Message);
|
|
}
|
|
}
|
|
|
|
private void HandleInitializingFirstCharacter()
|
|
{
|
|
if (currentState.RemainingCharacters.Count == 0)
|
|
{
|
|
log.Information("[EventQuest] No remaining characters - rotation complete");
|
|
currentState.Phase = EventQuestPhase.Completed;
|
|
isRotationActive = false;
|
|
return;
|
|
}
|
|
string firstChar = currentState.RemainingCharacters[0];
|
|
currentState.CurrentCharacter = firstChar;
|
|
log.Information("[EventQuest] >>> Initializing first character: " + firstChar);
|
|
if (autoRetainerIpc.SwitchCharacter(firstChar))
|
|
{
|
|
currentState.Phase = EventQuestPhase.WaitingForCharacterLogin;
|
|
currentState.PhaseStartTime = DateTime.Now;
|
|
log.Information("[EventQuest] Character switch initiated to " + firstChar);
|
|
}
|
|
else
|
|
{
|
|
log.Error("[EventQuest] Failed to switch to " + firstChar);
|
|
currentState.Phase = EventQuestPhase.Error;
|
|
currentState.ErrorMessage = "Failed to switch to " + firstChar;
|
|
}
|
|
}
|
|
|
|
private void HandleWaitingForCharacterLogin()
|
|
{
|
|
if ((DateTime.Now - currentState.PhaseStartTime).TotalSeconds > 60.0)
|
|
{
|
|
log.Error("[EventQuest] Login timeout for " + currentState.CurrentCharacter);
|
|
SkipToNextCharacter();
|
|
return;
|
|
}
|
|
string currentLoggedInChar = autoRetainerIpc.GetCurrentCharacter();
|
|
if (!string.IsNullOrEmpty(currentLoggedInChar) && currentLoggedInChar == currentState.CurrentCharacter && !((DateTime.Now - currentState.PhaseStartTime).TotalSeconds < 5.0))
|
|
{
|
|
log.Information("[EventQuest] Successfully logged in as " + currentLoggedInChar);
|
|
currentState.Phase = EventQuestPhase.CheckingQuestCompletion;
|
|
currentState.PhaseStartTime = DateTime.Now;
|
|
}
|
|
}
|
|
|
|
private void HandleCheckingQuestCompletion()
|
|
{
|
|
string eventQuestId = currentState.EventQuestId;
|
|
string rawId = QuestIdParser.ParseQuestId(eventQuestId).rawId;
|
|
QuestIdType questType = QuestIdParser.ClassifyQuestId(eventQuestId);
|
|
log.Debug($"[EventQuest] Checking completion for {eventQuestId} (Type: {questType}, RawId: {rawId})");
|
|
if (!uint.TryParse(rawId, out var questIdUint))
|
|
{
|
|
log.Error($"[EventQuest] Invalid quest ID: {eventQuestId} (cannot parse numeric part: {rawId})");
|
|
SkipToNextCharacter();
|
|
return;
|
|
}
|
|
bool isQuestComplete = false;
|
|
try
|
|
{
|
|
isQuestComplete = QuestManager.IsQuestComplete(questIdUint);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
log.Error("[EventQuest] Error checking quest completion: " + ex.Message);
|
|
}
|
|
if (isQuestComplete)
|
|
{
|
|
log.Information("[EventQuest] " + currentState.CurrentCharacter + " already completed event quest " + eventQuestId);
|
|
List<string> completedList = currentState.CompletedCharacters;
|
|
if (!completedList.Contains(currentState.CurrentCharacter))
|
|
{
|
|
completedList.Add(currentState.CurrentCharacter);
|
|
currentState.CompletedCharacters = completedList;
|
|
}
|
|
MarkEventQuestCompleted(eventQuestId, currentState.CurrentCharacter);
|
|
SkipToNextCharacter();
|
|
}
|
|
else
|
|
{
|
|
log.Information("[EventQuest] " + currentState.CurrentCharacter + " needs to complete event quest " + eventQuestId);
|
|
log.Information($"[EventQuest] >>> Starting event quest with {currentState.DependencyQuests.Count} prerequisites");
|
|
StartEventQuest();
|
|
}
|
|
}
|
|
|
|
private void HandleResolvingDependencies()
|
|
{
|
|
log.Information("[EventQuest] All prerequisites completed - starting event quest");
|
|
StartEventQuest();
|
|
}
|
|
|
|
private void HandleExecutingDependencies()
|
|
{
|
|
string depQuestId = currentState.CurrentExecutingQuest;
|
|
if (!uint.TryParse(depQuestId, out var questIdUint))
|
|
{
|
|
log.Error("[EventQuest] Invalid dependency quest ID: " + depQuestId);
|
|
currentState.DependencyIndex++;
|
|
currentState.Phase = EventQuestPhase.ResolvingDependencies;
|
|
return;
|
|
}
|
|
bool isDependencyComplete = false;
|
|
try
|
|
{
|
|
isDependencyComplete = QuestManager.IsQuestComplete(questIdUint);
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
if (isDependencyComplete)
|
|
{
|
|
log.Information("[EventQuest] Dependency " + eventQuestResolver.GetQuestName(depQuestId) + " already completed");
|
|
currentState.DependencyIndex++;
|
|
currentState.Phase = EventQuestPhase.ResolvingDependencies;
|
|
return;
|
|
}
|
|
try
|
|
{
|
|
commandManager.ProcessCommand("/qst start");
|
|
log.Information("[EventQuest] Started dependency quest: " + eventQuestResolver.GetQuestName(depQuestId));
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
log.Error("[EventQuest] Failed to start dependency: " + ex.Message);
|
|
}
|
|
currentState.Phase = EventQuestPhase.QuestActive;
|
|
currentState.HasEventQuestBeenAccepted = false;
|
|
currentState.PhaseStartTime = DateTime.Now;
|
|
}
|
|
|
|
private void HandleQuestMonitoring()
|
|
{
|
|
string eventQuestId = currentState.EventQuestId;
|
|
try
|
|
{
|
|
if (questionableIPC.IsQuestComplete(eventQuestId))
|
|
{
|
|
log.Information("[EventQuest] Event quest " + eventQuestId + " completed by " + currentState.CurrentCharacter);
|
|
MarkEventQuestCompleted(currentState.EventQuestId, currentState.CurrentCharacter);
|
|
List<string> completedList = currentState.CompletedCharacters;
|
|
if (!completedList.Contains(currentState.CurrentCharacter))
|
|
{
|
|
completedList.Add(currentState.CurrentCharacter);
|
|
currentState.CompletedCharacters = completedList;
|
|
}
|
|
try
|
|
{
|
|
commandManager.ProcessCommand("/qst stop");
|
|
log.Information("[EventQuest] Sent /qst stop");
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
currentState.Phase = EventQuestPhase.WaitingBeforeCharacterSwitch;
|
|
currentState.PhaseStartTime = DateTime.Now;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
log.Error("[EventQuest] Error checking quest completion via IPC: " + ex.Message);
|
|
}
|
|
}
|
|
|
|
private void HandleWaitingBeforeCharacterSwitch()
|
|
{
|
|
if (!condition[ConditionFlag.BetweenAreas] && (DateTime.Now - currentState.PhaseStartTime).TotalSeconds >= 2.0)
|
|
{
|
|
PerformCharacterSwitch();
|
|
}
|
|
}
|
|
|
|
private void HandleCompleted()
|
|
{
|
|
log.Information("[EventQuest] ═══ EVENT QUEST ROTATION COMPLETED ═══");
|
|
log.Information($"[EventQuest] All {currentState.CompletedCharacters.Count} characters completed the event quest");
|
|
if (questionableIPC.IsAvailable)
|
|
{
|
|
try
|
|
{
|
|
questionableIPC.ClearQuestPriority();
|
|
log.Information("[EventQuest] Cleared quest priority queue after completion");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
log.Warning("[EventQuest] Failed to clear quest priority: " + ex.Message);
|
|
}
|
|
}
|
|
isRotationActive = false;
|
|
currentState.Phase = EventQuestPhase.Idle;
|
|
}
|
|
|
|
private void StartEventQuest()
|
|
{
|
|
List<string> allQuests = new List<string>();
|
|
if (currentState.DependencyQuests.Count > 0)
|
|
{
|
|
foreach (string dep in currentState.DependencyQuests)
|
|
{
|
|
allQuests.Add(dep);
|
|
QuestIdType questType = QuestIdParser.ClassifyQuestId(dep);
|
|
log.Information($"[EventQuest] Adding dependency: {dep} (Type: {questType})");
|
|
}
|
|
}
|
|
string mainQuestId = currentState.EventQuestId;
|
|
allQuests.Add(mainQuestId);
|
|
QuestIdType mainQuestType = QuestIdParser.ClassifyQuestId(mainQuestId);
|
|
log.Information($"[EventQuest] Adding main event quest: {mainQuestId} (Type: {mainQuestType})");
|
|
log.Information($"[EventQuest] Setting {allQuests.Count} quests as Questionable priority");
|
|
if (questionableIPC.IsAvailable)
|
|
{
|
|
try
|
|
{
|
|
questionableIPC.ClearQuestPriority();
|
|
log.Information("[EventQuest] Cleared existing quest priority queue");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
log.Warning("[EventQuest] Failed to clear quest priority: " + ex.Message);
|
|
}
|
|
foreach (string questId in allQuests)
|
|
{
|
|
try
|
|
{
|
|
bool result = questionableIPC.AddQuestPriority(questId);
|
|
log.Information($"[EventQuest] Added quest {questId} to priority: {result}");
|
|
}
|
|
catch (Exception ex2)
|
|
{
|
|
log.Warning("[EventQuest] Failed to add quest " + questId + " to priority: " + ex2.Message);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
log.Warning("[EventQuest] Questionable IPC not available - cannot set priority");
|
|
}
|
|
if (condition[ConditionFlag.BetweenAreas])
|
|
{
|
|
log.Debug("[EventQuest] Character is between areas - waiting before starting quest");
|
|
return;
|
|
}
|
|
if (questionableIPC.IsAvailable && questionableIPC.IsRunning())
|
|
{
|
|
log.Debug("[EventQuest] Questionable is busy - waiting before starting quest");
|
|
return;
|
|
}
|
|
try
|
|
{
|
|
commandManager.ProcessCommand("/qst start");
|
|
log.Information("[EventQuest] Sent /qst start for event quest");
|
|
currentState.Phase = EventQuestPhase.QuestActive;
|
|
currentState.CurrentExecutingQuest = currentState.EventQuestId;
|
|
currentState.HasEventQuestBeenAccepted = false;
|
|
currentState.PhaseStartTime = DateTime.Now;
|
|
}
|
|
catch (Exception ex3)
|
|
{
|
|
log.Error("[EventQuest] Failed to start quest: " + ex3.Message);
|
|
}
|
|
}
|
|
|
|
private void SkipToNextCharacter()
|
|
{
|
|
try
|
|
{
|
|
commandManager.ProcessCommand("/qst stop");
|
|
log.Information("[EventQuest] Sent /qst stop before character switch");
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
List<string> remainingList = currentState.RemainingCharacters;
|
|
List<string> completedList = currentState.CompletedCharacters;
|
|
if (remainingList.Contains(currentState.CurrentCharacter))
|
|
{
|
|
remainingList.Remove(currentState.CurrentCharacter);
|
|
currentState.RemainingCharacters = remainingList;
|
|
}
|
|
if (!completedList.Contains(currentState.CurrentCharacter))
|
|
{
|
|
completedList.Add(currentState.CurrentCharacter);
|
|
currentState.CompletedCharacters = completedList;
|
|
log.Information("[EventQuest] Character " + currentState.CurrentCharacter + " marked as completed (skipped)");
|
|
}
|
|
currentState.Phase = EventQuestPhase.WaitingBeforeCharacterSwitch;
|
|
currentState.PhaseStartTime = DateTime.Now;
|
|
}
|
|
|
|
private void PerformCharacterSwitch()
|
|
{
|
|
List<string> remainingList = currentState.RemainingCharacters;
|
|
if (remainingList.Contains(currentState.CurrentCharacter))
|
|
{
|
|
remainingList.Remove(currentState.CurrentCharacter);
|
|
currentState.RemainingCharacters = remainingList;
|
|
}
|
|
if (currentState.RemainingCharacters.Count == 0)
|
|
{
|
|
currentState.Phase = EventQuestPhase.Completed;
|
|
return;
|
|
}
|
|
string nextChar = currentState.RemainingCharacters[0];
|
|
currentState.CurrentCharacter = nextChar;
|
|
currentState.NextCharacter = nextChar;
|
|
log.Information("[EventQuest] Switching to next character: " + nextChar);
|
|
log.Information($"[EventQuest] Progress: {currentState.CompletedCharacters.Count}/{currentState.SelectedCharacters.Count} completed");
|
|
if (autoRetainerIpc.SwitchCharacter(nextChar))
|
|
{
|
|
currentState.Phase = EventQuestPhase.WaitingForCharacterLogin;
|
|
currentState.PhaseStartTime = DateTime.Now;
|
|
}
|
|
else
|
|
{
|
|
log.Error("[EventQuest] Failed to switch to " + nextChar);
|
|
currentState.Phase = EventQuestPhase.Error;
|
|
currentState.ErrorMessage = "Failed to switch character";
|
|
}
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
framework.Update -= OnFrameworkUpdate;
|
|
log.Information("[EventQuest] Service disposed");
|
|
}
|
|
}
|