Handle Chocobos and GPose Ownership.

This commit is contained in:
Ottermandias 2022-12-04 00:48:05 +01:00
parent 5f4351d4f1
commit 882a59c1bf

View file

@ -4,6 +4,7 @@ using Dalamud.Game.ClientState.Objects.Enums;
using Dalamud.Game.ClientState.Objects.Types; using Dalamud.Game.ClientState.Objects.Types;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using Penumbra.String; using Penumbra.String;
using Character = FFXIVClientStructs.FFXIV.Client.Game.Character.Character;
namespace Penumbra.GameData.Actors; 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;
}
/// <summary> /// <summary>
/// Compute an ActorIdentifier from a GameObject. If check is true, the values are checked for validity. /// Compute an ActorIdentifier from a GameObject. If check is true, the values are checked for validity.
/// </summary> /// </summary>
@ -97,24 +114,17 @@ public partial class ActorManager
if (actor == null) if (actor == null)
return ActorIdentifier.Invalid; return ActorIdentifier.Invalid;
actor = HandleCutscene(actor);
var idx = actor->ObjectIndex; var idx = actor->ObjectIndex;
if (idx is >= (ushort)SpecialActor.CutsceneStart and < (ushort)SpecialActor.CutsceneEnd) if (idx is >= (ushort)SpecialActor.CharacterScreen and <= (ushort)SpecialActor.Portrait)
{
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)
{
return CreateIndividualUnchecked(IdentifierType.Special, ByteString.Empty, idx, ObjectKind.None, uint.MaxValue); return CreateIndividualUnchecked(IdentifierType.Special, ByteString.Empty, idx, ObjectKind.None, uint.MaxValue);
}
switch ((ObjectKind)actor->ObjectKind) switch ((ObjectKind)actor->ObjectKind)
{ {
case ObjectKind.Player: case ObjectKind.Player:
{ {
var name = new ByteString(actor->Name); var name = new ByteString(actor->Name);
var homeWorld = ((FFXIVClientStructs.FFXIV.Client.Game.Character.Character*)actor)->HomeWorld; var homeWorld = ((Character*)actor)->HomeWorld;
return check return check
? CreatePlayer(name, homeWorld) ? CreatePlayer(name, homeWorld)
: CreateIndividualUnchecked(IdentifierType.Player, name, homeWorld, ObjectKind.None, uint.MaxValue); : CreateIndividualUnchecked(IdentifierType.Player, name, homeWorld, ObjectKind.None, uint.MaxValue);
@ -122,27 +132,25 @@ public partial class ActorManager
case ObjectKind.BattleNpc: case ObjectKind.BattleNpc:
{ {
var ownerId = actor->OwnerID; 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) if (ownerId != 0xE0000000)
{ {
var owner = var owner = (Character*)HandleCutscene(
(FFXIVClientStructs.FFXIV.Client.Game.Character.Character*)(_objects.SearchById(ownerId)?.Address ?? IntPtr.Zero); (FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject*)(_objects.SearchById(ownerId)?.Address ?? IntPtr.Zero));
if (owner == null) if (owner == null)
return ActorIdentifier.Invalid; return ActorIdentifier.Invalid;
var name = new ByteString(owner->GameObject.Name); var name = new ByteString(owner->GameObject.Name);
var homeWorld = owner->HomeWorld; var homeWorld = owner->HomeWorld;
return check return check
? CreateOwned(name, homeWorld, ObjectKind.BattleNpc, ? CreateOwned(name, homeWorld, ObjectKind.BattleNpc, nameId)
((FFXIVClientStructs.FFXIV.Client.Game.Character.Character*)actor)->NameID) : CreateIndividualUnchecked(IdentifierType.Owned, name, homeWorld, ObjectKind.BattleNpc, nameId);
: CreateIndividualUnchecked(IdentifierType.Owned, name, homeWorld, ObjectKind.BattleNpc,
((FFXIVClientStructs.FFXIV.Client.Game.Character.Character*)actor)->NameID);
} }
return check return check
? CreateNpc(ObjectKind.BattleNpc, ((FFXIVClientStructs.FFXIV.Client.Game.Character.Character*)actor)->NameID, ? CreateNpc(ObjectKind.BattleNpc, nameId, actor->ObjectIndex)
actor->ObjectIndex) : CreateIndividualUnchecked(IdentifierType.Npc, ByteString.Empty, actor->ObjectIndex, ObjectKind.BattleNpc, nameId);
: CreateIndividualUnchecked(IdentifierType.Npc, ByteString.Empty, actor->ObjectIndex, ObjectKind.BattleNpc,
((FFXIVClientStructs.FFXIV.Client.Game.Character.Character*)actor)->NameID);
} }
case ObjectKind.EventNpc: case ObjectKind.EventNpc:
{ {
@ -175,10 +183,8 @@ public partial class ActorManager
case ObjectKind.Companion: case ObjectKind.Companion:
case (ObjectKind)15: // TODO: CS Update case (ObjectKind)15: // TODO: CS Update
{ {
if (actor->ObjectIndex % 2 == 0) var owner = (Character*)HandleCutscene(
return ActorIdentifier.Invalid; (FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject*)_objects.GetObjectAddress(actor->ObjectIndex - 1));
var owner = (FFXIVClientStructs.FFXIV.Client.Game.Character.Character*)_objects.GetObjectAddress(actor->ObjectIndex - 1);
if (owner == null) if (owner == null)
return ActorIdentifier.Invalid; return ActorIdentifier.Invalid;