using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using GameEvent; using HarmonyLib; using UnityEngine; using UnityEngine.Networking; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("SpawnpointSetter")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("SpawnpointSetter")] [assembly: AssemblyCopyright("Copyright © 2026")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("7c6e09cf-7302-4548-8f22-18594e3370f5")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("1.0.0.0")] namespace BetterFreeplayPlugin { [BepInPlugin("com.Bojack.uch.BetterFreeplay", "BetterFreeplay", "1.0.0")] public class BetterFreeplayPlugin : BaseUnityPlugin { public static ConfigEntry SetSpawnKey; public static ConfigEntry ResetSpawnKey; public static ConfigEntry CycleSpawnKey; public static ConfigEntry EnableInvincibility; public static ConfigEntry EnableCannonInstaKill; internal static ConfigEntry EnableCyclePersistence; internal static ManualLogSource Logger; private void Awake() { //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Expected O, but got Unknown Logger = ((BaseUnityPlugin)this).Logger; SetSpawnKey = ((BaseUnityPlugin)this).Config.Bind("Controls", "SetSpawnKey", (KeyCode)112, "Move spawn"); ResetSpawnKey = ((BaseUnityPlugin)this).Config.Bind("Controls", "ResetSpawnKey", (KeyCode)111, "Reset spawn"); CycleSpawnKey = ((BaseUnityPlugin)this).Config.Bind("Controls", "CycleSpawnKey", (KeyCode)108, "Cycle through existing spawn points"); EnableCyclePersistence = ((BaseUnityPlugin)this).Config.Bind("General", "Cycle Persistence", true, "Keep traps and moving blocks active during build mode"); EnableInvincibility = ((BaseUnityPlugin)this).Config.Bind("General", "Enable Respawn Invulnerability", false, "Toggle respawn invincibility"); EnableCannonInstaKill = ((BaseUnityPlugin)this).Config.Bind("General", "Cannon Insta-Kill", false, "Instantly kill and respawn the player if they enter a cannon"); Harmony val = new Harmony("com.Bojack.uch.BetterFreeplay"); val.PatchAll(); } } } namespace BetterFreeplayPlugin.Patches { [HarmonyPatch(typeof(Placeable), "EnablePlaced")] public static class KeepHitboxesDangerousPatch { [HarmonyPostfix] private static void Postfix(Placeable __instance) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Invalid comparison between Unknown and I4 if (TrapPersistencePatch.ForceColliderRunPhase && BetterFreeplayPlugin.EnableCyclePersistence.Value) { GameSettings instance = GameSettings.GetInstance(); if (instance != null && (int)instance.GameMode <= 0) { __instance.SwitchColliderTo((ColliderModeEnum)2); } } } } [HarmonyPatch(typeof(FreePlayControl), "handleEvent")] public static class PhaseIndependencePatch { [HarmonyPrefix] private static bool Prefix(FreePlayControl __instance, object e) { if (e.GetType().Name == "FreePlayPlayerSwitchEvent") { return true; } return true; } } [HarmonyPatch(typeof(ActiveBlock), "ToPlaceMode")] public static class TrapPersistencePatch { public static bool ForceColliderRunPhase; [HarmonyPrefix] private static bool Prefix(ActiveBlock __instance) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Invalid comparison between Unknown and I4 if (BetterFreeplayPlugin.EnableCyclePersistence.Value) { GameSettings instance = GameSettings.GetInstance(); if (instance != null && (int)instance.GameMode == 0) { if (!((Placeable)__instance).MarkedForDestruction) { ForceColliderRunPhase = true; try { ((Placeable)__instance).EnablePlaced(); } finally { ForceColliderRunPhase = false; } } return false; } } return true; } } [HarmonyPatch(typeof(ColliderModeControl), "SwitchToMode")] public static class WireColliderPatch { [HarmonyPrefix] private static bool Prefix(ColliderModeControl __instance, ref ColliderModeEnum newPhase) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Invalid comparison between Unknown and I4 if (BetterFreeplayPlugin.EnableCyclePersistence.Value) { GameSettings instance = GameSettings.GetInstance(); if (instance != null && (int)instance.GameMode == 0 && (int)newPhase == 1) { Placeable componentInParent = ((Component)__instance).GetComponentInParent(); if ((Object)(object)componentInParent != (Object)null && componentInParent.Name != null && componentInParent.Name.Contains("Barbed Wire")) { newPhase = (ColliderModeEnum)2; } } } return true; } } [HarmonyPatch(typeof(AnimalCannon), "OnTriggerStay2D")] public static class CannonInstaKillPatch { [HarmonyPrefix] private static bool Prefix(AnimalCannon __instance, Collider2D c) { if (!BetterFreeplayPlugin.EnableCannonInstaKill.Value) { return true; } CollisionTag component = ((Component)c).GetComponent(); if ((Object)(object)component == (Object)null) { return true; } if (!component.ContainsAnyTag((Tag)32)) { return true; } if (!component.ContainsAnyTag((Tag)65536)) { return true; } Transform parent = ((Component)c).transform.parent; if ((Object)(object)parent == (Object)null) { return true; } Character component2 = ((Component)parent).GetComponent(); if ((Object)(object)component2 == (Object)null && (Object)(object)parent.parent != (Object)null) { component2 = ((Component)parent.parent).GetComponent(); } if ((Object)(object)component2 == (Object)null) { return true; } if (!((NetworkBehaviour)component2).hasAuthority) { return true; } if (!component2.Dying && !component2.Dead && !component2.Success && !component2.InCannon) { component2.KillCharacter("Cannon", false, 0, true); } return false; } } [HarmonyPatch(typeof(FreePlayControl), "Update")] public static class ForceNoResetPatch { [HarmonyTranspiler] private static IEnumerable Transpiler(IEnumerable instructions) { List list = new List(instructions); for (int i = 0; i < list.Count; i++) { if (list[i].opcode == OpCodes.Ldc_I4_1 && ((object)list[i - 1]).ToString().Contains("get_Count")) { list[i].opcode = OpCodes.Ldc_I4_M1; } } return list; } } [HarmonyPatch(typeof(FreePlayControl))] internal class CycleResetShiftPatch { public static bool SuppressReset; [HarmonyPatch("ToPlaceMode")] [HarmonyPrefix] private static void PrePlaceMode() { if (BetterFreeplayPlugin.EnableCyclePersistence.Value) { SuppressReset = true; } } [HarmonyPatch("ToPlaceMode")] [HarmonyPostfix] private static void PostPlaceMode() { SuppressReset = false; } [HarmonyPatch("ToPlayMode")] [HarmonyPostfix] private static void TriggerPlayReset() { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown if (BetterFreeplayPlugin.EnableCyclePersistence.Value) { GameEventManager.SendEvent((GameEvent)new LevelResetEvent()); } } } [HarmonyPatch(typeof(GameEventManager), "SendEvent")] public static class EventBlocker { [HarmonyPrefix] private static bool Prefix(object e) { if (CycleResetShiftPatch.SuppressReset) { string name = e.GetType().Name; if (name == "LevelResetEvent" || name == "ClearProjectiles") { return false; } } return true; } } [HarmonyPatch(typeof(Character), "StartInvincibleTimer")] public static class InvincibilityTogglePatch { [HarmonyPrefix] public static bool Prefix() { return BetterFreeplayPlugin.EnableInvincibility.Value; } } [HarmonyPatch(typeof(FreePlayControl), "SetupStart")] public static class SpawnSetupPatch { [HarmonyPostfix] private static void Postfix(MonoBehaviour __instance) { if ((Object)(object)((Component)__instance).gameObject.GetComponent() == (Object)null) { ((Component)__instance).gameObject.AddComponent(); } } } public class SpawnPointMover : MonoBehaviour { private List _checkpoints = new List(); private int _currentIndex = 0; private Vector3 _platformOffset; private void Start() { //IL_0025: 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_003b: Unknown result type (might be due to invalid IL or missing references) Level val = Object.FindObjectOfType(); if ((Object)(object)val?.StartPoint != (Object)null) { _platformOffset = val.StartPoint.localPosition; _checkpoints.Add(val.StartPoint.position); } } private void Update() { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_015a: 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_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_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_01d9: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) Level val = Object.FindObjectOfType(); if ((Object)(object)val?.StartPoint == (Object)null) { return; } if (Input.GetKeyDown(BetterFreeplayPlugin.SetSpawnKey.Value)) { Character localCharacter = GetLocalCharacter(); if ((Object)(object)localCharacter != (Object)null) { Vector3 val2 = ((Component)localCharacter).transform.position - Level.GetSpawnFeetOffset(); _checkpoints.Add(val2); _currentIndex = _checkpoints.Count - 1; val.StartPoint.position = val2; SpawnPoof(val2); } } if (Input.GetKeyDown(BetterFreeplayPlugin.CycleSpawnKey.Value)) { if (_checkpoints.Count > 1) { _currentIndex = (_currentIndex + 1) % _checkpoints.Count; } else { _currentIndex = 0; } if (_currentIndex == 0) { val.StartPoint.localPosition = _platformOffset; } else { val.StartPoint.position = _checkpoints[_currentIndex]; } RespawnLocalPlayer(val.StartPoint.position); SpawnPoof(val.StartPoint.position); } if (Input.GetKeyDown(BetterFreeplayPlugin.ResetSpawnKey.Value) && _currentIndex > 0) { _checkpoints.RemoveAt(_currentIndex); _currentIndex = Mathf.Max(0, _currentIndex - 1); if (_currentIndex == 0) { val.StartPoint.localPosition = _platformOffset; } else { val.StartPoint.position = _checkpoints[_currentIndex]; } SpawnPoof(val.StartPoint.position); } } private void RespawnLocalPlayer(Vector3 targetPos) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) Character localCharacter = GetLocalCharacter(); if ((Object)(object)localCharacter != (Object)null) { ((Component)localCharacter).transform.position = targetPos + Level.GetSpawnFeetOffset(); Rigidbody2D component = ((Component)localCharacter).GetComponent(); if ((Object)(object)component != (Object)null) { component.velocity = Vector2.zero; component.angularVelocity = 0f; } } } private Character GetLocalCharacter() { Character[] array = Object.FindObjectsOfType(); foreach (Character val in array) { if ((Object)(object)val != (Object)null && ((NetworkBehaviour)val).hasAuthority) { return val; } } return null; } private void SpawnPoof(Vector3 pos) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)SmokePool.Instance != (Object)null) { SmokePool.Instance.SpawnSmoke((SmokeType)0, pos, 0.4f); } } } }