Angles New
A cmd carries the pitch and yaw of the view and the yaw of the head, in degrees: in createmove a change turns the camera and the player for real, in authinput it only changes the packet.
At a glance
Mapping from Source
In authinput the angles are the pitch, yaw and Player Head Rotation fields of the packet. In createmove they are
the player rotation (ActorRotationComponent, ActorHeadRotationComponent) and the first person camera
(CameraDirectLookComponent).
Functions
cmd:get_view_angles(): number, number, number
cmd:get_view_angles(): number, number, number
Returns: pitch, yaw, 0, with the changes the callbacks made so far in this cmd.
local pitch, yaw = cmd:get_view_angles()
cmd:set_view_angles(pitch, yaw, roll)
cmd:set_view_angles(pitch: number, yaw: number, roll: number = 0)
Sets pitch and yaw, and the head yaw to yaw.
In createmove the camera, the rotation and the head rotation are written after the callbacks: the client simulates the
tick and builds the packet with the new angles, and the view stays there. When the camera of the player cannot be found
(third person or a special camera), the rotation is written for this tick and the camera brings it back on the next one;
stats().apply_failures counts it.
In authinput only the packet changes. The movement of the packet still points where the player looks: use
rotate_movement or lock_angles so that the server moves you along the same path (see movement).
Returns: nothing.
Errors:
cmd:set_view_angles(0, 90)
cmd:get_head_yaw(): number
cmd:get_head_yaw(): number
Returns: the yaw of the head, in degrees.
print(cmd:get_head_yaw())
cmd:set_head_yaw(yaw)
cmd:set_head_yaw(yaw: number)
Turns the head only; the body and the view keep their yaw.
Returns: nothing.
Errors: bad argument #1 to 'set_head_yaw' (finite number expected).
local _, yaw = cmd:get_view_angles()
cmd:set_head_yaw(yaw + 45)
cmd:lock_angles()
cmd:lock_angles()
Makes the angle changes of this cmd silent: the server receives them, the view of the player does not move. Call it
before or after set_view_angles; the flag holds for the whole cmd, so one call in any callback of the tick makes every
angle change of that tick silent.
The rotation of the movement is what keeps the client and the server in agreement: the server applies the movement relative to the yaw it receives, so a silent yaw without that rotation would push you sideways and the server would correct you.
Returns: nothing.
cmd:lock_angles()
cmd:set_view_angles(0, 180)
The native aim (aura) works the same way in the network layer. When both change the angles of a packet, the script wins and the aura does not attack with that packet: see priority.
Complete example
Look at the nearest player within 8 blocks for the server only, while the view stays where the player looks. The target is read in think because xiao.game returns nothing inside a cmd callback.
local target
xiao.signal.add("think", "look_target", function()
target = nil
local best = 8
for _, p in ipairs(xiao.game.players()) do
if p.distance ~= nil and p.distance < best then
best, target = p.distance, {p.x, p.y, p.z}
end
end
end)
xiao.cmd.hook("createmove", "look", function(cmd)
if target == nil then return end
local x, y, z = cmd:get_position()
local dx, dy, dz = target[1] - x, target[2] - y, target[3] - z
local yaw = math.deg(math.atan2(-dx, dz))
local pitch = math.deg(-math.atan2(dy, math.sqrt(dx * dx + dz * dz)))
cmd:lock_angles()
cmd:set_view_angles(math.max(-90, math.min(90, pitch)), yaw)
end)