using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using GameNetcodeStuff;
using HarmonyLib;
using TMPro;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("LC_Bhop")]
[assembly: AssemblyDescription("LC_Bhop mod for Lethal Company")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Diman3012")]
[assembly: AssemblyProduct("LC_Bhop")]
[assembly: AssemblyCopyright("Copyright © 2026")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("658b1380-3c08-49da-aaec-43ad07a87f4a")]
[assembly: AssemblyFileVersion("1.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace lcbhop;
public class Config
{
private readonly ConfigFile config;
public ConfigEntry<bool> modEnabled;
public ConfigEntry<bool> autobhop;
public ConfigEntry<bool> speedometer;
public ConfigEntry<bool> enablebunnyhopping;
public ConfigEntry<float> gravity;
public ConfigEntry<float> friction;
public ConfigEntry<float> maxspeed;
public ConfigEntry<float> movespeed;
public ConfigEntry<float> accelerate;
public ConfigEntry<float> airaccelerate;
public ConfigEntry<float> stopspeed;
public Config(ConfigFile cfg)
{
config = cfg;
}
public void Init()
{
modEnabled = config.Bind<bool>("General", "ModEnabled", false, "Глобальный переключатель мода.");
autobhop = config.Bind<bool>("General", "Auto Bhop", true, "Авто-прыжок при зажатом пробеле.");
speedometer = config.Bind<bool>("General", "Speedometer", false, "Спидометр.");
enablebunnyhopping = config.Bind<bool>("Movement v4", "Enable bunnyhopping", true, "Отключение лимита скорости.");
gravity = config.Bind<float>("Movement v4", "Gravity", 800f, "Гравитация.");
friction = config.Bind<float>("Movement v4", "Friction", 4f, "Трение.");
maxspeed = config.Bind<float>("Movement v4", "Max Speed", 1500f, "Максимальный лимит (1500).");
movespeed = config.Bind<float>("Movement v4", "Move Speed", 250f, "Базовая скорость.");
accelerate = config.Bind<float>("Movement v4", "Accelerate", 5f, "Ускорение на земле.");
airaccelerate = config.Bind<float>("Movement v4", "Air Accelerate", 150f, "Ускорение в воздухе.");
stopspeed = config.Bind<float>("Movement v4", "Stop Speed", 75f, "Скорость остановки.");
}
}
internal struct Cmd
{
public float forwardMove;
public float rightMove;
public float upMove;
}
public class CPMPlayer : MonoBehaviour
{
public PlayerControllerB player;
private CharacterController _controller;
private Vector3 velocity = Vector3.zero;
public bool wishJump = false;
private Cmd _cmd;
private GameObject compass;
private TextMeshProUGUI speedo;
public float gravity => Plugin.cfg.gravity.Value;
public float friction => Plugin.cfg.friction.Value;
public float maxspeed => Plugin.cfg.maxspeed.Value;
public float movespeed => Plugin.cfg.movespeed.Value;
public float accelerate => Plugin.cfg.accelerate.Value;
public float airaccelerate => Plugin.cfg.airaccelerate.Value;
public float stopspeed => Plugin.cfg.stopspeed.Value;
private void Start()
{
_controller = player.thisController;
}
private void Update()
{
//IL_0213: Unknown result type (might be due to invalid IL or missing references)
//IL_021d: Unknown result type (might be due to invalid IL or missing references)
//IL_0227: Unknown result type (might be due to invalid IL or missing references)
//IL_022c: Unknown result type (might be due to invalid IL or missing references)
//IL_02bd: Unknown result type (might be due to invalid IL or missing references)
//IL_02c2: Unknown result type (might be due to invalid IL or missing references)
//IL_0304: Unknown result type (might be due to invalid IL or missing references)
if (((ButtonControl)Keyboard.current.f1Key).wasPressedThisFrame)
{
Plugin.cfg.modEnabled.Value = !Plugin.cfg.modEnabled.Value;
HUDManager instance = HUDManager.Instance;
if (instance != null)
{
instance.DisplayTip("LC Bhop", Plugin.cfg.modEnabled.Value ? "Enabled" : "Disabled", false, false, "LC_Tip1");
}
if (!Plugin.cfg.modEnabled.Value)
{
Plugin.patchMove = false;
Plugin.patchJump = false;
if (Object.op_Implicit((Object)(object)compass))
{
compass.SetActive(false);
}
}
}
if (!Plugin.cfg.modEnabled.Value)
{
return;
}
player.fallValue = 0f;
player.fallValueUncapped = 0f;
player.sprintMeter = 1f;
if (((!((NetworkBehaviour)player).IsOwner || !player.isPlayerControlled || (((NetworkBehaviour)player).IsServer && !player.isHostPlayerObject)) && !player.isTestingPlayer) || player.quickMenuManager.isMenuOpen || player.inSpecialInteractAnimation || player.isTypingChat)
{
return;
}
if (player.isClimbingLadder)
{
Plugin.patchMove = false;
return;
}
Jump();
if (!wishJump && _controller.isGrounded)
{
Friction();
}
if (_controller.isGrounded)
{
WalkMove();
}
else if (!_controller.isGrounded)
{
AirMove();
}
Plugin.patchMove = false;
_controller.Move(velocity / 32f * Time.deltaTime);
Plugin.patchMove = true;
wishJump = false;
if (Plugin.cfg.speedometer.Value)
{
if (!Object.op_Implicit((Object)(object)compass))
{
compass = GameObject.Find("/Systems/UI/Canvas/IngamePlayerHUD/TopLeftCorner/Compass");
GameObject obj = compass;
speedo = ((obj != null) ? obj.GetComponentInChildren<TextMeshProUGUI>() : null);
}
if (Object.op_Implicit((Object)(object)compass))
{
compass.SetActive(true);
Vector3 val = velocity;
val.y = 0f;
((TMP_Text)speedo).text = $"{(int)((Vector3)(ref val)).magnitude} u";
((TMP_Text)speedo).rectTransform.sizeDelta = ((TMP_Text)speedo).GetPreferredValues();
}
}
else if (Object.op_Implicit((Object)(object)compass))
{
compass.SetActive(false);
}
}
private void SetMovementDir()
{
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: 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_0046: Unknown result type (might be due to invalid IL or missing references)
//IL_004b: Unknown result type (might be due to invalid IL or missing references)
//IL_0053: Unknown result type (might be due to invalid IL or missing references)
ref Cmd cmd = ref _cmd;
MovementActions movement = player.playerActions.Movement;
cmd.forwardMove = ((MovementActions)(ref movement)).Move.ReadValue<Vector2>().y * movespeed;
ref Cmd cmd2 = ref _cmd;
movement = player.playerActions.Movement;
cmd2.rightMove = ((MovementActions)(ref movement)).Move.ReadValue<Vector2>().x * movespeed;
}
private void Jump()
{
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
//IL_005a: Unknown result type (might be due to invalid IL or missing references)
//IL_005f: Unknown result type (might be due to invalid IL or missing references)
MovementActions movement;
if (Plugin.cfg.autobhop.Value)
{
movement = player.playerActions.Movement;
wishJump = ((MovementActions)(ref movement)).Jump.ReadValue<float>() > 0f;
}
else if (!wishJump)
{
movement = player.playerActions.Movement;
wishJump = ((MovementActions)(ref movement)).SwitchItem.ReadValue<float>() != 0f;
}
if (!Plugin.cfg.enablebunnyhopping.Value)
{
PreventMegaBunnyJumping();
}
}
private void AirMove()
{
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
//IL_0038: 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)
SetMovementDir();
Vector3 val = default(Vector3);
((Vector3)(ref val))..ctor(_cmd.rightMove, 0f, _cmd.forwardMove);
val = ((Component)this).transform.TransformDirection(val);
Vector3 wishdir = val;
float magnitude = ((Vector3)(ref wishdir)).magnitude;
((Vector3)(ref wishdir)).Normalize();
if (magnitude > maxspeed)
{
magnitude = maxspeed;
}
AirAccelerate(wishdir, magnitude, airaccelerate);
velocity.y -= gravity * Time.deltaTime;
}
private void AirAccelerate(Vector3 wishdir, float wishspeed, float accel)
{
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_001d: 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_0079: Unknown result type (might be due to invalid IL or missing references)
//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
//IL_00d4: 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)
float num = wishspeed;
if (num > 75f)
{
num = 75f;
}
float num2 = Vector3.Dot(velocity, wishdir);
float num3 = num - num2;
if (!(num3 <= 0f))
{
float num4 = accel * wishspeed * Time.deltaTime;
if (num4 > num3)
{
num4 = num3;
}
velocity.x += num4 * wishdir.x;
velocity.z += num4 * wishdir.z;
Vector3 val = default(Vector3);
((Vector3)(ref val))..ctor(velocity.x, 0f, velocity.z);
if (((Vector3)(ref val)).magnitude > maxspeed)
{
val = ((Vector3)(ref val)).normalized * maxspeed;
velocity.x = val.x;
velocity.z = val.z;
}
}
}
private void WalkMove()
{
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
//IL_0031: Unknown result type (might be due to invalid IL or missing references)
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
//IL_006f: Unknown result type (might be due to invalid IL or missing references)
//IL_0057: 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_0065: Unknown result type (might be due to invalid IL or missing references)
SetMovementDir();
Vector3 val = default(Vector3);
((Vector3)(ref val))..ctor(_cmd.rightMove, 0f, _cmd.forwardMove);
val = ((Component)this).transform.TransformDirection(val);
Vector3 wishdir = val;
float magnitude = ((Vector3)(ref wishdir)).magnitude;
((Vector3)(ref wishdir)).Normalize();
if (magnitude > maxspeed)
{
val *= maxspeed / magnitude;
magnitude = maxspeed;
}
Accelerate(wishdir, magnitude, accelerate);
velocity.y = (0f - gravity) * Time.deltaTime;
if (wishJump)
{
velocity.y = 295f;
}
}
private void Friction()
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
Vector3 val = velocity;
val.y = 0f;
float magnitude = ((Vector3)(ref val)).magnitude;
if (!(magnitude < 0.1f))
{
float num = 0f;
if (_controller.isGrounded)
{
float num2 = ((magnitude < stopspeed) ? stopspeed : magnitude);
num += num2 * friction * Time.deltaTime;
}
float num3 = magnitude - num;
if (num3 < 0f)
{
num3 = 0f;
}
num3 /= magnitude;
velocity.x *= num3;
velocity.z *= num3;
}
}
private void Accelerate(Vector3 wishdir, float wishspeed, float accel)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_0047: Unknown result type (might be due to invalid IL or missing references)
//IL_005e: Unknown result type (might be due to invalid IL or missing references)
float num = Vector3.Dot(velocity, wishdir);
float num2 = wishspeed - num;
if (!(num2 <= 0f))
{
float num3 = accel * Time.deltaTime * wishspeed;
if (num3 > num2)
{
num3 = num2;
}
velocity.x += num3 * wishdir.x;
velocity.z += num3 * wishdir.z;
}
}
private void PreventMegaBunnyJumping()
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
Vector3 val = velocity;
float num = 1.7f * maxspeed;
if (!(num <= 0f))
{
val.y = 0f;
float magnitude = ((Vector3)(ref val)).magnitude;
if (!(magnitude <= num))
{
float num2 = num / magnitude * 0.65f;
velocity.x *= num2;
velocity.z *= num2;
}
}
}
}
[HarmonyPatch(typeof(CharacterController), "Move")]
internal class Move_Patch
{
[HarmonyPrefix]
internal static bool Prefix(ref Vector3 motion)
{
if (!Plugin.cfg.modEnabled.Value)
{
return true;
}
return !Plugin.patchMove;
}
}
[HarmonyPatch(typeof(PlayerControllerB), "Crouch_performed")]
internal class Crouch_performed_Patch
{
[HarmonyPrefix]
internal static bool Prefix(PlayerControllerB __instance, ref CallbackContext context)
{
if (!Plugin.cfg.modEnabled.Value)
{
return true;
}
if (!((CallbackContext)(ref context)).performed)
{
return false;
}
if (__instance.quickMenuManager.isMenuOpen)
{
return false;
}
if ((!((NetworkBehaviour)__instance).IsOwner || !__instance.isPlayerControlled || (((NetworkBehaviour)__instance).IsServer && !__instance.isHostPlayerObject)) && !__instance.isTestingPlayer)
{
return false;
}
if (__instance.inSpecialInteractAnimation || __instance.isTypingChat)
{
return false;
}
__instance.Crouch(!__instance.isCrouching);
return false;
}
}
[HarmonyPatch(typeof(PlayerControllerB), "Jump_performed")]
internal class Jump_performed_Patch
{
[HarmonyPrefix]
internal static bool Prefix(ref CallbackContext context)
{
if (!Plugin.cfg.modEnabled.Value)
{
return true;
}
Plugin.player.wishJump = true;
return !Plugin.patchJump;
}
}
[HarmonyPatch(typeof(PlayerControllerB), "ScrollMouse_performed")]
internal class ScrollMouse_performed_Patch
{
[HarmonyPrefix]
internal static bool Prefix(ref CallbackContext context)
{
if (!Plugin.cfg.modEnabled.Value)
{
return true;
}
return Plugin.cfg.autobhop.Value;
}
}
[HarmonyPatch(typeof(HUDManager), "SubmitChat_performed")]
internal class SubmitChat_performed_Patch
{
[HarmonyPrefix]
internal static bool Prefix(HUDManager __instance)
{
string text = __instance.chatTextField.text;
if (text.StartsWith("/autobhop"))
{
Plugin.cfg.autobhop.Value = !Plugin.cfg.autobhop.Value;
}
else
{
if (!text.StartsWith("/speedo"))
{
return true;
}
Plugin.cfg.speedometer.Value = !Plugin.cfg.speedometer.Value;
}
__instance.localPlayer.isTypingChat = false;
__instance.chatTextField.text = "";
EventSystem.current.SetSelectedGameObject((GameObject)null);
__instance.PingHUDElement(__instance.Chat, 2f, 1f, 0.2f);
((Behaviour)__instance.typingIndicator).enabled = false;
return false;
}
}
public class ComponentAdder : MonoBehaviour
{
private void Update()
{
PlayerControllerB[] array = Object.FindObjectsOfType<PlayerControllerB>();
foreach (PlayerControllerB val in array)
{
if ((Object)(object)val != (Object)null && (Object)(object)((Component)val).gameObject.GetComponentInChildren<CPMPlayer>() == (Object)null && ((NetworkBehaviour)val).IsOwner && val.isPlayerControlled)
{
Plugin.player = ((Component)val).gameObject.AddComponent<CPMPlayer>();
Plugin.player.player = val;
}
}
}
}
[BepInPlugin("lcbhop", "LC Bhop", "1.0.0")]
public class Plugin : BaseUnityPlugin
{
public static ManualLogSource logger;
private readonly Harmony harmony = new Harmony("lcbhop");
public static bool patchMove = true;
public static bool patchJump = true;
public static CPMPlayer player;
public static Config cfg { get; set; }
private void Awake()
{
cfg = new Config(((BaseUnityPlugin)this).Config);
cfg.Init();
logger = ((BaseUnityPlugin)this).Logger;
harmony.PatchAll();
((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin lcbhop is loaded!");
}
private void OnDestroy()
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Expected O, but got Unknown
GameObject val = new GameObject("ComponentAdder");
Object.DontDestroyOnLoad((Object)(object)val);
val.AddComponent<ComponentAdder>();
}
}
[HarmonyPatch(typeof(NetworkManager))]
internal static class NetworkPrefabPatch2
{
private static readonly string MOD_GUID = "lcbhop";
[HarmonyPostfix]
[HarmonyPatch("SetSingleton")]
private static void RegisterPrefab()
{
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Expected O, but got Unknown
//IL_0018: 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)
GameObject val = new GameObject(MOD_GUID + " Prefab");
((Object)val).hideFlags = (HideFlags)(((Object)val).hideFlags | 0x3D);
Object.DontDestroyOnLoad((Object)(object)val);
NetworkObject obj = val.AddComponent<NetworkObject>();
FieldInfo field = typeof(NetworkObject).GetField("GlobalObjectIdHash", BindingFlags.Instance | BindingFlags.NonPublic);
if (field != null)
{
field.SetValue(obj, GetHash(MOD_GUID));
}
if ((Object)(object)NetworkManager.Singleton != (Object)null && NetworkManager.Singleton.PrefabHandler != null)
{
NetworkManager.Singleton.PrefabHandler.AddNetworkPrefab(val);
}
}
private static uint GetHash(string value)
{
return value?.Aggregate(17u, (uint current, char c) => (current * 31) ^ c) ?? 0;
}
}