Do not associate timeline resources with characters in cutscenes.

This commit is contained in:
Ottermandias 2023-06-17 01:24:49 +02:00
parent 306c2ffd10
commit 3f1d84343a

View file

@ -1,5 +1,6 @@
using System; using System;
using System.Threading; using System.Threading;
using Dalamud.Game.ClientState.Conditions;
using Dalamud.Game.ClientState.Objects; using Dalamud.Game.ClientState.Objects;
using Dalamud.Hooking; using Dalamud.Hooking;
using Dalamud.Utility.Signatures; using Dalamud.Utility.Signatures;
@ -22,18 +23,20 @@ public unsafe class AnimationHookService : IDisposable
private readonly CollectionResolver _collectionResolver; private readonly CollectionResolver _collectionResolver;
private readonly DrawObjectState _drawObjectState; private readonly DrawObjectState _drawObjectState;
private readonly CollectionResolver _resolver; private readonly CollectionResolver _resolver;
private readonly Condition _conditions;
private readonly ThreadLocal<ResolveData> _animationLoadData = new(() => ResolveData.Invalid, true); private readonly ThreadLocal<ResolveData> _animationLoadData = new(() => ResolveData.Invalid, true);
private readonly ThreadLocal<ResolveData> _characterSoundData = new(() => ResolveData.Invalid, true); private readonly ThreadLocal<ResolveData> _characterSoundData = new(() => ResolveData.Invalid, true);
public AnimationHookService(PerformanceTracker performance, ObjectTable objects, CollectionResolver collectionResolver, public AnimationHookService(PerformanceTracker performance, ObjectTable objects, CollectionResolver collectionResolver,
DrawObjectState drawObjectState, CollectionResolver resolver) DrawObjectState drawObjectState, CollectionResolver resolver, Condition conditions)
{ {
_performance = performance; _performance = performance;
_objects = objects; _objects = objects;
_collectionResolver = collectionResolver; _collectionResolver = collectionResolver;
_drawObjectState = drawObjectState; _drawObjectState = drawObjectState;
_resolver = resolver; _resolver = resolver;
_conditions = conditions;
SignatureHelper.Initialise(this); SignatureHelper.Initialise(this);
@ -137,13 +140,17 @@ public unsafe class AnimationHookService : IDisposable
private ulong LoadTimelineResourcesDetour(IntPtr timeline) private ulong LoadTimelineResourcesDetour(IntPtr timeline)
{ {
using var performance = _performance.Measure(PerformanceType.TimelineResources); using var performance = _performance.Measure(PerformanceType.TimelineResources);
var last = _animationLoadData.Value; // Do not check timeline loading in cutscenes.
if (_conditions[ConditionFlag.OccupiedInCutSceneEvent] || _conditions[ConditionFlag.WatchingCutscene] || _conditions[ConditionFlag.WatchingCutscene78])
return _loadTimelineResourcesHook.Original(timeline);
var last = _animationLoadData.Value;
_animationLoadData.Value = GetDataFromTimeline(timeline); _animationLoadData.Value = GetDataFromTimeline(timeline);
var ret = _loadTimelineResourcesHook.Original(timeline); var ret = _loadTimelineResourcesHook.Original(timeline);
_animationLoadData.Value = last; _animationLoadData.Value = last;
return ret; return ret;
} }
/// <summary> /// <summary>
/// Probably used when the base idle animation gets loaded. /// Probably used when the base idle animation gets loaded.
/// Make it aware of the correct collection to load the correct pap files. /// Make it aware of the correct collection to load the correct pap files.
@ -287,17 +294,17 @@ public unsafe class AnimationHookService : IDisposable
} }
/// <summary> Use timelines vfuncs to obtain the associated game object. </summary> /// <summary> Use timelines vfuncs to obtain the associated game object. </summary>
private ResolveData GetDataFromTimeline(IntPtr timeline) private ResolveData GetDataFromTimeline(nint timeline)
{ {
try try
{ {
if (timeline != IntPtr.Zero) if (timeline != IntPtr.Zero)
{ {
var getGameObjectIdx = ((delegate* unmanaged<IntPtr, int>**)timeline)[0][Offsets.GetGameObjectIdxVfunc]; var getGameObjectIdx = ((delegate* unmanaged<nint, int>**)timeline)[0][Offsets.GetGameObjectIdxVfunc];
var idx = getGameObjectIdx(timeline); var idx = getGameObjectIdx(timeline);
if (idx >= 0 && idx < _objects.Length) if (idx >= 0 && idx < _objects.Length)
{ {
var obj = (GameObject*)_objects.GetObjectAddress(idx); var obj = (GameObject*)_objects.GetObjectAddress(idx);
return obj != null ? _collectionResolver.IdentifyCollection(obj, true) : ResolveData.Invalid; return obj != null ? _collectionResolver.IdentifyCollection(obj, true) : ResolveData.Invalid;
} }
} }
@ -310,7 +317,6 @@ public unsafe class AnimationHookService : IDisposable
return ResolveData.Invalid; return ResolveData.Invalid;
} }
private delegate void UnkMountAnimationDelegate(DrawObject* drawObject, uint unk1, byte unk2, uint unk3); private delegate void UnkMountAnimationDelegate(DrawObject* drawObject, uint unk1, byte unk2, uint unk3);
[Signature("48 89 5C 24 ?? 48 89 6C 24 ?? 89 54 24", DetourName = nameof(UnkMountAnimationDetour))] [Signature("48 89 5C 24 ?? 48 89 6C 24 ?? 89 54 24", DetourName = nameof(UnkMountAnimationDetour))]
@ -334,7 +340,7 @@ public unsafe class AnimationHookService : IDisposable
{ {
var last = _animationLoadData.Value; var last = _animationLoadData.Value;
_animationLoadData.Value = _collectionResolver.IdentifyCollection(drawObject, true); _animationLoadData.Value = _collectionResolver.IdentifyCollection(drawObject, true);
_unkParasolAnimationHook!.Original(drawObject, unk1); _unkParasolAnimationHook.Original(drawObject, unk1);
_animationLoadData.Value = last; _animationLoadData.Value = last;
} }