74 lines
3.5 KiB
Text
74 lines
3.5 KiB
Text
# walk.ludic - the step itself: swimming, in the air, or on the ground; the distance, for the gait
|
|
function chr_travel(character_st: mut CharacterState, dx: float, dz: float, fx: float, fz: float, jump: bool, dt: float) -> float {
|
|
if character_st.chr_swim {
|
|
chr_swim_tick(character_st, dx, dz, jump, dt)
|
|
return character_st.chr_speed * dt
|
|
}
|
|
return chr_walk(character_st, fx, fz, dx, dz, jump, dt)
|
|
}
|
|
|
|
# on land the game's walker moves the body (CharacterGround.walk): gravity, landing, a step up to
|
|
# CHAR_STEP, a slope up to what the boots take. The rules stay here: how fast, where, when a jump
|
|
# leaves, when the lake takes the body, and what is said about it.
|
|
function chr_walk(character_st: mut CharacterState, fx: float, fz: float, dx: float, dz: float, jump: bool, dt: float) -> float {
|
|
var vx = fx * character_st.chr_speed
|
|
var vz = fz * character_st.chr_speed
|
|
var up = 0.0
|
|
if character_st.chr_knock > 0.0 {
|
|
up = character_st.chr_knock
|
|
character_st.chr_knock = 0.0
|
|
vx = character_st.chr_air_vx
|
|
vz = character_st.chr_air_vz
|
|
} else if character_st.chr_air {
|
|
character_st.chr_air_vx = character_st.chr_air_vx + dx * (4.0 * dt)
|
|
character_st.chr_air_vz = character_st.chr_air_vz + dz * (4.0 * dt)
|
|
vx = character_st.chr_air_vx
|
|
vz = character_st.chr_air_vz
|
|
} else if jump and character_st.chr_can_run and character_st.chr_land < 0.05 {
|
|
up = 5.0
|
|
character_st.chr_air_vx = vx
|
|
character_st.chr_air_vz = vz
|
|
chr_say(character_st, CHAR_JUMPED, 0.0)
|
|
}
|
|
let slope = Math.atan2(CharacterGround.slope_limit(), 1.0) * 57.29578
|
|
let g = CharacterGround.walk(character_st.chr_x, character_st.chr_y, character_st.chr_z, vx, vz, up, CHAR_STEP, slope, dt)
|
|
return chr_walked(character_st, g, up > 0.0, dt)
|
|
}
|
|
|
|
# where the walker put the body, and what that means: the lake, a landing, a slope too steep
|
|
function chr_walked(character_st: mut CharacterState, g: int, jumped: bool, dt: float) -> float {
|
|
let nx = CharacterGround.walked_x()
|
|
let ny = CharacterGround.walked_y()
|
|
let nz = CharacterGround.walked_z()
|
|
if ny < CharacterGround.water(nx, nz) - CHAR_WADE_MAX {
|
|
chr_enter_water(character_st, nx, nz)
|
|
return character_st.chr_speed * dt
|
|
}
|
|
let was_air = character_st.chr_air
|
|
character_st.chr_air = g == CHAR_WALK_AIR or jumped
|
|
if was_air and not character_st.chr_air { chr_landed(character_st) }
|
|
if g == CHAR_WALK_STEEP and not character_st.chr_air {
|
|
if not (character_st.chr_steep > 0.0) { chr_say(character_st, CHAR_TOO_STEEP, ny - character_st.chr_y) }
|
|
character_st.chr_steep = 1.2
|
|
character_st.chr_speed = 0.0
|
|
}
|
|
let mx = nx - character_st.chr_x
|
|
let mz = nz - character_st.chr_z
|
|
character_st.chr_step = Math.sqrt(mx * mx + mz * mz)
|
|
character_st.chr_vy = (ny - character_st.chr_y) / Math.max(dt, 0.0001)
|
|
character_st.chr_x = nx
|
|
character_st.chr_y = ny
|
|
character_st.chr_z = nz
|
|
if character_st.chr_air { return character_st.chr_speed * (dt * 0.4) }
|
|
return character_st.chr_speed * dt
|
|
}
|
|
|
|
function chr_landed(character_st: mut CharacterState) -> void {
|
|
character_st.chr_land = 0.22
|
|
let carried = Math.sqrt(character_st.chr_air_vx * character_st.chr_air_vx + character_st.chr_air_vz * character_st.chr_air_vz)
|
|
# the walk goes on only as fast as the air was carrying it the way it faces (a knock from the
|
|
# front does not walk it back into what knocked it)
|
|
let along = -Math.sin(character_st.chr_yaw) * character_st.chr_air_vx - Math.cos(character_st.chr_yaw) * character_st.chr_air_vz
|
|
character_st.chr_speed = Math.max(along, 0.0)
|
|
chr_say(character_st, CHAR_LANDED, carried)
|
|
}
|