qstcompanion v1.0.5
This commit is contained in:
parent
52daefcfd7
commit
5e1e1decc5
9 changed files with 304 additions and 200 deletions
|
|
@ -202,7 +202,7 @@ public class ChauffeurModeService : IDisposable
|
|||
return;
|
||||
}
|
||||
}
|
||||
if (clientState.LocalPlayer == null)
|
||||
if (objectTable.LocalPlayer == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
@ -266,7 +266,7 @@ public class ChauffeurModeService : IDisposable
|
|||
{
|
||||
return;
|
||||
}
|
||||
IPlayerCharacter localPlayer = clientState.LocalPlayer;
|
||||
IPlayerCharacter localPlayer = objectTable.LocalPlayer;
|
||||
if (localPlayer == null)
|
||||
{
|
||||
return;
|
||||
|
|
@ -574,7 +574,7 @@ public class ChauffeurModeService : IDisposable
|
|||
|
||||
private async void SummonHelper(Vector3 targetPos, uint zoneId)
|
||||
{
|
||||
IPlayerCharacter localPlayer = clientState.LocalPlayer;
|
||||
IPlayerCharacter localPlayer = objectTable.LocalPlayer;
|
||||
if (localPlayer == null)
|
||||
{
|
||||
return;
|
||||
|
|
@ -789,7 +789,7 @@ public class ChauffeurModeService : IDisposable
|
|||
this.questerName = $"{questerName}@{questerWorld}";
|
||||
targetZoneId = zoneId;
|
||||
targetPosition = targetPos;
|
||||
IPlayerCharacter localPlayer = clientState.LocalPlayer;
|
||||
IPlayerCharacter localPlayer = objectTable.LocalPlayer;
|
||||
if (localPlayer != null)
|
||||
{
|
||||
string myName = localPlayer.Name.ToString();
|
||||
|
|
@ -881,7 +881,7 @@ public class ChauffeurModeService : IDisposable
|
|||
{
|
||||
try
|
||||
{
|
||||
IPlayerCharacter localPlayer2 = clientState.LocalPlayer;
|
||||
IPlayerCharacter localPlayer2 = objectTable.LocalPlayer;
|
||||
if (localPlayer2 == null)
|
||||
{
|
||||
log.Error("[ChauffeurMode] [WORKFLOW] LocalPlayer is null!");
|
||||
|
|
@ -1180,7 +1180,7 @@ public class ChauffeurModeService : IDisposable
|
|||
{
|
||||
try
|
||||
{
|
||||
IPlayerCharacter localPlayer2 = clientState.LocalPlayer;
|
||||
IPlayerCharacter localPlayer2 = objectTable.LocalPlayer;
|
||||
if (localPlayer2 != null)
|
||||
{
|
||||
float result = Vector3.Distance(localPlayer2.Position, questerPos);
|
||||
|
|
@ -1271,7 +1271,7 @@ public class ChauffeurModeService : IDisposable
|
|||
log.Information("[ChauffeurMode] [HELPER] ========================================");
|
||||
log.Information($"[ChauffeurMode] [HELPER] Sending mount ready signal to: {questerName}@{questerWorld}");
|
||||
log.Information($"[ChauffeurMode] [HELPER] Helper is mounted: {IsMounted()}");
|
||||
log.Information($"[ChauffeurMode] [HELPER] Helper position: ({clientState.LocalPlayer?.Position.X:F2}, {clientState.LocalPlayer?.Position.Y:F2}, {clientState.LocalPlayer?.Position.Z:F2})");
|
||||
log.Information($"[ChauffeurMode] [HELPER] Helper position: ({objectTable.LocalPlayer?.Position.X:F2}, {objectTable.LocalPlayer?.Position.Y:F2}, {objectTable.LocalPlayer?.Position.Z:F2})");
|
||||
crossProcessIPC.SendChauffeurMountReady(questerName, questerWorld);
|
||||
log.Information("[ChauffeurMode] [HELPER] Mount ready signal sent via IPC");
|
||||
log.Information("[ChauffeurMode] [WORKFLOW] Waiting 8 seconds for quester to mount...");
|
||||
|
|
@ -1323,7 +1323,7 @@ public class ChauffeurModeService : IDisposable
|
|||
config.AssignedQuester = "";
|
||||
config.CurrentHelperStatus = HelperStatus.Available;
|
||||
config.Save();
|
||||
IPlayerCharacter localPlayer = clientState.LocalPlayer;
|
||||
IPlayerCharacter localPlayer = objectTable.LocalPlayer;
|
||||
if (localPlayer != null)
|
||||
{
|
||||
string helperName = localPlayer.Name.ToString();
|
||||
|
|
@ -1363,7 +1363,7 @@ public class ChauffeurModeService : IDisposable
|
|||
if (isAttuneAetheryteTask && targetPosition.HasValue)
|
||||
{
|
||||
log.Information("[ChauffeurMode] [HELPER] AttuneAetheryte detected - flying 10 yalms away from target before dismount");
|
||||
Vector3 direction = Vector3.Normalize(await framework.RunOnFrameworkThread(() => clientState.LocalPlayer?.Position ?? Vector3.Zero) - targetPosition.Value);
|
||||
Vector3 direction = Vector3.Normalize(await framework.RunOnFrameworkThread(() => objectTable.LocalPlayer?.Position ?? Vector3.Zero) - targetPosition.Value);
|
||||
Vector3 flyAwayPosition = targetPosition.Value + direction * 10f;
|
||||
log.Information($"[ChauffeurMode] [HELPER] Flying to position 10 yalms away: ({flyAwayPosition.X:F2}, {flyAwayPosition.Y:F2}, {flyAwayPosition.Z:F2})");
|
||||
await framework.RunOnFrameworkThread(delegate
|
||||
|
|
@ -1382,7 +1382,7 @@ public class ChauffeurModeService : IDisposable
|
|||
DateTime timeout = DateTime.Now.AddSeconds(10.0);
|
||||
while (DateTime.Now < timeout)
|
||||
{
|
||||
float distanceToTarget = Vector3.Distance(await framework.RunOnFrameworkThread(() => clientState.LocalPlayer?.Position ?? Vector3.Zero), targetPosition.Value);
|
||||
float distanceToTarget = Vector3.Distance(await framework.RunOnFrameworkThread(() => objectTable.LocalPlayer?.Position ?? Vector3.Zero), targetPosition.Value);
|
||||
if (distanceToTarget >= 10f)
|
||||
{
|
||||
log.Information($"[ChauffeurMode] [HELPER] Successfully flew away (distance: {distanceToTarget:F2} yalms)");
|
||||
|
|
@ -1535,7 +1535,7 @@ public class ChauffeurModeService : IDisposable
|
|||
{
|
||||
try
|
||||
{
|
||||
if (clientState.LocalPlayer == null)
|
||||
if (objectTable.LocalPlayer == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
@ -1621,7 +1621,7 @@ public class ChauffeurModeService : IDisposable
|
|||
{
|
||||
try
|
||||
{
|
||||
IPlayerCharacter localPlayer = clientState.LocalPlayer;
|
||||
IPlayerCharacter localPlayer = objectTable.LocalPlayer;
|
||||
posTask.SetResult(localPlayer?.Position);
|
||||
}
|
||||
catch (Exception ex2)
|
||||
|
|
@ -1737,7 +1737,7 @@ public class ChauffeurModeService : IDisposable
|
|||
{
|
||||
try
|
||||
{
|
||||
Vector3? result = clientState.LocalPlayer?.Position;
|
||||
Vector3? result = objectTable.LocalPlayer?.Position;
|
||||
helperStartPosTask.SetResult(result);
|
||||
}
|
||||
catch
|
||||
|
|
@ -1759,7 +1759,7 @@ public class ChauffeurModeService : IDisposable
|
|||
{
|
||||
try
|
||||
{
|
||||
Vector3? result = clientState.LocalPlayer?.Position;
|
||||
Vector3? result = objectTable.LocalPlayer?.Position;
|
||||
helperCurrentPosTask.SetResult(result);
|
||||
}
|
||||
catch
|
||||
|
|
@ -1868,7 +1868,7 @@ public class ChauffeurModeService : IDisposable
|
|||
{
|
||||
try
|
||||
{
|
||||
Vector3? result = clientState.LocalPlayer?.Position;
|
||||
Vector3? result = objectTable.LocalPlayer?.Position;
|
||||
posTask.SetResult(result);
|
||||
}
|
||||
catch
|
||||
|
|
@ -1965,7 +1965,7 @@ public class ChauffeurModeService : IDisposable
|
|||
log.Debug("[ChauffeurMode] [QUESTER] RidePillion already executed this session, ignoring");
|
||||
return;
|
||||
}
|
||||
IPlayerCharacter localPlayer = clientState.LocalPlayer;
|
||||
IPlayerCharacter localPlayer = objectTable.LocalPlayer;
|
||||
if (localPlayer == null)
|
||||
{
|
||||
return;
|
||||
|
|
@ -2046,7 +2046,7 @@ public class ChauffeurModeService : IDisposable
|
|||
{
|
||||
try
|
||||
{
|
||||
IPlayerCharacter localPlayer2 = clientState.LocalPlayer;
|
||||
IPlayerCharacter localPlayer2 = objectTable.LocalPlayer;
|
||||
if (localPlayer2 == null)
|
||||
{
|
||||
log.Error("[ChauffeurMode] [QUESTER] Local player is null");
|
||||
|
|
@ -2270,7 +2270,7 @@ public class ChauffeurModeService : IDisposable
|
|||
}
|
||||
return;
|
||||
}
|
||||
IPlayerCharacter localPlayer = clientState.LocalPlayer;
|
||||
IPlayerCharacter localPlayer = objectTable.LocalPlayer;
|
||||
if (localPlayer != null)
|
||||
{
|
||||
try
|
||||
|
|
@ -2312,7 +2312,7 @@ public class ChauffeurModeService : IDisposable
|
|||
{
|
||||
return;
|
||||
}
|
||||
IPlayerCharacter localPlayer = clientState.LocalPlayer;
|
||||
IPlayerCharacter localPlayer = objectTable.LocalPlayer;
|
||||
if (localPlayer == null)
|
||||
{
|
||||
return;
|
||||
|
|
@ -2428,7 +2428,7 @@ public class ChauffeurModeService : IDisposable
|
|||
if (config.IsQuester && !((DateTime.Now - lastZoneUpdate).TotalSeconds < 5.0))
|
||||
{
|
||||
lastZoneUpdate = DateTime.Now;
|
||||
IPlayerCharacter localPlayer = clientState.LocalPlayer;
|
||||
IPlayerCharacter localPlayer = objectTable.LocalPlayer;
|
||||
if (localPlayer != null)
|
||||
{
|
||||
string zoneName = GetZoneName(territoryId);
|
||||
|
|
@ -2493,7 +2493,7 @@ public class ChauffeurModeService : IDisposable
|
|||
config.AssignedQuester = "";
|
||||
config.CurrentHelperStatus = HelperStatus.Available;
|
||||
config.Save();
|
||||
IPlayerCharacter localPlayer = clientState.LocalPlayer;
|
||||
IPlayerCharacter localPlayer = objectTable.LocalPlayer;
|
||||
if (localPlayer != null)
|
||||
{
|
||||
string helperName = localPlayer.Name.ToString();
|
||||
|
|
@ -2533,7 +2533,7 @@ public class ChauffeurModeService : IDisposable
|
|||
config.CurrentHelperStatus = HelperStatus.Available;
|
||||
config.Save();
|
||||
log.Information("[ChauffeurMode] [HELPER] Status: Available");
|
||||
IPlayerCharacter localPlayer = clientState.LocalPlayer;
|
||||
IPlayerCharacter localPlayer = objectTable.LocalPlayer;
|
||||
if (localPlayer != null)
|
||||
{
|
||||
string helperName = localPlayer.Name.ToString();
|
||||
|
|
@ -2614,7 +2614,7 @@ public class ChauffeurModeService : IDisposable
|
|||
return;
|
||||
}
|
||||
lastFollowCheck = now;
|
||||
IPlayerCharacter localPlayer = clientState.LocalPlayer;
|
||||
IPlayerCharacter localPlayer = objectTable.LocalPlayer;
|
||||
if (localPlayer == null)
|
||||
{
|
||||
return;
|
||||
|
|
@ -2746,7 +2746,7 @@ public class ChauffeurModeService : IDisposable
|
|||
log.Information($"[ChauffeurMode] [HelperFollowing] Territory Load State: Zone load complete ({timeSinceZoneChange:F1}s) - resuming position broadcasts");
|
||||
lastZoneChangeTime = null;
|
||||
}
|
||||
IPlayerCharacter localPlayer = clientState.LocalPlayer;
|
||||
IPlayerCharacter localPlayer = objectTable.LocalPlayer;
|
||||
if (localPlayer != null)
|
||||
{
|
||||
string questerName = localPlayer.Name.ToString();
|
||||
|
|
@ -2791,7 +2791,7 @@ public class ChauffeurModeService : IDisposable
|
|||
{
|
||||
return null;
|
||||
}
|
||||
IPlayerCharacter localPlayer = clientState.LocalPlayer;
|
||||
IPlayerCharacter localPlayer = objectTable.LocalPlayer;
|
||||
if (localPlayer == null)
|
||||
{
|
||||
return null;
|
||||
|
|
|
|||
|
|
@ -267,7 +267,6 @@ public class AutoRetainerIPC : IDisposable
|
|||
{
|
||||
resolvedName = name2 + "@" + world2;
|
||||
characterCache[cid] = resolvedName;
|
||||
log.Debug($"[AutoRetainerIPC] CID {cid} resolved to {resolvedName} (via properties)");
|
||||
return resolvedName;
|
||||
}
|
||||
}
|
||||
|
|
@ -277,7 +276,6 @@ public class AutoRetainerIPC : IDisposable
|
|||
if (!string.IsNullOrEmpty(resolvedName))
|
||||
{
|
||||
characterCache[cid] = resolvedName;
|
||||
log.Debug($"[AutoRetainerIPC] CID {cid} resolved to {resolvedName} (via JSON)");
|
||||
return resolvedName;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,8 +55,6 @@ public class DungeonAutomationService : IDisposable
|
|||
|
||||
private bool isAutomationActive;
|
||||
|
||||
private int originalDutyMode;
|
||||
|
||||
private bool hasSentAtY;
|
||||
|
||||
public bool IsWaitingForParty => isWaitingForParty;
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ public class MSQProgressionService
|
|||
|
||||
private readonly QuestDetectionService questDetectionService;
|
||||
|
||||
private readonly IClientState clientState;
|
||||
private readonly IObjectTable objectTable;
|
||||
|
||||
private readonly IFramework framework;
|
||||
|
||||
|
|
@ -96,12 +96,12 @@ public class MSQProgressionService
|
|||
}
|
||||
};
|
||||
|
||||
public MSQProgressionService(IDataManager dataManager, IPluginLog log, QuestDetectionService questDetectionService, IClientState clientState, IFramework framework)
|
||||
public MSQProgressionService(IDataManager dataManager, IPluginLog log, QuestDetectionService questDetectionService, IObjectTable objectTable, IFramework framework)
|
||||
{
|
||||
this.dataManager = dataManager;
|
||||
this.log = log;
|
||||
this.questDetectionService = questDetectionService;
|
||||
this.clientState = clientState;
|
||||
this.objectTable = objectTable;
|
||||
this.framework = framework;
|
||||
InitializeMSQData();
|
||||
framework.RunOnTick(delegate
|
||||
|
|
@ -114,95 +114,68 @@ public class MSQProgressionService
|
|||
{
|
||||
try
|
||||
{
|
||||
log.Information("[MSQProgression] === INITIALIZING MSQ DATA ===");
|
||||
ExcelSheet<Quest> questSheet = dataManager.GetExcelSheet<Quest>();
|
||||
if (questSheet == null)
|
||||
{
|
||||
log.Error("[MSQProgression] Failed to load Quest sheet from Lumina!");
|
||||
return;
|
||||
}
|
||||
int totalQuests = questSheet.Count();
|
||||
log.Information($"[MSQProgression] ✓ Lumina Quest Sheet loaded: {totalQuests} total quests");
|
||||
questSheet.Count();
|
||||
int manualCount = 0;
|
||||
foreach (Quest item in questSheet)
|
||||
{
|
||||
_ = item;
|
||||
manualCount++;
|
||||
}
|
||||
log.Information($"[MSQProgression] Manual iteration count: {manualCount} quests");
|
||||
List<Quest> highIdQuests = questSheet.Where((Quest q) => q.RowId > 66000).ToList();
|
||||
log.Information($"[MSQProgression] Quests with RowId > 66000: {highIdQuests.Count}");
|
||||
if (highIdQuests.Count > 0)
|
||||
{
|
||||
Quest firstHighId = highIdQuests.First();
|
||||
log.Information($"[MSQProgression] First High ID Quest: {firstHighId.RowId}");
|
||||
log.Information($"[MSQProgression] - Name: {firstHighId.Name}");
|
||||
log.Information($"[MSQProgression] - Expansion.RowId: {firstHighId.Expansion.RowId}");
|
||||
log.Information($"[MSQProgression] - JournalGenre.RowId: {firstHighId.JournalGenre.RowId}");
|
||||
highIdQuests.First();
|
||||
}
|
||||
log.Information("[MSQProgression] Analyzing JournalGenre distribution...");
|
||||
foreach (IGrouping<uint, Quest> group in (from q in questSheet
|
||||
foreach (IGrouping<uint, Quest> item2 in (from q in questSheet
|
||||
where q.RowId != 0
|
||||
group q by q.JournalGenre.RowId into g
|
||||
orderby g.Key
|
||||
select g).Take(10))
|
||||
{
|
||||
log.Information($"[MSQProgression] Genre {group.Key}: {group.Count()} quests");
|
||||
_ = item2;
|
||||
}
|
||||
log.Information("[MSQProgression] Filtering MSQ quests by JournalGenre categories (1-14)...");
|
||||
mainScenarioQuests = (from q in questSheet
|
||||
where ((ReadOnlySpan<uint>)MSQ_JOURNAL_GENRE_IDS).Contains(q.JournalGenre.RowId)
|
||||
orderby q.RowId
|
||||
select q).ToList();
|
||||
log.Information($"[MSQProgression] ✓ Found {mainScenarioQuests.Count} total MSQ quests across all expansions!");
|
||||
if (mainScenarioQuests.Count == 0)
|
||||
{
|
||||
log.Error("[MSQProgression] No MSQ quests found! JournalGenre filter may be incorrect.");
|
||||
return;
|
||||
}
|
||||
log.Information("[MSQProgression] === DETAILED MSQ QUEST ANALYSIS (First 20) ===");
|
||||
foreach (Quest quest in mainScenarioQuests.Take(20))
|
||||
{
|
||||
log.Information($"[MSQProgression] Quest {quest.RowId}:");
|
||||
log.Information($"[MSQProgression] - Name: {quest.Name}");
|
||||
log.Information($"[MSQProgression] - Expansion.RowId: {quest.Expansion.RowId}");
|
||||
try
|
||||
{
|
||||
string expansionName = quest.Expansion.Value.Name.ToString();
|
||||
log.Information("[MSQProgression] - Expansion.Name: " + expansionName);
|
||||
quest.Expansion.Value.Name.ToString();
|
||||
}
|
||||
catch (Exception ex)
|
||||
catch (Exception)
|
||||
{
|
||||
log.Information("[MSQProgression] - Expansion.Name: ERROR - " + ex.Message);
|
||||
}
|
||||
log.Information($"[MSQProgression] - JournalGenre.RowId: {quest.JournalGenre.RowId}");
|
||||
}
|
||||
log.Information("[MSQProgression] === MSQ QUESTS BY JOURNALGENRE (EXPANSION) ===");
|
||||
foreach (IGrouping<uint, Quest> group2 in from q in mainScenarioQuests
|
||||
foreach (IGrouping<uint, Quest> group in from q in mainScenarioQuests
|
||||
group q by q.JournalGenre.RowId into g
|
||||
orderby g.Key
|
||||
select g)
|
||||
{
|
||||
uint genreId = group2.Key;
|
||||
MSQExpansionData.Expansion expansion = JournalGenreToExpansion.GetValueOrDefault(genreId, MSQExpansionData.Expansion.ARealmReborn);
|
||||
string genreName = group2.First().JournalGenre.Value.Name.ToString();
|
||||
string sampleQuests = string.Join(", ", from q in group2.Take(3)
|
||||
uint genreId = group.Key;
|
||||
JournalGenreToExpansion.GetValueOrDefault(genreId, MSQExpansionData.Expansion.ARealmReborn);
|
||||
group.First().JournalGenre.Value.Name.ToString();
|
||||
string.Join(", ", from q in @group.Take(3)
|
||||
select q.RowId);
|
||||
log.Information($"[MSQProgression] JournalGenre {genreId} ({expansion}):");
|
||||
log.Information("[MSQProgression] - Name: " + genreName);
|
||||
log.Information($"[MSQProgression] - Count: {group2.Count()} quests");
|
||||
log.Information("[MSQProgression] - Samples: " + sampleQuests + "...");
|
||||
}
|
||||
log.Information("[MSQProgression] === MSQ QUESTS BY EXPANSION (GROUPED) ===");
|
||||
foreach (IGrouping<MSQExpansionData.Expansion, Quest> group3 in from q in mainScenarioQuests
|
||||
foreach (IGrouping<MSQExpansionData.Expansion, Quest> item3 in from q in mainScenarioQuests
|
||||
group q by JournalGenreToExpansion.GetValueOrDefault(q.JournalGenre.RowId, MSQExpansionData.Expansion.ARealmReborn) into g
|
||||
orderby g.Key
|
||||
select g)
|
||||
{
|
||||
log.Information($"[MSQProgression] {group3.Key}: {group3.Count()} quests total");
|
||||
_ = item3;
|
||||
}
|
||||
MSQExpansionData.ClearQuests();
|
||||
log.Information("[MSQProgression] Building expansion quest mappings...");
|
||||
foreach (Quest quest2 in mainScenarioQuests)
|
||||
{
|
||||
string name = quest2.Name.ToString();
|
||||
|
|
@ -210,11 +183,11 @@ public class MSQProgressionService
|
|||
{
|
||||
questNameCache[quest2.RowId] = name;
|
||||
}
|
||||
MSQExpansionData.Expansion expansion2 = JournalGenreToExpansion.GetValueOrDefault(quest2.JournalGenre.RowId, MSQExpansionData.Expansion.ARealmReborn);
|
||||
MSQExpansionData.Expansion expansion = JournalGenreToExpansion.GetValueOrDefault(quest2.JournalGenre.RowId, MSQExpansionData.Expansion.ARealmReborn);
|
||||
if (quest2.JournalGenre.RowId != 2 || quest2.RowId <= 65964)
|
||||
{
|
||||
MSQExpansionData.RegisterQuest(quest2.RowId, expansion2);
|
||||
string shortName = MSQExpansionData.GetExpansionShortName(expansion2);
|
||||
MSQExpansionData.RegisterQuest(quest2.RowId, expansion);
|
||||
string shortName = MSQExpansionData.GetExpansionShortName(expansion);
|
||||
if (!questsByExpansion.ContainsKey(shortName))
|
||||
{
|
||||
questsByExpansion[shortName] = new List<Quest>();
|
||||
|
|
@ -222,29 +195,19 @@ public class MSQProgressionService
|
|||
questsByExpansion[shortName].Add(quest2);
|
||||
}
|
||||
}
|
||||
log.Information("[MSQProgression] === EXPANSION BREAKDOWN ===");
|
||||
foreach (MSQExpansionData.Expansion exp in MSQExpansionData.GetAllExpansions())
|
||||
foreach (MSQExpansionData.Expansion allExpansion in MSQExpansionData.GetAllExpansions())
|
||||
{
|
||||
string shortName2 = MSQExpansionData.GetExpansionShortName(exp);
|
||||
string shortName2 = MSQExpansionData.GetExpansionShortName(allExpansion);
|
||||
List<Quest> quests = questsByExpansion.GetValueOrDefault(shortName2);
|
||||
int count = quests?.Count ?? 0;
|
||||
if (count > 0 && quests != null)
|
||||
if ((quests?.Count ?? 0) > 0 && quests != null)
|
||||
{
|
||||
string sampleIds = string.Join(", ", from q in quests.Take(5)
|
||||
string.Join(", ", from q in quests.Take(5)
|
||||
select q.RowId);
|
||||
log.Information($"[MSQProgression] ✓ {MSQExpansionData.GetExpansionName(exp)} ({shortName2}): {count} quests (IDs: {sampleIds}...)");
|
||||
}
|
||||
else
|
||||
{
|
||||
log.Warning($"[MSQProgression] ⚠ {MSQExpansionData.GetExpansionName(exp)} ({shortName2}): {count} quests (EMPTY!)");
|
||||
}
|
||||
}
|
||||
log.Information("[MSQProgression] === MSQ DATA INITIALIZATION COMPLETE ===");
|
||||
}
|
||||
catch (Exception ex2)
|
||||
catch (Exception)
|
||||
{
|
||||
log.Error("[MSQProgression] EXCEPTION during MSQ data initialization: " + ex2.Message);
|
||||
log.Error("[MSQProgression] Stack trace: " + ex2.StackTrace);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -267,9 +230,8 @@ public class MSQProgressionService
|
|||
return (questId: lastMSQ.RowId, questName: questName);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
catch (Exception)
|
||||
{
|
||||
log.Error("[MSQProgression] Failed to get last completed MSQ: " + ex.Message);
|
||||
}
|
||||
return (questId: 0u, questName: "—");
|
||||
}
|
||||
|
|
@ -285,9 +247,8 @@ public class MSQProgressionService
|
|||
List<uint> completedQuests = questDetectionService.GetAllCompletedQuestIds();
|
||||
return (float)mainScenarioQuests.Count((Quest q) => completedQuests.Contains(q.RowId)) / (float)mainScenarioQuests.Count * 100f;
|
||||
}
|
||||
catch (Exception ex)
|
||||
catch (Exception)
|
||||
{
|
||||
log.Error("[MSQProgression] Failed to calculate MSQ completion: " + ex.Message);
|
||||
return 0f;
|
||||
}
|
||||
}
|
||||
|
|
@ -308,9 +269,8 @@ public class MSQProgressionService
|
|||
List<uint> completedQuests = questDetectionService.GetAllCompletedQuestIds();
|
||||
return mainScenarioQuests.Count((Quest q) => completedQuests.Contains(q.RowId));
|
||||
}
|
||||
catch (Exception ex)
|
||||
catch (Exception)
|
||||
{
|
||||
log.Error("[MSQProgression] Failed to get completed MSQ count: " + ex.Message);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -364,49 +324,25 @@ public class MSQProgressionService
|
|||
{
|
||||
try
|
||||
{
|
||||
log.Information("[MSQProgression] ========================================");
|
||||
log.Information("[MSQProgression] === DETECTING CURRENT EXPANSION ===");
|
||||
log.Information("[MSQProgression] ========================================");
|
||||
List<uint> completedQuests = questDetectionService.GetAllCompletedQuestIds();
|
||||
log.Information($"[MSQProgression] Total completed quests: {completedQuests.Count}");
|
||||
log.Information("[MSQProgression] METHOD 1: Using AgentScenarioTree (Game Data)");
|
||||
log.Information("[MSQProgression] ------------------------------------------------");
|
||||
(MSQExpansionData.Expansion expansion, string debugInfo) currentExpansionFromGameWithDebug = MSQExpansionData.GetCurrentExpansionFromGameWithDebug();
|
||||
MSQExpansionData.Expansion gameExpansion = currentExpansionFromGameWithDebug.expansion;
|
||||
string[] array = currentExpansionFromGameWithDebug.debugInfo.Split('\n');
|
||||
foreach (string line in array)
|
||||
for (int i = 0; i < array.Length; i++)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(line))
|
||||
{
|
||||
log.Information("[MSQProgression] " + line);
|
||||
}
|
||||
string.IsNullOrWhiteSpace(array[i]);
|
||||
}
|
||||
log.Information("[MSQProgression] Game Data Result: " + MSQExpansionData.GetExpansionName(gameExpansion));
|
||||
log.Information("[MSQProgression] METHOD 2: Using Completed Quests Analysis");
|
||||
log.Information("[MSQProgression] ------------------------------------------------");
|
||||
MSQExpansionData.Expansion analysisExpansion = MSQExpansionData.GetCurrentExpansion(completedQuests);
|
||||
log.Information("[MSQProgression] Analysis Result: " + MSQExpansionData.GetExpansionName(analysisExpansion));
|
||||
array = MSQExpansionData.GetExpansionDetectionDebugInfo(completedQuests).Split('\n');
|
||||
foreach (string line2 in array)
|
||||
for (int i = 0; i < array.Length; i++)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(line2))
|
||||
{
|
||||
log.Debug("[MSQProgression] " + line2);
|
||||
}
|
||||
string.IsNullOrWhiteSpace(array[i]);
|
||||
}
|
||||
log.Information("[MSQProgression] COMPARISON:");
|
||||
log.Information("[MSQProgression] Game Data: " + MSQExpansionData.GetExpansionName(gameExpansion));
|
||||
log.Information("[MSQProgression] Analysis: " + MSQExpansionData.GetExpansionName(analysisExpansion));
|
||||
MSQExpansionData.Expansion finalExpansion = gameExpansion;
|
||||
if (gameExpansion == MSQExpansionData.Expansion.ARealmReborn && analysisExpansion != MSQExpansionData.Expansion.ARealmReborn)
|
||||
{
|
||||
log.Warning("[MSQProgression] Game data returned ARR but analysis found higher expansion!");
|
||||
log.Warning("[MSQProgression] Using analysis result: " + MSQExpansionData.GetExpansionName(analysisExpansion));
|
||||
finalExpansion = analysisExpansion;
|
||||
}
|
||||
log.Information("[MSQProgression] ========================================");
|
||||
log.Information("[MSQProgression] >>> FINAL EXPANSION: " + MSQExpansionData.GetExpansionName(finalExpansion) + " <<<");
|
||||
log.Information("[MSQProgression] ========================================");
|
||||
return new ExpansionInfo
|
||||
{
|
||||
Name = MSQExpansionData.GetExpansionName(finalExpansion),
|
||||
|
|
@ -416,10 +352,8 @@ public class MSQProgressionService
|
|||
ExpectedQuestCount = MSQExpansionData.GetExpectedQuestCount(finalExpansion)
|
||||
};
|
||||
}
|
||||
catch (Exception ex)
|
||||
catch (Exception)
|
||||
{
|
||||
log.Error("[MSQProgression] Error detecting expansion: " + ex.Message);
|
||||
log.Error("[MSQProgression] Stack: " + ex.StackTrace);
|
||||
return GetExpansions().FirstOrDefault();
|
||||
}
|
||||
}
|
||||
|
|
@ -514,28 +448,23 @@ public class MSQProgressionService
|
|||
{
|
||||
try
|
||||
{
|
||||
log.Information("[MSQProgression] === DEBUG CURRENT CHARACTER QUEST ===");
|
||||
IPlayerCharacter player = clientState.LocalPlayer;
|
||||
IPlayerCharacter player = objectTable.LocalPlayer;
|
||||
if (player == null)
|
||||
{
|
||||
log.Warning("[MSQProgression] LocalPlayer is null - not logged in yet?");
|
||||
framework.RunOnTick(delegate
|
||||
{
|
||||
DebugCurrentCharacterQuest();
|
||||
}, default(TimeSpan), 60);
|
||||
return;
|
||||
}
|
||||
string characterName = player.Name.TextValue;
|
||||
string worldName = player.HomeWorld.Value.Name.ToString();
|
||||
log.Information("[MSQProgression] Character: " + characterName + " @ " + worldName);
|
||||
_ = player.Name.TextValue;
|
||||
player.HomeWorld.Value.Name.ToString();
|
||||
ExcelSheet<Quest> questSheet = dataManager.GetExcelSheet<Quest>();
|
||||
if (questSheet == null)
|
||||
{
|
||||
log.Error("[MSQProgression] Failed to load Quest sheet!");
|
||||
return;
|
||||
}
|
||||
List<Quest> completedMSQQuests = new List<Quest>();
|
||||
log.Information("[MSQProgression] Checking MSQ quest completion...");
|
||||
foreach (Quest quest in questSheet)
|
||||
{
|
||||
if (((ReadOnlySpan<uint>)MSQ_JOURNAL_GENRE_IDS).Contains(quest.JournalGenre.RowId) && QuestManager.IsQuestComplete((ushort)quest.RowId))
|
||||
|
|
@ -543,60 +472,39 @@ public class MSQProgressionService
|
|||
completedMSQQuests.Add(quest);
|
||||
}
|
||||
}
|
||||
log.Information($"[MSQProgression] Character has {completedMSQQuests.Count} completed MSQ quests");
|
||||
if (completedMSQQuests.Count == 0)
|
||||
{
|
||||
log.Warning("[MSQProgression] No completed MSQ quests found!");
|
||||
return;
|
||||
}
|
||||
Quest latestMSQQuest = completedMSQQuests.OrderByDescending((Quest quest2) => quest2.RowId).First();
|
||||
log.Information($"[MSQProgression] Latest completed MSQ quest ID: {latestMSQQuest.RowId}");
|
||||
Quest questData = latestMSQQuest;
|
||||
log.Information("[MSQProgression] === LATEST MSQ QUEST DETAILS ===");
|
||||
log.Information($"[MSQProgression] Quest ID: {questData.RowId}");
|
||||
log.Information($"[MSQProgression] Quest Name: {questData.Name}");
|
||||
log.Information($"[MSQProgression] JournalGenre.RowId: {questData.JournalGenre.RowId}");
|
||||
Quest questData = completedMSQQuests.OrderByDescending((Quest q) => q.RowId).First();
|
||||
try
|
||||
{
|
||||
string genreName = questData.JournalGenre.Value.Name.ToString();
|
||||
log.Information("[MSQProgression] JournalGenre.Name: " + genreName);
|
||||
questData.JournalGenre.Value.Name.ToString();
|
||||
}
|
||||
catch
|
||||
{
|
||||
log.Information("[MSQProgression] JournalGenre.Name: ERROR");
|
||||
}
|
||||
log.Information($"[MSQProgression] Expansion.RowId: {questData.Expansion.RowId}");
|
||||
try
|
||||
{
|
||||
string expansionName = questData.Expansion.Value.Name.ToString();
|
||||
log.Information("[MSQProgression] Expansion.Name: " + expansionName);
|
||||
questData.Expansion.Value.Name.ToString();
|
||||
}
|
||||
catch
|
||||
{
|
||||
log.Information("[MSQProgression] Expansion.Name: ERROR");
|
||||
}
|
||||
log.Information("[MSQProgression] === CHARACTER IS IN THIS EXPANSION ===");
|
||||
log.Information($"[MSQProgression] Character is at Quest {questData.RowId} which is in:");
|
||||
log.Information($"[MSQProgression] - JournalGenre: {questData.JournalGenre.RowId}");
|
||||
log.Information($"[MSQProgression] - Expansion: {questData.Expansion.RowId}");
|
||||
log.Information("[MSQProgression] === RECENT COMPLETED MSQ QUESTS (Last 10) ===");
|
||||
foreach (Quest q in completedMSQQuests.OrderByDescending((Quest quest2) => quest2.RowId).Take(10).ToList())
|
||||
foreach (Quest item in completedMSQQuests.OrderByDescending((Quest q) => q.RowId).Take(10).ToList())
|
||||
{
|
||||
log.Information($"[MSQProgression] Quest {q.RowId}: {q.Name} (Genre: {q.JournalGenre.RowId}, Exp: {q.Expansion.RowId})");
|
||||
_ = item;
|
||||
}
|
||||
log.Information("[MSQProgression] === COMPLETED MSQ QUESTS BY EXPANSION ===");
|
||||
foreach (IGrouping<MSQExpansionData.Expansion, Quest> group in from quest2 in completedMSQQuests
|
||||
group quest2 by JournalGenreToExpansion.GetValueOrDefault(quest2.JournalGenre.RowId, MSQExpansionData.Expansion.ARealmReborn) into g
|
||||
foreach (IGrouping<MSQExpansionData.Expansion, Quest> item2 in from q in completedMSQQuests
|
||||
group q by JournalGenreToExpansion.GetValueOrDefault(q.JournalGenre.RowId, MSQExpansionData.Expansion.ARealmReborn) into g
|
||||
orderby g.Key
|
||||
select g)
|
||||
{
|
||||
log.Information($"[MSQProgression] {group.Key}: {group.Count()} quests completed");
|
||||
_ = item2;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
catch (Exception)
|
||||
{
|
||||
log.Error("[MSQProgression] ERROR in DebugCurrentCharacterQuest: " + ex.Message);
|
||||
log.Error("[MSQProgression] Stack trace: " + ex.StackTrace);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,6 +48,8 @@ public class QuestRotationExecutionService : IDisposable
|
|||
|
||||
private StepsOfFaithHandler? stepsOfFaithHandler;
|
||||
|
||||
private ErrorRecoveryService? errorRecoveryService;
|
||||
|
||||
private readonly List<StopPoint> stopPoints = new List<StopPoint>();
|
||||
|
||||
private RotationState currentState = new RotationState();
|
||||
|
|
@ -64,10 +66,6 @@ public class QuestRotationExecutionService : IDisposable
|
|||
|
||||
private bool waitingForQuestAcceptForSubmarines;
|
||||
|
||||
private uint? lastDungeonQuestId;
|
||||
|
||||
private int? lastDungeonSequence;
|
||||
|
||||
private uint? lastSoloDutyQuestId;
|
||||
|
||||
private const double CharacterLoginTimeoutSeconds = 60.0;
|
||||
|
|
@ -480,6 +478,12 @@ public class QuestRotationExecutionService : IDisposable
|
|||
log.Information("[QuestRotation] Steps of Faith Handler service linked");
|
||||
}
|
||||
|
||||
public void SetErrorRecoveryService(ErrorRecoveryService service)
|
||||
{
|
||||
errorRecoveryService = service;
|
||||
log.Information("[QuestRotation] Error Recovery service linked");
|
||||
}
|
||||
|
||||
private void MarkQuestCompleted(uint questId, string characterName)
|
||||
{
|
||||
if (!questCompletionByCharacter.ContainsKey(questId))
|
||||
|
|
@ -626,6 +630,24 @@ public class QuestRotationExecutionService : IDisposable
|
|||
return;
|
||||
}
|
||||
lastCheckTime = now;
|
||||
if (isRotationActive && errorRecoveryService != null && errorRecoveryService.IsErrorDisconnect)
|
||||
{
|
||||
string charToRelog = errorRecoveryService.LastDisconnectedCharacter ?? currentState.CurrentCharacter;
|
||||
if (!string.IsNullOrEmpty(charToRelog))
|
||||
{
|
||||
log.Warning("[ErrorRecovery] Disconnect detected for " + charToRelog);
|
||||
log.Information("[ErrorRecovery] Automatically relogging to " + charToRelog + "...");
|
||||
errorRecoveryService.Reset();
|
||||
currentState.Phase = RotationPhase.WaitingForCharacterLogin;
|
||||
currentState.CurrentCharacter = charToRelog;
|
||||
currentState.PhaseStartTime = DateTime.Now;
|
||||
autoRetainerIpc.SwitchCharacter(charToRelog);
|
||||
log.Information("[ErrorRecovery] Relog initiated for " + charToRelog);
|
||||
return;
|
||||
}
|
||||
log.Warning("[ErrorRecovery] Disconnect detected but no character to relog to");
|
||||
errorRecoveryService.Reset();
|
||||
}
|
||||
if (deathHandler != null && combatDutyDetection != null && !combatDutyDetection.IsInDuty)
|
||||
{
|
||||
deathHandler.Update();
|
||||
|
|
@ -1037,7 +1059,19 @@ public class QuestRotationExecutionService : IDisposable
|
|||
private unsafe void HandleQuestMonitoring()
|
||||
{
|
||||
uint questId = currentState.CurrentStopQuestId;
|
||||
if (!submarineManager.IsSubmarinePaused && !submarineManager.IsSubmarineCooldownActive())
|
||||
bool hasReachedStopSequence = false;
|
||||
StopPoint stopPointForSubmarine = stopPoints.FirstOrDefault((StopPoint sp) => sp.QuestId == questId && sp.IsActive);
|
||||
if (stopPointForSubmarine != null && stopPointForSubmarine.Sequence.HasValue)
|
||||
{
|
||||
string currentQuestIdStr = questionableIPC.GetCurrentQuestId();
|
||||
byte? currentSequence = questionableIPC.GetCurrentSequence();
|
||||
if (!string.IsNullOrEmpty(currentQuestIdStr) && currentSequence.HasValue && uint.TryParse(currentQuestIdStr, out var currentQuestId) && currentQuestId == questId && currentSequence.Value >= stopPointForSubmarine.Sequence.Value)
|
||||
{
|
||||
hasReachedStopSequence = true;
|
||||
log.Debug($"[QuestRotation] Stop sequence reached (Quest {questId} Seq {currentSequence.Value} >= {stopPointForSubmarine.Sequence.Value}) - skipping submarine check");
|
||||
}
|
||||
}
|
||||
if (!hasReachedStopSequence && !submarineManager.IsSubmarinePaused && !submarineManager.IsSubmarineCooldownActive())
|
||||
{
|
||||
TimeSpan submarineCheckInterval = TimeSpan.FromSeconds(configuration.SubmarineCheckInterval);
|
||||
if (DateTime.Now - lastSubmarineCheckTime >= submarineCheckInterval)
|
||||
|
|
@ -1128,16 +1162,16 @@ public class QuestRotationExecutionService : IDisposable
|
|||
bool shouldRotate = false;
|
||||
if (activeStopPoint != null && activeStopPoint.Sequence.HasValue)
|
||||
{
|
||||
string currentQuestIdStr = questionableIPC.GetCurrentQuestId();
|
||||
byte? currentSequence = questionableIPC.GetCurrentSequence();
|
||||
if (!string.IsNullOrEmpty(currentQuestIdStr) && currentSequence.HasValue && uint.TryParse(currentQuestIdStr, out var currentQuestId))
|
||||
string currentQuestIdStr2 = questionableIPC.GetCurrentQuestId();
|
||||
byte? currentSequence2 = questionableIPC.GetCurrentSequence();
|
||||
if (!string.IsNullOrEmpty(currentQuestIdStr2) && currentSequence2.HasValue && uint.TryParse(currentQuestIdStr2, out var currentQuestId2))
|
||||
{
|
||||
if (currentQuestId == questId)
|
||||
if (currentQuestId2 == questId)
|
||||
{
|
||||
if (currentSequence.Value >= activeStopPoint.Sequence.Value)
|
||||
if (currentSequence2.Value >= activeStopPoint.Sequence.Value)
|
||||
{
|
||||
log.Information($"[QuestRotation] ✓ Quest {questId} Sequence {activeStopPoint.Sequence.Value} reached by {currentState.CurrentCharacter}!");
|
||||
log.Information($"[QuestRotation] Current Sequence: {currentSequence.Value} (reached {activeStopPoint.Sequence.Value})");
|
||||
log.Information($"[QuestRotation] Current Sequence: {currentSequence2.Value} (reached {activeStopPoint.Sequence.Value})");
|
||||
shouldRotate = true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using Dalamud.Plugin.Services;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
|
@ -228,7 +229,32 @@ public class SubmarineManager : IDisposable
|
|||
try
|
||||
{
|
||||
JObject json = JObject.Parse(jsonContent);
|
||||
FindReturnTimes(json, returnTimes);
|
||||
HashSet<string> enabledSubs = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||
if (json.SelectTokens("$..EnabledSubs").FirstOrDefault() is JArray enabledSubsArray)
|
||||
{
|
||||
foreach (JToken item in enabledSubsArray)
|
||||
{
|
||||
string subName = item.Value<string>();
|
||||
if (!string.IsNullOrEmpty(subName))
|
||||
{
|
||||
enabledSubs.Add(subName);
|
||||
}
|
||||
}
|
||||
if (enabledSubs.Count > 0)
|
||||
{
|
||||
log.Information($"[SubmarineManager] Found {enabledSubs.Count} enabled submarines: {string.Join(", ", enabledSubs)}");
|
||||
}
|
||||
else
|
||||
{
|
||||
log.Information("[SubmarineManager] EnabledSubs array found but empty - NO submarines will be checked");
|
||||
}
|
||||
FindReturnTimes(json, returnTimes, enabledSubs);
|
||||
}
|
||||
else
|
||||
{
|
||||
log.Information("[SubmarineManager] No EnabledSubs found in config - checking all submarines");
|
||||
FindReturnTimes(json, returnTimes);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
|
@ -244,21 +270,27 @@ public class SubmarineManager : IDisposable
|
|||
return returnTimes;
|
||||
}
|
||||
|
||||
private void FindReturnTimes(JToken token, List<long> returnTimes)
|
||||
private void FindReturnTimes(JToken token, List<long> returnTimes, HashSet<string>? enabledSubs = null)
|
||||
{
|
||||
if (token is JObject obj)
|
||||
{
|
||||
if (obj.TryGetValue("Name", out JToken nameToken) && obj.TryGetValue("ReturnTime", out JToken returnTimeToken))
|
||||
{
|
||||
string submarineName = nameToken.Value<string>();
|
||||
if ((enabledSubs == null || (submarineName != null && enabledSubs.Contains(submarineName))) && returnTimeToken.Type == JTokenType.Integer)
|
||||
{
|
||||
long returnTime = returnTimeToken.Value<long>();
|
||||
returnTimes.Add(returnTime);
|
||||
if (enabledSubs != null)
|
||||
{
|
||||
log.Debug($"[SubmarineManager] Including submarine '{submarineName}' (ReturnTime: {returnTime})");
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
foreach (JProperty property in obj.Properties())
|
||||
{
|
||||
if (property.Name == "ReturnTime" && property.Value.Type == JTokenType.Integer)
|
||||
{
|
||||
returnTimes.Add(property.Value.Value<long>());
|
||||
}
|
||||
else
|
||||
{
|
||||
FindReturnTimes(property.Value, returnTimes);
|
||||
}
|
||||
FindReturnTimes(property.Value, returnTimes, enabledSubs);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
|
@ -269,7 +301,7 @@ public class SubmarineManager : IDisposable
|
|||
}
|
||||
foreach (JToken item in array)
|
||||
{
|
||||
FindReturnTimes(item, returnTimes);
|
||||
FindReturnTimes(item, returnTimes, enabledSubs);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -50,6 +50,8 @@ public class NewMainWindow : Window, IDisposable
|
|||
|
||||
private readonly MSQProgressionService msqProgressionService;
|
||||
|
||||
private readonly Configuration configuration;
|
||||
|
||||
private readonly IPluginLog log;
|
||||
|
||||
private readonly IUiBuilder uiBuilder;
|
||||
|
|
@ -128,12 +130,6 @@ public class NewMainWindow : Window, IDisposable
|
|||
|
||||
private string selectedWorldFilter = "All";
|
||||
|
||||
private bool showWorldActionDropdown;
|
||||
|
||||
private uint inputStopQuestId;
|
||||
|
||||
private int inputStopSequence = -1;
|
||||
|
||||
private string selectedEventQuestId = "";
|
||||
|
||||
private List<(string QuestId, string QuestName)> availableEventQuests = new List<(string, string)>();
|
||||
|
|
@ -314,8 +310,8 @@ public class NewMainWindow : Window, IDisposable
|
|||
}
|
||||
}
|
||||
|
||||
public NewMainWindow(Plugin plugin, AutoRetainerIPC autoRetainerIpc, QuestTrackingService questTrackingService, QuestRotationExecutionService questRotationService, EventQuestExecutionService eventQuestService, AlliedSocietyRotationService alliedSocietyRotationService, AlliedSocietyPriorityWindow alliedSocietyPriorityWindow, DataCenterService dataCenterService, MSQProgressionService msqProgressionService, IPluginLog log, IUiBuilder uiBuilder, IDataManager dataManager)
|
||||
: base("Questionable Companion##NewMainWindow", ImGuiWindowFlags.NoTitleBar | ImGuiWindowFlags.NoScrollbar | ImGuiWindowFlags.NoScrollWithMouse | ImGuiWindowFlags.NoBackground)
|
||||
public NewMainWindow(Plugin plugin, AutoRetainerIPC autoRetainerIpc, QuestTrackingService questTrackingService, QuestRotationExecutionService questRotationService, EventQuestExecutionService eventQuestService, AlliedSocietyRotationService alliedSocietyRotationService, AlliedSocietyPriorityWindow alliedSocietyPriorityWindow, DataCenterService dataCenterService, MSQProgressionService msqProgressionService, Configuration configuration, IPluginLog log, IUiBuilder uiBuilder, IDataManager dataManager)
|
||||
: base("Questionable Companion##NewMainWindow", ImGuiWindowFlags.NoTitleBar | ImGuiWindowFlags.NoScrollbar | ImGuiWindowFlags.NoScrollWithMouse | ImGuiWindowFlags.NoCollapse | ImGuiWindowFlags.NoBackground)
|
||||
{
|
||||
this.plugin = plugin;
|
||||
this.autoRetainerIpc = autoRetainerIpc;
|
||||
|
|
@ -326,6 +322,7 @@ public class NewMainWindow : Window, IDisposable
|
|||
this.alliedSocietyPriorityWindow = alliedSocietyPriorityWindow;
|
||||
this.dataCenterService = dataCenterService;
|
||||
this.msqProgressionService = msqProgressionService;
|
||||
this.configuration = configuration;
|
||||
this.log = log;
|
||||
this.uiBuilder = uiBuilder;
|
||||
this.dataManager = dataManager;
|
||||
|
|
@ -431,7 +428,6 @@ public class NewMainWindow : Window, IDisposable
|
|||
if (registeredCharacters.Count > 0)
|
||||
{
|
||||
initialCharacterLoadComplete = true;
|
||||
log.Information("[NewMainWindow] ✅ Initial character load successful");
|
||||
}
|
||||
charactersByDataCenter = dataCenterService.GroupCharactersByDataCenter(registeredCharacters);
|
||||
availableWorlds = (from w in (from c in registeredCharacters
|
||||
|
|
@ -447,6 +443,13 @@ public class NewMainWindow : Window, IDisposable
|
|||
characterSelection[character] = false;
|
||||
}
|
||||
}
|
||||
foreach (string savedChar in configuration.SelectedCharactersForUI)
|
||||
{
|
||||
if (characterSelection.ContainsKey(savedChar))
|
||||
{
|
||||
characterSelection[savedChar] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
|
@ -613,7 +616,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.4");
|
||||
drawList.AddText(titlePos, ImGui.ColorConvertFloat4ToU32(new Vector4(1f, 1f, 1f, 0.9f)), "Questionable Companion V.1.0.5");
|
||||
Vector2 minimizeButtonPos = windowPos + new Vector2(windowSize.X - 60f, 3f);
|
||||
Vector2 minimizeButtonSize = new Vector2(24f, 24f);
|
||||
if (ImGui.IsMouseHoveringRect(minimizeButtonPos, minimizeButtonPos + minimizeButtonSize))
|
||||
|
|
@ -624,7 +627,22 @@ public class NewMainWindow : Window, IDisposable
|
|||
isMinimized = !isMinimized;
|
||||
}
|
||||
}
|
||||
drawList.AddText(minimizeButtonPos + new Vector2(8f, 2f), ImGui.ColorConvertFloat4ToU32(new Vector4(1f, 1f, 1f, 1f)), "_");
|
||||
uint arrowColor = ImGui.ColorConvertFloat4ToU32(new Vector4(1f, 1f, 1f, 1f));
|
||||
Vector2 arrowCenter = minimizeButtonPos + new Vector2(12f, 12f);
|
||||
if (isMinimized)
|
||||
{
|
||||
Vector2 p1 = arrowCenter + new Vector2(-4f, -5f);
|
||||
Vector2 p2 = arrowCenter + new Vector2(-4f, 5f);
|
||||
Vector2 p3 = arrowCenter + new Vector2(4f, 0f);
|
||||
drawList.AddTriangleFilled(p1, p2, p3, arrowColor);
|
||||
}
|
||||
else
|
||||
{
|
||||
Vector2 p4 = arrowCenter + new Vector2(-5f, -4f);
|
||||
Vector2 p5 = arrowCenter + new Vector2(5f, -4f);
|
||||
Vector2 p6 = arrowCenter + new Vector2(0f, 4f);
|
||||
drawList.AddTriangleFilled(p4, p5, p6, arrowColor);
|
||||
}
|
||||
Vector2 closeButtonPos = windowPos + new Vector2(windowSize.X - 30f, 3f);
|
||||
Vector2 closeButtonSize = new Vector2(24f, 24f);
|
||||
if (ImGui.IsMouseHoveringRect(closeButtonPos, closeButtonPos + closeButtonSize))
|
||||
|
|
@ -1909,6 +1927,10 @@ public class NewMainWindow : Window, IDisposable
|
|||
{
|
||||
characterSelection[character] = true;
|
||||
}
|
||||
configuration.SelectedCharactersForUI = (from kvp in characterSelection
|
||||
where kvp.Value
|
||||
select kvp.Key).ToList();
|
||||
configuration.Save();
|
||||
}
|
||||
ImGui.SameLine();
|
||||
if (ImGui.Button("Deselect All"))
|
||||
|
|
@ -1917,6 +1939,10 @@ public class NewMainWindow : Window, IDisposable
|
|||
{
|
||||
characterSelection[character2] = false;
|
||||
}
|
||||
configuration.SelectedCharactersForUI = (from kvp in characterSelection
|
||||
where kvp.Value
|
||||
select kvp.Key).ToList();
|
||||
configuration.Save();
|
||||
}
|
||||
ImGui.SameLine();
|
||||
ImGui.SetNextItemWidth(150f);
|
||||
|
|
@ -1967,6 +1993,10 @@ public class NewMainWindow : Window, IDisposable
|
|||
if (ImGui.Checkbox("##Select", ref isSelected))
|
||||
{
|
||||
characterSelection[character3] = isSelected;
|
||||
configuration.SelectedCharactersForUI = (from kvp in characterSelection
|
||||
where kvp.Value
|
||||
select kvp.Key).ToList();
|
||||
configuration.Save();
|
||||
}
|
||||
}
|
||||
ImGui.SetCursorScreenPos(cursorPos + new Vector2(40f, 8f));
|
||||
|
|
|
|||
|
|
@ -42,6 +42,8 @@ public class Configuration : IPluginConfiguration
|
|||
|
||||
public List<string> SelectedCharactersForRotation { get; set; } = new List<string>();
|
||||
|
||||
public List<string> SelectedCharactersForUI { get; set; } = new List<string>();
|
||||
|
||||
public Dictionary<uint, List<string>> QuestCompletionByCharacter { get; set; } = new Dictionary<uint, List<string>>();
|
||||
|
||||
public Dictionary<string, List<string>> EventQuestCompletionByCharacter { get; set; } = new Dictionary<string, List<string>>();
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
using System.Reflection;
|
||||
using Dalamud.Game.ClientState.Objects.SubKinds;
|
||||
using Dalamud.Game.Command;
|
||||
|
|
@ -126,6 +127,8 @@ public sealed class Plugin : IDalamudPlugin, IDisposable
|
|||
|
||||
private AlliedSocietyPriorityWindow AlliedSocietyPriorityWindow { get; init; }
|
||||
|
||||
private ErrorRecoveryService ErrorRecoveryService { get; init; }
|
||||
|
||||
private ConfigWindow ConfigWindow { get; init; }
|
||||
|
||||
private NewMainWindow NewMainWindow { get; init; }
|
||||
|
|
@ -182,7 +185,7 @@ public sealed class Plugin : IDalamudPlugin, IDisposable
|
|||
Log.Debug("[Plugin] Initializing StepsOfFaithHandler...");
|
||||
StepsOfFaithHandler = new StepsOfFaithHandler(Condition, Log, ClientState, CommandManager, Framework, Configuration);
|
||||
Log.Debug("[Plugin] Initializing MSQProgressionService...");
|
||||
MSQProgressionService = new MSQProgressionService(DataManager, Log, QuestDetection, ClientState, Framework);
|
||||
MSQProgressionService = new MSQProgressionService(DataManager, Log, QuestDetection, ObjectTable, Framework);
|
||||
Log.Debug("[Plugin] Initializing ChauffeurMode...");
|
||||
ChauffeurMode = new ChauffeurModeService(Configuration, Log, ClientState, Condition, Framework, CommandManager, DataManager, PartyList, ObjectTable, QuestionableIPC, CrossProcessIPC, PartyInviteService, PartyInviteAutoAccept, PluginInterface, MemoryHelper, MovementMonitor);
|
||||
MovementMonitor.SetChauffeurMode(ChauffeurMode);
|
||||
|
|
@ -194,6 +197,9 @@ public sealed class Plugin : IDalamudPlugin, IDisposable
|
|||
AlliedSocietyQuestSelector = new AlliedSocietyQuestSelector(QuestionableIPC, Log);
|
||||
AlliedSocietyRotationService = new AlliedSocietyRotationService(QuestionableIPC, AlliedSocietyDatabase, AlliedSocietyQuestSelector, AutoRetainerIPC, Configuration, Log, Framework, CommandManager, Condition, ClientState);
|
||||
AlliedSocietyPriorityWindow = new AlliedSocietyPriorityWindow(Configuration, AlliedSocietyDatabase);
|
||||
Log.Debug("[Plugin] Initializing Error Recovery Service...");
|
||||
ErrorRecoveryService = new ErrorRecoveryService(Log, GameInterop, ClientState, AutoRetainerIPC, Framework, GameGui);
|
||||
QuestRotationService.SetErrorRecoveryService(ErrorRecoveryService);
|
||||
MultiClientIPC.OnChatMessageReceived += OnMultiClientChatReceived;
|
||||
CrossProcessIPC.OnChatMessageReceived += OnMultiClientChatReceived;
|
||||
CrossProcessIPC.OnCommandReceived += OnCommandReceived;
|
||||
|
|
@ -218,7 +224,7 @@ public sealed class Plugin : IDalamudPlugin, IDisposable
|
|||
}
|
||||
Log.Debug("[Plugin] Initializing windows...");
|
||||
ConfigWindow = new ConfigWindow(this);
|
||||
NewMainWindow = new NewMainWindow(this, AutoRetainerIPC, QuestTrackingService, QuestRotationService, EventQuestService, AlliedSocietyRotationService, AlliedSocietyPriorityWindow, dataCenterService, MSQProgressionService, Log, PluginInterface.UiBuilder, DataManager);
|
||||
NewMainWindow = new NewMainWindow(this, AutoRetainerIPC, QuestTrackingService, QuestRotationService, EventQuestService, AlliedSocietyRotationService, AlliedSocietyPriorityWindow, dataCenterService, MSQProgressionService, Configuration, Log, PluginInterface.UiBuilder, DataManager);
|
||||
DebugWindow = new DebugWindow(this, CombatDutyDetection, DeathHandler, DungeonAutomation);
|
||||
WindowSystem.AddWindow(ConfigWindow);
|
||||
WindowSystem.AddWindow(NewMainWindow);
|
||||
|
|
@ -228,6 +234,14 @@ public sealed class Plugin : IDalamudPlugin, IDisposable
|
|||
{
|
||||
HelpMessage = "Open the Quest Sequence Manager"
|
||||
});
|
||||
string[] array = new string[2] { "/qstc", "/qstcompanion" };
|
||||
foreach (string alias in array)
|
||||
{
|
||||
CommandManager.AddHandler(alias, new CommandInfo(OnCommand)
|
||||
{
|
||||
HelpMessage = "Open the Quest Sequence Manager"
|
||||
});
|
||||
}
|
||||
CommandManager.AddHandler("/qsthelper", new CommandInfo(OnHelperCommand)
|
||||
{
|
||||
HelpMessage = "Helper commands: /qsthelper reset - Reset helper status to Available"
|
||||
|
|
@ -393,6 +407,7 @@ public sealed class Plugin : IDalamudPlugin, IDisposable
|
|||
LifestreamIPC?.Dispose();
|
||||
AutoRetainerIPC?.Dispose();
|
||||
QuestionableIPC?.Dispose();
|
||||
ErrorRecoveryService?.Dispose();
|
||||
Log.Debug("[Plugin] Services disposed");
|
||||
}
|
||||
catch (Exception ex3)
|
||||
|
|
@ -418,6 +433,11 @@ public sealed class Plugin : IDalamudPlugin, IDisposable
|
|||
{
|
||||
CommandManager.RemoveHandler("/qstcomp");
|
||||
CommandManager.RemoveHandler("/qsthelper");
|
||||
string[] array = new string[2] { "/qstc", "/qstcompanion" };
|
||||
foreach (string alias in array)
|
||||
{
|
||||
CommandManager.RemoveHandler(alias);
|
||||
}
|
||||
Log.Debug("[Plugin] Command handlers removed");
|
||||
}
|
||||
catch (Exception ex5)
|
||||
|
|
@ -487,6 +507,9 @@ public sealed class Plugin : IDalamudPlugin, IDisposable
|
|||
case "mounts":
|
||||
TestListMounts();
|
||||
break;
|
||||
case "aetheryte":
|
||||
TestFindNearestAetheryte();
|
||||
break;
|
||||
default:
|
||||
NewMainWindow.Toggle();
|
||||
break;
|
||||
|
|
@ -802,6 +825,85 @@ public sealed class Plugin : IDalamudPlugin, IDisposable
|
|||
Log.Information("========================================");
|
||||
}
|
||||
|
||||
private void TestFindNearestAetheryte()
|
||||
{
|
||||
Log.Information("========================================");
|
||||
Log.Information("[TEST] Finding Nearest Aetheryte (Map Data)");
|
||||
Log.Information("========================================");
|
||||
IPlayerCharacter player = ClientState.LocalPlayer;
|
||||
if (player == null)
|
||||
{
|
||||
Log.Error("[TEST] Player not logged in!");
|
||||
Log.Information("========================================");
|
||||
return;
|
||||
}
|
||||
Vector3 playerPos = player.Position;
|
||||
ushort territoryId = ClientState.TerritoryType;
|
||||
Log.Information($"[TEST] Player Position: ({playerPos.X:F2}, {playerPos.Y:F2}, {playerPos.Z:F2})");
|
||||
Log.Information($"[TEST] Territory ID: {territoryId}");
|
||||
ExcelSheet<Aetheryte> aetheryteSheet = DataManager.GetExcelSheet<Aetheryte>();
|
||||
ExcelSheet<Map> mapSheet = DataManager.GetExcelSheet<Map>();
|
||||
if (aetheryteSheet == null || mapSheet == null)
|
||||
{
|
||||
Log.Error("[TEST] Failed to load sheets!");
|
||||
Log.Information("========================================");
|
||||
return;
|
||||
}
|
||||
float minDistance = float.MaxValue;
|
||||
string nearestName = "Unknown";
|
||||
uint nearestId = 0u;
|
||||
int aetheryteCount = 0;
|
||||
foreach (Aetheryte aetheryte in aetheryteSheet)
|
||||
{
|
||||
if (aetheryte.Territory.RowId != territoryId || !aetheryte.IsAetheryte)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
aetheryteCount++;
|
||||
PlaceName? placeName = aetheryte.PlaceName.ValueNullable;
|
||||
string nameStr = (placeName.HasValue ? placeName.Value.Name.ExtractText() : $"Aetheryte #{aetheryte.RowId}");
|
||||
Map? map = aetheryte.Map.ValueNullable;
|
||||
if (map.HasValue)
|
||||
{
|
||||
float mapX = ConvertMapCoordinateToRawPosition(aetheryte.AetherstreamX, map.Value.SizeFactor);
|
||||
float mapY = ConvertMapCoordinateToRawPosition(aetheryte.AetherstreamY, map.Value.SizeFactor);
|
||||
Vector3 aethPos = new Vector3(mapX, 0f, mapY);
|
||||
float num = playerPos.X - aethPos.X;
|
||||
float dz = playerPos.Z - aethPos.Z;
|
||||
float distance = (float)Math.Sqrt(num * num + dz * dz);
|
||||
Log.Information($"[TEST] Aetheryte #{aetheryteCount}: {nameStr}");
|
||||
Log.Information($"[TEST] Position: ({aethPos.X:F2}, ?, {aethPos.Z:F2})");
|
||||
Log.Information($"[TEST] Distance (2D): {distance:F2} yalms");
|
||||
Log.Information($"[TEST] Aetheryte ID: {aetheryte.RowId}");
|
||||
if (distance < minDistance)
|
||||
{
|
||||
minDistance = distance;
|
||||
nearestName = nameStr;
|
||||
nearestId = aetheryte.RowId;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (aetheryteCount == 0)
|
||||
{
|
||||
Log.Warning("[TEST] No aetherytes found in this territory!");
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Information("========================================");
|
||||
Log.Information("[TEST] NEAREST AETHERYTE: " + nearestName);
|
||||
Log.Information($"[TEST] Distance (2D): {minDistance:F2} yalms");
|
||||
Log.Information($"[TEST] Aetheryte ID: {nearestId}");
|
||||
Log.Information("========================================");
|
||||
}
|
||||
Log.Information("========================================");
|
||||
}
|
||||
|
||||
private float ConvertMapCoordinateToRawPosition(int coordinate, ushort scale)
|
||||
{
|
||||
float c = (float)(int)scale / 100f;
|
||||
return ((((float)coordinate - 1024f) / 2048f + 1f) * c / 2f - 1f) * (2048f / c) * 1000f / 2048f;
|
||||
}
|
||||
|
||||
private void TestAlliedSociety()
|
||||
{
|
||||
Log.Information("========================================");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue