Movement New
The movement of a cmd is relative to the yaw of the view: forward and left, each from -1 to 1, plus an up value for flying, swimming and jumping.
At a glance
Conventions
A vector longer than 1 is scaled down to length 1, as the game does: W+D gives 0.707, -0.707.
Every setter takes finite numbers only: NaN or infinity raises bad argument #n to '<method>' (finite number expected), with n the position of the argument.
Functions
cmd:get_move(): number, number, number
cmd:get_move(): number, number, number
Returns: forward, left, up. Up is 1, -1 or 0.
local forward, left, up = cmd:get_move()
cmd:set_move(forward, side, up)
cmd:set_move(forward: number, side: number, up: number = nil)
Returns: nothing.
Errors: a component out of -1 to 1: move components must be finite and within [-1, 1].
cmd:set_move(1, 0)
cmd:set_move(0, 0, 1)
cmd:get_forward_move(): number, cmd:set_forward_move(value)
cmd:get_forward_move(): number
cmd:set_forward_move(value: number)
Sets forward and keeps the left value.
Returns: get_forward_move returns the forward value.
Errors: as set_move.
if cmd:get_forward_move() < 0 then cmd:set_forward_move(0) end
cmd:get_left_move(): number, cmd:set_left_move(value)
cmd:get_left_move(): number
cmd:set_left_move(value: number)
Sets left and keeps the forward value.
Returns: get_left_move returns the left value.
Errors: as set_move.
cmd:set_left_move(-1)
cmd:get_up_move(): number, cmd:set_up_move(value)
cmd:get_up_move(): number
cmd:set_up_move(value: number)
See the conventions table. In createmove, set_up_move(1) is the same as set_button("jump_down") plus releasing
sneak_down.
Returns: get_up_move returns 1, -1 or 0.
cmd:set_up_move(1)
cmd:get_analog_move(): number, number, cmd:set_analog_move(forward, side)
cmd:get_analog_move(): number, number
cmd:set_analog_move(forward: number, side: number)
The Analog Move Vector field, filled by a gamepad stick and 0, 0 with a keyboard. authinput only.
Returns: get_analog_move returns forward, side.
Errors: in createmove, analog_move is only available in authinput; components as set_move.
local forward, side = cmd:get_analog_move()
cmd:rotate_movement(yaw)
cmd:rotate_movement(yaw: number)
The movement was meant for a view at yaw; rewrite it for the current yaw of the cmd so that the player moves in the
same world direction. Call it after set_view_angles with the yaw you had before.
The world direction of a movement at yaw y is, in x, z:
world.x = left * cos(y) - forward * sin(y)
world.z = left * sin(y) + forward * cos(y)
rotate_movement(from) turns (left, forward) by from - yaw, which keeps world unchanged. In authinput the move,
raw and analog vectors turn together and up, down, left, right are set again from the new vector; the length is
kept. In createmove each component is kept within -1 to 1.
Returns: nothing.
Errors: bad argument #1 to 'rotate_movement' (finite number expected).
local _, yaw = cmd:get_view_angles()
cmd:set_view_angles(0, yaw + 90)
cmd:rotate_movement(yaw)
In authinput, lock_angles() does this for you at the end of the callbacks.
Complete example
Strafe left and right every 10 ticks while the player walks forward, and keep the server movement aligned on a packet only yaw.
xiao.cmd.hook("createmove", "zigzag", function(cmd)
local forward = cmd:get_forward_move()
if forward <= 0 then return end
local side = (math.floor((cmd:command_number() or 0) / 10) % 2 == 0) and 1 or -1
cmd:set_move(forward, side)
end)
xiao.cmd.hook("authinput", "offset", function(cmd)
if cmd:native_aim() then return end
local pitch, yaw = cmd:get_view_angles()
cmd:set_view_angles(pitch, yaw + 15)
cmd:rotate_movement(yaw)
end)