mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-14 12:44:19 +01:00
Add a hook for updating looped scds.
This commit is contained in:
parent
baf3b06060
commit
72408bf45c
3 changed files with 58 additions and 25 deletions
2
OtterGui
2
OtterGui
|
|
@ -1 +1 @@
|
||||||
Subproject commit 6a1e25a6c6aea6165c0a38771953e35550a1f9cf
|
Subproject commit 7c7b641feb30c1a03c47a5653c7f7cdde529dfc7
|
||||||
|
|
@ -70,6 +70,7 @@ public unsafe partial class PathResolver
|
||||||
_loadCharacterSoundHook.Enable();
|
_loadCharacterSoundHook.Enable();
|
||||||
_loadCharacterVfxHook.Enable();
|
_loadCharacterVfxHook.Enable();
|
||||||
_loadAreaVfxHook.Enable();
|
_loadAreaVfxHook.Enable();
|
||||||
|
_scheduleClipUpdateHook.Enable();
|
||||||
|
|
||||||
//_loadSomeAvfxHook.Enable();
|
//_loadSomeAvfxHook.Enable();
|
||||||
//_someOtherAvfxHook.Enable();
|
//_someOtherAvfxHook.Enable();
|
||||||
|
|
@ -84,6 +85,7 @@ public unsafe partial class PathResolver
|
||||||
_loadCharacterSoundHook.Disable();
|
_loadCharacterSoundHook.Disable();
|
||||||
_loadCharacterVfxHook.Disable();
|
_loadCharacterVfxHook.Disable();
|
||||||
_loadAreaVfxHook.Disable();
|
_loadAreaVfxHook.Disable();
|
||||||
|
_scheduleClipUpdateHook.Disable();
|
||||||
|
|
||||||
//_loadSomeAvfxHook.Disable();
|
//_loadSomeAvfxHook.Disable();
|
||||||
//_someOtherAvfxHook.Disable();
|
//_someOtherAvfxHook.Disable();
|
||||||
|
|
@ -98,6 +100,7 @@ public unsafe partial class PathResolver
|
||||||
_loadCharacterSoundHook.Dispose();
|
_loadCharacterSoundHook.Dispose();
|
||||||
_loadCharacterVfxHook.Dispose();
|
_loadCharacterVfxHook.Dispose();
|
||||||
_loadAreaVfxHook.Dispose();
|
_loadAreaVfxHook.Dispose();
|
||||||
|
_scheduleClipUpdateHook.Dispose();
|
||||||
|
|
||||||
//_loadSomeAvfxHook.Dispose();
|
//_loadSomeAvfxHook.Dispose();
|
||||||
//_someOtherAvfxHook.Dispose();
|
//_someOtherAvfxHook.Dispose();
|
||||||
|
|
@ -119,6 +122,29 @@ public unsafe partial class PathResolver
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static ResolveData GetDataFromTimeline( IntPtr timeline )
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if( timeline != IntPtr.Zero )
|
||||||
|
{
|
||||||
|
var getGameObjectIdx = ( ( delegate* unmanaged< IntPtr, int >** )timeline )[ 0 ][ 28 ];
|
||||||
|
var idx = getGameObjectIdx( timeline );
|
||||||
|
if( idx >= 0 && idx < Dalamud.Objects.Length )
|
||||||
|
{
|
||||||
|
var obj = Dalamud.Objects[ idx ];
|
||||||
|
return obj != null ? IdentifyCollection( ( GameObject* )obj.Address, true ) : ResolveData.Invalid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch( Exception e )
|
||||||
|
{
|
||||||
|
Penumbra.Log.Error( $"Error getting timeline data for 0x{timeline:X}:\n{e}" );
|
||||||
|
}
|
||||||
|
|
||||||
|
return ResolveData.Invalid;
|
||||||
|
}
|
||||||
|
|
||||||
// The timeline object loads the requested .tmb and .pap files. The .tmb files load the respective .avfx files.
|
// The timeline object loads the requested .tmb and .pap files. The .tmb files load the respective .avfx files.
|
||||||
// We can obtain the associated game object from the timelines 28'th vfunc and use that to apply the correct collection.
|
// We can obtain the associated game object from the timelines 28'th vfunc and use that to apply the correct collection.
|
||||||
private delegate ulong LoadTimelineResourcesDelegate( IntPtr timeline );
|
private delegate ulong LoadTimelineResourcesDelegate( IntPtr timeline );
|
||||||
|
|
@ -129,30 +155,9 @@ public unsafe partial class PathResolver
|
||||||
private ulong LoadTimelineResourcesDetour( IntPtr timeline )
|
private ulong LoadTimelineResourcesDetour( IntPtr timeline )
|
||||||
{
|
{
|
||||||
using var performance = Penumbra.Performance.Measure( PerformanceType.TimelineResources );
|
using var performance = Penumbra.Performance.Measure( PerformanceType.TimelineResources );
|
||||||
ulong ret;
|
var old = _animationLoadData;
|
||||||
var old = _animationLoadData;
|
_animationLoadData = GetDataFromTimeline( timeline );
|
||||||
try
|
var ret = _loadTimelineResourcesHook.Original( timeline );
|
||||||
{
|
|
||||||
if( timeline != IntPtr.Zero )
|
|
||||||
{
|
|
||||||
var getGameObjectIdx = ( ( delegate* unmanaged< IntPtr, int >** )timeline )[ 0 ][ 28 ];
|
|
||||||
var idx = getGameObjectIdx( timeline );
|
|
||||||
if( idx >= 0 && idx < Dalamud.Objects.Length )
|
|
||||||
{
|
|
||||||
var obj = Dalamud.Objects[ idx ];
|
|
||||||
_animationLoadData = obj != null ? IdentifyCollection( ( GameObject* )obj.Address, true ) : ResolveData.Invalid;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_animationLoadData = ResolveData.Invalid;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
ret = _loadTimelineResourcesHook.Original( timeline );
|
|
||||||
}
|
|
||||||
|
|
||||||
_animationLoadData = old;
|
_animationLoadData = old;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
@ -309,6 +314,32 @@ public unsafe partial class PathResolver
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[StructLayout( LayoutKind.Explicit )]
|
||||||
|
private struct ClipScheduler
|
||||||
|
{
|
||||||
|
[FieldOffset( 0 )]
|
||||||
|
public IntPtr* VTable;
|
||||||
|
|
||||||
|
[FieldOffset( 0x38 )]
|
||||||
|
public IntPtr SchedulerTimeline;
|
||||||
|
}
|
||||||
|
|
||||||
|
private delegate void ScheduleClipUpdate( ClipScheduler* x );
|
||||||
|
|
||||||
|
[Signature( "40 53 55 56 57 41 56 48 81 EC ?? ?? ?? ?? 48 8B F9", DetourName = nameof( ScheduleClipUpdateDetour ) )]
|
||||||
|
private readonly Hook< ScheduleClipUpdate > _scheduleClipUpdateHook = null!;
|
||||||
|
|
||||||
|
private void ScheduleClipUpdateDetour( ClipScheduler* x )
|
||||||
|
{
|
||||||
|
using var performance = Penumbra.Performance.Measure( PerformanceType.ScheduleClipUpdate );
|
||||||
|
var old = _animationLoadData;
|
||||||
|
var timeline = x->SchedulerTimeline;
|
||||||
|
_animationLoadData = GetDataFromTimeline( timeline );
|
||||||
|
_scheduleClipUpdateHook.Original( x );
|
||||||
|
_animationLoadData = old;
|
||||||
|
}
|
||||||
|
|
||||||
// ========== Those hooks seem to be superseded by LoadCharacterVfx =========
|
// ========== Those hooks seem to be superseded by LoadCharacterVfx =========
|
||||||
|
|
||||||
// public delegate ulong LoadSomeAvfx( uint a1, IntPtr gameObject, IntPtr gameObject2, float unk1, IntPtr unk2, IntPtr unk3 );
|
// public delegate ulong LoadSomeAvfx( uint a1, IntPtr gameObject, IntPtr gameObject2, float unk1, IntPtr unk2, IntPtr unk3 );
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@ public enum PerformanceType
|
||||||
LoadCharacterVfx,
|
LoadCharacterVfx,
|
||||||
LoadAreaVfx,
|
LoadAreaVfx,
|
||||||
LoadSound,
|
LoadSound,
|
||||||
|
ScheduleClipUpdate,
|
||||||
LoadAction,
|
LoadAction,
|
||||||
LoadCharacterBaseAnimation,
|
LoadCharacterBaseAnimation,
|
||||||
LoadPap,
|
LoadPap,
|
||||||
|
|
@ -51,6 +52,7 @@ public static class PerformanceTypeExtensions
|
||||||
PerformanceType.SetupCharacter => "SetupCharacter Hook",
|
PerformanceType.SetupCharacter => "SetupCharacter Hook",
|
||||||
PerformanceType.ChangeCustomize => "ChangeCustomize Hook",
|
PerformanceType.ChangeCustomize => "ChangeCustomize Hook",
|
||||||
PerformanceType.LoadSound => "LoadSound Hook",
|
PerformanceType.LoadSound => "LoadSound Hook",
|
||||||
|
PerformanceType.ScheduleClipUpdate => "ScheduleClipUpdate Hook",
|
||||||
PerformanceType.LoadCharacterBaseAnimation => "LoadCharacterAnimation Hook",
|
PerformanceType.LoadCharacterBaseAnimation => "LoadCharacterAnimation Hook",
|
||||||
PerformanceType.LoadPap => "LoadPap Hook",
|
PerformanceType.LoadPap => "LoadPap Hook",
|
||||||
PerformanceType.LoadAction => "LoadAction Hook",
|
PerformanceType.LoadAction => "LoadAction Hook",
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue