Decompiled source of SnatcherBugFix v0.6.0

SnatcherBugFix.dll

Decompiled 3 days ago
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using AIGraph;
using Agents;
using BepInEx;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using BepInEx.Unity.IL2CPP.Hook;
using Enemies;
using ExteriorRendering;
using GTFO.API;
using HarmonyLib;
using Il2CppInterop.Runtime.Injection;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppInterop.Runtime.Runtime;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using LevelGeneration;
using Microsoft.CodeAnalysis;
using Player;
using PlayerCoverage;
using SNetwork;
using SnatcherBugFix.Utils;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("SnatcherBugFix")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+6ce156843ab1a86f2a2a2f4f499ac21a80508700")]
[assembly: AssemblyProduct("SnatcherBugFix")]
[assembly: AssemblyTitle("SnatcherBugFix")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[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]
	[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 SnatcherBugFix
{
	[BepInPlugin("Amor.SnatcherBugFix", "SnatcherBugFix", "0.6.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	internal sealed class EntryPoint : BasePlugin
	{
		public override void Load()
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			Logger.MLS = ((BasePlugin)this).Log;
			ClassInjector.RegisterTypeInIl2Cpp<SnatcherHandler>();
			SnatcherNativePatches.Init();
			new Harmony("Amor.SnatcherBugFix").PatchAll();
			Logger.Message("SnatcherBugFix is done loading!");
		}
	}
	internal static class Logger
	{
		public static ManualLogSource MLS { get; internal set; }

		public static void Error(BepInExErrorLogInterpolatedStringHandler handler)
		{
			MLS.LogError(handler);
		}

		public static void Error(string str)
		{
			MLS.LogError((object)str);
		}

		public static void Warn(BepInExWarningLogInterpolatedStringHandler handler)
		{
			MLS.LogWarning(handler);
		}

		public static void Warn(string str)
		{
			MLS.LogWarning((object)str);
		}

		public static void Message(BepInExMessageLogInterpolatedStringHandler handler)
		{
			MLS.LogMessage(handler);
		}

		public static void Message(string str)
		{
			MLS.LogMessage((object)str);
		}

		public static void Info(BepInExInfoLogInterpolatedStringHandler handler)
		{
			MLS.LogInfo(handler);
		}

		public static void Info(string str)
		{
			MLS.LogInfo((object)str);
		}

		public static void Debug(BepInExDebugLogInterpolatedStringHandler handler)
		{
			MLS.LogDebug(handler);
		}

		public static void Debug(string str)
		{
			MLS.LogDebug((object)str);
		}
	}
	public class SnatcherHandler : MonoBehaviour
	{
		public PlayerAgent Player = null;

		public EnemyAgent? Captor;

		public AIG_CourseNode? LastNode;

		public eDimensionIndex LastDimension;

		public Vector3 LastPosition;

		private float _warpTime;

		private const float DeadBuffer = 0.5f;

		public AIG_CourseNode? GoodNode
		{
			get
			{
				EnemyAgent? captor = Captor;
				return ((captor != null) ? ((Agent)captor).CourseNode : null) ?? LastNode;
			}
		}

		public eDimensionIndex GoodDimension
		{
			get
			{
				//IL_0012: Unknown result type (might be due to invalid IL or missing references)
				//IL_000b: Unknown result type (might be due to invalid IL or missing references)
				EnemyAgent? captor = Captor;
				return (captor != null) ? ((Agent)captor).DimensionIndex : LastDimension;
			}
		}

		public Vector3 GoodPosition
		{
			get
			{
				//IL_0012: Unknown result type (might be due to invalid IL or missing references)
				//IL_000b: Unknown result type (might be due to invalid IL or missing references)
				EnemyAgent? captor = Captor;
				return (captor != null) ? captor.Position : LastPosition;
			}
		}

		public bool IsInArenaDim
		{
			get
			{
				PlayerAgent player = Player;
				bool? obj;
				if (player == null)
				{
					obj = null;
				}
				else
				{
					Dimension dimension = ((Agent)player).Dimension;
					obj = ((dimension != null) ? new bool?(dimension.IsArenaDimension) : ((bool?)null));
				}
				bool? flag = obj;
				return flag == true;
			}
		}

		public void Awake()
		{
			Player = ((Component)this).GetComponent<PlayerAgent>();
			Logger.Debug("SnatcherHandler is ready");
		}

		public void Update()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Invalid comparison between Unknown and I4
			//IL_013b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: 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)
			if ((int)GameStateManager.CurrentStateName != 10 || (Object)(object)Player == (Object)null)
			{
				return;
			}
			bool isInArenaDim = IsInArenaDim;
			if (_warpTime > 0f && Clock.Time > _warpTime)
			{
				if (isInArenaDim)
				{
					Player.RequestWarpToSync(GoodDimension, GoodPosition, Player.FPSCamera.CameraRayDir, (WarpOptions)0);
					if (((Agent)Player).Alive)
					{
						Player.Locomotion.GrabbedByPouncer.StandUp();
					}
					FixWarpFX();
					Player.FPSCamera.PouncerScreenFX.SetCovered(false);
				}
				else if (Player.FPSCamera.PouncerScreenFX.covered)
				{
					Player.FPSCamera.PouncerScreenFX.SetCovered(false);
				}
				Captor = null;
				_warpTime = 0f;
			}
			else if (!isInArenaDim)
			{
				LastNode = ((Agent)Player).CourseNode;
				LastDimension = ((Agent)Player).DimensionIndex;
				LastPosition = ((Agent)Player).Position;
			}
		}

		public void OnConsumed(EnemyAgent pouncer, PouncerDataContainer data)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//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_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			bool flag = default(bool);
			BepInExDebugLogInterpolatedStringHandler val = new BepInExDebugLogInterpolatedStringHandler(34, 1, ref flag);
			if (flag)
			{
				((BepInExLogInterpolatedStringHandler)val).AppendLiteral("SnatcherHandler OnConsumed, Enemy ");
				((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(((Object)pouncer).GetInstanceID());
			}
			Logger.Debug(val);
			Captor = pouncer;
			HeldStateData heldStateData = data.HeldStateData;
			_warpTime = Clock.Time + data.ConsumeDuration + heldStateData.HeldStartAnimationDuration + heldStateData.MaxHeldDuration + heldStateData.SpitOutStateDuration;
		}

		public void OnDead(EnemyAgent pouncer)
		{
			if (!((Object)(object)Captor == (Object)null) && ((Object)Captor).GetInstanceID() == ((Object)pouncer).GetInstanceID())
			{
				Logger.Debug("SnatcherHandler OnDead");
				Captor = null;
				_warpTime = Clock.Time + 0.5f;
			}
		}

		private void FixWarpFX()
		{
			Dimension dimension = GoodNode.m_dimension;
			ExteriorCamera.GlobalSwitch = dimension.DimensionData.IsOutside;
			if (Object.op_Implicit((Object)(object)dimension.DimensionRootTemp.SkyOcclusionVolume))
			{
				dimension.DimensionRootTemp.SkyOcclusionVolume.Upload();
			}
			if (dimension.DimensionData.IsOutside)
			{
				Lighting.ReflectionsDirty = true;
			}
			if (dimension.IsMainDimension)
			{
				Dimension.SetRealitySoundEnvironment();
			}
			Player.UpdateSoundScape();
		}
	}
	internal static class SnatcherNativePatches
	{
		private unsafe delegate bool d_TryGetClosestAlivePlayerAgent(IntPtr node, out IntPtr playerAgent, Il2CppMethodInfo* methodInfo);

		private static INativeDetour _detour;

		private static d_TryGetClosestAlivePlayerAgent orig_TryGetClosestAlivePlayerAgent;

		internal static void Init()
		{
			ApplyNativePatch();
		}

		private unsafe static void ApplyNativePatch()
		{
			_detour = INativeDetour.CreateAndApply<d_TryGetClosestAlivePlayerAgent>((IntPtr)(nint)Il2CppAPI.GetIl2CppMethod<PlayerManager>("TryGetClosestAlivePlayerAgent", typeof(bool).FullName, false, new string[2]
			{
				typeof(AIG_CourseNode).FullName,
				typeof(PlayerAgent).MakeByRefType().FullName
			}), (d_TryGetClosestAlivePlayerAgent)TryGetClosestAlivePlayerAgentPatch, ref orig_TryGetClosestAlivePlayerAgent);
		}

		private unsafe static bool TryGetClosestAlivePlayerAgentPatch(IntPtr node, out IntPtr playerAgent, Il2CppMethodInfo* methodInfo)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Expected O, but got Unknown
			AIG_CourseNode val = new AIG_CourseNode(node);
			PlayerAgent val2 = null;
			PlayerAgent val3 = null;
			int num = int.MaxValue;
			for (int i = 0; i < PlayerManager.PlayerAgentsInLevel.Count; i++)
			{
				PlayerAgent val4 = PlayerManager.PlayerAgentsInLevel[i];
				if (!((Object)(object)val4 != (Object)null) || !((Agent)val4).Alive)
				{
					continue;
				}
				Dimension dimension = ((Agent)val4).Dimension;
				if (dimension != null && dimension.IsArenaDimension)
				{
					continue;
				}
				val3 = val4;
				if (i < ((Il2CppArrayBase<PlayerCoverageData>)(object)val.m_playerCoverage.m_coverageDatas).Length)
				{
					PlayerCoverageData val5 = ((Il2CppArrayBase<PlayerCoverageData>)(object)val.m_playerCoverage.m_coverageDatas)[i];
					if (val5.IsValidNodeDistance && num > val5.m_nodeDistance)
					{
						num = val5.m_nodeDistance;
						val2 = val4;
					}
				}
			}
			if ((Object)(object)val2 == (Object)null)
			{
				val2 = val3;
			}
			playerAgent = ((val2 != null) ? ((Il2CppObjectBase)val2).Pointer : IntPtr.Zero);
			return playerAgent != IntPtr.Zero;
		}
	}
	[HarmonyPatch]
	internal static class SnatcherPatches
	{
		private static SnatcherHandler? _handler;

		private static bool _prepared;

		[HarmonyPrepare]
		private static void Prepare()
		{
			if (!_prepared)
			{
				LevelAPI.OnEnterLevel += OnEnterLevel;
				_prepared = true;
			}
		}

		private static void OnEnterLevel()
		{
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Expected O, but got Unknown
			bool flag = false;
			Enumerator<Dimension> enumerator = Builder.CurrentFloor.m_dimensions.GetEnumerator();
			while (enumerator.MoveNext())
			{
				Dimension current = enumerator.Current;
				if (!current.IsArenaDimension)
				{
					continue;
				}
				flag = (byte)((flag ? 1u : 0u) | 1u) != 0;
				for (int i = 0; i < ((Component)current.DimensionLevel).transform.childCount; i++)
				{
					Transform child = ((Component)current.DimensionLevel).transform.GetChild(i);
					if (((Object)child).name.Contains("Cube", StringComparison.OrdinalIgnoreCase))
					{
						LODGroup val = ((Component)child).gameObject.AddOrGetComponent<LODGroup>();
						val.fadeMode = (LODFadeMode)0;
						MeshRenderer component = ((Component)child).GetComponent<MeshRenderer>();
						if (!((Object)(object)component == (Object)null))
						{
							LOD[] array = new LOD[1];
							LOD val2 = new LOD();
							val2.screenRelativeTransitionHeight = 0.7f;
							val2.fadeTransitionWidth = 0f;
							Renderer[] array2 = (Renderer[])(object)new MeshRenderer[1] { component };
							val2.renderers = Il2CppReferenceArray<Renderer>.op_Implicit(array2);
							array[0] = val2;
							val.SetLODs(Il2CppReferenceArray<LOD>.op_Implicit((LOD[])(object)array));
							val.RecalculateBounds();
						}
					}
				}
			}
			_handler = (flag ? ((Component)PlayerManager.GetLocalPlayerAgent()).gameObject.GetComponent<SnatcherHandler>() : null);
		}

		[HarmonyPatch(typeof(PlayerAgent), "Setup")]
		[HarmonyPostfix]
		[HarmonyWrapSafe]
		private static void Post_PlayerAgent_Setup(PlayerAgent __instance)
		{
			if (((Agent)__instance).IsLocallyOwned)
			{
				((Component)__instance).gameObject.AddOrGetComponent<SnatcherHandler>();
			}
		}

		[HarmonyPatch(typeof(SurvivalWave), "OnSpawn")]
		[HarmonyPostfix]
		[HarmonyWrapSafe]
		private static void Post_SurvivalWave_OnSpawn(SurvivalWave __instance)
		{
			AIG_CourseNode courseNode = __instance.m_courseNode;
			if (courseNode != null && courseNode.m_dimension.IsArenaDimension)
			{
				__instance.m_courseNode = _handler?.GoodNode ?? __instance.m_courseNode;
			}
		}

		[HarmonyPatch(typeof(EnemySync), "OnSpawn")]
		[HarmonyPostfix]
		[HarmonyPriority(600)]
		[HarmonyWrapSafe]
		private static void Post_EnemySync_OnSpawn(EnemySync __instance)
		{
			EnemyAgent enemy = __instance.m_agent;
			if (enemy.IsSetup && enemy.IsArenaDimensionEnemy)
			{
				enemy.AddOnDeadOnce(delegate
				{
					_handler?.OnDead(enemy);
				});
			}
		}

		[HarmonyPatch(typeof(PouncerBehaviour), "OnConsumeRequestReceived")]
		[HarmonyPostfix]
		[HarmonyWrapSafe]
		private static void Post_Consume(PouncerBehaviour __instance, pEB_PouncerTargetInfoPacket data)
		{
			PlayerAgent val = default(PlayerAgent);
			if (PlayerManager.TryGetPlayerAgent(ref data.PlayerSlot, ref val) && ((Agent)val).IsLocallyOwned)
			{
				_handler?.OnConsumed(((EnemyBehaviour)__instance).m_ai.m_enemyAgent, __instance.Data);
			}
		}

		[HarmonyPatch(typeof(PouncerBehaviour), "RequestConsume")]
		[HarmonyPostfix]
		[HarmonyWrapSafe]
		private static void Post_Consume(PouncerBehaviour __instance, int playerSlotIndex)
		{
			PlayerAgent val = default(PlayerAgent);
			if (SNet.IsMaster && PlayerManager.TryGetPlayerAgent(ref playerSlotIndex, ref val) && ((Agent)val).IsLocallyOwned)
			{
				_handler?.OnConsumed(((EnemyBehaviour)__instance).m_ai.m_enemyAgent, __instance.Data);
			}
		}

		[HarmonyPatch(typeof(PouncerScreenFX), "SetCovered", new Type[] { typeof(bool) })]
		[HarmonyPrefix]
		[HarmonyWrapSafe]
		private static void Pre_CoverScreen()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Invalid comparison between Unknown and I4
			if ((int)GameStateManager.CurrentStateName == 10)
			{
				FocusStateManager.ChangeState((eFocusState)4, true);
			}
		}
	}
}
namespace SnatcherBugFix.Utils
{
	internal static class EnemyAgentExtensions
	{
		public static void AddOnDeadOnce(this EnemyAgent agent, Action onDead)
		{
			bool called = false;
			agent.OnDeadCallback += Action.op_Implicit((Action)delegate
			{
				if (!called)
				{
					onDead?.Invoke();
					called = true;
				}
			});
		}
	}
	internal static class GameObjectExtensions
	{
		public static bool TryAndGetComponent<T>(this GameObject go, out T component)
		{
			component = go.GetComponent<T>();
			return component != null;
		}

		public static T AddOrGetComponent<T>(this GameObject go) where T : Component
		{
			if (!go.TryAndGetComponent<T>(out var component))
			{
				return go.AddComponent<T>();
			}
			return component;
		}
	}
}