Decompiled source of EnemyAnimationFix v1.0.0

EnemyAnimationFix.dll

Decompiled 10 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using AIGraph;
using Agents;
using BepInEx;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using BepInEx.Unity.IL2CPP.Hook;
using Enemies;
using EnemyAnimationFix.API;
using EnemyAnimationFix.NativePatches;
using EnemyAnimationFix.Networking.Notify;
using EnemyAnimationFix.Patches;
using GTFO.API;
using HarmonyLib;
using Il2CppInterop.Runtime;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppInterop.Runtime.Runtime;
using Il2CppInterop.Runtime.Runtime.VersionSpecific.Class;
using Il2CppInterop.Runtime.Runtime.VersionSpecific.MethodInfo;
using Microsoft.CodeAnalysis;
using SNetwork;
using StateMachines;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("EnemyAnimationFix")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+5c495248eefd641857f9e93b338d475cd9bd511e")]
[assembly: AssemblyProduct("EnemyAnimationFix")]
[assembly: AssemblyTitle("EnemyAnimationFix")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
}
namespace EnemyAnimationFix
{
	[BepInPlugin("Dinorush.EnemyAnimationFix", "EnemyAnimationFix", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	internal sealed class EntryPoint : BasePlugin
	{
		public const string MODNAME = "EnemyAnimationFix";

		public override void Load()
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			((BasePlugin)this).Log.LogMessage((object)"Loading EnemyAnimationFix");
			new Harmony("EnemyAnimationFix").PatchAll();
			ChangeStatePatches.ApplyNativePatch();
			AssetAPI.OnStartupAssetsLoaded += AssetAPI_OnStartupAssetsLoaded;
			((BasePlugin)this).Log.LogMessage((object)"Loaded EnemyAnimationFix");
		}

		private void AssetAPI_OnStartupAssetsLoaded()
		{
			NotifyManager.Init();
		}
	}
}
namespace EnemyAnimationFix.Utils
{
	internal static class DinoLogger
	{
		private static ManualLogSource logger = Logger.CreateLogSource("EnemyAnimationFix");

		public static void Log(string format, params object[] args)
		{
			Log(string.Format(format, args));
		}

		public static void Log(string str)
		{
			if (logger != null)
			{
				logger.Log((LogLevel)8, (object)str);
			}
		}

		public static void Warning(string format, params object[] args)
		{
			Warning(string.Format(format, args));
		}

		public static void Warning(string str)
		{
			if (logger != null)
			{
				logger.Log((LogLevel)4, (object)str);
			}
		}

		public static void Error(string format, params object[] args)
		{
			Error(string.Format(format, args));
		}

		public static void Error(string str)
		{
			if (logger != null)
			{
				logger.Log((LogLevel)2, (object)str);
			}
		}

		public static void Debug(string format, params object[] args)
		{
			Debug(string.Format(format, args));
		}

		public static void Debug(string str)
		{
			if (logger != null)
			{
				logger.Log((LogLevel)32, (object)str);
			}
		}
	}
}
namespace EnemyAnimationFix.Patches
{
	[HarmonyPatch]
	internal static class EnemyAttackPatches
	{
		[HarmonyPatch(typeof(ES_StrikerAttack), "OnAttackPerform")]
		[HarmonyPostfix]
		private static void Post_StrikerAttackPerform(ES_StrikerAttack __instance)
		{
			__instance.m_tentacleAbility.m_tentacle.m_inAttackMove = true;
		}

		[HarmonyPatch(typeof(ES_ShooterAttack), "OnAttackPerform")]
		[HarmonyPostfix]
		private static void Post_ShooterAttackPerform(ES_ShooterAttack __instance)
		{
			if (!(((ES_EnemyAttackBase)__instance).m_attackDoneTimer >= Clock.Time))
			{
				EAB_ProjectileShooter projectileAbility = __instance.m_projectileAbility;
				((ES_EnemyAttackBase)__instance).m_attackDoneTimer = Clock.Time + (projectileAbility.m_shotDelayMin + projectileAbility.m_shotDelayMax) / 2f * (float)projectileAbility.m_burstCount * 0.7f + __instance.m_burstCoolDownBeforeExit;
			}
		}

		[HarmonyPatch(typeof(ES_StrikerAttack), "CommonExit")]
		[HarmonyPostfix]
		private static void Post_StrikerAttackExit(ES_StrikerAttack __instance)
		{
			if (NotifyManager.MasterHasFix && !(Clock.Time <= ((ES_EnemyAttackBase)__instance).m_performAttackTimer))
			{
				MovingEnemyTentacleBase tentacle = __instance.m_tentacleAbility.m_tentacle;
				if (tentacle.m_currentRoutine != null)
				{
					tentacle.SwitchCoroutine(tentacle.AttackIn(tentacle.m_attackInDuration));
				}
			}
		}

