Skip to content

Player control

Lesson 12.9

Mods often change how a player moves, looks or plays: a broken leg, a missing arm, a cursed item that can’t be dropped, a cutscene that walks for you. This lesson does all of that on the server, so every player sees the same thing and nobody rubber-bands.

Slow them down

player:add_movement_modifier{ id = "broken_leg", speed_mult = 0.6, can_sprint = false, sway = 2 }
player:remove_movement_modifier("broken_leg")
print(player:movement().speed_mult)

Each modifier has an id, so several stack (speed_mult values multiply) and you can remove one alone. jump_mult, can_jump = false and step_height work the same way. Speed, jump and step height are vanilla attributes, so even players without Celestial move correctly. sway makes the camera wobble a little (Celestial clients).

Change the model

player:set_part_visible("left_arm", false)
player:set_part_model("right_leg", "my_mod:models/peg_leg.glb")
player:set_part_model("right_leg", nil)          -- the normal leg again

The parts are head, hat, body, jacket, left_arm, left_sleeve, right_arm, right_sleeve, left_leg, left_pants, right_leg, right_pants and cape.

For animations, register a glTF file whose nodes are named like the parts once, then play its clips on the player:

cl.on("lifecycle.register", function() cl.render.player_animations("my_mod:models/player/moves.glb") end)
player:anim_play("wave", { layer = 1 })

Hands, slots and keys

player:set_hand_disabled("off_hand", true)
player:lock_slot(0)                                  -- can't move, drop or swap the item in slot 0
player:unlock_slot(0)
player:set_input_override{ crouch = true }           -- the player crouches until you clear it
player:clear_input_override()

Food and air

player:set_food(4)
player:exhaust(2)
player:set_air(100)
player:set_natural_regen(false)                      -- no healing from a full food bar

The camera (client)

if cl.camera.is_first_person() then cl.log("first person at %s", tostring(cl.camera.position())) end

Exercise

Make a command /curse that locks the selected slot of the player, slows them to half speed, and undoes both after 10 seconds.

Show a solution
cl.on("server.command_register", function()
  cl.cmd.register(cl.cmd.literal("curse"):executes(function(ctx)
    local p = ctx:player()
    if not p then return 0 end
    local slot = p:selected_slot()
    p:lock_slot(slot)
    p:add_movement_modifier{ id = "curse", speed_mult = 0.5 }
    cl.spawn(function()
      cl.sleep_ticks(200)
      p:unlock_slot(slot)
      p:remove_movement_modifier("curse")
    end)
    return 1
  end))
end)

Recap: movement modifiers change speed, jumps and sprinting, part functions change the model, player_animations animates it, hands, slots and keys can be locked or forced, and food, air and healing are yours to set. More in the guide Player Control.