ludic/packages/ludic.character/update.ludic
Orkuncakilkaya 71735b10a2 feat(base): 0.R4 - a queue keeps its own count, so every package verb takes only its own state; ludic migrate state --prune
ludic.base's Queue<T> carries a QueueTag (its name and pending count): queue_new(name), q_push(q, v),
q_drain(q), q_clear(q) take no BaseState, and core_undrained(tags) names the given queues still holding
facts. A reducer on a package's state can now call that package's verbs (wallet_earn(wallet_st, n)).

ludic migrate state --prune (ludicc --migrate-prune) takes out each state parameter a function no
longer uses, nor anything it calls, and the argument that fills it - including an argument for a
parameter the callee has dropped, which is taken out before the call is checked, so a generic's T is
told by the argument that says it. A reducer keeps its state. --dry-run now counts the edits it would
make. Every package was moved with it: 608 base_st parameters and their arguments, 1889 edits.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-26 04:19:56 +03:00

68 lines
2.8 KiB
Text

# update.ludic - a frame of the body: the stick in the camera's frame, the step, the gait, the camera
export function char_update(character_st: mut CharacterState, ix0: float, iz0: float, run0: bool, jump0: bool, dyaw: float, dpitch: float, dt: float) -> void {
var run = run0 and character_st.chr_can_run
var ix = ix0
var iz = iz0
var jump = jump0
character_st.chr_step = 0.0
character_st.chr_time = character_st.chr_time + dt
character_st.chr_water = CharacterGround.water(character_st.chr_x, character_st.chr_z)
chr_sit_tick(character_st, dt)
if CharacterBody.riding() {
chr_ride_update(character_st, ix, iz, run, dyaw, dpitch, dt)
return
}
if CharacterBody.sneaking() { run = false }
# sitting: any step stands up, and nothing else moves
if character_st.chr_sit and (Math.abs(ix) > 0.3 or Math.abs(iz) > 0.3 or jump) { character_st.chr_sit = false }
if character_st.chr_sit {
ix = 0.0
iz = 0.0
jump = false
}
# the stick in the camera's frame: forward on the ground is (-sin yaw, -cos yaw)
let cy = Math.cos(character_st.chr_cam_yaw)
let sy = Math.sin(character_st.chr_cam_yaw)
var dx = -sy * iz + cy * ix
var dz = -cy * iz - sy * ix
var mag = Math.sqrt(dx * dx + dz * dz)
if mag > 1.0 {
dx = dx / mag
dz = dz / mag
mag = 1.0
}
chr_steer(character_st, dx, dz, mag, run, dt)
let dist = chr_travel(character_st, dx, dz, -Math.sin(character_st.chr_yaw), -Math.cos(character_st.chr_yaw), jump, dt)
chr_gait(character_st, dist, dyaw, dpitch, dt)
char_camera(character_st, dt)
}
# something else carries the body (CharacterBody.ride moves it with char_ride_at); the orbit
# drifts behind whatever it is on
function chr_ride_update(character_st: mut CharacterState, ix: float, iz: float, run: bool, dyaw: float, dpitch: float, dt: float) -> void {
CharacterBody.ride(ix, iz, run, dt)
chr_look(character_st, dyaw, dpitch)
if dyaw == 0.0 and not CharacterInput.look_always() { character_st.chr_cam_yaw = character_st.chr_cam_yaw + char_wrap(character_st.chr_yaw - character_st.chr_cam_yaw) * Math.min(1.0, 1.5 * dt) }
char_camera(character_st, dt)
}
# a frame from the input port: the game's devices, read once, stepping the body
export function char_tick(character_st: mut CharacterState, dt: float) -> void {
var ix = 0.0
var iz = 0.0
var run = false
var jump = false
var dyaw = 0.0
var dpitch = 0.0
if character_st.chr_holds == 0 {
ix = CharacterInput.move_x()
iz = CharacterInput.move_z()
run = CharacterInput.run()
jump = CharacterInput.jump()
dyaw = CharacterInput.look_yaw()
dpitch = CharacterInput.look_pitch()
let wheel = CharacterInput.zoom()
if wheel != 0.0 { character_st.chr_cam_dist = Math.clamp(character_st.chr_cam_dist - wheel * 0.35, 1.8, 9.0) }
}
char_update(character_st, ix, iz, run, jump, dyaw, dpitch, dt)
}