Created
January 27, 2025 19:41
-
-
Save 21Joakim/480f2bae588df54d2f34faba8b2861bc to your computer and use it in GitHub Desktop.
Example of how to use ReplicateConVar to enable bhop on a per player basis.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using CounterStrikeSharp.API.Core; | |
| using CounterStrikeSharp.API.Core.Attributes.Registration; | |
| using CounterStrikeSharp.API.Modules.Commands; | |
| using CounterStrikeSharp.API.Modules.Memory.DynamicFunctions; | |
| using CounterStrikeSharp.API.Modules.Cvars; | |
| // Example of how to use ReplicateConVar | |
| // to enable bhop on a per player basis. | |
| public class BhopPlugin : BasePlugin | |
| { | |
| // The signature is for Linux (this has not been tested on Windows) | |
| private static readonly MemoryFunctionVoid<CCSPlayer_MovementServices, IntPtr> CCSPlayer_MovementServices_ProcessMovement = | |
| new("55 48 89 E5 41 57 41 56 41 55 41 54 49 89 FC 53 48 83 EC ? 48 8B 7F 30"); | |
| public override string ModuleName => "BhopPlugin"; | |
| public override string ModuleVersion => "0.0.1"; | |
| private readonly bool[] _bhopEnabled = new bool[64]; | |
| private readonly ConVar? _autobunnyhopping = ConVar.Find("sv_autobunnyhopping"); | |
| private readonly ConVar? _enablebunnyhopping = ConVar.Find("sv_enablebunnyhopping"); | |
| public override void Load(bool hotReload) | |
| { | |
| CCSPlayer_MovementServices_ProcessMovement.Hook(ProcessMovementPre, HookMode.Pre); | |
| CCSPlayer_MovementServices_ProcessMovement.Hook(ProcessMovementPost, HookMode.Post); | |
| } | |
| public override void Unload(bool hotReload) | |
| { | |
| CCSPlayer_MovementServices_ProcessMovement.Unhook(ProcessMovementPre, HookMode.Pre); | |
| CCSPlayer_MovementServices_ProcessMovement.Unhook(ProcessMovementPost, HookMode.Post); | |
| } | |
| [ConsoleCommand("bhop")] | |
| public void BhopCommand(CCSPlayerController? player, CommandInfo command) | |
| { | |
| CCSPlayerPawn? pawn = player?.PlayerPawn.Value; | |
| if (player == null || pawn == null) | |
| { | |
| command.ReplyToCommand("Only a player can run this command"); | |
| return; | |
| } | |
| bool enabled = !_bhopEnabled[player.Slot]; | |
| _bhopEnabled[player.Slot] = enabled; | |
| player.ReplicateConVar("sv_autobunnyhopping", Convert.ToString(enabled)); | |
| player.ReplicateConVar("sv_enablebunnyhopping", Convert.ToString(enabled)); | |
| command.ReplyToCommand($"Bhop has been {(enabled ? "enabled" : "disabled")}"); | |
| } | |
| public int? GetSlot(CCSPlayer_MovementServices? movementServices) | |
| { | |
| uint? index = movementServices?.Pawn.Value?.Controller.Value?.Index; | |
| if (index == null) | |
| { | |
| return null; | |
| } | |
| return (int) index.Value - 1; | |
| } | |
| public bool IsBhopEnabled(CCSPlayer_MovementServices movementServices) | |
| { | |
| int? slot = GetSlot(movementServices); | |
| if (slot == null) | |
| { | |
| return false; | |
| } | |
| return _bhopEnabled[slot.Value]; | |
| } | |
| private bool _wasAutobunnyhoppingChanged = false; | |
| private bool _wasEnablebunnyhoppingChanged = false; | |
| public HookResult ProcessMovementPre(DynamicHook hook) | |
| { | |
| if (_autobunnyhopping == null || _enablebunnyhopping == null) | |
| { | |
| return HookResult.Continue; | |
| } | |
| _wasAutobunnyhoppingChanged = false; | |
| _wasEnablebunnyhoppingChanged = false; | |
| CCSPlayer_MovementServices movementServices = hook.GetParam<CCSPlayer_MovementServices>(0); | |
| if (!IsBhopEnabled(movementServices)) | |
| { | |
| return HookResult.Continue; | |
| } | |
| if (!_autobunnyhopping.GetPrimitiveValue<bool>()) | |
| { | |
| _autobunnyhopping.SetValue(true); | |
| _wasAutobunnyhoppingChanged = true; | |
| } | |
| if (!_enablebunnyhopping.GetPrimitiveValue<bool>()) | |
| { | |
| _enablebunnyhopping.SetValue(true); | |
| _wasEnablebunnyhoppingChanged = true; | |
| } | |
| return HookResult.Continue; | |
| } | |
| public HookResult ProcessMovementPost(DynamicHook hook) | |
| { | |
| if (_autobunnyhopping == null || _enablebunnyhopping == null) | |
| { | |
| return HookResult.Continue; | |
| } | |
| if (_wasAutobunnyhoppingChanged) | |
| { | |
| _autobunnyhopping.SetValue(false); | |
| _wasAutobunnyhoppingChanged = false; | |
| } | |
| if (_wasEnablebunnyhoppingChanged) | |
| { | |
| _enablebunnyhopping.SetValue(false); | |
| _wasEnablebunnyhoppingChanged = false; | |
| } | |
| return HookResult.Continue; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment