#cmd:buttons() → integer
The buttons held in this command.
Every tick the game builds a command - buttons, view angles, movement. A script can read it and change it before it is sent.
CS2 is driven by commands. Sixty-four times a second the client builds one: which buttons are held, where the player is looking, how they want to move. That command is what the server acts on. A script that wants to press a button for you, turn the view without moving your screen, or change where you walk does it by editing the command.
Two events hand it over:
move - before the cheat's own features run. A change here is part of the command the features see.move_post - after every feature, right before the command is finalised. The last word.local hop = ui.group( "bunny hop" ):toggle( "enabled", false )
on( "move", function( cmd )
if not hop:get( ) or not cmd:down( btn.jump ) then
return
end
local me = ents.local_pawn( )
if me and not me:on_ground( ) then
cmd:release( btn.jump ) -- in the air: let go, so touching the ground is followed by a fresh press
end
end )The command object is only valid inside the handler that received it; using one you kept raises this command is only valid inside the move handler that received it. Both events run only while the local player is alive.
Buttons are a bit set: one number with a bit per button. The btn table names the bits, and the calls below take and return such numbers, so several buttons go together with + or bits.bor: btn.attack + btn.duck.
cmd:buttons() → integerThe buttons held in this command.
cmd:set_buttons( mask )Replaces the whole set. The game is told which buttons changed.
cmd:press( mask )Holds the buttons in mask down in this command, as if the key was pressed.
cmd:release( mask )Lets the buttons in mask go in this command.
cmd:down( mask ) → booleantrue when every button of mask is held. false for a mask of 0.
cmd:any( mask ) → booleantrue when at least one button of mask is held.
if cmd:any( btn.move_left + btn.move_right ) then
-- strafing
endbtn table| Name | Button | Name | Button |
|---|---|---|---|
btn.attack | primary fire | btn.attack2 | secondary fire |
btn.jump | jump | btn.duck | crouch |
btn.forward | move forward | btn.back | move back |
btn.move_left | strafe left | btn.move_right | strafe right |
btn.turn_left | turn left | btn.turn_right | turn right |
btn.use | use | btn.reload | reload |
btn.walk | walk (quiet steps) | btn.scoreboard | scoreboard |
btn.zoom | zoom | btn.inspect | inspect weapon |
cmd:angles() → vec3The view angles the command carries: x is the pitch (positive looks down), y the yaw, z the roll, in degrees. If the command carries none yet, the player's current view angles.
cmd:set_angles( angles [, silent] )Writes the angles the command is sent with. silent is true by default.
silent = false the player's view turns to the new angles as well.Raises an error if a component is not a finite number.
-- look at a point, silently
local function look_at( cmd, point )
local me = ents.local_pawn( )
local before = cmd:angles( )
local after = vec3.angle_to( me:eye( ), point ):wrapped( )
cmd:set_angles( after )
cmd:rotate_move( before.y, after.y ) -- keep walking where the player meant to
endThe command's movement is two numbers - forward and left, each from -1 to 1 - plus an up value that only matters on ladders and in water.
cmd:move() → forward, left, upcmd:set_move( forward, left [, up] )Sets the movement. Values are clamped to -1..1. CS2 normally moves a player from the sub-tick steps attached to a command, which tell the exact moment each key changed; with steps present it ignores the plain numbers. set_move therefore drops the steps so that your values apply as given.
cmd:rotate_move( from_yaw, to_yaw )The movement in the command was meant for a view looking along from_yaw. This rewrites it so it produces the same direction in the world for a view looking along to_yaw. It is what to call after changing the angles of a command: without it, turning the view sideways would turn the walking direction with it.
cmd:mouse() → dx, dyThe mouse movement the command carries.
cmd:number() → integerThe command's sequence number.
cmd:tick() → integerThe client tick the command was built for.
cmd:seed() → integerThe command's random seed.
cmd:impulse() → integercmd:set_impulse( n )The command's impulse: 0 for none, 100 flashlight, 201 spray paint.
cmd:select_weapon( weapon ) → booleanSwitches to a weapon the player owns. weapon is a weapon entity - from ent:weapons(). Answers true when the switch was put into the command and false when the weapon's slot cannot be worked out. Raises an error when weapon is not an entity.
-- hold use + duck to pull out the knife
on( "move", function( cmd )
if not cmd:down( btn.use + btn.duck ) then
return
end
for _, weapon in ipairs( ents.local_pawn( ):weapons( ) ) do
if weapon:is_knife( ) then
cmd:select_weapon( weapon )
end
end
end )move is the command the features start from; a feature - the ragebot setting angles when it shoots, the movement features steering - can overwrite it. If your change has to survive, make it in move_post.move_post is after the history. By then the command's input history is already written, so angles changed there are not reflected in it. Do not rely on touching the history from a script.move is on the game's thread, once per tick; a slow handler delays the command itself.