		[HarmonyPatch(typeof(ES_PathMove), "Exit")]
		[HarmonyPostfix]
		private static void Post_TankPathMoveExit(ES_PathMove __instance)
		{
			if (NotifyManager.MasterHasFix)
			{
				EnemyAbilities abilities = ((ES_Base)__instance).m_enemyAgent.Abilities;
				if (!ResetTankTongues(abilities, (AgentAbility)2))
				{
					ResetTankTongues(abilities, (AgentAbility)1);
				}
			}
		}

		private static bool ResetTankTongues(EnemyAbilities abilities, AgentAbility abilityType)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			EnemyAbility ability = abilities.GetAbility(abilityType, 0);
			if ((Object)(object)ability == (Object)null)
			{
				return false;
			}
			EAB_MovingEnemyTentacleMultiple val = ((Il2CppObjectBase)ability).TryCast<EAB_MovingEnemyTentacleMultiple>();
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			foreach (MovingEnemyTentacleBase item in (Il2CppArrayBase<MovingEnemyTentacleBase>)(object)val.m_tentacles)
			{
				if (item.m_currentRoutine != null)
				{
					item.SwitchCoroutine(item.AttackIn(item.m_attackInDuration));
				}
			}
			return true;
		}

		[HarmonyPatch(typeof(ES_ShooterAttack), "CommonExit")]
		[HarmonyPostfix]
		private static void Post_ShooterAttackExit(ES_ShooterAttack __instance)
		{
			if (NotifyManager.MasterHasFix && !(Clock.Time <= ((ES_EnemyAttackBase)__instance).m_performAttackTimer))
			{
				__instance.m_projectileAbility.FireEnd();
			}
		}
	}
	[HarmonyPatch]
	internal static class EnemyMovementPatches
	{
		private const float MinBufferTime = 0.1f;

		private static float _exitTime;

		internal static bool Pre_ChangeState(StateMachine<ES_Base> _, ES_Base newState)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Invalid comparison between Unknown and I4
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			if (SNet.IsMaster || (int)newState.m_stateEnum != 2 || Clock.Time - _exitTime > 0.1f)
			{
				return true;
			}
			ES_PathMove val = ((Il2CppObjectBase)newState).Cast<ES_PathMove>();
			EnemyAgent enemyAgent = ((ES_Base)val).m_enemyAgent;
			PositionSnapshotBuffer<pES_PathMoveData> positionBuffer = val.m_positionBuffer;
			ForcePosition(enemyAgent, val, positionBuffer[positionBuffer.Count - 1]);
			return false;
		}

		[HarmonyPatch(typeof(ES_PathMove), "Exit")]
		[HarmonyPrefix]
		private static void Pre_Exit(ES_PathMove __instance)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			_exitTime = Clock.Time;
			EnemyAgent enemyAgent = ((ES_Base)__instance).m_enemyAgent;
			pES_PathMoveData val;
			if (SNet.IsMaster)
			{
				val = __instance.m_pathMoveData;
				((pCourseNode)(ref val.CourseNode)).Set(((Agent)enemyAgent).CourseNode);
				val.Position = enemyAgent.Position;
				((LowResVector3_NoY)(ref val.Movement)).Set(__instance.m_moveDir, 1f);
				((LowResVector3_NoY_Normalized)(ref val.TargetLookDir)).Value = ((Agent)enemyAgent).TargetLookDir;
				val.Tick++;
				__instance.m_pathMoveData = val;
				{
					foreach (SNet_Player fixedClient in NotifyManager.FixedClients)
					{
						__instance.m_pathMovePacket.Send(val, (SNet_ChannelType)4, fixedClient);
					}
					return;
				}
			}
			if (__instance.m_positionBuffer.Count != 0)
			{
				PositionSnapshotBuffer<pES_PathMoveData> positionBuffer = __instance.m_positionBuffer;
				val = positionBuffer[positionBuffer.Count - 1];
				ForcePosition(enemyAgent, __instance, val);
			}
		}

		private static void ForcePosition(EnemyAgent enemy, ES_PathMove pathMove, pES_PathMoveData data)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			((Component)enemy).transform.position = enemy.Position;
			enemy.MovingCuller.UpdatePosition(((Agent)enemy).DimensionIndex, enemy.Position);
			enemy.Position = data.Position;
			((ES_PathMoveBase)pathMove).m_lastPos = data.Position;
			enemy.Locomotion.ForceNode(data.CourseNode);
			pathMove.m_targetPosition = data.Position;
			pathMove.m_moveDir = ((LowResVector3_NoY)(ref data.Movement)).Get(1f);
			((Agent)enemy).TargetLookDir = ((LowResVector3_NoY_Normalized)(ref data.TargetLookDir)).Value;
			((ES_PathMoveBase)pathMove).UpdateRotation();
			((ES_PathMoveBase)pathMove).UpdateLocalAnimator();
			pathMove.UpdateAnimationBlend(((ES_PathMoveBase)pathMove).m_animFwd, ((ES_PathMoveBase)pathMove).m_animRight, false);
		}
	}
	[HarmonyPatch]
	internal static class NetworkingPatches
	{
		[HarmonyPatch(typeof(SNet_SyncManager), "OnFoundMaster")]
		[HarmonyPatch(typeof(SNet_SyncManager), "OnFoundNewMasterDuringMigration")]
		[HarmonyPostfix]
		private static void Post_Joined()
		{
			if (!SNet.IsMaster)
			{
				NotifyManager.SendNotify(SNet.Master);
			}
			else
			{
				NotifyManager.SetMaster();
			}
		}

		[HarmonyPatch(typeof(SNet_SyncManager), "OnPlayerJoinedSessionHub")]
		[HarmonyPostfix]
		private static void Post_Joined(SNet_Player player)
		{
			if (SNet.IsMaster && !player.IsLocal)
			{
				NotifyManager.SendNotify(player);
			}
		}

		[HarmonyPatch(typeof(SNet_SessionHub), "OnLeftLobby")]
		[HarmonyPatch(typeof(SNet_SessionHub), "RemovePlayerFromSession")]
		[HarmonyPrefix]
		private static void Pre_Eject(SNet_Player player)
		{
			if (SNet.IsMaster)
			{
				NotifyManager.RemoveClient(player);
			}
		}

		[HarmonyPatch(typeof(SNet_SyncManager), "OnResetSession")]
		[HarmonyPrefix]
		private static void Pre_OnReset()
		{
			NotifyManager.Reset();
		}
	}
}
namespace EnemyAnimationFix.Networking
{
	public abstract class SyncedEvent<T> where T : struct
	{
		public delegate void ReceiveHandler(T packet);

		private bool _isSetup;

		public abstract string GUID { get; }

		public bool IsSetup => _isSetup;

		public string EventName { get; private set; } = string.Empty;


		public event ReceiveHandler? OnReceive;

		public event ReceiveHandler? OnReceiveLocal;

		public void Setup()
		{
			if (!_isSetup)
			{
				EventName = "EWC" + GUID;
				NetworkAPI.RegisterEvent<T>(EventName, (Action<ulong, T>)ReceiveClient_Callback);
				_isSetup = true;
			}
		}

		public void Send(T packetData, SNet_Player? target = null, SNet_ChannelType priority = 4)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)target != (Object)null)
			{
				NetworkAPI.InvokeEvent<T>(EventName, packetData, target, priority);
			}
			else
			{
				NetworkAPI.InvokeEvent<T>(EventName, packetData, priority);
			}
			ReceiveLocal_Callback(packetData);
		}

		private void ReceiveLocal_Callback(T packet)
		{
			ReceiveLocal(packet);
			this.OnReceiveLocal?.Invoke(packet);
		}

		private void ReceiveClient_Callback(ulong sender, T packet)
		{
			Receive(packet);
			this.OnReceive?.Invoke(packet);
		}

		protected virtual void ReceiveLocal(T packet)
		{
		}

		protected virtual void Receive(T packet)
		{
		}
	}
}
namespace EnemyAnimationFix.Networking.Notify
{
	internal static class NotifyManager
	{
		private static readonly NotifySync Sync = new NotifySync();

		public static readonly List<SNet_Player> FixedClients = new List<SNet_Player>();

		public static bool MasterHasFix { get; private set; } = false;


		internal static void Init()
		{
			Sync.Setup();
		}

		internal static void SendNotify(SNet_Player player)
		{
			Sync.Send(new NotifyData
			{
				lookup = SNet.LocalPlayer.Lookup
			}, player, (SNet_ChannelType)4);
		}

		internal static void ReceiveNotify(SNet_Player player)
		{
			if (SNet.IsMaster)
			{
				FixedClients.Add(player);
			}
			else
			{
				MasterHasFix = true;
			}
		}

		internal static void SetMaster()
		{
			MasterHasFix = true;
		}

		internal static void Reset()
		{
			MasterHasFix = false;
			FixedClients.Clear();
		}

