diff --git a/FFXIVClientStructs/FFXIV/Client/Game/WKS/WKSManager.cs b/FFXIVClientStructs/FFXIV/Client/Game/WKS/WKSManager.cs
index 97b79fbd9..fda02e598 100644
--- a/FFXIVClientStructs/FFXIV/Client/Game/WKS/WKSManager.cs
+++ b/FFXIVClientStructs/FFXIV/Client/Game/WKS/WKSManager.cs
@@ -13,6 +13,8 @@ public unsafe partial struct WKSManager {
public static partial WKSManager* Instance();
[FieldOffset(0x18)] public ushort TerritoryId;
+ /// Set to 1 when WKS territory loads; cleared on unload. Checked by .
+ [FieldOffset(0x1A)] public bool IsLoaded;
[FieldOffset(0x50)] public WKSState State;
@@ -54,6 +56,12 @@ public unsafe partial struct WKSManager {
[FieldOffset(0x1150)] private void* UnkStruct1150;
[FieldOffset(0x1158)] public StdVector> Modules;
+ [MemberFunction("48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 57 48 83 EC 20 0F B7 DA 48 8B F9 E8 ?? ?? ?? ?? 8B CB")]
+ public partial void Load(ushort territoryId);
+
+ [MemberFunction("E8 ?? ?? ?? ?? 0F B6 F8 49 8B 4E")]
+ public partial bool IsFunctionUnlocked(byte functionRowId);
+
public bool IsMissionCompleted(uint missionUnitId) => State.MissionCompletionFlags.CheckBitInSpan(missionUnitId);
public bool IsMissionGolded(uint missionUnitId) => State.MissionGoldFlags.CheckBitInSpan(missionUnitId);
@@ -66,17 +74,52 @@ public enum MissionRank {
Failed = 5,
}
+ [StructLayout(LayoutKind.Explicit, Size = 0xC)]
+ public struct WKSMissionState {
+ [FieldOffset(0x00)] public ushort MissionUnitId;
+ /// Used by AgentWKSMission to set silver/gold mission flags when this is 1 or 2.
+ [FieldOffset(0x04)] public uint MissionFlag;
+ [FieldOffset(0x08)] private ushort Unk8;
+ [FieldOffset(0x0A)] public byte Condition; // Needs more testing, but was set to 1 when Critical Mission was abandoned. Could be a bool for showing locked out status?
+ }
+
+ /// Per-job state block. WKSState contains 11 of these (one per cosmic class job).
+ [StructLayout(LayoutKind.Explicit, Size = 0x148)]
+ public struct WKSJobState {
+ [FieldOffset(0xB0)] public WKSMissionState ExtraBasicMission; // This held a single extra A-rank mission entry. Emitted by AgentWKSMission.GetBasicMissions. Purpose yet unclear.
+ [FieldOffset(0xC0)] public StdVector SequentialMissions;
+ [FieldOffset(0xD8)] public StdVector ProvisionalMissions;
+ [FieldOffset(0xF0)] public StdVector CriticalMissions;
+ [FieldOffset(0x108)] public uint CriticalMissionData; // All jobs with currently open critical missions hold the same value. (e.g. 1779307018). Purpose yet unclear.
+ }
+
[GenerateInterop]
[StructLayout(LayoutKind.Explicit, Size = 0x1088)]
public partial struct WKSState {
- /// RowId of WKSDevGrade sheet.
+ [FieldOffset(0x00)] private ushort Unk00;
+ [FieldOffset(0x04)] private byte Unk04;
+ [FieldOffset(0x08)] private ushort Unk08;
+
+ /// RowId of WKSDevGrade sheet.
[FieldOffset(0x0A)] public ushort DevGrade;
- /// For Hub upgrades. RowId of WKSFateControl sheet.
+ [FieldOffset(0x0C)] private uint Unk0C;
+
+ /// For Hub upgrades. RowId of WKSFateControl sheet.
[FieldOffset(0x10)] public ushort CurrentFateControlRowId;
- /// For Hub upgrades. Id of Fate in FateManager.
+ /// For Hub upgrades. Id of Fate in FateManager.
[FieldOffset(0x12)] public ushort CurrentFateId;
+ [FieldOffset(0x14)] private byte Unk14; // Seems like some state flags which are checked in IsFunctionUnlocked. Bit 0 seems like "hub is built/active"
+
+ /// 0-based WKSPioneeringTrail row index for the currently visited planet (sheet row = this + 1).
+ [FieldOffset(0x15)] public byte CurrentPlanetIndex; // Full row is highest subrow where WKSPioneeringTrail[row][sub].ActivationStage <= WKSState.DevGrade
+
+ /// 0-based WKSPioneeringTrail row index for the latest unlocked planet. (sheet row = this + 1)
+ [FieldOffset(0x16)] public byte LatestPlanetIndex;
+
+ [FieldOffset(0x18), FixedSizeArray] internal FixedSizeArray11 _jobStates;
+
/// RowId of WKSMissionUnit sheet.
[FieldOffset(0xE30)] public ushort CurrentMissionUnitRowId;
diff --git a/FFXIVClientStructs/FFXIV/Client/UI/Agent/AgentWKSMission.cs b/FFXIVClientStructs/FFXIV/Client/UI/Agent/AgentWKSMission.cs
index 4e682cce6..5f23c7c23 100644
--- a/FFXIVClientStructs/FFXIV/Client/UI/Agent/AgentWKSMission.cs
+++ b/FFXIVClientStructs/FFXIV/Client/UI/Agent/AgentWKSMission.cs
@@ -11,7 +11,9 @@ public unsafe partial struct AgentWKSMission {
[FieldOffset(0x28)] public MissionData* Data;
[FieldOffset(0x30)] public uint SelectedEntry;
[FieldOffset(0x34)] public byte SelectedTab;
+ [FieldOffset(0x35)] private bool HasSavedTab;
[FieldOffset(0x38)] public Utf8String MapTitle;
+ [FieldOffset(0xA0)] private bool BypassItemLevelCheck; // Wild guess as no low level gatherer/crafter was available. Gets set if ReceiveVent EventKind is 3. See MissionData.StartStep
[MemberFunction("40 53 48 83 EC ?? 8B DA E8 ?? ?? ?? ?? 48 85 C0 74 ?? E8 ?? ?? ?? ?? 48 83 B8 ?? ?? ?? ?? ?? 74 ?? E8 ?? ?? ?? ?? 0F B7 D3")]
public partial void StartMission(ushort missionUnitId);
@@ -25,6 +27,9 @@ public unsafe partial struct AgentWKSMission {
[MemberFunction("E8 ?? ?? ?? ?? EB ?? 48 81 C2")]
public partial bool GetProvisionalMissions(StdVector* list);
+ [MemberFunction("48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 57 41 54 41 55 41 56 41 57 48 83 EC ?? 48 8B EA E8")]
+ public partial bool GetCriticalMissions(StdVector* list);
+
[MemberFunction("E8 ?? ?? ?? ?? E9 ?? ?? ?? ?? 0F B6 4A ?? 85 C9")]
public partial bool GetMissionLog(StdVector* list);
@@ -33,6 +38,8 @@ public struct MissionData {
[FieldOffset(0x01)] public byte SelectedJobIndex;
[FieldOffset(0x02)] public byte SelectedTabIndex;
[FieldOffset(0x03)] public byte SelectedFilterIndex;
+ [FieldOffset(0x04)] private byte StartStep; // This gets set if ReceiveVent EventKind is 3 and somewho involved with ControlFlags and missions average item level
+ [FieldOffset(0x05)] public bool IsMissionLog;
[FieldOffset(0x08)] public uint SelectedMissionUnitId;
[FieldOffset(0x0C)] public MissionFlags SelectedMissionFlags;
@@ -46,7 +53,9 @@ public struct MissionData {
[FieldOffset(0x90)] public Utf8String ItemLevelWarningText;
[FieldOffset(0xF8)] public StdVector MissionList;
+ [FieldOffset(0x115)] private byte MissionLogTabIndex; // used instead of SelectedTabIndex when IsMissionLog is set
[FieldOffset(0x118)] public byte UpdateFlags;
+ [FieldOffset(0x119)] private byte ControlFlags; // Bit 2 gets set when Addon closes
}
[StructLayout(LayoutKind.Explicit, Size = 0x20)]
@@ -54,7 +63,7 @@ public struct MissionEntry {
[FieldOffset(0x00)] public uint MissionUnitId;
[FieldOffset(0x04)] public uint IconId;
- [FieldOffset(0x14)] public MissionFlags Flags; // maybe byte?
+ [FieldOffset(0x14)] public MissionFlags Flags;
///
/// 1,2,3,4 = D,C,B,A (LevelGroup)
/// 12 = Weather-restricted
@@ -63,6 +72,8 @@ public struct MissionEntry {
/// 15 = Critical (IsSpecialQuest)
///
[FieldOffset(0x18)] public byte MissionGroup;
+ /// ClassJob index derived from WKSMissionUnit.ClassJobCategory.
+ [FieldOffset(0x19)] public byte ClassJobIndex;
}
[Flags]
@@ -73,6 +84,8 @@ public enum MissionFlags {
Silver = 1 << 2,
Gold = 1 << 3,
WeatherRestricted = 1 << 4,
- Locked = 1 << 5
+ Locked = 1 << 5,
+ //WeatherActive = 1 << 7, // Couldn't check enough due to large timespans between missions
+ //CurrentlyActive = 1 << 11, // Couldn't check enough due to large timespans between missions
}
}
diff --git a/FFXIVClientStructs/FFXIV/Client/UI/Agent/AgentWKSMissionInfomation.cs b/FFXIVClientStructs/FFXIV/Client/UI/Agent/AgentWKSMissionInfomation.cs
index db300c672..7e949768b 100644
--- a/FFXIVClientStructs/FFXIV/Client/UI/Agent/AgentWKSMissionInfomation.cs
+++ b/FFXIVClientStructs/FFXIV/Client/UI/Agent/AgentWKSMissionInfomation.cs
@@ -14,6 +14,7 @@ public unsafe partial struct AgentWKSMissionInfomation {
[StructLayout(LayoutKind.Explicit, Size = 0x18)]
public struct MissionInfo {
[FieldOffset(0x00)] public long ServerTime;
+ [FieldOffset(0x08)] public uint AddonId; // AbandonAddon
[FieldOffset(0x0C)] public uint CurrentMissionUnitId;
[FieldOffset(0x10)] public byte State;
[FieldOffset(0x14)] public byte Flags;