Decompiled source of GunshyREUPLOAD v1.0.2

Gunshy.dll

Decompiled 10 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BoneLib;
using BoneLib.BoneMenu;
using Gunshy;
using HarmonyLib;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppSLZ.Marrow;
using Il2CppSLZ.Marrow.AI;
using Il2CppSLZ.Marrow.PuppetMasta;
using MelonLoader;
using MelonLoader.Preferences;
using UnityEngine;
using UnityEngine.AI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: MelonInfo(typeof(GunshyMod), "Gunshy", "1.0.0", "Gunshy", null)]
[assembly: MelonGame("Stress Level Zero", "BONELAB")]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("Gunshy")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("Gunshy")]
[assembly: AssemblyTitle("Gunshy")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace Gunshy;

public class GunshyMod : MelonMod
{
	private sealed class Panic
	{
		public BehaviourBaseNav behaviour;

		public NavMeshAgent agent;

		public float originalSpeed;

		public float originalAccel;

		public bool originalBraking;

		public Vector3 awayFrom;

		public Vector3 dest;

		public float until;

		public float repathAt;
	}

	internal static MelonPreferences_Entry<bool> Enabled;

	internal static MelonPreferences_Entry<float> HearRadius;

	internal static MelonPreferences_Entry<float> FleeSeconds;

	internal static MelonPreferences_Entry<float> FleeSpeed;

	private readonly Dictionary<int, Panic> panics = new Dictionary<int, Panic>();

	private Harmony harmony;

	private Action<Gun> gunHandler;

	private Action unloadHandler;

	private float nextLogTime;

	private bool loggedDriveError;

	private bool menuReady;

	private static GunshyMod current;

	private bool diagScareLogged;

	private bool diagAgentLogged;

	private bool diagPatchLogged;

	private bool diagSetDestLogged;

	private bool diagDumpLogged;

	private static readonly string[] TargetFields = new string[5] { "cur_target", "targetTriggerRef", "targetProxy", "_target", "enemyTarget" };

	public override void OnInitializeMelon()
	{
		//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e2: Expected O, but got Unknown
		MelonPreferences_Category obj = MelonPreferences.CreateCategory("Gunshy");
		Enabled = obj.CreateEntry<bool>("Enabled", true, "Enabled", (string)null, false, false, (ValueValidator)null, (string)null);
		HearRadius = obj.CreateEntry<float>("HearRadius", 22f, "Hearing radius (m)", (string)null, false, false, (ValueValidator)null, (string)null);
		FleeSeconds = obj.CreateEntry<float>("FleeSeconds", 4.5f, "Flee time (s)", (string)null, false, false, (ValueValidator)null, (string)null);
		FleeSpeed = obj.CreateEntry<float>("FleeSpeed", 6.5f, "Flee speed", (string)null, false, false, (ValueValidator)null, (string)null);
		gunHandler = OnGunFired;
		unloadHandler = ClearPanics;
		Hooking.OnPostFireGun += gunHandler;
		Hooking.OnLevelUnloaded += unloadHandler;
		Hooking.OnMarrowGameStarted += CreateMenu;
		current = this;
		harmony = new Harmony("gunshy.flee");
		TryPatchDriver();
		CreateMenu();
		((MelonBase)this).LoggerInstance.Msg("Gunshy loaded. Your gunshots make nearby NPCs run.");
	}

	public override void OnDeinitializeMelon()
	{
		if (gunHandler != null)
		{
			Hooking.OnPostFireGun -= gunHandler;
		}
		if (unloadHandler != null)
		{
			Hooking.OnLevelUnloaded -= unloadHandler;
		}
		Hooking.OnMarrowGameStarted -= CreateMenu;
		if (harmony != null)
		{
			harmony.UnpatchSelf();
		}
		ClearPanics();
	}

	public override void OnLateUpdate()
	{
		if (panics.Count == 0)
		{
			return;
		}
		float time = Time.time;
		List<int> list = null;
		foreach (KeyValuePair<int, Panic> panic in panics)
		{
			Panic value = panic.Value;
			if ((Object)(object)value.behaviour == (Object)null || time >= value.until)
			{
				Restore(value);
				if (list == null)
				{
					list = new List<int>();
				}
				list.Add(panic.Key);
			}
			else
			{
				Drive(value, time);
			}
		}
		if (list != null)
		{
			for (int i = 0; i < list.Count; i++)
			{
				panics.Remove(list[i]);
			}
		}
	}

	private void CreateMenu()
	{
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: 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)
		//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_010d: Unknown result type (might be due to invalid IL or missing references)
		if (!menuReady && Page.Root != null)
		{
			menuReady = true;
			Page obj = Page.Root.CreatePage("Gunshy", new Color(0.84f, 1f, 0.25f), 0, true);
			obj.CreateBool("Enabled", Color.white, Enabled.Value, (Action<bool>)delegate(bool value)
			{
				Enabled.Value = value;
			});
			obj.CreateFloat("Hearing radius", Color.white, HearRadius.Value, 1f, 4f, 60f, (Action<float>)delegate(float value)
			{
				HearRadius.Value = value;
			});
			obj.CreateFloat("Flee seconds", Color.white, FleeSeconds.Value, 0.5f, 1f, 12f, (Action<float>)delegate(float value)
			{
				FleeSeconds.Value = value;
			});
			obj.CreateFloat("Flee speed", Color.white, FleeSpeed.Value, 0.5f, 2f, 12f, (Action<float>)delegate(float value)
			{
				FleeSpeed.Value = value;
			});
		}
	}

	private void TryPatchDriver()
	{
		//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b5: Expected O, but got Unknown
		MethodInfo methodInfo = AccessTools.Method(typeof(BehaviourBaseNav), "Update", (Type[])null, (Type[])null) ?? AccessTools.Method(typeof(BehaviourBaseNav), "OnUpdate", (Type[])null, (Type[])null) ?? AccessTools.Method(typeof(BehaviourBaseNav), "FixedUpdate", (Type[])null, (Type[])null);
		if (methodInfo == null)
		{
			((MelonBase)this).LoggerInstance.Msg("No behaviour update to patch. LateUpdate still drives the flee.");
			return;
		}
		((MelonBase)this).LoggerInstance.Msg("[Gunshy][DIAG] Patching " + methodInfo.DeclaringType.Name + "." + methodInfo.Name);
		harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(GunshyMod), "RepathPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
	}

	public static void RepathPostfix(BehaviourBaseNav __instance)
	{
		GunshyMod gunshyMod = current;
		if (gunshyMod != null && !gunshyMod.diagPatchLogged)
		{
			gunshyMod.diagPatchLogged = true;
			((MelonBase)gunshyMod).LoggerInstance.Msg("[Gunshy][DIAG] RepathPostfix fired - Harmony patch is live.");
		}
		if (gunshyMod != null && !((Object)(object)__instance == (Object)null))
		{
			int instanceID = ((Object)__instance).GetInstanceID();
			if (gunshyMod.panics.TryGetValue(instanceID, out var value) && !(Time.time >= value.until))
			{
				gunshyMod.ApplyDestination(value);
			}
		}
	}

	private void OnGunFired(Gun gun)
	{
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0031: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
		//IL_0043: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
		if (Enabled == null || !Enabled.Value || !IsPlayerGun(gun))
		{
			return;
		}
		Vector3 val = (((Object)(object)gun.firePointTransform != (Object)null) ? gun.firePointTransform.position : ((Component)gun).transform.position);
		AIBrain[] array = Il2CppArrayBase<AIBrain>.op_Implicit(Object.FindObjectsOfType<AIBrain>());
		if (array == null)
		{
			return;
		}
		float value = HearRadius.Value;
		float num = value * value;
		int num2 = 0;
		foreach (AIBrain val2 in array)
		{
			if ((Object)(object)val2 == (Object)null)
			{
				continue;
			}
			bool flag = false;
			try
			{
				flag = val2.isDead;
			}
			catch
			{
			}
			if (flag || ((Object)(object)Player.RigManager != (Object)null && ((Component)val2).transform.IsChildOf(((Component)Player.RigManager).transform)))
			{
				continue;
			}
			BehaviourBaseNav behaviour = val2.behaviour;
			if (!((Object)(object)behaviour == (Object)null))
			{
				Vector3 val3 = ((Component)val2).transform.position - val;
				if (!(((Vector3)(ref val3)).sqrMagnitude > num))
				{
					Scare(behaviour, val2, val);
					num2++;
				}
			}
		}
		if (num2 > 0 && Time.time >= nextLogTime)
		{
			nextLogTime = Time.time + 1f;
			((MelonBase)this).LoggerInstance.Msg("Spooked " + num2 + " NPC" + ((num2 == 1) ? "" : "s") + ".");
		}
	}

	private void Scare(BehaviourBaseNav behaviour, AIBrain brain, Vector3 shot)
	{
		//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_0157: Unknown result type (might be due to invalid IL or missing references)
		//IL_0158: Unknown result type (might be due to invalid IL or missing references)
		//IL_0176: Unknown result type (might be due to invalid IL or missing references)
		//IL_017b: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
		if (!diagScareLogged)
		{
			diagScareLogged = true;
			NavMeshAgent val = FindAgent(behaviour, brain);
			((MelonBase)this).LoggerInstance.Msg("[Gunshy][DIAG] behaviour=" + ((object)behaviour).GetType().FullName);
			((MelonBase)this).LoggerInstance.Msg("[Gunshy][DIAG] FindAgent=" + (((Object)(object)val == (Object)null) ? "NULL" : (((Object)val).name + " active=" + ((Behaviour)val).isActiveAndEnabled + " onNav=" + val.isOnNavMesh)));
			if ((Object)(object)val == (Object)null)
			{
				DumpBehaviourDiagnostics(behaviour, brain);
			}
		}
		int instanceID = ((Object)behaviour).GetInstanceID();
		float until = Time.time + FleeSeconds.Value;
		if (!panics.TryGetValue(instanceID, out var value))
		{
			NavMeshAgent val2 = FindAgent(behaviour, brain);
			value = new Panic
			{
				behaviour = behaviour,
				agent = val2,
				originalSpeed = (((Object)(object)val2 != (Object)null) ? val2.speed : 3.5f),
				originalAccel = (((Object)(object)val2 != (Object)null) ? val2.acceleration : 8f),
				originalBraking = ((Object)(object)val2 == (Object)null || val2.autoBraking),
				awayFrom = shot,
				until = until,
				repathAt = 0f,
				dest = ((Component)behaviour).transform.position
			};
			panics[instanceID] = value;
			DropTarget(behaviour);
			PushRoam(behaviour);
			Shove(behaviour, ((Component)behaviour).transform.position - shot, 2.1f);
		}
		else
		{
			value.until = until;
			value.awayFrom = shot;
			value.repathAt = 0f;
			if ((Object)(object)value.agent == (Object)null)
			{
				value.agent = FindAgent(behaviour, brain);
				if ((Object)(object)value.agent != (Object)null)
				{
					value.originalSpeed = value.agent.speed;
					value.originalAccel = value.agent.acceleration;
					value.originalBraking = value.agent.autoBraking;
				}
			}
		}
		Drive(value, Time.time);
	}

	private void Drive(Panic panic, float now)
	{
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_0026: Unknown result type (might be due to invalid IL or missing references)
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0030: Unknown result type (might be due to invalid IL or missing references)
		PushRoam(panic.behaviour);
		if (now >= panic.repathAt)
		{
			panic.dest = PickFleePoint(((Component)panic.behaviour).transform.position, panic.awayFrom);
			panic.repathAt = now + 0.4f;
		}
		ApplyDestination(panic);
	}

	private void ApplyDestination(Panic panic)
	{
		//IL_0101: Unknown result type (might be due to invalid IL or missing references)
		NavMeshAgent agent = panic.agent;
		if ((Object)(object)agent == (Object)null)
		{
			if (!diagAgentLogged)
			{
				diagAgentLogged = true;
				((MelonBase)this).LoggerInstance.Msg("[Gunshy][DIAG] ApplyDestination: agent is NULL.");
			}
			return;
		}
		if (!diagAgentLogged)
		{
			diagAgentLogged = true;
			((MelonBase)this).LoggerInstance.Msg("[Gunshy][DIAG] agent=" + ((Object)agent).name + " active=" + ((Behaviour)agent).isActiveAndEnabled + " onNav=" + agent.isOnNavMesh + " speed=" + agent.speed);
		}
		try
		{
			if (((Behaviour)agent).isActiveAndEnabled && agent.isOnNavMesh)
			{
				agent.speed = FleeSpeed.Value;
				agent.acceleration = 40f;
				agent.angularSpeed = 720f;
				agent.autoBraking = false;
				agent.stoppingDistance = 0.4f;
				if (!agent.SetDestination(panic.dest) && !diagSetDestLogged)
				{
					diagSetDestLogged = true;
					((MelonBase)this).LoggerInstance.Msg("[Gunshy][DIAG] SetDestination returned FALSE.");
				}
			}
		}
		catch (Exception ex)
		{
			if (!loggedDriveError)
			{
				loggedDriveError = true;
				((MelonBase)this).LoggerInstance.Warning("Could not drive a fleeing agent: " + ex.Message);
			}
		}
	}

	private static Vector3 PickFleePoint(Vector3 from, Vector3 threat)
	{
		//IL_0000: Unknown result type (might be due to invalid IL or missing references)
		//IL_0001: Unknown result type (might be due to invalid IL or missing references)
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0063: Unknown result type (might be due to invalid IL or missing references)
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		//IL_010e: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
		//IL_00be: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
		Vector3 val = from - threat;
		val.y = 0f;
		if (((Vector3)(ref val)).sqrMagnitude < 0.04f)
		{
			((Vector3)(ref val))..ctor(Random.Range(-1f, 1f), 0f, Random.Range(-1f, 1f));
		}
		((Vector3)(ref val)).Normalize();
		float num = Random.Range(10f, 16f);
		Vector3 result = from;
		float num2 = -1f;
		NavMeshHit val3 = default(NavMeshHit);
		for (int i = 0; i < 9; i++)
		{
			float num3 = ((i % 2 == 0) ? 1f : (-1f));
			float num4 = ((i == 0) ? 0f : (num3 * (15f * (float)((i + 1) / 2))));
			Vector3 val2 = Quaternion.Euler(0f, num4, 0f) * val;
			if (NavMesh.SamplePosition(from + val2 * num, ref val3, 7f, -1))
			{
				float num5 = Vector3.Dot(((NavMeshHit)(ref val3)).position - from, val);
				if (num5 > num2)
				{
					num2 = num5;
					result = ((NavMeshHit)(ref val3)).position;
				}
			}
		}
		return result;
	}

	private static NavMeshAgent FindAgent(BehaviourBaseNav behaviour, AIBrain brain)
	{
		if ((Object)(object)behaviour == (Object)null)
		{
			return null;
		}
		NavMeshAgent val = TryGetAgentMember(behaviour);
		if ((Object)(object)val != (Object)null)
		{
			return val;
		}
		if ((Object)(object)brain != (Object)null)
		{
			val = TryGetAgentMember(brain);
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
		}
		try
		{
			val = ((Component)behaviour).GetComponent<NavMeshAgent>();
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
		}
		catch
		{
		}
		try
		{
			val = ((Component)behaviour).GetComponentInChildren<NavMeshAgent>(true);
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
		}
		catch
		{
		}
		try
		{
			val = ((Component)behaviour).GetComponentInChildren<NavMeshAgent>();
			if ((Object)(object)val != (Object)null)
			{
				return val;
			}
		}
		catch
		{
		}
		try
		{
			Transform val2 = ((Component)behaviour).transform;
			while ((Object)(object)val2 != (Object)null)
			{
				val = ((Component)val2).GetComponent<NavMeshAgent>();
				if ((Object)(object)val != (Object)null)
				{
					return val;
				}
				try
				{
					val = ((Component)val2).GetComponentInChildren<NavMeshAgent>(true);
					if ((Object)(object)val != (Object)null)
					{
						return val;
					}
				}
				catch
				{
				}
				val2 = val2.parent;
			}
		}
		catch
		{
		}
		return null;
	}

	private static NavMeshAgent TryGetAgentMember(object obj)
	{
		if (obj == null)
		{
			return null;
		}
		Type type = obj.GetType();
		int num = 0;
		while (type != null && type != typeof(object) && num < 8)
		{
			try
			{
				FieldInfo[] fields = type.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (FieldInfo fieldInfo in fields)
				{
					if (!typeof(NavMeshAgent).IsAssignableFrom(fieldInfo.FieldType))
					{
						continue;
					}
					try
					{
						object? value = fieldInfo.GetValue(obj);
						NavMeshAgent val = (NavMeshAgent)((value is NavMeshAgent) ? value : null);
						if ((Object)(object)val != (Object)null)
						{
							return val;
						}
					}
					catch
					{
					}
				}
			}
			catch
			{
			}
			try
			{
				PropertyInfo[] properties = type.GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (PropertyInfo propertyInfo in properties)
				{
					if (!typeof(NavMeshAgent).IsAssignableFrom(propertyInfo.PropertyType))
					{
						continue;
					}
					try
					{
						object? value2 = propertyInfo.GetValue(obj, null);
						NavMeshAgent val2 = (NavMeshAgent)((value2 is NavMeshAgent) ? value2 : null);
						if ((Object)(object)val2 != (Object)null)
						{
							return val2;
						}
					}
					catch
					{
					}
				}
			}
			catch
			{
			}
			type = type.BaseType;
			num++;
		}
		return null;
	}

	private void DumpBehaviourDiagnostics(BehaviourBaseNav behaviour, AIBrain brain)
	{
		if (diagDumpLogged)
		{
			return;
		}
		diagDumpLogged = true;
		((MelonBase)this).LoggerInstance.Msg("[Gunshy][DIAG] ========= DUMP START =========");
		((MelonBase)this).LoggerInstance.Msg("[Gunshy][DIAG] === BehaviourBaseNav members ===");
		DumpTypeMembers(((object)behaviour).GetType());
		if ((Object)(object)brain != (Object)null)
		{
			((MelonBase)this).LoggerInstance.Msg("[Gunshy][DIAG] === AIBrain members ===");
			DumpTypeMembers(((object)brain).GetType());
		}
		((MelonBase)this).LoggerInstance.Msg("[Gunshy][DIAG] === Scene NavMeshAgents ===");
		try
		{
			NavMeshAgent[] array = Il2CppArrayBase<NavMeshAgent>.op_Implicit(Object.FindObjectsOfType<NavMeshAgent>());
			((MelonBase)this).LoggerInstance.Msg("[Gunshy][DIAG] count=" + ((array != null) ? array.Length : 0));
			if (array != null)
			{
				int num = 0;
				NavMeshAgent[] array2 = array;
				foreach (NavMeshAgent val in array2)
				{
					if (!((Object)(object)val == (Object)null))
					{
						((MelonBase)this).LoggerInstance.Msg("[Gunshy][DIAG]   " + SafePath(((Component)val).transform) + "  enabled=" + ((Behaviour)val).enabled + " onNav=" + val.isOnNavMesh);
						num++;
						if (num >= 25)
						{
							((MelonBase)this).LoggerInstance.Msg("[Gunshy][DIAG]   ...(more omitted)");
							break;
						}
					}
				}
			}
		}
		catch (Exception ex)
		{
			((MelonBase)this).LoggerInstance.Msg("[Gunshy][DIAG] scene scan failed: " + ex.Message);
		}
		((MelonBase)this).LoggerInstance.Msg("[Gunshy][DIAG] ========= DUMP END =========");
	}

	private void DumpTypeMembers(Type t)
	{
		int num = 0;
		while (t != null && t != typeof(object) && num < 6)
		{
			((MelonBase)this).LoggerInstance.Msg("[Gunshy][DIAG] " + t.FullName);
			try
			{
				FieldInfo[] fields = t.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (FieldInfo fieldInfo in fields)
				{
					bool flag = fieldInfo.Name.IndexOf("agent", StringComparison.OrdinalIgnoreCase) >= 0 || fieldInfo.Name.IndexOf("nav", StringComparison.OrdinalIgnoreCase) >= 0;
					((MelonBase)this).LoggerInstance.Msg("[Gunshy][DIAG]   " + (flag ? "** " : "   ") + "F " + fieldInfo.FieldType.Name + " " + fieldInfo.Name);
				}
			}
			catch (Exception ex)
			{
				((MelonBase)this).LoggerInstance.Msg("[Gunshy][DIAG]   (fields error: " + ex.GetType().Name + ")");
			}
			try
			{
				PropertyInfo[] properties = t.GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (PropertyInfo propertyInfo in properties)
				{
					bool flag2 = propertyInfo.Name.IndexOf("agent", StringComparison.OrdinalIgnoreCase) >= 0 || propertyInfo.Name.IndexOf("nav", StringComparison.OrdinalIgnoreCase) >= 0;
					((MelonBase)this).LoggerInstance.Msg("[Gunshy][DIAG]   " + (flag2 ? "** " : "   ") + "P " + propertyInfo.PropertyType.Name + " " + propertyInfo.Name);
				}
			}
			catch (Exception ex2)
			{
				((MelonBase)this).LoggerInstance.Msg("[Gunshy][DIAG]   (props error: " + ex2.GetType().Name + ")");
			}
			t = t.BaseType;
			num++;
		}
	}

	private static string SafePath(Transform t)
	{
		if ((Object)(object)t == (Object)null)
		{
			return "<null>";
		}
		string text = ((Object)t).name;
		int num = 0;
		while ((Object)(object)t.parent != (Object)null && num < 6)
		{
			t = t.parent;
			text = ((Object)t).name + "/" + text;
			num++;
		}
		return text;
	}

	private static void PushRoam(BehaviourBaseNav behaviour)
	{
		if ((Object)(object)behaviour == (Object)null)
		{
			return;
		}
		try
		{
			MethodInfo methodInfo = AccessTools.Method(((object)behaviour).GetType(), "SetMentalState", (Type[])null, (Type[])null) ?? AccessTools.Method(typeof(BehaviourBaseNav), "SetMentalState", (Type[])null, (Type[])null);
			if (methodInfo != null && TryInvokeState(methodInfo, behaviour))
			{
				return;
			}
			FieldInfo fieldInfo = AccessTools.Field(((object)behaviour).GetType(), "mentalState") ?? AccessTools.Field(typeof(BehaviourBaseNav), "mentalState");
			if (!(fieldInfo == null) && fieldInfo.FieldType.IsEnum)
			{
				object obj = FindRoam(fieldInfo.FieldType);
				if (obj != null && !obj.Equals(fieldInfo.GetValue(behaviour)))
				{
					fieldInfo.SetValue(behaviour, obj);
				}
			}
		}
		catch
		{
		}
	}

	private static bool TryInvokeState(MethodInfo method, BehaviourBaseNav behaviour)
	{
		ParameterInfo[] parameters = method.GetParameters();
		if (parameters.Length != 1 || !parameters[0].ParameterType.IsEnum)
		{
			return false;
		}
		object obj = FindRoam(parameters[0].ParameterType);
		if (obj == null)
		{
			return false;
		}
		method.Invoke(behaviour, new object[1] { obj });
		return true;
	}

	private static object FindRoam(Type enumType)
	{
		string[] names = Enum.GetNames(enumType);
		for (int i = 0; i < names.Length; i++)
		{
			if (names[i].Equals("Roam", StringComparison.OrdinalIgnoreCase))
			{
				return Enum.Parse(enumType, names[i]);
			}
		}
		for (int j = 0; j < names.Length; j++)
		{
			if (names[j].IndexOf("Roam", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return Enum.Parse(enumType, names[j]);
			}
		}
		return null;
	}

	private static void DropTarget(BehaviourBaseNav behaviour)
	{
		for (int i = 0; i < TargetFields.Length; i++)
		{
			FieldInfo fieldInfo = AccessTools.Field(((object)behaviour).GetType(), TargetFields[i]) ?? AccessTools.Field(typeof(BehaviourBaseNav), TargetFields[i]);
			if (!(fieldInfo == null))
			{
				try
				{
					fieldInfo.SetValue(behaviour, null);
				}
				catch
				{
				}
			}
		}
	}

	private static void Shove(BehaviourBaseNav behaviour, Vector3 away, float strength)
	{
		//IL_004e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		away.y = 0f;
		if (((Vector3)(ref away)).sqrMagnitude < 0.001f)
		{
			return;
		}
		((Vector3)(ref away)).Normalize();
		Rigidbody[] array = Il2CppArrayBase<Rigidbody>.op_Implicit(((Component)behaviour).GetComponentsInChildren<Rigidbody>());
		if (array == null)
		{
			return;
		}
		int num = 0;
		foreach (Rigidbody val in array)
		{
			if (!((Object)(object)val == (Object)null) && !val.isKinematic)
			{
				val.AddForce(away * strength, (ForceMode)2);
				num++;
				if (num >= 8)
				{
					break;
				}
			}
		}
	}

	private static void Restore(Panic panic)
	{
		NavMeshAgent agent = panic.agent;
		if ((Object)(object)agent == (Object)null)
		{
			return;
		}
		try
		{
			agent.speed = panic.originalSpeed;
			agent.acceleration = panic.originalAccel;
			agent.autoBraking = panic.originalBraking;
		}
		catch
		{
		}
	}

	private void ClearPanics()
	{
		foreach (KeyValuePair<int, Panic> panic in panics)
		{
			Restore(panic.Value);
		}
		panics.Clear();
	}

	private static bool IsPlayerGun(Gun gun)
	{
		if ((Object)(object)gun == (Object)null || !Player.HandsExist)
		{
			return false;
		}
		Gun componentInHand = Player.GetComponentInHand<Gun>(Player.LeftHand);
		if ((Object)(object)componentInHand != (Object)null && ((Object)componentInHand).GetInstanceID() == ((Object)gun).GetInstanceID())
		{
			return true;
		}
		Gun componentInHand2 = Player.GetComponentInHand<Gun>(Player.RightHand);
		if ((Object)(object)componentInHand2 != (Object)null)
		{
			return ((Object)componentInHand2).GetInstanceID() == ((Object)gun).GetInstanceID();
		}
		return false;
	}
}