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";
}
}