diff --git a/FFXIVClientStructs/FFXIV/Client/Game/Character/Character.cs b/FFXIVClientStructs/FFXIV/Client/Game/Character/Character.cs index 226ddfa95..b4d6209f0 100644 --- a/FFXIVClientStructs/FFXIV/Client/Game/Character/Character.cs +++ b/FFXIVClientStructs/FFXIV/Client/Game/Character/Character.cs @@ -47,6 +47,7 @@ public unsafe partial struct Character { [FieldOffset(0x1CE8)] public byte ActorControlFlags; [FieldOffset(0x21E0)] public Balloon Balloon; + [FieldOffset(0x2260)] public NpcYellBalloon YellBalloon; [FieldOffset(0x22E8)] public float Alpha; diff --git a/FFXIVClientStructs/FFXIV/Client/Game/NpcYellBalloon.cs b/FFXIVClientStructs/FFXIV/Client/Game/NpcYellBalloon.cs new file mode 100644 index 000000000..884099584 --- /dev/null +++ b/FFXIVClientStructs/FFXIV/Client/Game/NpcYellBalloon.cs @@ -0,0 +1,159 @@ +using FFXIVClientStructs.FFXIV.Client.System.String; + +namespace FFXIVClientStructs.FFXIV.Client.Game; + +// Client::Game::NpcYellBalloon +// Probably part of Client::Game::Character::Character +[GenerateInterop] +[StructLayout(LayoutKind.Explicit, Size = 0x88)] +public unsafe partial struct NpcYellBalloon { + + /// + /// The text that this balloon will display. + /// + /// + /// Empty when balloon is . + /// + [FieldOffset(0x0)] public Utf8String Text; + + /// + /// Pointer to the that contains this balloon. + /// + [FieldOffset(0x68)] public Character.Character* Character; + + /// + /// How much longer (in seconds) the balloon should remain open. + /// + /// + /// Starting value set by OpenBalloon. Starts counting down once in state. If this is set + /// to zero before the balloon is activated, the balloon will remain open indefinitely, subject to the value of . + /// + [FieldOffset(0x70)] public float PlayTimer; + + /// + /// How much longer (in seconds) before the balloon should actually be opened with AgentScreenLog. + /// + /// + /// Starting value is set by OpenBalloon. Resets to one second when balloon exits state. + /// + [FieldOffset(0x74)] public float DelayTime; + + /// + /// The balloon's current state. + /// + [FieldOffset(0x78)] public NpcYellBalloonState State; + + /// + /// Controls how the balloon determines when to close. + /// + /// + /// If OpenBalloon's reducedCloseChecks parameter is true, this is , else if + /// playTime is zero this is , else this is . + /// + [FieldOffset(0x7C)] public NpcYellBalloonCloseType CloseType; + + /// + /// The bone index to which the balloon is attached on the character. + /// + [FieldOffset(0x80)] public byte ParentBone; + + /// + /// Miscellaneous balloon behaviors. + /// + [FieldOffset(0x81)] public NpcYellBalloonFlags Flags; + + /// + /// Prepares the balloon to be opened during the next applicable Update. + /// + /// A null-terminated string containing the text to display. + /// Time in seconds that the balloon should remain visible. If zero, the balloon will remain open indefinitely (until is called). + /// If this is true, the bubble will fade in more gently than the normal "popping" in. + /// Time in seconds to wait before actually opening the balloon. + /// Whether the balloon text should also be printed to the chat log. + /// Skips certain non-timer checks for closing the balloon. Unknown purpose. Usually false. + /// Ignore whether the character is "in range" when checking whether to display the balloon. + /// The bone index to which the balloon is visually attached. A value of 25 is used if the specified bone does not exist. + [MemberFunction("E8 ?? ?? ?? ?? 0F 28 B4 24 ?? ?? ?? ?? 48 8D 4D"), GenerateStringOverloads] + public partial void OpenBalloon(CStringPointer str, float playTime, bool softOpen, float openDelay, bool printToLog, bool reducedCloseChecks, bool ignoreRangeCheck, byte parentBone); + + /// + /// Closes and resets the balloon. + /// + /// + /// Only required if balloon is set to hold open (or needs to be closed early). + /// + [MemberFunction("E8 ?? ?? ?? ?? 66 3B BB ?? ?? ?? ?? 75")] + public partial void CloseBalloon(); +} + +public enum NpcYellBalloonState : int { + + /// + /// Balloon is inactive and in the default state. + /// + Inactive = 0, + + /// + /// Balloon is waiting to open (until expires). + /// + Waiting = 1, + + /// + /// Balloon is open. + /// + Active = 2, + + /// + /// Balloon is attempting to open. + /// + Activating = 3, +} + +public enum NpcYellBalloonCloseType : int { + + /// + /// Performs normal timer checks every active update cycle. + /// + Normal = 0, + + /// + /// Ignore and hold open indefinitely until is called. + /// + HoldOpen = 1, + + /// + /// Similar to , but skips some non- checks. + /// + ReducedCloseChecks = 2, +} + +[Flags] +public enum NpcYellBalloonFlags : byte { + None = 0, + + /// + /// All balloons will have this flag while in use. + /// + /// + /// If this is not set, the balloon will not be opened (or will be immediately closed). + /// + Valid = 1, + + /// + /// The balloon fades in instead of opening with a "pop". + /// + /// + /// Is passed as the bool third parameter to AgentScreenLog::OpenBalloon, and probably has the same effect as the Balloon EXD's boolean "Slowly" column. + /// + SoftOpen = 2, + + /// + /// Call AgentScreenLog::OpenBalloon regardless of character range test result. + /// + IgnoreRangeCheck = 4, + + /// + /// Also call RaptureLogModule::PrintMessage with balloon text when the balloon is opened. + /// + PrintToLog = 8, +} diff --git a/FFXIVClientStructs/FFXIV/Client/Game/UI/NpcYell.cs b/FFXIVClientStructs/FFXIV/Client/Game/UI/NpcYell.cs index 74e18fc40..a03fe5a77 100644 --- a/FFXIVClientStructs/FFXIV/Client/Game/UI/NpcYell.cs +++ b/FFXIVClientStructs/FFXIV/Client/Game/UI/NpcYell.cs @@ -1,5 +1,113 @@ +using FFXIVClientStructs.FFXIV.Client.Game.Object; +using FFXIVClientStructs.FFXIV.Client.System.String; + namespace FFXIVClientStructs.FFXIV.Client.Game.UI; // Client::Game::UI::NpcYell -[StructLayout(LayoutKind.Explicit, Size = 0x1750)] -public struct NpcYell; +[GenerateInterop] +[StructLayout(LayoutKind.Explicit, Size = 0x2850)] +public partial struct NpcYell { + + /// + /// Entries at index and above are stale. + /// + [FieldOffset(0x48), FixedSizeArray] internal FixedSizeArray32 _yellSlots; + + /// + /// Entries at index and above are stale. + /// + [FieldOffset(0x548), FixedSizeArray] internal FixedSizeArray32 _yellInfo; + + /// + /// The number of new and entries that have not yet been handled. + /// + [FieldOffset(0x2848)] public byte UnhandledYellCount; + [FieldOffset(0x2849)] private byte Unk_2849; // Looks like a counter that has something to do specifically with entries that show a BattleTalk. + [FieldOffset(0x284A)] private bool Unk_284A; + + [StructLayout(LayoutKind.Explicit, Size = 0x28)] + public struct NpcYellSlot { + [FieldOffset(0x0)] public GameObjectId ObjectId; + [FieldOffset(0xC)] public uint NameId; + [FieldOffset(0x10)] private uint Unk_MessageParams; // A (probably) four-long array of integer parameters for the message string. + [FieldOffset(0x20)] private float Unk_20; // Probably a delay. Has effective frame delta subracted each update. + } + + [StructLayout(LayoutKind.Explicit, Size = 0x118)] + public struct NpcYellInfo { + [FieldOffset(0x0)] public uint NpcYellRowId; + [FieldOffset(0x8)] public GameObjectId ObjectId; + [FieldOffset(0x10)] public uint NameId; + [FieldOffset(0x18)] public Utf8String Name; + [FieldOffset(0x80)] public Utf8String Message; + [FieldOffset(0xE8)] private uint Unk_MessageParams; // A (probably) four-long array of integer parameters for the message string. + [FieldOffset(0xF8)] private float Unk_F8; // Countdown timer of unknown use. Has effective frame delta subracted each update. + + /// + /// How long (in seconds) to display the message as a balloon. + /// + /// + /// Only used if includes . + /// + [FieldOffset(0xFC)] public float BalloonTime; + + /// + /// How long (in seconds) to display the message in the BattleTalk addon. + /// + /// + /// Only used if includes . + /// + [FieldOffset(0x100)] public float BattleTalkTime; + + /// + /// The method(s) used to show the dialogue to the player. + /// + [FieldOffset(0x104)] public NpcYellOutputFlags OutputType; + + /// + /// Controls which UIModule::ShowBattleTalk overload is called. + /// + [FieldOffset(0x108)] private uint Unk_108; + + /// + /// The index of the character bone to which to attach the . + /// + /// + /// Only used if includes . + /// + [FieldOffset(0x10C)] public byte ParentBone; + [FieldOffset(0x110)] public NpcYellFlags Flags; + } + + [Flags] + public enum NpcYellOutputFlags : byte { + None = 0, + PrintToLog = 1, + ShowBalloon = 2, + ShowBattleTalk = 4, + } + + [Flags] + public enum NpcYellFlags : byte { + None = 0, + /// + /// Controls the corresponding flag in the . + /// + SkipCloseChecks = 1, + /// + /// Controls the corresponding flag in the . + /// + /// + /// Also checked when formatting NPC name. + /// + SkipRangeCheck = 2, + Unk_4 = 4, + Unk_8 = 8, + /// + /// This is the default value after initialization. + /// + Unk_10 = 0x10, + Unk_20 = 0x20, + Unk_40 = 0x40, + } +} diff --git a/ida/data.yml b/ida/data.yml index ce71cf5fd..afe43ffb7 100644 --- a/ida/data.yml +++ b/ida/data.yml @@ -1505,6 +1505,16 @@ classes: 0x14188EB00: Terminate #oldfail 0x141831340: StartTimerMode # (Balloon* this, float timer, ushort id) if id == 1 use default id else use id #oldfail 0x141831380: StartOtherMode # (Balloon* this, ushort id) id same as above + Client::Game::NpcYellBalloon: + funcs: + 0x14188EC50: Reset + 0x14188ECB0: Ctor + 0x14188ED10: Dtor + 0x14188ED70: Initialize # (this, chara*) + 0x14188EDC0: Update + 0x14188F0A0: OpenBalloon # (this, char*, float, bool, float, bool, bool, bool, byte) + 0x14188F320: Reset2 # This is identical to Reset, but called from things outside of the class instead of from other member functions. + 0x14188F360: CloseBalloon Client::Game::Fate::FateManager: instances: - ea: 0x1429EC2B8 @@ -3178,6 +3188,7 @@ classes: 0x140D78D80: Dtor 0x140B61120: Initialize 0x140B61920: Update + 0x140B62200: HandleYell Client::Game::UI::CharaCard: instances: - ea: 0x1429E7C88