Added debug information regarding minions
This commit is contained in:
@@ -508,7 +508,10 @@ public sealed class ActorObjectService : IHostedService, IDisposable, IMediatorS
|
||||
return new ActorDescriptor(name, hashedCid, address, objectIndex, isLocal, isInGpose, objectKind, ownedKind, ownerEntityId);
|
||||
}
|
||||
|
||||
private unsafe (LightlessObjectKind? OwnedKind, uint OwnerEntityId) DetermineOwnedKind(GameObject* gameObject, DalamudObjectKind objectKind, bool isLocalPlayer)
|
||||
private unsafe (LightlessObjectKind? OwnedKind, uint OwnerEntityId) DetermineOwnedKind(
|
||||
GameObject* gameObject,
|
||||
DalamudObjectKind objectKind,
|
||||
bool isLocalPlayer)
|
||||
{
|
||||
if (gameObject == null)
|
||||
return (null, 0);
|
||||
@@ -520,6 +523,7 @@ public sealed class ActorObjectService : IHostedService, IDisposable, IMediatorS
|
||||
}
|
||||
|
||||
var ownerId = ResolveOwnerId(gameObject);
|
||||
|
||||
var localPlayerAddress = _objectTable.LocalPlayer?.Address ?? nint.Zero;
|
||||
if (localPlayerAddress == nint.Zero)
|
||||
return (null, ownerId);
|
||||
@@ -531,9 +535,7 @@ public sealed class ActorObjectService : IHostedService, IDisposable, IMediatorS
|
||||
if (objectKind is DalamudObjectKind.MountType or DalamudObjectKind.Companion)
|
||||
{
|
||||
var expectedMinionOrMount = GetMinionOrMountAddress(localPlayerAddress, localEntityId);
|
||||
if (expectedMinionOrMount != nint.Zero
|
||||
&& (nint)gameObject == expectedMinionOrMount
|
||||
&& IsPlayerRelatedOwnedAddress(expectedMinionOrMount, LightlessObjectKind.MinionOrMount))
|
||||
if (expectedMinionOrMount != nint.Zero && (nint)gameObject == expectedMinionOrMount)
|
||||
{
|
||||
var resolvedOwner = ownerId != 0 ? ownerId : localEntityId;
|
||||
return (LightlessObjectKind.MinionOrMount, resolvedOwner);
|
||||
@@ -543,20 +545,16 @@ public sealed class ActorObjectService : IHostedService, IDisposable, IMediatorS
|
||||
if (objectKind != DalamudObjectKind.BattleNpc)
|
||||
return (null, ownerId);
|
||||
|
||||
if (ownerId != localEntityId)
|
||||
if (ownerId != 0 && ownerId != localEntityId)
|
||||
return (null, ownerId);
|
||||
|
||||
var expectedPet = GetPetAddress(localPlayerAddress, localEntityId);
|
||||
if (expectedPet != nint.Zero
|
||||
&& (nint)gameObject == expectedPet
|
||||
&& IsPlayerRelatedOwnedAddress(expectedPet, LightlessObjectKind.Pet))
|
||||
return (LightlessObjectKind.Pet, ownerId);
|
||||
if (expectedPet != nint.Zero && (nint)gameObject == expectedPet)
|
||||
return (LightlessObjectKind.Pet, ownerId != 0 ? ownerId : localEntityId);
|
||||
|
||||
var expectedCompanion = GetCompanionAddress(localPlayerAddress, localEntityId);
|
||||
if (expectedCompanion != nint.Zero
|
||||
&& (nint)gameObject == expectedCompanion
|
||||
&& IsPlayerRelatedOwnedAddress(expectedCompanion, LightlessObjectKind.Companion))
|
||||
return (LightlessObjectKind.Companion, ownerId);
|
||||
if (expectedCompanion != nint.Zero && (nint)gameObject == expectedCompanion)
|
||||
return (LightlessObjectKind.Companion, ownerId != 0 ? ownerId : localEntityId);
|
||||
|
||||
return (null, ownerId);
|
||||
}
|
||||
@@ -584,21 +582,25 @@ public sealed class ActorObjectService : IHostedService, IDisposable, IMediatorS
|
||||
return nint.Zero;
|
||||
|
||||
var playerObject = (GameObject*)localPlayerAddress;
|
||||
var candidateAddress = _objectTable.GetObjectAddress(playerObject->ObjectIndex + 1);
|
||||
if (ownerEntityId == 0)
|
||||
return nint.Zero;
|
||||
|
||||
var candidateAddress = _objectTable.GetObjectAddress(playerObject->ObjectIndex + 1);
|
||||
if (candidateAddress != nint.Zero)
|
||||
{
|
||||
var candidate = (GameObject*)candidateAddress;
|
||||
var candidateKind = (DalamudObjectKind)candidate->ObjectKind;
|
||||
|
||||
if (candidateKind is DalamudObjectKind.MountType or DalamudObjectKind.Companion)
|
||||
{
|
||||
if (ResolveOwnerId(candidate) == ownerEntityId)
|
||||
var resolvedOwner = ResolveOwnerId(candidate);
|
||||
|
||||
if (resolvedOwner == ownerEntityId || resolvedOwner == 0)
|
||||
return candidateAddress;
|
||||
}
|
||||
}
|
||||
|
||||
if (ownerEntityId == 0)
|
||||
return nint.Zero;
|
||||
|
||||
foreach (var obj in _objectTable)
|
||||
{
|
||||
if (obj is null || obj.Address == nint.Zero || obj.Address == localPlayerAddress)
|
||||
@@ -615,6 +617,90 @@ public sealed class ActorObjectService : IHostedService, IDisposable, IMediatorS
|
||||
return nint.Zero;
|
||||
}
|
||||
|
||||
public unsafe bool TryFindOwnedObject(uint ownerEntityId, LightlessObjectKind kind, out nint address)
|
||||
{
|
||||
address = nint.Zero;
|
||||
if (ownerEntityId == 0) return false;
|
||||
|
||||
foreach (var addr in EnumerateActiveCharacterAddresses())
|
||||
{
|
||||
if (addr == nint.Zero) continue;
|
||||
|
||||
var go = (GameObject*)addr;
|
||||
var ok = (DalamudObjectKind)go->ObjectKind;
|
||||
|
||||
switch (kind)
|
||||
{
|
||||
case LightlessObjectKind.MinionOrMount:
|
||||
if (ok is DalamudObjectKind.MountType or DalamudObjectKind.Companion
|
||||
&& ResolveOwnerId(go) == ownerEntityId)
|
||||
{
|
||||
address = addr;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
case LightlessObjectKind.Pet:
|
||||
if (ok == DalamudObjectKind.BattleNpc
|
||||
&& go->BattleNpcSubKind == BattleNpcSubKind.Pet
|
||||
&& ResolveOwnerId(go) == ownerEntityId)
|
||||
{
|
||||
address = addr;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
case LightlessObjectKind.Companion:
|
||||
if (ok == DalamudObjectKind.BattleNpc
|
||||
&& go->BattleNpcSubKind == BattleNpcSubKind.Buddy
|
||||
&& ResolveOwnerId(go) == ownerEntityId)
|
||||
{
|
||||
address = addr;
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public unsafe IReadOnlyList<nint> GetMinionOrMountCandidates(uint ownerEntityId, ushort preferredPlayerIndex)
|
||||
{
|
||||
var results = new List<(nint Ptr, int Score)>(4);
|
||||
|
||||
var manager = GameObjectManager.Instance();
|
||||
if (manager == null || ownerEntityId == 0)
|
||||
return Array.Empty<nint>();
|
||||
|
||||
const int objectLimit = 200;
|
||||
for (var i = 0; i < objectLimit; i++)
|
||||
{
|
||||
var obj = manager->Objects.IndexSorted[i].Value;
|
||||
if (obj == null)
|
||||
continue;
|
||||
|
||||
var kind = (DalamudObjectKind)obj->ObjectKind;
|
||||
if (kind is not (DalamudObjectKind.MountType or DalamudObjectKind.Companion))
|
||||
continue;
|
||||
|
||||
var owner = ResolveOwnerId(obj);
|
||||
if (owner != ownerEntityId)
|
||||
continue;
|
||||
|
||||
var idx = obj->ObjectIndex;
|
||||
var score = Math.Abs(idx - (preferredPlayerIndex + 1));
|
||||
if (obj->DrawObject == null) score += 50;
|
||||
|
||||
results.Add(((nint)obj, score));
|
||||
}
|
||||
|
||||
return results
|
||||
.OrderBy(r => r.Score)
|
||||
.Select(r => r.Ptr)
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
private unsafe nint GetPetAddress(nint localPlayerAddress, uint ownerEntityId)
|
||||
{
|
||||
if (localPlayerAddress == nint.Zero || ownerEntityId == 0)
|
||||
@@ -1219,21 +1305,19 @@ public sealed class ActorObjectService : IHostedService, IDisposable, IMediatorS
|
||||
|
||||
private static unsafe bool IsObjectFullyLoaded(nint address)
|
||||
{
|
||||
if (address == nint.Zero)
|
||||
return false;
|
||||
if (address == nint.Zero) return false;
|
||||
|
||||
var gameObject = (GameObject*)address;
|
||||
if (gameObject == null)
|
||||
return false;
|
||||
if (gameObject == null) return false;
|
||||
|
||||
var drawObject = gameObject->DrawObject;
|
||||
if (drawObject == null)
|
||||
return false;
|
||||
if (drawObject == null) return false;
|
||||
|
||||
if ((ulong)gameObject->RenderFlags == 2048)
|
||||
return false;
|
||||
|
||||
var characterBase = (CharacterBase*)drawObject;
|
||||
|
||||
if (characterBase->HasModelInSlotLoaded != 0)
|
||||
return false;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user