Files
last-hearth/mods/hearth/movement.lua
T
2026-11-03 12:41:09 -05:00

44 lines
2.4 KiB
Lua
Executable File

-- Pure M1 controller. Only ephemeral session fields and state.stamina mutate.
-- No engine access: the runtime supplies weapon, velocity, ground and water.
local M = {}
function M.delta(dt)
if type(dt) ~= "number" or dt ~= dt or dt <= 0 then return 0 end
return math.min(dt, 0.1) -- never replay stalls as movement/exhaustion
end
function M.step(session, state, controls, dt, env)
controls, env = controls or {}, env or {}
dt = M.delta(dt)
local velocity = env.velocity or {x = 0, y = 0, z = 0}
local grounded = env.grounded == true and math.abs(velocity.y or 0) < 0.2
local swimming = env.swimming == true
local moving = (velocity.x or 0)^2 + (velocity.z or 0)^2 > 0.04
if state.stamina <= 8 and not session.exhausted then
session.exhausted = true; session.sprint_released = false
end
if session.exhausted and not controls.aux1 then session.sprint_released = true end
if session.exhausted and session.sprint_released and state.stamina >= 30 then
session.exhausted, session.sprint_released = false, false
end
local blocking = env.weapon == "hearth:spear" and controls.RMB == true and not swimming
local sprinting = controls.aux1 == true and controls.up == true and not controls.down
and not controls.sneak and not blocking and grounded and not swimming
and not session.exhausted and state.stamina > 8
-- Keep survival rates identical to model.needs; runtime restores its duplicate
-- stamina result but retains that model's sprint hunger/thirst expenditure.
local rate = sprinting and -13 or ((state.food > 0 and state.water > 0) and 9 or 2)
state.stamina = math.max(0, math.min(100, state.stamina + rate * dt))
if sprinting and state.stamina <= 8 then
session.exhausted, session.sprint_released, sprinting = true, false, false
end
local target = swimming and 0.75 or (blocking and 0.6 or (sprinting and 1.45 or 1))
if not swimming and not blocking and (state.wet or 0) >= 60 then target = target * 0.95 end
local speed = session.movement_speed or 1
local change = math.max(-3 * dt, math.min(3 * dt, target - speed))
speed = speed + change
session.movement_speed, session.sprinting, session.blocking = speed, sprinting, blocking
session.grounded, session.swimming, session.moving = grounded, swimming, moving
return {speed = speed, sprinting = sprinting, blocking = blocking,
grounded = grounded, swimming = swimming, moving = moving}
end
return M