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<KeyCode> SetSpawnKey;
public static ConfigEntry<KeyCode> ResetSpawnKey;
public static ConfigEntry<KeyCode> CycleSpawnKey;
public static ConfigEntry<bool> EnableInvincibility;
public static ConfigEntry<bool> EnableCannonInstaKill;
internal static ConfigEntry<bool> 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<KeyCode>("Controls", "SetSpawnKey", (KeyCode)112, "Move spawn");
ResetSpawnKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Controls", "ResetSpawnKey", (KeyCode)111, "Reset spawn");
CycleSpawnKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Controls", "CycleSpawnKey", (KeyCode)108, "Cycle through existing spawn points");
EnableCyclePersistence = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Cycle Persistence", true, "Keep traps and moving blocks active during build mode");
EnableInvincibility = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enable Respawn Invulnerability", false, "Toggle respawn invincibility");
EnableCannonInstaKill = ((BaseUnityPlugin)this).Config.Bind<bool>("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<Placeable>();
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<CollisionTag>();
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<Character>();
if ((Object)(object)component2 == (Object)null && (Object)(object)parent.parent != (Object)null)
{
component2 = ((Component)parent.parent).GetComponent<Character>();
}
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<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
{
List<CodeInstruction> list = new List<CodeInstruction>(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<SpawnPointMover>() == (Object)null)
{
((Component)__instance).gameObject.AddComponent<SpawnPointMover>();
}
}
}
public class SpawnPointMover : MonoBehaviour
{
private List<Vector3> _checkpoints = new List<Vector3>();
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<Level>();
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<Level>();
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<Rigidbody2D>();
if ((Object)(object)component != (Object)null)
{
component.velocity = Vector2.zero;
component.angularVelocity = 0f;
}
}
}
private Character GetLocalCharacter()
{
Character[] array = Object.FindObjectsOfType<Character>();
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);
}
}
}
}