		internal static void RemoveClient(SNet_Player player)
		{
			for (int num = FixedClients.Count - 1; num >= 0; num--)
			{
				if ((Object)(object)FixedClients[num] == (Object)null || FixedClients[num].Lookup == player.Lookup)
				{
					FixedClients.RemoveAt(num);
				}
			}
		}
	}
	internal sealed class NotifySync : SyncedEvent<NotifyData>
	{
		public override string GUID => "EAFNF";

		protected override void Receive(NotifyData packet)
		{
			SNet_Player player = default(SNet_Player);
			if (SNet.TryGetPlayer(packet.lookup, ref player))
			{
				NotifyManager.ReceiveNotify(player);
			}
		}
	}
	public struct NotifyData
	{
		public ulong lookup;
	}
}
namespace EnemyAnimationFix.NativePatches
{
	internal static class ChangeStatePatches
	{
		private unsafe delegate void d_ChangeStateFromQueue(IntPtr _this, Il2CppMethodInfo* methodInfo);

		private static INativeDetour? ChangeStateDetour;

		private static d_ChangeStateFromQueue? orig_ChangeStateFromQueue;

		internal unsafe static void ApplyNativePatch()
		{
			NativePatchAPI.AddChangeStatePrefix(FixMeleeCancel);
			NativePatchAPI.AddChangeStatePrefix(EnemyMovementPatches.Pre_ChangeState);
			INativeClassStruct val = UnityVersionHandler.Wrap((Il2CppClass*)(void*)Il2CppClassPointerStore<StateMachine<ES_Base>>.NativeClassPtr);
			for (int i = 0; i < val.MethodCount; i++)
			{
				INativeMethodInfoStruct val2 = UnityVersionHandler.Wrap(val.Methods[i]);
				if (Marshal.PtrToStringAnsi(val2.Name) == "ChangeStateFromQueue")
				{
					ChangeStateDetour = INativeDetour.CreateAndApply<d_ChangeStateFromQueue>(val2.MethodPointer, (d_ChangeStateFromQueue)ChangeStatePatch, ref orig_ChangeStateFromQueue);
					break;
				}
			}
		}

		private unsafe static void ChangeStatePatch(IntPtr _this, Il2CppMethodInfo* methodInfo)
		{
			StateMachine<ES_Base> val = new StateMachine<ES_Base>(_this);
			if (val.CurrentState == null)
			{
				orig_ChangeStateFromQueue(_this, methodInfo);
				return;
			}
			ES_Base state = val.m_stateQueue.Peek();
			if (NativePatchAPI.RunChangeStatePrefix(val, state))
			{
				orig_ChangeStateFromQueue(_this, methodInfo);
			}
			else
			{
				val.m_stateQueue.Dequeue();
			}
			NativePatchAPI.RunChangeStatePostfix(val, state);
		}

		private static bool FixMeleeCancel(StateMachine<ES_Base> __instance, ES_Base newState)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Invalid comparison between Unknown and I4
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Invalid comparison between Unknown and I4
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			ES_Base currentState = __instance.CurrentState;
			if (!NotifyManager.MasterHasFix || (int)newState.m_stateEnum != 2 || (int)currentState.m_stateEnum != 23)
			{
				return true;
			}
			ES_StrikerMelee val = ((Il2CppObjectBase)currentState).Cast<ES_StrikerMelee>();
			return (Clock.Time - val.m_startTime) * val.m_animSpeed >= val.m_attackData.Duration;
		}
	}
}
namespace EnemyAnimationFix.API
{
	public static class NativePatchAPI
	{
		public delegate bool ChangeStatePrefix(StateMachine<ES_Base> __instance, ES_Base state);

		public delegate void ChangeStatePostfix(StateMachine<ES_Base> __instance, ES_Base state);

		private static readonly List<ChangeStatePrefix> s_changePrefix = new List<ChangeStatePrefix>();

		private static readonly List<ChangeStatePostfix> s_changePostfix = new List<ChangeStatePostfix>();

		public static void AddChangeStatePrefix(ChangeStatePrefix detectPrefix)
		{
			s_changePrefix.Add(detectPrefix);
		}

		public static void AddChangeStatePostfix(ChangeStatePostfix detectPostfix)
		{
			s_changePostfix.Add(detectPostfix);
		}

		internal static bool RunChangeStatePrefix(StateMachine<ES_Base> __instance, ES_Base state)
		{
			bool flag = true;
			foreach (ChangeStatePrefix item in s_changePrefix)
			{
				flag &= item(__instance, state);
			}
			return flag;
		}

		internal static void RunChangeStatePostfix(StateMachine<ES_Base> __instance, ES_Base state)
		{
			foreach (ChangeStatePostfix item in s_changePostfix)
			{
				item(__instance, state);
			}
		}
	}
}