Decompiled source of TweaksAndFixes v1.0.0

BepInEx/plugins/Crawlspace2TweaksFixes.dll

Decompiled 7 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Crawlspace2TweaksFixes")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("Performance optimizations and bug fixes for Crawlspace 2")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("Crawlspace2TweaksFixes")]
[assembly: AssemblyTitle("Crawlspace2TweaksFixes")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace Crawlspace2TweaksFixes
{
	[BepInPlugin("com.yourname.crawlspace2.tweaksfixes", "Crawlspace 2 Tweaks & Fixes", "1.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		[CompilerGenerated]
		private sealed class <SmoothCrawlCoroutine>d__31 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public MoveTypeController instance;

			private Vector3 <startPos>5__2;

			private Vector3 <endPos>5__3;

			private float <elapsed>5__4;

			private float <duration>5__5;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <SmoothCrawlCoroutine>d__31(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0062: Unknown result type (might be due to invalid IL or missing references)
				//IL_0067: Unknown result type (might be due to invalid IL or missing references)
				//IL_006e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0082: Unknown result type (might be due to invalid IL or missing references)
				//IL_0087: Unknown result type (might be due to invalid IL or missing references)
				//IL_008c: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f8: 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)
				//IL_0141: Unknown result type (might be due to invalid IL or missing references)
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					isInTransition = true;
					instance.debugSwitch = false;
					instance.standSound.pitch = 1f;
					instance.standSound.Play();
					<startPos>5__2 = instance.playerObj.transform.position;
					<endPos>5__3 = <startPos>5__2 + new Vector3(0f, -1f, 0f);
					<elapsed>5__4 = 0f;
					<duration>5__5 = 0.4f;
					break;
				case 1:
					<>1__state = -1;
					break;
				}
				if (<elapsed>5__4 < <duration>5__5)
				{
					<elapsed>5__4 += Time.deltaTime;
					float num = <elapsed>5__4 / <duration>5__5;
					num = 1f - Mathf.Pow(1f - num, 3f);
					instance.playerObj.transform.position = Vector3.Lerp(<startPos>5__2, <endPos>5__3, num);
					<>2__current = null;
					<>1__state = 1;
					return true;
				}
				instance.playerObj.transform.position = <endPos>5__3;
				isInTransition = false;
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		[CompilerGenerated]
		private sealed class <SmoothStandCoroutine>d__30 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public MoveTypeController instance;

			private Vector3 <startPos>5__2;

			private Vector3 <endPos>5__3;

			private float <elapsed>5__4;

			private float <duration>5__5;

			object IEnumerator<object>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <SmoothStandCoroutine>d__30(int <>1__state)
			{
				this.<>1__state = <>1__state;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0056: Unknown result type (might be due to invalid IL or missing references)
				//IL_005b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0062: Unknown result type (might be due to invalid IL or missing references)
				//IL_0076: Unknown result type (might be due to invalid IL or missing references)
				//IL_007b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0080: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
				//IL_0135: Unknown result type (might be due to invalid IL or missing references)
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					isInTransition = true;
					instance.standSound.pitch = 1.2f;
					instance.standSound.Play();
					<startPos>5__2 = instance.playerObj.transform.position;
					<endPos>5__3 = <startPos>5__2 + new Vector3(0f, 1.2f, 0f);
					<elapsed>5__4 = 0f;
					<duration>5__5 = 0.4f;
					break;
				case 1:
					<>1__state = -1;
					break;
				}
				if (<elapsed>5__4 < <duration>5__5)
				{
					<elapsed>5__4 += Time.deltaTime;
					float num = <elapsed>5__4 / <duration>5__5;
					num = 1f - Mathf.Pow(1f - num, 3f);
					instance.playerObj.transform.position = Vector3.Lerp(<startPos>5__2, <endPos>5__3, num);
					<>2__current = null;
					<>1__state = 1;
					return true;
				}
				instance.playerObj.transform.position = <endPos>5__3;
				instance.debugSwitch = true;
				isInTransition = false;
				return false;
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		internal static ManualLogSource Logger;

		internal static ConfigEntry<bool> OptimizeMonsterAI;

		internal static ConfigEntry<int> MonsterUpdateInterval;

		internal static ConfigEntry<bool> FixPuzzleRecursion;

		internal static ConfigEntry<bool> FixSceneLoadRaceCondition;

		internal static ConfigEntry<bool> FixPaintingMaterialLeak;

		internal static ConfigEntry<bool> FixAttackRNG;

		internal static ConfigEntry<bool> RemoveDebugLogs;

		internal static ConfigEntry<bool> SmoothStandCrawlTransition;

		private static bool isInTransition;

		private static int sparkyFrameCounter;

		private static int jeffFrameCounter;

		private static int henryFrameCounter;

		private static int smileFrameCounter;

		private static Material lastPaintingMaterial;

		private void Awake()
		{
			Logger = ((BaseUnityPlugin)this).Logger;
			OptimizeMonsterAI = ((BaseUnityPlugin)this).Config.Bind<bool>("Performance", "OptimizeMonsterAI", true, "Reduce monster AI update frequency for better performance");
			MonsterUpdateInterval = ((BaseUnityPlugin)this).Config.Bind<int>("Performance", "MonsterUpdateInterval", 3, "How many FixedUpdate frames to skip between monster AI updates (higher = better performance, lower = more responsive AI)");
			FixPuzzleRecursion = ((BaseUnityPlugin)this).Config.Bind<bool>("BugFixes", "FixPuzzleRecursion", true, "Fix potential stack overflow in puzzle randomization (can cause crashes)");
			FixSceneLoadRaceCondition = ((BaseUnityPlugin)this).Config.Bind<bool>("BugFixes", "FixSceneLoadRaceCondition", true, "Add delays to scene loading to prevent race conditions on startup");
			FixPaintingMaterialLeak = ((BaseUnityPlugin)this).Config.Bind<bool>("BugFixes", "FixPaintingMaterialLeak", true, "Fix painting material switching creating memory leaks");
			FixAttackRNG = ((BaseUnityPlugin)this).Config.Bind<bool>("BugFixes", "FixAttackRNG", true, "Fix backwards RNG logic that made nights 4-6 nearly impossible");
			RemoveDebugLogs = ((BaseUnityPlugin)this).Config.Bind<bool>("QualityOfLife", "RemoveDebugLogs", true, "Remove annoying debug log spam");
			SmoothStandCrawlTransition = ((BaseUnityPlugin)this).Config.Bind<bool>("QualityOfLife", "SmoothStandCrawlTransition", true, "Use smooth camera animation for stand/crawl transitions instead of fade to black");
			Logger.LogInfo((object)"Crawlspace 2 Tweaks & Fixes v1.0.0 loaded!");
			Logger.LogInfo((object)$"Performance: MonsterAI={OptimizeMonsterAI.Value}");
			Logger.LogInfo((object)$"Bug Fixes: AttackRNG={FixAttackRNG.Value}, PuzzleRecursion={FixPuzzleRecursion.Value}, SceneLoad={FixSceneLoadRaceCondition.Value}");
			Logger.LogInfo((object)$"QoL: SmoothTransition={SmoothStandCrawlTransition.Value}");
			Harmony.CreateAndPatchAll(typeof(Plugin), (string)null);
		}

		[HarmonyPatch(typeof(EnemyDifMaster), "attackTrigger")]
		[HarmonyPrefix]
		private static bool FixAttackTriggerRNG(EnemyDifMaster __instance)
		{
			if (!FixAttackRNG.Value)
			{
				return true;
			}
			FieldInfo fieldInfo = AccessTools.Field(typeof(EnemyDifMaster), "switchID");
			int num = (int)fieldInfo.GetValue(__instance);
			if (Random.Range(0, 101) < __instance.triggerOdds)
			{
				return false;
			}
			if (__instance.nightNumber == 2)
			{
				__instance.sparkybrain.triggerAttack();
			}
			else if (__instance.nightNumber == 3)
			{
				if (num == 1)
				{
					__instance.jeffbrain.triggerAttack();
					fieldInfo.SetValue(__instance, 2);
				}
				else
				{
					__instance.sparkybrain.triggerAttack();
					fieldInfo.SetValue(__instance, 1);
				}
			}
			else if (__instance.nightNumber == 4 || __instance.nightNumber == 5)
			{
				switch (Random.Range(0, 3))
				{
				case 0:
					if (num == 1)
					{
						__instance.sparkybrain.triggerAttack();
						fieldInfo.SetValue(__instance, 2);
					}
					else
					{
						__instance.jeffbrain.triggerAttack();
						fieldInfo.SetValue(__instance, 1);
					}
					break;
				case 1:
					if (num == 2)
					{
						__instance.jeffbrain.triggerAttack();
						fieldInfo.SetValue(__instance, 3);
					}
					else
					{
						__instance.smilebrain.onTrigger();
						fieldInfo.SetValue(__instance, 2);
					}
					break;
				default:
					if (num == 3)
					{
						__instance.smilebrain.onTrigger();
						fieldInfo.SetValue(__instance, 1);
					}
					else
					{
						__instance.sparkybrain.triggerAttack();
						fieldInfo.SetValue(__instance, 3);
					}
					break;
				}
			}
			return false;
		}

		[HarmonyPatch(typeof(PuzzleMaster), "enableFan")]
		[HarmonyPrefix]
		private static bool FixPuzzleRecursionPatch(PuzzleMaster __instance)
		{
			if (!FixPuzzleRecursion.Value)
			{
				return true;
			}
			int num = 100;
			for (int i = 0; i < num; i++)
			{
				int num2 = Random.Range(0, 9);
				object value = AccessTools.Field(typeof(PuzzleMaster), "ps1").GetValue(__instance);
				object value2 = AccessTools.Field(typeof(PuzzleMaster), "ps2").GetValue(__instance);
				object value3 = AccessTools.Field(typeof(PuzzleMaster), "ps3").GetValue(__instance);
				object value4 = AccessTools.Field(typeof(PuzzleMaster), "ps4").GetValue(__instance);
				object value5 = AccessTools.Field(typeof(PuzzleMaster), "ps5").GetValue(__instance);
				object value6 = AccessTools.Field(typeof(PuzzleMaster), "ps6").GetValue(__instance);
				object value7 = AccessTools.Field(typeof(PuzzleMaster), "ps7").GetValue(__instance);
				object value8 = AccessTools.Field(typeof(PuzzleMaster), "ps8").GetValue(__instance);
				object value9 = AccessTools.Field(typeof(PuzzleMaster), "ps9").GetValue(__instance);
				bool flag = false;
				PuzzleController val = null;
				string text = "";
				switch (num2)
				{
				case 0:
					flag = (bool)value9;
					val = __instance.pCon9;
					text = "ps9";
					break;
				case 1:
					flag = (bool)value;
					val = __instance.pCon1;
					text = "ps1";
					break;
				case 2:
					flag = (bool)value2;
					val = __instance.pCon2;
					text = "ps2";
					break;
				case 3:
					flag = (bool)value3;
					val = __instance.pCon3;
					text = "ps3";
					break;
				case 4:
					flag = (bool)value4;
					val = __instance.pCon4;
					text = "ps4";
					break;
				case 5:
					flag = (bool)value5;
					val = __instance.pCon5;
					text = "ps5";
					break;
				case 6:
					flag = (bool)value6;
					val = __instance.pCon6;
					text = "ps6";
					break;
				case 7:
					flag = (bool)value7;
					val = __instance.pCon7;
					text = "ps7";
					break;
				case 8:
					flag = (bool)value8;
					val = __instance.pCon8;
					text = "ps8";
					break;
				}
				if (!flag && (Object)(object)val != (Object)null)
				{
					val.thisFan(1);
					AccessTools.Field(typeof(PuzzleMaster), text).SetValue(__instance, true);
					return false;
				}
			}
			Logger.LogWarning((object)"PuzzleMaster.enableFan() exceeded max attempts");
			return false;
		}

		[HarmonyPatch(typeof(paintingControl), "setPaintingMatSquare")]
		[HarmonyPrefix]
		private static bool FixPaintingMaterialLeakPatch(MeshRenderer painting)
		{
			if (!FixPaintingMaterialLeak.Value)
			{
				return true;
			}
			if ((Object)(object)((Renderer)painting).material == (Object)(object)lastPaintingMaterial)
			{
				return false;
			}
			lastPaintingMaterial = ((Renderer)painting).material;
			return true;
		}

		[HarmonyPatch(typeof(henryBrain), "audiocontrol")]
		[HarmonyPrefix]
		private static bool FixHenryAudioDuringTeleport(henryBrain __instance)
		{
			if ((Object)(object)__instance.sparkyJS != (Object)null && (Object)(object)((Renderer)__instance.sparkyJS).material == (Object)(object)__instance.spNull)
			{
				return false;
			}
			return true;
		}

		[HarmonyPatch(typeof(SmileBrain), "Start")]
		[HarmonyPostfix]
		private static void FixSmileIdleSpawn(SmileBrain __instance)
		{
			if ((Object)(object)__instance.sparkyJS != (Object)null)
			{
				((Renderer)__instance.sparkyJS).enabled = false;
			}
		}

		[HarmonyPatch(typeof(mapEnBrain), "Start")]
		[HarmonyPostfix]
		private static void FixHaroldInitialization(mapEnBrain __instance)
		{
			__instance.setRandomPos();
		}

		[HarmonyPatch(typeof(sparkyBrain), "FixedUpdate")]
		[HarmonyPrefix]
		private static bool OptimizeSparkyUpdate(sparkyBrain __instance)
		{
			if (!OptimizeMonsterAI.Value)
			{
				return true;
			}
			sparkyFrameCounter++;
			if (sparkyFrameCounter < MonsterUpdateInterval.Value)
			{
				return false;
			}
			sparkyFrameCounter = 0;
			return true;
		}

		[HarmonyPatch(typeof(jeffBrain), "FixedUpdate")]
		[HarmonyPrefix]
		private static bool OptimizeJeffUpdate(jeffBrain __instance)
		{
			if (!OptimizeMonsterAI.Value)
			{
				return true;
			}
			jeffFrameCounter++;
			if (jeffFrameCounter < MonsterUpdateInterval.Value)
			{
				return false;
			}
			jeffFrameCounter = 0;
			return true;
		}

		[HarmonyPatch(typeof(henryBrain), "FixedUpdate")]
		[HarmonyPrefix]
		private static bool OptimizeHenryUpdate(henryBrain __instance)
		{
			if (!OptimizeMonsterAI.Value)
			{
				return true;
			}
			henryFrameCounter++;
			if (henryFrameCounter < MonsterUpdateInterval.Value)
			{
				return false;
			}
			henryFrameCounter = 0;
			return true;
		}

		[HarmonyPatch(typeof(SmileBrain), "FixedUpdate")]
		[HarmonyPrefix]
		private static bool OptimizeSmileUpdate(SmileBrain __instance)
		{
			if ((Object)(object)__instance.sparkyJS != (Object)null && !((Renderer)__instance.sparkyJS).enabled)
			{
				FieldInfo field = typeof(SmileBrain).GetField("isChasing", BindingFlags.Instance | BindingFlags.NonPublic);
				if (field != null && (bool)field.GetValue(__instance))
				{
					((Renderer)__instance.sparkyJS).enabled = true;
				}
			}
			if (!OptimizeMonsterAI.Value)
			{
				return true;
			}
			smileFrameCounter++;
			if (smileFrameCounter < MonsterUpdateInterval.Value)
			{
				return false;
			}
			smileFrameCounter = 0;
			return true;
		}

		[HarmonyPatch(typeof(Debug), "Log", new Type[] { typeof(object) })]
		[HarmonyPrefix]
		private static bool RemoveDebugLog(object message)
		{
			if (!RemoveDebugLogs.Value)
			{
				return true;
			}
			string text = message?.ToString() ?? "";
			if (text.Contains("you fucked up") || text.Contains("dumbass") || text.Contains("SHOULDENT HAPPEN") || text.Contains("ERRRRRRRRROR") || text.Contains("WRTRTSBFJK") || text.Contains("AAAAAAAAAAAAAAAAAAAAAA"))
			{
				return false;
			}
			return true;
		}

		[HarmonyPatch(typeof(Transform), "RotateAround", new Type[]
		{
			typeof(Vector3),
			typeof(Vector3),
			typeof(float)
		})]
		[HarmonyPrefix]
		private static bool BlockSnapTurnsDuringTransition(Transform __instance, Vector3 point, Vector3 axis, float angle)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			if (isInTransition && Mathf.Abs(axis.y) > 0.5f && (Mathf.Abs(angle) == 10f || Mathf.Abs(Mathf.Abs(angle) - 10f) < 0.01f))
			{
				return false;
			}
			return true;
		}

		[HarmonyPatch(typeof(MoveTypeController), "goToStanding")]
		[HarmonyPrefix]
		private static bool SmoothStandTransition(MoveTypeController __instance, ref IEnumerator __result)
		{
			if (!SmoothStandCrawlTransition.Value)
			{
				return true;
			}
			__result = SmoothStandCoroutine(__instance);
			return false;
		}

		[HarmonyPatch(typeof(MoveTypeController), "goToCrawl")]
		[HarmonyPrefix]
		private static bool SmoothCrawlTransition(MoveTypeController __instance, ref IEnumerator __result)
		{
			if (!SmoothStandCrawlTransition.Value)
			{
				return true;
			}
			__result = SmoothCrawlCoroutine(__instance);
			return false;
		}

		[IteratorStateMachine(typeof(<SmoothStandCoroutine>d__30))]
		private static IEnumerator SmoothStandCoroutine(MoveTypeController instance)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <SmoothStandCoroutine>d__30(0)
			{
				instance = instance
			};
		}

		[IteratorStateMachine(typeof(<SmoothCrawlCoroutine>d__31))]
		private static IEnumerator SmoothCrawlCoroutine(MoveTypeController instance)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <SmoothCrawlCoroutine>d__31(0)
			{
				instance = instance
			};
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "com.yourname.crawlspace2.tweaksfixes";

		public const string PLUGIN_NAME = "Crawlspace 2 Tweaks & Fixes";

		public const string PLUGIN_VERSION = "1.0.0";
	}
}