From 882a59c1bf09c69beeb58f884bee3364fd230303 Mon Sep 17 00:00:00 2001 From: Ottermandias Date: Sun, 4 Dec 2022 00:48:05 +0100 Subject: [PATCH] Handle Chocobos and GPose Ownership. --- .../Actors/ActorManager.Identifiers.cs | 54 ++++++++++--------- 1 file changed, 30 insertions(+), 24 deletions(-) diff --git a/Penumbra.GameData/Actors/ActorManager.Identifiers.cs b/Penumbra.GameData/Actors/ActorManager.Identifiers.cs index 75cb7043..fbfe235e 100644 --- a/Penumbra.GameData/Actors/ActorManager.Identifiers.cs +++ b/Penumbra.GameData/Actors/ActorManager.Identifiers.cs @@ -4,6 +4,7 @@ using Dalamud.Game.ClientState.Objects.Enums; using Dalamud.Game.ClientState.Objects.Types; using Newtonsoft.Json.Linq; using Penumbra.String; +using Character = FFXIVClientStructs.FFXIV.Client.Game.Character.Character; namespace Penumbra.GameData.Actors; @@ -89,6 +90,22 @@ public partial class ActorManager }; } + private unsafe FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject* HandleCutscene( + FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject* main) + { + if (main == null) + return null; + + if (main->ObjectIndex is >= (ushort)SpecialActor.CutsceneStart and < (ushort)SpecialActor.CutsceneEnd) + { + var parentIdx = _toParentIdx(main->ObjectIndex); + if (parentIdx >= 0) + return (FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject*)_objects.GetObjectAddress(parentIdx); + } + + return main; + } + /// /// Compute an ActorIdentifier from a GameObject. If check is true, the values are checked for validity. /// @@ -97,24 +114,17 @@ public partial class ActorManager if (actor == null) return ActorIdentifier.Invalid; + actor = HandleCutscene(actor); var idx = actor->ObjectIndex; - if (idx is >= (ushort)SpecialActor.CutsceneStart and < (ushort)SpecialActor.CutsceneEnd) - { - var parentIdx = _toParentIdx(idx); - if (parentIdx >= 0) - return FromObject((FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject*)_objects.GetObjectAddress(parentIdx), check); - } - else if (idx is >= (ushort)SpecialActor.CharacterScreen and <= (ushort)SpecialActor.Portrait) - { + if (idx is >= (ushort)SpecialActor.CharacterScreen and <= (ushort)SpecialActor.Portrait) return CreateIndividualUnchecked(IdentifierType.Special, ByteString.Empty, idx, ObjectKind.None, uint.MaxValue); - } switch ((ObjectKind)actor->ObjectKind) { case ObjectKind.Player: { var name = new ByteString(actor->Name); - var homeWorld = ((FFXIVClientStructs.FFXIV.Client.Game.Character.Character*)actor)->HomeWorld; + var homeWorld = ((Character*)actor)->HomeWorld; return check ? CreatePlayer(name, homeWorld) : CreateIndividualUnchecked(IdentifierType.Player, name, homeWorld, ObjectKind.None, uint.MaxValue); @@ -122,27 +132,25 @@ public partial class ActorManager case ObjectKind.BattleNpc: { var ownerId = actor->OwnerID; + // 952 -> 780 is a special case for chocobos because they have NameId == 0 otherwise. + var nameId = actor->DataID == 952 ? 780 : ((Character*)actor)->NameID; if (ownerId != 0xE0000000) { - var owner = - (FFXIVClientStructs.FFXIV.Client.Game.Character.Character*)(_objects.SearchById(ownerId)?.Address ?? IntPtr.Zero); + var owner = (Character*)HandleCutscene( + (FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject*)(_objects.SearchById(ownerId)?.Address ?? IntPtr.Zero)); if (owner == null) return ActorIdentifier.Invalid; var name = new ByteString(owner->GameObject.Name); var homeWorld = owner->HomeWorld; return check - ? CreateOwned(name, homeWorld, ObjectKind.BattleNpc, - ((FFXIVClientStructs.FFXIV.Client.Game.Character.Character*)actor)->NameID) - : CreateIndividualUnchecked(IdentifierType.Owned, name, homeWorld, ObjectKind.BattleNpc, - ((FFXIVClientStructs.FFXIV.Client.Game.Character.Character*)actor)->NameID); + ? CreateOwned(name, homeWorld, ObjectKind.BattleNpc, nameId) + : CreateIndividualUnchecked(IdentifierType.Owned, name, homeWorld, ObjectKind.BattleNpc, nameId); } return check - ? CreateNpc(ObjectKind.BattleNpc, ((FFXIVClientStructs.FFXIV.Client.Game.Character.Character*)actor)->NameID, - actor->ObjectIndex) - : CreateIndividualUnchecked(IdentifierType.Npc, ByteString.Empty, actor->ObjectIndex, ObjectKind.BattleNpc, - ((FFXIVClientStructs.FFXIV.Client.Game.Character.Character*)actor)->NameID); + ? CreateNpc(ObjectKind.BattleNpc, nameId, actor->ObjectIndex) + : CreateIndividualUnchecked(IdentifierType.Npc, ByteString.Empty, actor->ObjectIndex, ObjectKind.BattleNpc, nameId); } case ObjectKind.EventNpc: { @@ -175,10 +183,8 @@ public partial class ActorManager case ObjectKind.Companion: case (ObjectKind)15: // TODO: CS Update { - if (actor->ObjectIndex % 2 == 0) - return ActorIdentifier.Invalid; - - var owner = (FFXIVClientStructs.FFXIV.Client.Game.Character.Character*)_objects.GetObjectAddress(actor->ObjectIndex - 1); + var owner = (Character*)HandleCutscene( + (FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject*)_objects.GetObjectAddress(actor->ObjectIndex - 1)); if (owner == null) return ActorIdentifier.Invalid;