mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-12 10:17:22 +01:00
Do GPose Actor handling correctly in PlayerWatcher.
This commit is contained in:
parent
589dcfd751
commit
83954aec29
1 changed files with 59 additions and 20 deletions
|
|
@ -11,13 +11,14 @@ namespace Penumbra.PlayerWatch
|
|||
internal class PlayerWatchBase : IDisposable
|
||||
{
|
||||
public const int GPosePlayerActorIdx = 201;
|
||||
public const int GPoseActorEnd = GPosePlayerActorIdx + 48;
|
||||
private const int ActorsPerFrame = 8;
|
||||
|
||||
private readonly DalamudPluginInterface _pi;
|
||||
internal readonly HashSet< PlayerWatcher > RegisteredWatchers = new();
|
||||
private readonly Dictionary< string, (ActorEquipment, HashSet< PlayerWatcher >) > _equip = new();
|
||||
private int _frameTicker;
|
||||
private IntPtr _lastGPoseAddress = IntPtr.Zero;
|
||||
private bool _inGPose = false;
|
||||
|
||||
internal PlayerWatchBase( DalamudPluginInterface pi )
|
||||
{
|
||||
|
|
@ -117,26 +118,61 @@ namespace Penumbra.PlayerWatch
|
|||
}
|
||||
}
|
||||
|
||||
internal void TriggerGPose()
|
||||
{
|
||||
for( var i = GPosePlayerActorIdx; i < GPoseActorEnd; ++i )
|
||||
{
|
||||
var actor = _pi.ClientState.Actors[ i ];
|
||||
if( actor == null )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if( _equip.TryGetValue( actor.Name, out var watcher ) )
|
||||
{
|
||||
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 gPoseActor = actors[ GPosePlayerActorIdx ];
|
||||
if( gPoseActor == null )
|
||||
|
||||
var newInGPose = actors[ GPosePlayerActorIdx ] != null;
|
||||
|
||||
if( newInGPose != _inGPose )
|
||||
{
|
||||
if( _lastGPoseAddress != IntPtr.Zero && actors[ 0 ] != null && _equip.TryGetValue( actors[ 0 ].Name, out var player ) )
|
||||
if( newInGPose )
|
||||
{
|
||||
TriggerEvents( player.Item2, actors[ 0 ] );
|
||||
TriggerGPose();
|
||||
}
|
||||
|
||||
_lastGPoseAddress = IntPtr.Zero;
|
||||
}
|
||||
else if( gPoseActor.Address != _lastGPoseAddress )
|
||||
{
|
||||
_lastGPoseAddress = gPoseActor.Address;
|
||||
if( _equip.TryGetValue( gPoseActor.Name, out var gPose ) )
|
||||
{
|
||||
TriggerEvents( gPose.Item2, gPoseActor );
|
||||
}
|
||||
_inGPose = newInGPose;
|
||||
}
|
||||
|
||||
for( var i = 0; i < ActorsPerFrame; ++i )
|
||||
|
|
@ -145,16 +181,19 @@ namespace Penumbra.PlayerWatch
|
|||
? _frameTicker + 2
|
||||
: 0;
|
||||
|
||||
var actor = _frameTicker == 0 && gPoseActor != null ? gPoseActor : actors[ _frameTicker ];
|
||||
var actor = actors[ _frameTicker ];
|
||||
if( actor == null
|
||||
|| actor.ObjectKind != ObjectKind.Player
|
||||
|| actor.Name == null
|
||||
|| actor.Name.Length == 0 )
|
||||
|| actor.Name.Length == 0
|
||||
|| !_equip.TryGetValue( actor.Name, out var equip ) )
|
||||
{
|
||||
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 );
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue