Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of SourceBhop v0.3.9
BepInEx/plugins/SourceBhop.dll
Decompiled 2 weeks agousing System; using System.Collections.Generic; using System.Globalization; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using GameNetcodeStuff; using HarmonyLib; using Unity.Netcode; using UnityEngine; using UnityEngine.InputSystem; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: AssemblyVersion("0.0.0.0")] namespace SourceBhop; internal enum SpeedometerCorner { TopLeft, TopRight, BottomLeft, BottomRight } [BepInPlugin("Tim.SourceBhop", "Source Bhop", "0.3.9")] public sealed class Plugin : BaseUnityPlugin { internal const string Guid = "Tim.SourceBhop"; internal static ConfigEntry<bool> Enabled; internal static ConfigEntry<bool> AutoHop; internal static ConfigEntry<bool> ShowSpeedometer; internal static ConfigEntry<SpeedometerCorner> Corner; internal static ConfigEntry<float> GroundAcceleration; internal static ConfigEntry<float> AirAcceleration; internal static ConfigEntry<float> GroundFriction; internal static ConfigEntry<float> StopSpeed; internal static ConfigEntry<float> AirWishSpeedFraction; internal static ConfigEntry<float> AirTurnAssistRate; internal static ConfigEntry<float> JumpTakeoffDelaySeconds; internal static ConfigEntry<float> JumpStaminaMultiplier; internal static ConfigEntry<bool> DebugOverlay; internal static ConfigEntry<bool> DebugFallDamage; internal static ConfigEntry<bool> DebugAirStrafe; internal static ManualLogSource Log; internal static bool NetworkRequirementReady; private Harmony _harmony; private GUIStyle _speedometerStyle; private GUIStyle _statusStyle; private bool _loggedGui; private float _nextStatusLog; private void Awake() { //IL_02ac: Unknown result type (might be due to invalid IL or missing references) //IL_02b6: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable Source-style bunnyhopping for the local player."); AutoHop = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "AutoHop", true, "Hold Jump to jump again on landing."); ShowSpeedometer = ((BaseUnityPlugin)this).Config.Bind<bool>("HUD", "ShowSpeedometer", true, "Show current horizontal movement speed in a screen corner."); Corner = ((BaseUnityPlugin)this).Config.Bind<SpeedometerCorner>("HUD", "Corner", SpeedometerCorner.TopRight, "Speedometer location: TopLeft, TopRight, BottomLeft, or BottomRight."); GroundAcceleration = ((BaseUnityPlugin)this).Config.Bind<float>("Movement", "GroundAcceleration", 10f, "Acceleration toward the desired direction while grounded."); AirAcceleration = ((BaseUnityPlugin)this).Config.Bind<float>("Movement", "AirAcceleration", 10f, "Acceleration toward the desired direction in the air."); GroundFriction = ((BaseUnityPlugin)this).Config.Bind<float>("Movement", "GroundFriction", 6f, "Horizontal friction while grounded and not jumping."); StopSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Movement", "StopSpeed", 2f, "Minimum speed used in the ground friction calculation, in game units per second."); AirWishSpeedFraction = ((BaseUnityPlugin)this).Config.Bind<float>("Movement", "AirWishSpeedFraction", 0.3f, "Directional air speed limit as a fraction of normal movement speed. This does not cap total speed."); AirTurnAssistRate = ((BaseUnityPlugin)this).Config.Bind<float>("Movement", "AirTurnAssistDegreesPerSecond", 720f, "Maximum extra rotation of existing airborne momentum per second during a matching fast look turn and side strafe. Set to 0 to disable."); JumpTakeoffDelaySeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Jump", "TakeoffDelaySeconds", 0.02f, "Time between jump input and upward movement. Vanilla is 0.15 seconds."); JumpStaminaMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Jump", "StaminaCostMultiplier", 0.5f, "Multiplier on the normal jump stamina cost of 0.08. Default 0.5 costs 0.04."); DebugOverlay = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "ShowStatus", false, "Show local-player and input status for troubleshooting."); DebugFallDamage = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "LogFallDamage", false, "Log local-player landing and fall-damage events for troubleshooting."); DebugAirStrafe = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "LogAirStrafe", false, "Log local airborne side-strafing directions and velocities for troubleshooting."); Log.LogInfo((object)("Configuration: enabled=" + Enabled.Value + " speedometer=" + ShowSpeedometer.Value + " showStatus=" + DebugOverlay.Value + " logFallDamage=" + DebugFallDamage.Value + " logAirStrafe=" + DebugAirStrafe.Value)); _harmony = new Harmony("Tim.SourceBhop"); _harmony.PatchAll(typeof(Plugin).Assembly); RequiredNetworkPrefabPatch.Register(NetworkManager.Singleton); PatchJumpMethods(); Log.LogInfo((object)"Source Bhop loaded"); } private void OnEnable() { ((BaseUnityPlugin)this).Logger.LogInfo((object)"Source Bhop component enabled"); } private void Start() { ((BaseUnityPlugin)this).Logger.LogInfo((object)"Source Bhop component started"); } private void PatchJumpMethods() { //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Expected O, but got Unknown //IL_00b3: Expected O, but got Unknown //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Expected O, but got Unknown try { MethodInfo methodInfo = AccessTools.Method(typeof(PlayerControllerB), "Jump_performed", (Type[])null, (Type[])null); MethodInfo methodInfo2 = AccessTools.Method(typeof(JumpCostPatch), "Prefix", (Type[])null, (Type[])null); MethodInfo methodInfo3 = AccessTools.Method(typeof(JumpCostPatch), "Postfix", (Type[])null, (Type[])null); if (methodInfo != null && methodInfo2 != null && methodInfo3 != null && AccessTools.Field(typeof(PlayerControllerB), "sprintMeter") != null && AccessTools.Field(typeof(PlayerControllerB), "isJumping") != null) { _harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(methodInfo2), new HarmonyMethod(methodInfo3), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Log.LogInfo((object)"Jump stamina patch installed"); } else { Log.LogError((object)"Could not find the jump stamina hook; vanilla jump cost remains active."); } } catch (Exception ex) { Log.LogError((object)("Jump stamina patch failed: " + ex)); } try { Type type = null; Type[] nestedTypes = typeof(PlayerControllerB).GetNestedTypes(BindingFlags.NonPublic); foreach (Type type2 in nestedTypes) { if (type2.Name.StartsWith("<PlayerJump>d__", StringComparison.Ordinal)) { type = type2; break; } } MethodInfo methodInfo4 = ((type == null) ? null : AccessTools.Method(type, "MoveNext", (Type[])null, (Type[])null)); MethodInfo methodInfo5 = AccessTools.Method(typeof(JumpTakeoffPatch), "Transpiler", (Type[])null, (Type[])null); if (methodInfo4 != null && methodInfo5 != null) { _harmony.Patch((MethodBase)methodInfo4, (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(methodInfo5), (HarmonyMethod)null, (HarmonyMethod)null); Log.LogInfo((object)"Jump takeoff patch installed"); } else { Log.LogError((object)"Could not find the jump takeoff hook; vanilla delay remains active."); } } catch (Exception ex2) { Log.LogError((object)("Jump takeoff patch failed: " + ex2)); } } private void OnGUI() { //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Expected O, but got Unknown //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Expected O, but got Unknown //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_026d: Unknown result type (might be due to invalid IL or missing references) //IL_0272: Unknown result type (might be due to invalid IL or missing references) //IL_0288: Unknown result type (might be due to invalid IL or missing references) //IL_0292: Unknown result type (might be due to invalid IL or missing references) //IL_029e: Unknown result type (might be due to invalid IL or missing references) //IL_02a8: Unknown result type (might be due to invalid IL or missing references) //IL_02d5: Unknown result type (might be due to invalid IL or missing references) if (DebugOverlay.Value && !_loggedGui) { _loggedGui = true; Log.LogInfo((object)"Debug display is running"); } if (DebugOverlay.Value) { if (_statusStyle == null) { _statusStyle = new GUIStyle(GUI.skin.label); _statusStyle.fontSize = 14; _statusStyle.fontStyle = (FontStyle)1; _statusStyle.alignment = (TextAnchor)3; _statusStyle.normal.textColor = Color.white; } Rect val = default(Rect); ((Rect)(ref val))..ctor(12f, 12f, Mathf.Max(100f, (float)Screen.width - 24f), 32f); Color color = GUI.color; GUI.color = new Color(0f, 0f, 0f, 0.8f); GUI.DrawTexture(val, (Texture)(object)Texture2D.whiteTexture); GUI.color = Color.white; GUI.Label(new Rect(((Rect)(ref val)).x + 8f, ((Rect)(ref val)).y, ((Rect)(ref val)).width - 16f, ((Rect)(ref val)).height), "SOURCE BHOP 0.3.9 " + Movement.DebugStatus(), _statusStyle); GUI.color = color; } if (ShowSpeedometer.Value && Movement.TryGetCurrentSpeed(out var speed)) { if (_speedometerStyle == null) { _speedometerStyle = new GUIStyle(GUI.skin.label); _speedometerStyle.alignment = (TextAnchor)4; _speedometerStyle.fontSize = 18; _speedometerStyle.fontStyle = (FontStyle)1; _speedometerStyle.normal.textColor = Color.white; } float num = ((Corner.Value == SpeedometerCorner.TopRight || Corner.Value == SpeedometerCorner.BottomRight) ? ((float)Screen.width - 180f - 16f) : 16f); float num2 = ((Corner.Value == SpeedometerCorner.BottomLeft || Corner.Value == SpeedometerCorner.BottomRight) ? ((float)Screen.height - 36f - 16f) : 16f); if (DebugOverlay.Value && (Corner.Value == SpeedometerCorner.TopLeft || Corner.Value == SpeedometerCorner.TopRight)) { num2 = 52f; } Rect val2 = default(Rect); ((Rect)(ref val2))..ctor(Mathf.Max(0f, num), Mathf.Max(0f, num2), 180f, 36f); Color color2 = GUI.color; GUI.color = new Color(0f, 0f, 0f, 0.65f); GUI.DrawTexture(val2, (Texture)(object)Texture2D.whiteTexture); GUI.color = Color.white; GUI.Label(val2, "SPEED " + speed.ToString("0.0", CultureInfo.InvariantCulture) + " u/s", _speedometerStyle); GUI.color = color2; } } private void Update() { if (DebugOverlay.Value && !(Time.unscaledTime < _nextStatusLog)) { _nextStatusLog = Time.unscaledTime + 10f; Log.LogInfo((object)("Runtime status: " + Movement.DebugStatus())); } } private void OnDestroy() { if (_harmony != null) { _harmony.UnpatchSelf(); } } } [HarmonyPatch(typeof(NetworkManager), "SetSingleton")] internal static class RequiredNetworkPrefabPatch { private static readonly FieldInfo GlobalObjectIdHash = typeof(NetworkObject).GetField("GlobalObjectIdHash", BindingFlags.Instance | BindingFlags.NonPublic); private static NetworkManager _registeredManager; private static GameObject _prefab; private static void Postfix(NetworkManager __instance) { Register(__instance); } internal static void Register(NetworkManager __instance) { //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Expected O, but got Unknown //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null || (Object)(object)__instance != (Object)(object)NetworkManager.Singleton || (Object)(object)_registeredManager == (Object)(object)__instance) { return; } Plugin.NetworkRequirementReady = false; if (GlobalObjectIdHash == null || GlobalObjectIdHash.FieldType != typeof(uint) || __instance.NetworkConfig == null) { Plugin.Log.LogError((object)"Cannot require Source Bhop for the lobby: Netcode prefab registration is unavailable."); return; } try { if ((Object)(object)_prefab == (Object)null) { _prefab = new GameObject("Tim.SourceBhop Required Prefab"); GameObject prefab = _prefab; ((Object)prefab).hideFlags = (HideFlags)(((Object)prefab).hideFlags | 0x3D); Object.DontDestroyOnLoad((Object)(object)_prefab); NetworkObject obj = _prefab.AddComponent<NetworkObject>(); GlobalObjectIdHash.SetValue(obj, GetHash("Tim.SourceBhop")); } __instance.NetworkConfig.ForceSamePrefabs = true; __instance.PrefabHandler.AddNetworkPrefab(_prefab); if (!__instance.NetworkConfig.Prefabs.Contains(_prefab)) { throw new InvalidOperationException("Netcode did not add the required prefab."); } _registeredManager = __instance; Plugin.NetworkRequirementReady = true; Plugin.Log.LogInfo((object)("Source Bhop network requirement registered (hash=" + GetHash("Tim.SourceBhop") + ").")); } catch (Exception ex) { Plugin.Log.LogError((object)("Cannot require Source Bhop for the lobby: " + ex)); } } private static uint GetHash(string value) { uint num = 17u; foreach (char c in value) { num = (num * 31) ^ c; } return num; } } internal static class Movement { private static readonly FieldInfo SprintMultiplier = AccessTools.Field(typeof(PlayerControllerB), "sprintMultiplier"); private static readonly FieldInfo IsJumping = AccessTools.Field(typeof(PlayerControllerB), "isJumping"); private static readonly FieldInfo IsFallingFromJump = AccessTools.Field(typeof(PlayerControllerB), "isFallingFromJump"); private static readonly FieldInfo IsFallingNoJump = AccessTools.Field(typeof(PlayerControllerB), "isFallingNoJump"); private static readonly MethodInfo JumpPerformed = AccessTools.Method(typeof(PlayerControllerB), "Jump_performed", (Type[])null, (Type[])null); private static PlayerControllerB _player; private static Vector3 _velocity; private static bool _hasVelocity; private static InputAction _jumpAction; private static int _walkingHookCalls; private static int _lateHookCalls; private static float _nextAirTraceTime; private static int _pendingAirTraceFrame = -1; private static string _pendingAirTrace; private static float _lastBodyYaw; private static bool _hasBodyYaw; internal static bool TryGetCurrentSpeed(out float speed) { //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_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) speed = 0f; GameNetworkManager instance = GameNetworkManager.Instance; if ((Object)(object)instance == (Object)null || (Object)(object)instance.localPlayerController == (Object)null) { return false; } PlayerControllerB localPlayerController = instance.localPlayerController; if (!localPlayerController.isPlayerControlled || localPlayerController.isPlayerDead || localPlayerController.isFreeCamera || (Object)(object)localPlayerController.thisController == (Object)null || (Object)(object)localPlayerController.quickMenuManager == (Object)null || localPlayerController.quickMenuManager.isMenuOpen) { return false; } Vector3 velocity = localPlayerController.thisController.velocity; Vector2 val = new Vector2(velocity.x, velocity.z); speed = ((Vector2)(ref val)).magnitude; return true; } internal static bool Eligible(PlayerControllerB player) { GameNetworkManager instance = GameNetworkManager.Instance; if (Plugin.Enabled.Value && Plugin.NetworkRequirementReady && (Object)(object)instance != (Object)null && (Object)(object)instance.localPlayerController == (Object)(object)player && player.isPlayerControlled && !player.isPlayerDead && !player.disableMoveInput && !player.inSpecialInteractAnimation && !player.isClimbingLadder && !player.isFreeCamera && !player.jetpackControls && !player.isUnderwater && !player.isPlayerSliding && !player.teleportedLastFrame && !player.isTypingChat && player.isMovementHindered == 0 && (Object)(object)player.quickMenuManager != (Object)null && !player.quickMenuManager.isMenuOpen) { return (Object)(object)player.thisController != (Object)null; } return false; } internal static string DebugStatus() { //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) GameNetworkManager instance = GameNetworkManager.Instance; if ((Object)(object)instance == (Object)null) { return "waiting for game manager"; } PlayerControllerB localPlayerController = instance.localPlayerController; if ((Object)(object)localPlayerController == (Object)null) { return "waiting for local player"; } if (_jumpAction == null && (Object)(object)InputSystem.actions != (Object)null) { _jumpAction = InputSystem.actions.FindAction("Jump", false); } object[] array = new object[16] { "eligible=", Eligible(localPlayerController), " controlled=", localPlayerController.isPlayerControlled, " dead=", localPlayerController.isPlayerDead, " grounded=", (Object)(object)localPlayerController.thisController != (Object)null && localPlayerController.thisController.isGrounded, " jumpAction=", _jumpAction != null, " walkHook=", _walkingHookCalls, " lateHook=", _lateHookCalls, " speed=", null }; object obj; if (!((Object)(object)localPlayerController.thisController == (Object)null)) { Vector3 velocity = localPlayerController.thisController.velocity; obj = ((Vector3)(ref velocity)).magnitude.ToString("0.0", CultureInfo.InvariantCulture); } else { obj = "n/a"; } array[15] = obj; return string.Concat(array); } internal static void TryAutoHopAfterLanding(PlayerControllerB player) { //IL_00ce: 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) GameNetworkManager instance = GameNetworkManager.Instance; if ((Object)(object)instance != (Object)null && (Object)(object)instance.localPlayerController == (Object)(object)player) { _lateHookCalls++; } if (Eligible(player) && Plugin.AutoHop.Value && !(JumpPerformed == null) && !(IsJumping == null) && !(IsFallingFromJump == null) && !(IsFallingNoJump == null) && IsJumpHeld() && player.thisController.isGrounded && !(bool)IsJumping.GetValue(player) && !(bool)IsFallingFromJump.GetValue(player) && !(bool)IsFallingNoJump.GetValue(player)) { JumpPerformed.Invoke(player, new object[1] { (object)default(CallbackContext) }); } } internal static Vector3 AdjustBaseVelocity(Vector3 vanilla, PlayerControllerB player) { //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01f0: Unknown result type (might be due to invalid IL or missing references) //IL_0202: Unknown result type (might be due to invalid IL or missing references) //IL_01f5: Unknown result type (might be due to invalid IL or missing references) //IL_0207: Unknown result type (might be due to invalid IL or missing references) //IL_0213: Unknown result type (might be due to invalid IL or missing references) //IL_020c: Unknown result type (might be due to invalid IL or missing references) //IL_0218: Unknown result type (might be due to invalid IL or missing references) //IL_022a: Unknown result type (might be due to invalid IL or missing references) //IL_0266: Unknown result type (might be due to invalid IL or missing references) //IL_0270: Unknown result type (might be due to invalid IL or missing references) //IL_0275: Unknown result type (might be due to invalid IL or missing references) //IL_027d: Unknown result type (might be due to invalid IL or missing references) //IL_0289: Unknown result type (might be due to invalid IL or missing references) //IL_0294: Unknown result type (might be due to invalid IL or missing references) //IL_02a0: Unknown result type (might be due to invalid IL or missing references) //IL_02a5: Unknown result type (might be due to invalid IL or missing references) //IL_02aa: Unknown result type (might be due to invalid IL or missing references) //IL_0259: Unknown result type (might be due to invalid IL or missing references) //IL_02d4: Unknown result type (might be due to invalid IL or missing references) //IL_02dd: Unknown result type (might be due to invalid IL or missing references) //IL_02e2: Unknown result type (might be due to invalid IL or missing references) //IL_0372: Unknown result type (might be due to invalid IL or missing references) //IL_0377: Unknown result type (might be due to invalid IL or missing references) //IL_03b7: Unknown result type (might be due to invalid IL or missing references) //IL_03bc: Unknown result type (might be due to invalid IL or missing references) //IL_0428: Unknown result type (might be due to invalid IL or missing references) //IL_045d: Unknown result type (might be due to invalid IL or missing references) //IL_0462: Unknown result type (might be due to invalid IL or missing references) //IL_0404: Unknown result type (might be due to invalid IL or missing references) //IL_0686: Unknown result type (might be due to invalid IL or missing references) //IL_05c8: Unknown result type (might be due to invalid IL or missing references) //IL_05f4: Unknown result type (might be due to invalid IL or missing references) //IL_05ff: Unknown result type (might be due to invalid IL or missing references) //IL_060a: Unknown result type (might be due to invalid IL or missing references) //IL_0654: Unknown result type (might be due to invalid IL or missing references) //IL_0580: Unknown result type (might be due to invalid IL or missing references) //IL_0585: Unknown result type (might be due to invalid IL or missing references) //IL_058a: Unknown result type (might be due to invalid IL or missing references) //IL_058f: Unknown result type (might be due to invalid IL or missing references) GameNetworkManager instance = GameNetworkManager.Instance; bool flag = (Object)(object)instance != (Object)null && (Object)(object)instance.localPlayerController == (Object)(object)player; if (flag) { _walkingHookCalls++; } bool flag2 = flag && Plugin.DebugAirStrafe.Value && (Object)(object)player.thisController != (Object)null && !player.thisController.isGrounded && Mathf.Abs(player.moveInputVector.x) > 0.2f && Time.unscaledTime >= _nextAirTraceTime; if (flag2) { _nextAirTraceTime = Time.unscaledTime + 0.05f; } if (!Eligible(player) || SprintMultiplier == null || IsJumping == null) { if (flag2) { Plugin.Log.LogInfo((object)("AirTrace frame=" + Time.frameCount + " inactive eligible=" + Eligible(player) + " sprintField=" + (SprintMultiplier != null) + " jumpingField=" + (IsJumping != null) + " input=" + FormatInput(player.moveInputVector))); } Reset(); return vanilla; } if ((Object)(object)_player != (Object)(object)player || !_hasVelocity) { _player = player; _velocity = player.thisController.velocity; _velocity.y = 0f; _hasVelocity = true; _hasBodyYaw = false; } float y = ((Component)player).transform.eulerAngles.y; float num = (_hasBodyYaw ? Mathf.DeltaAngle(_lastBodyYaw, y) : 0f); _lastBodyYaw = y; _hasBodyYaw = true; float deltaTime = Time.deltaTime; if (deltaTime <= 0f) { return vanilla; } Vector3 velocity = (flag2 ? player.thisController.velocity : Vector3.zero); Vector3 velocity2 = (flag2 ? _velocity : Vector3.zero); float num2 = (flag2 ? ((Component)player).transform.eulerAngles.y : 0f); float num3 = ((flag2 && (Object)(object)player.gameplayCamera != (Object)null) ? ((Component)player.gameplayCamera).transform.eulerAngles.y : 0f); Vector2 input = Vector2.ClampMagnitude(player.moveInputVector, 1f); Vector3 val = ((Component)player).transform.right * input.x + ((Component)player).transform.forward * input.y; val.y = 0f; float num4 = Mathf.Min(1f, ((Vector3)(ref val)).magnitude); if (num4 > 0.0001f) { val /= ((Vector3)(ref val)).magnitude; } float num5 = Mathf.Max(0f, (float)SprintMultiplier.GetValue(player)); float num6 = Mathf.Max(0f, player.movementSpeed) / Mathf.Max(0.1f, player.carryWeight) * num5 * num4; bool flag3 = (bool)IsJumping.GetValue(player); bool isGrounded = player.thisController.isGrounded; bool flag4 = Plugin.AutoHop.Value && IsJumpHeld(); Vector2 val2 = new Vector2(_velocity.x, _velocity.z); float magnitude = ((Vector2)(ref val2)).magnitude; bool flag5 = isGrounded && (flag3 || flag4) && magnitude > num6; float num7 = num6 * Mathf.Clamp01(Plugin.AirWishSpeedFraction.Value); float num8 = (flag2 ? Vector3.Dot(_velocity, val) : 0f); float num9 = Mathf.Atan2(_velocity.x, _velocity.z) * 57.29578f; float num10 = 0f; if (isGrounded && !flag5) { if (!flag3 && !flag4) { ApplyFriction(deltaTime); } Accelerate(val, num6, Mathf.Max(0f, Plugin.GroundAcceleration.Value), deltaTime); } else { Accelerate(val, num7, Mathf.Max(0f, Plugin.AirAcceleration.Value), deltaTime, num6); Vector2 val3 = new Vector2(_velocity.x, _velocity.z); float magnitude2 = ((Vector2)(ref val3)).magnitude; if (Mathf.Abs(input.x) > 0.1f && magnitude > 0.001f && magnitude2 > 0.001f && magnitude2 < magnitude) { float num11 = magnitude / magnitude2; _velocity.x *= num11; _velocity.z *= num11; } if (!isGrounded && Mathf.Abs(input.x) > 0.2f && magnitude > 0.001f && num * input.x > 0f) { float num12 = Mathf.Atan2(_velocity.x, _velocity.z) * 57.29578f; float num13 = Mathf.DeltaAngle(num9, num12) * Mathf.Sign(num); float num14 = Mathf.Max(0f, Mathf.Abs(num) - num13); num10 = Mathf.Min(num14, Mathf.Max(0f, Plugin.AirTurnAssistRate.Value) * deltaTime); _velocity = Quaternion.Euler(0f, Mathf.Sign(num) * num10, 0f) * _velocity; } } if (flag2) { _pendingAirTraceFrame = Time.frameCount; _pendingAirTrace = string.Format(CultureInfo.InvariantCulture, "AirTrace frame={0} input={1} dt={2:0.000} bodyYawBefore={3:0.0} cameraYawBefore={4:0.0} wish={5} actualBefore={6} storedBefore={7} cap={8:0.00} projected={9:0.00} room={10:0.00} lookTurn={11:0.00} assist={12:0.00} storedAfter={13}", Time.frameCount, FormatInput(input), deltaTime, num2, num3, FormatHorizontal(val), FormatHorizontal(velocity), FormatHorizontal(velocity2), num7, num8, num7 - num8, num, num10, FormatHorizontal(_velocity)); } return new Vector3(_velocity.x, vanilla.y, _velocity.z); } internal static void LogAirStrafeAfterLook(PlayerControllerB player) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) if (_pendingAirTraceFrame == Time.frameCount && _pendingAirTrace != null && !((Object)(object)GameNetworkManager.Instance == (Object)null) && !((Object)(object)GameNetworkManager.Instance.localPlayerController != (Object)(object)player)) { Plugin.Log.LogInfo((object)(_pendingAirTrace + string.Format(CultureInfo.InvariantCulture, " bodyYawAfter={0:0.0} cameraYawAfter={1:0.0} actualAfter={2}", ((Component)player).transform.eulerAngles.y, ((Object)(object)player.gameplayCamera == (Object)null) ? 0f : ((Component)player.gameplayCamera).transform.eulerAngles.y, FormatHorizontal(player.thisController.velocity)))); _pendingAirTrace = null; _pendingAirTraceFrame = -1; } } private static string FormatInput(Vector2 input) { return string.Format(CultureInfo.InvariantCulture, "({0:0.00},{1:0.00})", input.x, input.y); } private static string FormatHorizontal(Vector3 velocity) { //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) CultureInfo invariantCulture = CultureInfo.InvariantCulture; Vector2 val = new Vector2(velocity.x, velocity.z); return string.Format(invariantCulture, "{0:0.00}@{1:0.0}", ((Vector2)(ref val)).magnitude, Mathf.Atan2(velocity.x, velocity.z) * 57.29578f); } private static bool IsJumpHeld() { if (_jumpAction == null && (Object)(object)InputSystem.actions != (Object)null) { _jumpAction = InputSystem.actions.FindAction("Jump", false); } if (_jumpAction != null) { return _jumpAction.IsPressed(); } return false; } private static void ApplyFriction(float dt) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) Vector2 val = new Vector2(_velocity.x, _velocity.z); float magnitude = ((Vector2)(ref val)).magnitude; if (!(magnitude < 0.0001f)) { float num = Mathf.Max(magnitude, Mathf.Max(0f, Plugin.StopSpeed.Value)); float num2 = Mathf.Max(0f, magnitude - num * Mathf.Max(0f, Plugin.GroundFriction.Value) * dt); float num3 = num2 / magnitude; _velocity.x *= num3; _velocity.z *= num3; } } private static void Accelerate(Vector3 direction, float directionalLimit, float acceleration, float dt) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) Accelerate(direction, directionalLimit, acceleration, dt, directionalLimit); } private static void Accelerate(Vector3 direction, float directionalLimit, float acceleration, float dt, float uncappedWishSpeed) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: 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_003c: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) if (!(directionalLimit <= 0f) && !(acceleration <= 0f)) { float num = Vector3.Dot(_velocity, direction); float num2 = directionalLimit - num; if (!(num2 <= 0f)) { float num3 = Mathf.Min(num2, acceleration * uncappedWishSpeed * dt); _velocity += direction * num3; } } } internal static void Reset() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) _player = null; _velocity = Vector3.zero; _hasVelocity = false; _hasBodyYaw = false; } } [HarmonyPatch(typeof(PlayerControllerB), "Update")] internal static class PlayerUpdatePatch { private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> source) { //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Expected O, but got Unknown //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Expected O, but got Unknown List<CodeInstruction> list = new List<CodeInstruction>(source); MethodInfo methodInfo = AccessTools.Method(typeof(Movement), "AdjustBaseVelocity", (Type[])null, (Type[])null); int num = 0; for (int i = 3; i < list.Count; i++) { FieldInfo fieldInfo = list[i - 2].operand as FieldInfo; MethodInfo methodInfo2 = list[i - 1].operand as MethodInfo; if (!(fieldInfo == null) && !(fieldInfo.Name != "sprintMultiplier") && !(methodInfo2 == null) && !(methodInfo2.DeclaringType != typeof(Vector3)) && !(methodInfo2.Name != "op_Multiply") && IsStoreLocal(list[i].opcode)) { list.Insert(i, new CodeInstruction(OpCodes.Ldarg_0, (object)null)); list.Insert(i + 1, new CodeInstruction(OpCodes.Call, (object)methodInfo)); num++; break; } } if (num != 1) { Plugin.Log.LogError((object)"Could not find the walking velocity hook; vanilla movement remains active."); } return list; } private static bool IsStoreLocal(OpCode opcode) { if (!(opcode == OpCodes.Stloc) && !(opcode == OpCodes.Stloc_S) && !(opcode == OpCodes.Stloc_0) && !(opcode == OpCodes.Stloc_1) && !(opcode == OpCodes.Stloc_2)) { return opcode == OpCodes.Stloc_3; } return true; } } [HarmonyPatch(typeof(PlayerControllerB), "LateUpdate")] internal static class PlayerLateUpdatePatch { private static void Postfix(PlayerControllerB __instance) { Movement.TryAutoHopAfterLanding(__instance); Movement.LogAirStrafeAfterLook(__instance); } } internal static class JumpCostPatch { private struct JumpState { internal bool Active; internal bool WasJumping; internal float StaminaBefore; } private static readonly FieldInfo SprintMeter = AccessTools.Field(typeof(PlayerControllerB), "sprintMeter"); private static readonly FieldInfo IsJumping = AccessTools.Field(typeof(PlayerControllerB), "isJumping"); private static void Prefix(PlayerControllerB __instance, out JumpState __state) { __state = default(JumpState); GameNetworkManager instance = GameNetworkManager.Instance; if (Plugin.Enabled.Value && Plugin.NetworkRequirementReady && (Object)(object)instance != (Object)null && (Object)(object)instance.localPlayerController == (Object)(object)__instance) { __state.Active = true; __state.WasJumping = (bool)IsJumping.GetValue(__instance); __state.StaminaBefore = (float)SprintMeter.GetValue(__instance); } } private static void Postfix(PlayerControllerB __instance, JumpState __state) { if (__state.Active && !__state.WasJumping && (bool)IsJumping.GetValue(__instance)) { float num = 0.08f * Mathf.Clamp01(Plugin.JumpStaminaMultiplier.Value); SprintMeter.SetValue(__instance, Mathf.Clamp01(__state.StaminaBefore - num)); } } } internal static class JumpTakeoffPatch { private static float ResolveDelay(float vanillaDelay) { if (!Plugin.Enabled.Value || !Plugin.NetworkRequirementReady) { return vanillaDelay; } return Mathf.Clamp(Plugin.JumpTakeoffDelaySeconds.Value, 0f, vanillaDelay); } private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> source) { //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Expected O, but got Unknown List<CodeInstruction> list = new List<CodeInstruction>(source); MethodInfo methodInfo = AccessTools.Method(typeof(JumpTakeoffPatch), "ResolveDelay", (Type[])null, (Type[])null); int num = 0; for (int i = 0; i < list.Count - 1; i++) { ConstructorInfo constructorInfo = list[i + 1].operand as ConstructorInfo; if (!(list[i].opcode != OpCodes.Ldc_R4) && list[i].operand is float && (float)list[i].operand == 0.15f && !(constructorInfo == null) && !(constructorInfo.DeclaringType != typeof(WaitForSeconds))) { list.Insert(i + 1, new CodeInstruction(OpCodes.Call, (object)methodInfo)); num++; break; } } if (num != 1) { Plugin.Log.LogError((object)"Could not find the jump takeoff delay; vanilla delay remains active."); } return list; } } [HarmonyPatch(typeof(PlayerControllerB), "PlayerHitGroundEffects")] internal static class FallLandingDebugPatch { private static readonly FieldInfo FallValue = AccessTools.Field(typeof(PlayerControllerB), "fallValue"); private static readonly FieldInfo FallValueUncapped = AccessTools.Field(typeof(PlayerControllerB), "fallValueUncapped"); private static readonly FieldInfo TakingFallDamage = AccessTools.Field(typeof(PlayerControllerB), "takingFallDamage"); private static readonly FieldInfo IsSpeedCheating = AccessTools.Field(typeof(PlayerControllerB), "isSpeedCheating"); private static void Prefix(PlayerControllerB __instance) { if (Plugin.DebugFallDamage.Value && IsLocal(__instance)) { float num = (float)FallValueUncapped.GetValue(__instance); bool flag = (bool)TakingFallDamage.GetValue(__instance); if (!(num > -30f) || flag) { Plugin.Log.LogInfo((object)string.Concat("Landing: fall=", ((float)FallValue.GetValue(__instance)).ToString("0.0", CultureInfo.InvariantCulture), " uncapped=", num.ToString("0.0", CultureInfo.InvariantCulture), " taking=", flag, " speedCheat=", IsSpeedCheating.GetValue(__instance), " health=", __instance.health)); } } } internal static bool IsLocal(PlayerControllerB player) { GameNetworkManager instance = GameNetworkManager.Instance; if ((Object)(object)instance != (Object)null) { return (Object)(object)instance.localPlayerController == (Object)(object)player; } return false; } } [HarmonyPatch(typeof(PlayerControllerB), "DamagePlayer")] internal static class FallDamageDebugPatch { private static void Prefix(PlayerControllerB __instance, int damageNumber, bool fallDamage, out int __state) { __state = __instance.health; if (Plugin.DebugFallDamage.Value && fallDamage && FallLandingDebugPatch.IsLocal(__instance)) { Plugin.Log.LogInfo((object)("Fall damage requested: " + damageNumber + " healthBefore=" + __state)); } } private static void Postfix(PlayerControllerB __instance, bool fallDamage, int __state) { if (Plugin.DebugFallDamage.Value && fallDamage && FallLandingDebugPatch.IsLocal(__instance)) { Plugin.Log.LogInfo((object)("Fall damage result: healthBefore=" + __state + " healthAfter=" + __instance.health + " dead=" + __instance.isPlayerDead)); } } }