The BepInEx console will not appear when launching like it does for other games on Thunderstore (you can turn it back on in your BepInEx.cfg file). If your PEAK crashes on startup, add -dx12 to your launch parameters.
Decompiled source of BetterCannon v1.1.0
plugins/Better Cannon.dll
Decompiled 3 weeks agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using BepInEx; using ExitGames.Client.Photon; using HarmonyLib; using Photon.Pun; using Photon.Realtime; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("PEAK")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("PEAK")] [assembly: AssemblyCopyright("Copyright © 2025")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("94d12321-9932-43d2-ba03-502c40b6fcee")] [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")] [BepInPlugin("com.leer.peak.bettercannon", "Better Cannon", "1.0.0")] public class DetachableCannonMod : BaseUnityPlugin { private void Awake() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected O, but got Unknown //IL_0036: Expected O, but got Unknown new Harmony("com.leerhansson.peak.bettercannon").PatchAll(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Detachable Cannon Mod loaded!"); Hashtable val = new Hashtable(); ((Dictionary<object, object>)val).Add((object)"HasDetachableCannonMod", (object)true); Hashtable val2 = val; PhotonNetwork.LocalPlayer.SetCustomProperties(val2, (Hashtable)null, (WebFlags)null); } } [HarmonyPatch(typeof(ScoutCannon), "Awake")] internal class ScoutCannon_Awake_Patch { private static void Postfix(ScoutCannon __instance) { if ((Object)(object)((Component)__instance).GetComponent<BetterCannonInteract>() == (Object)null) { ((Component)__instance).gameObject.AddComponent<BetterCannonInteract>(); } } } public class BetterCannonInteract : MonoBehaviour, IInteractible, IInteractibleConstant { private PhotonView photonView; private Transform cannonTransform; private float minAngle = -75f; private float maxAngle = -10f; private float currentAngle; private float rotationSpeed = 3f; private bool hovering; public bool holdOnFinish => false; private void Awake() { photonView = ((Component)this).GetComponent<PhotonView>(); cannonTransform = ((Component)this).transform.Find("Cannon"); } private void Update() { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) if (hovering) { float num = Input.mouseScrollDelta.y; if (Input.GetKey((KeyCode)335)) { num = 0.5f; } else if (Input.GetKey((KeyCode)334)) { num = -0.5f; } if (Mathf.Abs(num) > 0f && (Object)(object)cannonTransform != (Object)null) { float num2 = currentAngle + num * rotationSpeed * Time.deltaTime * 60f; num2 = Mathf.Clamp(num2, minAngle, maxAngle); cannonTransform.localRotation = Quaternion.Euler(num2, cannonTransform.localEulerAngles.y, cannonTransform.localEulerAngles.z); currentAngle = num2; photonView.RPC("RotateCannonRPC", (RpcTarget)4, new object[1] { currentAngle }); } } } [PunRPC] private void RotateCannonRPC(float angle) { //IL_001b: 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_0035: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)cannonTransform != (Object)null) { cannonTransform.localRotation = Quaternion.Euler(angle, cannonTransform.localEulerAngles.y, cannonTransform.localEulerAngles.z); currentAngle = angle; } } public void HoverEnter() { hovering = true; } public void HoverExit() { hovering = false; } public void CancelCast(Character interactor) { } public bool IsConstantlyInteractable(Character interactor) { return true; } public void Interact(Character interactor) { } public void ReleaseInteract(Character interactor) { } public Vector3 Center() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return ((Component)this).transform.position; } public string GetInteractionText() { return LocalizedText.GetText("PICKUP", true); } public string GetName() { return LocalizedText.GetText("NAME_SCOUT CANNON", true); } public Transform GetTransform() { return ((Component)this).transform; } public bool IsInteractible(Character interactor) { Player owner = photonView.Owner; if (owner == null || !((Dictionary<object, object>)(object)owner.CustomProperties).ContainsKey((object)"HasDetachableCannonMod") || !(bool)owner.CustomProperties[(object)"HasDetachableCannonMod"]) { return photonView.IsMine; } return true; } public float GetInteractTime(Character interactor) { if (interactor.refs.items.currentSelectedSlot.Value != 250) { return 2f; } return 0f; } public void Interact_CastFinished(Character interactor) { if (interactor.refs.items.currentSelectedSlot.Value != 250) { ((MonoBehaviourPun)interactor.refs.items).photonView.RPC("RPC_SpawnItemInHandMaster", (RpcTarget)2, new object[1] { "ScoutCannonItem" }); photonView.RPC("DestroyCannon", (RpcTarget)3, Array.Empty<object>()); } } [PunRPC] private void DestroyCannon() { PhotonNetwork.Destroy(((Component)this).gameObject); } }