Handle ownership in gpose / cutscenes better.

This commit is contained in:
Ottermandias 2022-12-04 01:35:11 +01:00
parent 882a59c1bf
commit 2b6275fe67
3 changed files with 29 additions and 29 deletions

View file

@ -109,8 +109,10 @@ public partial class ActorManager
/// <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>
public unsafe ActorIdentifier FromObject(FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject* actor, bool check = true) public unsafe ActorIdentifier FromObject(FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject* actor,
out FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject* owner, bool check = true)
{ {
owner = null;
if (actor == null) if (actor == null)
return ActorIdentifier.Invalid; return ActorIdentifier.Invalid;
@ -136,13 +138,13 @@ public partial class ActorManager
var nameId = actor->DataID == 952 ? 780 : ((Character*)actor)->NameID; var nameId = actor->DataID == 952 ? 780 : ((Character*)actor)->NameID;
if (ownerId != 0xE0000000) if (ownerId != 0xE0000000)
{ {
var owner = (Character*)HandleCutscene( owner = HandleCutscene(
(FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject*)(_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->Name);
var homeWorld = owner->HomeWorld; var homeWorld = ((Character*)owner)->HomeWorld;
return check return check
? CreateOwned(name, homeWorld, ObjectKind.BattleNpc, nameId) ? CreateOwned(name, homeWorld, ObjectKind.BattleNpc, nameId)
: CreateIndividualUnchecked(IdentifierType.Owned, name, homeWorld, ObjectKind.BattleNpc, nameId); : CreateIndividualUnchecked(IdentifierType.Owned, name, homeWorld, ObjectKind.BattleNpc, nameId);
@ -183,16 +185,18 @@ public partial class ActorManager
case ObjectKind.Companion: case ObjectKind.Companion:
case (ObjectKind)15: // TODO: CS Update case (ObjectKind)15: // TODO: CS Update
{ {
var owner = (Character*)HandleCutscene( owner = HandleCutscene(
(FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject*)_objects.GetObjectAddress(actor->ObjectIndex - 1)); (FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject*)_objects.GetObjectAddress(actor->ObjectIndex - 1));
if (owner == null) if (owner == null)
return ActorIdentifier.Invalid; return ActorIdentifier.Invalid;
var dataId = GetCompanionId(actor, &owner->GameObject); var dataId = GetCompanionId(actor, owner);
var name = new ByteString(owner->Name);
var homeWorld = ((Character*)owner)->HomeWorld;
var kind = (ObjectKind)actor->ObjectKind;
return check return check
? CreateOwned(new ByteString(owner->GameObject.Name), owner->HomeWorld, (ObjectKind)actor->ObjectKind, dataId) ? CreateOwned(name, homeWorld, kind, dataId)
: CreateIndividualUnchecked(IdentifierType.Owned, new ByteString(owner->GameObject.Name), owner->HomeWorld, : CreateIndividualUnchecked(IdentifierType.Owned, name, homeWorld, kind, dataId);
(ObjectKind)actor->ObjectKind, dataId);
} }
case ObjectKind.Retainer: case ObjectKind.Retainer:
{ {
@ -225,8 +229,12 @@ public partial class ActorManager
}; };
} }
public unsafe ActorIdentifier FromObject(GameObject? actor, out FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject* owner,
bool check = true)
=> FromObject((FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject*)(actor?.Address ?? IntPtr.Zero), out owner, check);
public unsafe ActorIdentifier FromObject(GameObject? actor, bool check = true) public unsafe ActorIdentifier FromObject(GameObject? actor, bool check = true)
=> FromObject((FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject*)(actor?.Address ?? IntPtr.Zero), check); => FromObject(actor, out _, check);
public ActorIdentifier CreateIndividual(IdentifierType type, ByteString name, ushort homeWorld, ObjectKind kind, uint dataId) public ActorIdentifier CreateIndividual(IdentifierType type, ByteString name, ushort homeWorld, ObjectKind kind, uint dataId)
=> type switch => type switch

View file

@ -26,6 +26,12 @@ public sealed partial class IndividualCollections : IReadOnlyList< (string Displ
public bool TryGetCollection( ActorIdentifier identifier, [NotNullWhen( true )] out ModCollection? collection, out ActorIdentifier specialIdentifier ) public bool TryGetCollection( ActorIdentifier identifier, [NotNullWhen( true )] out ModCollection? collection, out ActorIdentifier specialIdentifier )
{ {
specialIdentifier = ActorIdentifier.Invalid; specialIdentifier = ActorIdentifier.Invalid;
if( Count == 0 )
{
collection = null;
return false;
}
switch( identifier.Type ) switch( identifier.Type )
{ {
case IdentifierType.Player: return CheckWorlds( identifier, out collection ); case IdentifierType.Player: return CheckWorlds( identifier, out collection );
@ -94,7 +100,7 @@ public sealed partial class IndividualCollections : IReadOnlyList< (string Displ
=> TryGetCollection( _actorManager.FromObject( gameObject, false ), out collection, out specialIdentifier ); => TryGetCollection( _actorManager.FromObject( gameObject, false ), out collection, out specialIdentifier );
public unsafe bool TryGetCollection( FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject* gameObject, out ModCollection? collection, out ActorIdentifier specialIdentifier ) public unsafe bool TryGetCollection( FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject* gameObject, out ModCollection? collection, out ActorIdentifier specialIdentifier )
=> TryGetCollection( _actorManager.FromObject( gameObject, false ), out collection, out specialIdentifier ); => TryGetCollection( _actorManager.FromObject( gameObject, out _, false ), out collection, out specialIdentifier );
private bool CheckWorlds( ActorIdentifier identifier, out ModCollection? collection ) private bool CheckWorlds( ActorIdentifier identifier, out ModCollection? collection )
{ {

View file

@ -43,11 +43,11 @@ public unsafe partial class PathResolver
} }
else else
{ {
var identifier = Penumbra.Actors.FromObject( gameObject, false ); var identifier = Penumbra.Actors.FromObject( gameObject, out var owner, false );
var collection = CollectionByIdentifier( identifier, out var specialIdentifier ) var collection = CollectionByIdentifier( identifier, out var specialIdentifier )
?? CheckYourself( identifier.Type == IdentifierType.Special ? specialIdentifier : identifier, gameObject ) ?? CheckYourself( identifier.Type == IdentifierType.Special ? specialIdentifier : identifier, gameObject )
?? CollectionByAttributes( gameObject ) ?? CollectionByAttributes( gameObject )
?? CheckOwnedCollection( identifier, gameObject ) ?? CheckOwnedCollection( identifier, owner )
?? Penumbra.CollectionManager.Default; ?? Penumbra.CollectionManager.Default;
return IdentifiedCache.Set( collection, identifier, gameObject ); return IdentifiedCache.Set( collection, identifier, gameObject );
} }
@ -124,23 +124,9 @@ public unsafe partial class PathResolver
} }
// Get the collection applying to the owner if it is available. // Get the collection applying to the owner if it is available.
private static ModCollection? CheckOwnedCollection( ActorIdentifier identifier, GameObject* obj ) private static ModCollection? CheckOwnedCollection( ActorIdentifier identifier, GameObject* owner )
{ {
if( identifier.Type != IdentifierType.Owned || !Penumbra.Config.UseOwnerNameForCharacterCollection ) if( identifier.Type != IdentifierType.Owned || !Penumbra.Config.UseOwnerNameForCharacterCollection || owner == null )
{
return null;
}
var owner = identifier.Kind switch
{
ObjectKind.BattleNpc when obj->OwnerID != 0xE0000000 => ( GameObject* )( Dalamud.Objects.SearchById( obj->OwnerID )?.Address ?? IntPtr.Zero ),
ObjectKind.MountType when obj->ObjectIndex % 2 == 1 => ( GameObject* )Dalamud.Objects.GetObjectAddress( obj->ObjectIndex - 1 ),
ObjectKind.Companion when obj->ObjectIndex % 2 == 1 => ( GameObject* )Dalamud.Objects.GetObjectAddress( obj->ObjectIndex - 1 ),
( ObjectKind )15 when obj->ObjectIndex % 2 == 1 => ( GameObject* )Dalamud.Objects.GetObjectAddress( obj->ObjectIndex - 1 ), // TODO: CS Update
_ => null,
};
if( owner == null )
{ {
return null; return null;
} }