Do GPose Actor handling correctly in PlayerWatcher.

This commit is contained in:
Ottermandias 2021-08-10 16:14:08 +02:00
parent 589dcfd751
commit 83954aec29

View file

@ -11,13 +11,14 @@ namespace Penumbra.PlayerWatch
internal class PlayerWatchBase : IDisposable internal class PlayerWatchBase : IDisposable
{ {
public const int GPosePlayerActorIdx = 201; public const int GPosePlayerActorIdx = 201;
public const int GPoseActorEnd = GPosePlayerActorIdx + 48;
private const int ActorsPerFrame = 8; private const int ActorsPerFrame = 8;
private readonly DalamudPluginInterface _pi; private readonly DalamudPluginInterface _pi;
internal readonly HashSet< PlayerWatcher > RegisteredWatchers = new(); internal readonly HashSet< PlayerWatcher > RegisteredWatchers = new();
private readonly Dictionary< string, (ActorEquipment, HashSet< PlayerWatcher >) > _equip = new(); private readonly Dictionary< string, (ActorEquipment, HashSet< PlayerWatcher >) > _equip = new();
private int _frameTicker; private int _frameTicker;
private IntPtr _lastGPoseAddress = IntPtr.Zero; private bool _inGPose = false;
internal PlayerWatchBase( DalamudPluginInterface pi ) internal PlayerWatchBase( DalamudPluginInterface pi )
{ {
@ -117,27 +118,62 @@ namespace Penumbra.PlayerWatch
} }
} }
private void OnFrameworkUpdate( object framework ) internal void TriggerGPose()
{ {
var actors = _pi.ClientState.Actors; for( var i = GPosePlayerActorIdx; i < GPoseActorEnd; ++i )
var gPoseActor = actors[ GPosePlayerActorIdx ];
if( gPoseActor == null )
{ {
if( _lastGPoseAddress != IntPtr.Zero && actors[ 0 ] != null && _equip.TryGetValue( actors[ 0 ].Name, out var player ) ) var actor = _pi.ClientState.Actors[ i ];
if( actor == null )
{ {
TriggerEvents( player.Item2, actors[ 0 ] ); return;
} }
_lastGPoseAddress = IntPtr.Zero; if( _equip.TryGetValue( actor.Name, out var watcher ) )
}
else if( gPoseActor.Address != _lastGPoseAddress )
{
_lastGPoseAddress = gPoseActor.Address;
if( _equip.TryGetValue( gPoseActor.Name, out var gPose ) )
{ {
TriggerEvents( gPose.Item2, gPoseActor ); TriggerEvents( watcher.Item2, actor );
} }
} }
}
private Actor CheckGPoseActor( Actor actor )
{
if( !_inGPose )
{
return actor;
}
for( var i = GPosePlayerActorIdx; i < GPoseActorEnd; ++i )
{
var a = _pi.ClientState.Actors[ i ];
if( a == null )
{
return actor;
}
if( a.Name == actor.Name )
{
return a;
}
}
return actor;
}
private void OnFrameworkUpdate( object framework )
{
var actors = _pi.ClientState.Actors;
var newInGPose = actors[ GPosePlayerActorIdx ] != null;
if( newInGPose != _inGPose )
{
if( newInGPose )
{
TriggerGPose();
}
_inGPose = newInGPose;
}
for( var i = 0; i < ActorsPerFrame; ++i ) for( var i = 0; i < ActorsPerFrame; ++i )
{ {
@ -145,16 +181,19 @@ namespace Penumbra.PlayerWatch
? _frameTicker + 2 ? _frameTicker + 2
: 0; : 0;
var actor = _frameTicker == 0 && gPoseActor != null ? gPoseActor : actors[ _frameTicker ]; var actor = actors[ _frameTicker ];
if( actor == null if( actor == null
|| actor.ObjectKind != ObjectKind.Player || actor.ObjectKind != ObjectKind.Player
|| actor.Name == null || actor.Name == null
|| actor.Name.Length == 0 ) || actor.Name.Length == 0
|| !_equip.TryGetValue( actor.Name, out var equip ) )
{ {
continue; continue;
} }
if( _equip.TryGetValue( actor.Name, out var equip ) && !equip.Item1.CompareAndUpdate( actor ) ) actor = CheckGPoseActor( actor );
if( !equip.Item1.CompareAndUpdate( actor ) )
{ {
TriggerEvents( equip.Item2, actor ); TriggerEvents( equip.Item2, actor );
} }