diff --git a/FFXIVClientStructs/FFXIV/Client/Game/InstanceContent/ContentDirector.cs b/FFXIVClientStructs/FFXIV/Client/Game/InstanceContent/ContentDirector.cs
index 6d9537cb2b..f66fdc2ca4 100644
--- a/FFXIVClientStructs/FFXIV/Client/Game/InstanceContent/ContentDirector.cs
+++ b/FFXIVClientStructs/FFXIV/Client/Game/InstanceContent/ContentDirector.cs
@@ -15,11 +15,14 @@ public unsafe partial struct ContentDirector {
[FieldOffset(0x528)] public DutyActionManager DutyActionManager;
+ [FieldOffset(0xC88)] public Utf8String* InstanceContentTexts;
[FieldOffset(0xC90)] public MapEffectList* MapEffects;
[FieldOffset(0xC98)] private DynamicEventContainer* DynamicEvents;
/// This might also be a countdown until the content starts (e.g. Frontlines), then the actual time left of the content.
[FieldOffset(0xCF0)] public float ContentTimeLeft;
+ [FieldOffset(0xCFC)] public uint InstanceContentTextStartRowId;
+ [FieldOffset(0xD00)] public uint InstanceContentTextRowCount;
[VirtualFunction(303)]
public partial uint GetCurrentLevel();
@@ -38,6 +41,15 @@ public unsafe partial struct ContentDirector {
[VirtualFunction(329)]
public partial uint GetContentTimeMax();
+ [VirtualFunction(354)]
+ public partial Utf8String* GetInstanceContentText(uint rowId);
+
+ [MemberFunction("40 55 56 41 57 48 83 EC ?? 44 8B FA 4C 89 74 24")]
+ public partial void* LoadInstanceContentTexts(uint startRowId, uint rowCount);
+
+ [MemberFunction("2B 91 FC 0C 00 00 4C 8B C9 8B C2 49 8B D0 48 6B C8 68 49 03 89 88 0C 00 00 E9 ?? ?? ?? ??")]
+ public partial void SetInstanceContentText(uint rowId, CStringPointer text);
+
/// Changes the state of a map effect.
/// Index into MapEffects.
/// The new state for this MapEffect.
diff --git a/FFXIVClientStructs/FFXIV/Client/Game/InstanceContent/InstanceContentDirector.cs b/FFXIVClientStructs/FFXIV/Client/Game/InstanceContent/InstanceContentDirector.cs
index e0f0484952..c8e8207b0e 100644
--- a/FFXIVClientStructs/FFXIV/Client/Game/InstanceContent/InstanceContentDirector.cs
+++ b/FFXIVClientStructs/FFXIV/Client/Game/InstanceContent/InstanceContentDirector.cs
@@ -83,6 +83,9 @@ public unsafe partial struct InstanceContentDirector {
[FieldOffset(0xDE0)] public ContentDirector.MapEffectList ManagedSharedGroups;
+ /// InstanceContentTextData Row 0 - 11
+ [FieldOffset(0x1A60), FixedSizeArray] internal FixedSizeArray12 _commonInstanceContentTexts;
+
/// Dispatches updates specific to the content. This ends up calling ProcessContentSpecificDirectorUpdate and unrolls the parameters array.
[VirtualFunction(380)]
public partial void DispatchContentSpecificDirectorUpdate(uint category, uint* parameters);
diff --git a/FFXIVClientStructs/FFXIV/Client/System/Scheduler/Clip/InstanceContentTextClip.cs b/FFXIVClientStructs/FFXIV/Client/System/Scheduler/Clip/InstanceContentTextClip.cs
new file mode 100644
index 0000000000..27be5b60a1
--- /dev/null
+++ b/FFXIVClientStructs/FFXIV/Client/System/Scheduler/Clip/InstanceContentTextClip.cs
@@ -0,0 +1,59 @@
+using FFXIVClientStructs.FFXIV.Component.GUI;
+
+namespace FFXIVClientStructs.FFXIV.Client.System.Scheduler.Clip;
+
+// Client::System::Scheduler::Clip::InstanceContentTextClip
+[GenerateInterop]
+[Inherits]
+[StructLayout(LayoutKind.Explicit, Size = 0xD0)]
+[VirtualTable("48 8D 05 ?? ?? ?? ?? 33 D2 C7 41 ?? ?? ?? ?? ?? 48 89 51 ?? 88 51 ?? 48 89 51 ?? 48 89 51 ?? 48 89 51 ?? 48 89 51 ?? 48 89 51 ?? 48 89 51 ?? 48 89 51 ?? 48 89 51 ?? 48 89 51 ?? 48 89 51 ?? 89 51 ?? 48 89 51 ?? 89 51 ?? 89 91 ?? ?? ?? ?? C7 41 ?? ?? ?? ?? ?? C7 81 ?? ?? ?? ?? ?? ?? ?? ?? 48 89 91 ?? ?? ?? ?? 48 89 01 48 8B C1 66 C7 81 ?? ?? ?? ?? ?? ?? 48 89 91 ?? ?? ?? ?? 48 89 91 ?? ?? ?? ?? 48 89 91 ?? ?? ?? ?? 88 91 ?? ?? ?? ?? 48 89 91 ?? ?? ?? ?? 48 89 91 ?? ?? ?? ?? 48 89 91 ?? ?? ?? ?? C3", 3, 63)]
+public unsafe partial struct InstanceContentTextClip {
+ [FieldOffset(0x48), CExporterIgnore] public InstanceContentTextClipData* Data;
+
+ /// InstanceContentTextData
+ [FieldOffset(0x98)] public CStringPointer Text;
+
+ /// BNpcName
+ [FieldOffset(0xA0)] public CStringPointer Speaker;
+
+ [FieldOffset(0xA8)] public uint ResolvedRowId;
+ [FieldOffset(0xAC)] public uint ResolvedBNpcNameRowId;
+ [FieldOffset(0xB0)] public bool Finished;
+
+ /// The TalkSubtitle addon ID, or zero when the addon is not open.
+ [FieldOffset(0xB4)] public uint AddonId;
+
+ [FieldOffset(0xB8)] public float ElapsedTime;
+ [FieldOffset(0xBC)] public float SubtitleScaleX;
+ [FieldOffset(0xC0)] public float SubtitleScaleY;
+ [FieldOffset(0xC4)] public float SubtitlePositionX;
+ [FieldOffset(0xC8)] public float SubtitlePositionY;
+
+ [VirtualFunction(7)] public partial bool IsFinished();
+ [VirtualFunction(16)] public partial bool ResolveText();
+ [VirtualFunction(31)] public partial void Publish();
+
+ [MemberFunction("E8 ?? ?? ?? ?? 33 ED 84 C0 0F 84 ?? ?? ?? ?? 48 89 9C 24 ?? ?? ?? ?? 48 8D 44 24 ?? BB")]
+ public partial bool UpdateTalkSubtitleLayout(float* scaleX, float* scaleY, float* positionY, float* positionX);
+
+ [MemberFunction("48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 57 48 83 EC ?? 48 8B D9 48 63 EA")]
+ public partial void OpenOrUpdateTalkSubtitle(int eventKind, AtkValue* values, uint valueCount);
+
+ [StructLayout(LayoutKind.Explicit, Size = 0x1C)]
+ public struct InstanceContentTextClipData {
+ [FieldOffset(0x0C)] public InstanceContentTextDisplayMode DisplayMode;
+ [FieldOffset(0x10)] public uint RowId;
+ [FieldOffset(0x14)] public uint BNpcNameRowId;
+
+ /// The display duration in seconds.
+ [FieldOffset(0x18)] public float Duration;
+ }
+
+ public enum InstanceContentTextDisplayMode : uint {
+ /// Displays the text through UIModule.ShowBattleTalkImage.
+ BattleTalkImage,
+
+ /// Displays the text in the TalkSubtitle addon.
+ TalkSubtitle,
+ }
+}
diff --git a/ida/data.yml b/ida/data.yml
index 1a6e07623a..e47fa110b6 100644
--- a/ida/data.yml
+++ b/ida/data.yml
@@ -18337,8 +18337,11 @@ classes:
329: GetContentTimeMax
330: GetContentTypeIconId
335: SetExperience
+ 354: GetInstanceContentText
funcs:
0x140B6E290: ctor
+ 0x140B6B760: LoadInstanceContentTexts
+ 0x140B6B850: SetInstanceContentText
0x140B6FE60: ApplyMapEffect
0x140B6FCD0: PlayMapEffectTimeline
0x140B70DE0: IsPlayCutscene
@@ -27177,6 +27180,18 @@ classes:
base: Client::System::Scheduler::Clip::BaseClip
funcs:
0x141906170: ctor
+ Client::System::Scheduler::Clip::InstanceContentTextClip:
+ vtbls:
+ - ea: 0x14232A288
+ base: Client::System::Scheduler::Clip::BaseClip
+ vfuncs:
+ 7: IsFinished
+ 16: ResolveText
+ 31: Publish
+ funcs:
+ 0x1419101F0: ctor
+ 0x141910AA0: UpdateTalkSubtitleLayout
+ 0x141910CC0: OpenOrUpdateTalkSubtitle
Client::System::Scheduler::Base::SceneConnectionBlock:
vtbls:
- ea: 0x142453BA0