Try to resolve banner players better.

This commit is contained in:
Ottermandias 2023-01-16 13:03:26 +01:00
parent 4059e0630a
commit 123ed256b1
3 changed files with 119 additions and 11 deletions

View file

@ -5,20 +5,22 @@ using System.Linq;
using System.Text;
using Dalamud;
using Dalamud.Data;
using Dalamud.Game;
using Dalamud.Game.ClientState;
using Dalamud.Game.ClientState.Objects;
using Dalamud.Game.ClientState.Objects.Enums;
using Dalamud.Game.Gui;
using Dalamud.Plugin;
using Dalamud.Utility;
using Dalamud.Utility.Signatures;
using FFXIVClientStructs.FFXIV.Client.Game.Group;
using FFXIVClientStructs.FFXIV.Client.Game.Object;
using FFXIVClientStructs.FFXIV.Client.UI.Agent;
using Lumina.Excel.GeneratedSheets;
using Lumina.Text;
using Penumbra.GameData.Data;
using Penumbra.GameData.Structs;
using Penumbra.String;
using Character = FFXIVClientStructs.FFXIV.Client.Game.Character.Character;
using ObjectKind = Dalamud.Game.ClientState.Objects.Enums.ObjectKind;
namespace Penumbra.GameData.Actors;
@ -198,6 +200,107 @@ public sealed partial class ActorManager : IDisposable
return CreatePlayer(InspectName, InspectWorldId);
}
public unsafe bool ResolvePartyBannerPlayer(ScreenActor type, out ActorIdentifier id)
{
id = ActorIdentifier.Invalid;
var addon = _gameGui.GetAddonByName("BannerParty");
if (addon == IntPtr.Zero)
return false;
var idx = (ushort)type - (ushort)ScreenActor.CharacterScreen;
if (idx is < 0 or > 7)
return true;
if (idx == 0)
{
id = GetCurrentPlayer();
return true;
}
var obj = GroupManager.Instance()->GetPartyMemberByIndex(idx - 1);
if (obj != null)
id = CreatePlayer(new ByteString(obj->Name), obj->HomeWorld);
return true;
}
private unsafe bool SearchPlayerCustomize(Character* character, int idx, out ActorIdentifier id)
{
var other = (Character*)_objects.GetObjectAddress(idx);
if (other == null || !CustomizeData.Equals((CustomizeData*)character->CustomizeData, (CustomizeData*)other->CustomizeData))
{
id = ActorIdentifier.Invalid;
return false;
}
id = FromObject(&other->GameObject, out _, false, true);
return true;
}
private unsafe ActorIdentifier SearchPlayersCustomize(Character* gameObject, int idx1, int idx2, int idx3)
=> SearchPlayerCustomize(gameObject, idx1, out var ret)
|| SearchPlayerCustomize(gameObject, idx2, out ret)
|| SearchPlayerCustomize(gameObject, idx3, out ret)
? ret
: ActorIdentifier.Invalid;
private unsafe ActorIdentifier SearchPlayersCustomize(Character* gameObject)
{
for (var i = 0; i < (int)ScreenActor.CutsceneStart; i += 2)
{
var obj = (GameObject*)_objects.GetObjectAddress(i);
if (obj != null
&& obj->ObjectKind is (byte)ObjectKind.Player
&& !CustomizeData.Equals((CustomizeData*)gameObject->CustomizeData, (CustomizeData*)((Character*)obj)->CustomizeData))
return FromObject(obj, out _, false, true);
}
return ActorIdentifier.Invalid;
}
public unsafe bool ResolveMahjongPlayer(ScreenActor type, out ActorIdentifier id)
{
id = ActorIdentifier.Invalid;
if (_clientState.TerritoryType != 831 && _gameGui.GetAddonByName("EmjIntro") == IntPtr.Zero)
return false;
var obj = (Character*)_objects.GetObjectAddress((int)type);
if (obj == null)
return false;
id = type switch
{
ScreenActor.CharacterScreen => GetCurrentPlayer(),
ScreenActor.ExamineScreen => SearchPlayersCustomize(obj, 2, 4, 6),
ScreenActor.FittingRoom => SearchPlayersCustomize(obj, 4, 2, 6),
ScreenActor.DyePreview => SearchPlayersCustomize(obj, 6, 2, 4),
_ => ActorIdentifier.Invalid,
};
return true;
}
public unsafe bool ResolvePvPBannerPlayer(ScreenActor type, out ActorIdentifier id)
{
id = ActorIdentifier.Invalid;
var addon = _gameGui.GetAddonByName("PvPMKSIntroduction");
if (addon == IntPtr.Zero)
return false;
var obj = (Character*)_objects.GetObjectAddress((int)type);
if (obj == null)
return false;
var identifier = type switch
{
ScreenActor.CharacterScreen => SearchPlayersCustomize(obj),
ScreenActor.ExamineScreen => SearchPlayersCustomize(obj),
ScreenActor.FittingRoom => SearchPlayersCustomize(obj),
ScreenActor.DyePreview => SearchPlayersCustomize(obj),
ScreenActor.Portrait => SearchPlayersCustomize(obj),
_ => ActorIdentifier.Invalid,
};
return true;
}
public unsafe ActorIdentifier GetCardPlayer()
{
var agent = AgentCharaCard.Instance();

View file

@ -86,6 +86,13 @@ public sealed partial class IndividualCollections : IReadOnlyList< (string Displ
return identifier;
}
if( _actorManager.ResolvePartyBannerPlayer( identifier.Special, out var id )
|| _actorManager.ResolvePvPBannerPlayer( identifier.Special, out id )
|| _actorManager.ResolveMahjongPlayer( identifier.Special, out id ) )
{
return identifier;
}
switch( identifier.Special )
{
case ScreenActor.CharacterScreen when Penumbra.Config.UseCharacterCollectionInMainWindow:

View file

@ -88,12 +88,6 @@ public unsafe partial class PathResolver
return IdentifiedCache.Set( collection2, ActorIdentifier.Invalid, gameObject );
}
// Mahjong special case.
if( Dalamud.ClientState.TerritoryType == 831 )
{
return IdentifyMahjong( gameObject );
}
// Aesthetician. The relevant actor is yourself, so use player collection when possible.
if( Dalamud.GameGui.GetAddonByName( "ScreenLog", 1 ) == IntPtr.Zero )
{
@ -106,12 +100,16 @@ public unsafe partial class PathResolver
}
var identifier = Penumbra.Actors.FromObject( gameObject, out var owner, true, false );
if( Penumbra.Config.UseNoModsInInspect && identifier.Type == IdentifierType.Special && identifier.Special == ScreenActor.ExamineScreen )
if( identifier.Type is IdentifierType.Special )
{
return IdentifiedCache.Set( ModCollection.Empty, identifier, gameObject );
if( Penumbra.Config.UseNoModsInInspect && identifier.Special == ScreenActor.ExamineScreen )
{
return IdentifiedCache.Set( ModCollection.Empty, identifier, gameObject );
}
identifier = Penumbra.CollectionManager.Individuals.ConvertSpecialIdentifier( identifier );
}
identifier = Penumbra.CollectionManager.Individuals.ConvertSpecialIdentifier( identifier );
var collection = CollectionByIdentifier( identifier )
?? CheckYourself( identifier, gameObject )
?? CollectionByAttributes( gameObject )