make kill anim patch update resilient

This commit is contained in:
XtraCube committed 2025-10-14 14:35:20 -04:00
1 parent 88329bef79
commit cb794c3fc2
3 files changed
+69 -31

No files matched your search

@@ -0,0 +1,35 @@
using System.Reflection;
using HarmonyLib;
using Il2CppInterop.Runtime.InteropTypes;
using MiraAPI.Events;
using MiraAPI.Events.Vanilla.Gameplay;
using MiraAPI.Utilities;
namespace MiraAPI.Patches.Events;
/// <summary>
/// Patch to invoke AfterMurderEvent after a kill animation is performed.
/// </summary>
[HarmonyPatch]
public static class KillAnimationMurderEventPatch
{
public static MethodBase TargetMethod()
{
return Helpers.GetStateMachineMoveNext<KillAnimation>(nameof(KillAnimation.CoPerformKill))!;
}
public static void Postfix(Il2CppObjectBase __instance)
{
var wrapper = new StateMachineWrapper<KillAnimation>(__instance);
if (wrapper.GetState() != 1)
{
return;
}
var source = wrapper.GetParameter<PlayerControl>("source");
var target = wrapper.GetParameter<PlayerControl>("target");
var afterMurderEvent = new AfterMurderEvent(source, target, Helpers.GetBodyById(target.PlayerId));
MiraEventManager.InvokeEvent(afterMurderEvent);
}
}
@@ -1,30 +0,0 @@
using HarmonyLib;
using MiraAPI.Events;
using MiraAPI.Events.Vanilla.Gameplay;
using MiraAPI.Utilities;
namespace MiraAPI.Patches.Events;
/// <summary>
/// General patches for the KillAnimation class.
/// </summary>
[HarmonyPatch]
public static class KillAnimationPatches
{
/// <summary>
/// Used to trigger the <see cref="AfterMurderEvent"/>.
/// </summary>
[HarmonyPostfix]
[HarmonyPatch(typeof(KillAnimation._CoPerformKill_d__2), nameof(KillAnimation._CoPerformKill_d__2.MoveNext))]
public static void KillAnimPostfix(KillAnimation._CoPerformKill_d__2 __instance)
{
// Checking if state is -1 to wait for the end of coroutine.
if (__instance.__1__state != -1)
{
return;
}
var afterMurderEvent = new AfterMurderEvent(__instance.source, __instance.target, Helpers.GetBodyById(__instance.target.PlayerId));
MiraEventManager.InvokeEvent(afterMurderEvent);
}
}
+34 -1
View File
@@ -1,4 +1,6 @@
using System.Reflection;
using System;
using System.Collections.Generic;
using System.Reflection;
using HarmonyLib;
using Il2CppInterop.Runtime.InteropTypes;
@@ -11,8 +13,11 @@ namespace MiraAPI.Utilities;
public class StateMachineWrapper<T> where T : Il2CppObjectBase
{
private readonly Il2CppObjectBase _stateMachine;
// normally it is fields, but IL2CPP turns them into properties
private readonly PropertyInfo _thisProperty;
private readonly PropertyInfo _stateProperty;
private readonly Dictionary<string, PropertyInfo> _propertyCache;
private T? _parentInstance;
@@ -32,6 +37,13 @@ public class StateMachineWrapper<T> where T : Il2CppObjectBase
var type = _stateMachine.GetType();
_thisProperty = AccessTools.Property(type, "__4__this");
_stateProperty = AccessTools.Property(type, "__1__state");
if (_thisProperty == null || _stateProperty == null)
{
throw new MissingMemberException($"Could not find required properties in type '{type}'.");
}
_propertyCache = [];
}
/// <summary>
@@ -39,4 +51,25 @@ public class StateMachineWrapper<T> where T : Il2CppObjectBase
/// </summary>
/// <returns>The current state as an integer.</returns>
public int GetState() => (int)_stateProperty.GetValue(_stateMachine)!;
/// <summary>
/// Gets a parameter from the state machine by its name.
/// </summary>
/// <param name="parameterName">The name of the parameter to retrieve.</param>
/// <typeparam name="TField">The type of the parameter to retrieve.</typeparam>
/// <returns>>The value of the specified parameter.</returns>
/// <exception cref="MissingFieldException">Thrown if the specified parameter does not exist.</exception>
public TField GetParameter<TField>(string parameterName)
{
if (_propertyCache.TryGetValue(parameterName, out var property))
{
return (TField)property.GetValue(_stateMachine)!;
}
property = AccessTools.Property(_stateMachine.GetType(), parameterName)
?? throw new MissingFieldException($"Could not find parameter '{parameterName}' in state machine of type '{_stateMachine.GetType()}'.");
_propertyCache[parameterName] = property;
return (TField)property.GetValue(_stateMachine)!;
}
}