sm64coopdx/mods/shell-rush/actions.lua
2022-03-30 20:15:17 -07:00

278 lines
8.4 KiB
Lua

gExtraMarioState = { }
for i = 0, (MAX_PLAYERS - 1) do
gExtraMarioState[i] = { }
gExtraMarioState[i].lastY = 0
end
function race_get_slope_physics(m)
local friction = 0.96
local force = 3
if mario_floor_is_slope(m) ~= 0 then
local slopeClass = 0
if m.action ~= ACT_SOFT_BACKWARD_GROUND_KB and m.action ~= ACT_SOFT_FORWARD_GROUND_KB then
slopeClass = mario_get_floor_class(m)
end
if slopeClass == SURFACE_CLASS_VERY_SLIPPERY then
friction = 0.98
force = 3.3
elseif slopeClass == SURFACE_CLASS_SLIPPERY then
friction = 0.97
force = 3.2
end
end
return {
force = force,
friction = friction,
}
end
function race_apply_slope_accel(m)
local physics = race_get_slope_physics(m)
local floor = m.floor
local floorNormal = m.floor.normal
local mTheta = m.faceAngle.y
local mSpeed = m.forwardVel * 1.5 * gGlobalSyncTable.speed
if mSpeed > 135 * gGlobalSyncTable.speed then mSpeed = 135 * gGlobalSyncTable.speed end
local mDir = {
x = sins(mTheta),
y = 0,
z = coss(mTheta)
}
m.slideYaw = m.faceAngle.y
m.slideVelX = 0
m.slideVelZ = 0
-- apply direction
local angle = vec3f_angle_between(m.vel, mDir)
local parallel = vec3f_project(m.vel, mDir)
local perpendicular = { x = m.vel.x - parallel.x, y = m.vel.y - parallel.y, z = m.vel.z - parallel.z }
local parallelMag = vec3f_length(parallel)
local perpendicularMag = vec3f_length(perpendicular)
local originalPerpendicularMag = perpendicularMag
if angle >= math.pi / 2 then
parallelMag = -1
elseif parallelMag < mSpeed then
local lastMag = parallelMag
parallelMag = parallelMag * 0.85 + mSpeed * 0.15
perpendicularMag = perpendicularMag - (parallelMag - lastMag) * 0.12
if perpendicularMag < 0 then perpendicularMag = 0 end
end
vec3f_normalize(parallel)
vec3f_normalize(perpendicular)
vec3f_non_nan(parallel)
vec3f_non_nan(perpendicular)
local combined = {
x = parallel.x * parallelMag + perpendicular.x * perpendicularMag,
y = parallel.y * parallelMag + perpendicular.y * perpendicularMag,
z = parallel.z * parallelMag + perpendicular.z * perpendicularMag,
}
m.vel.x = combined.x
m.vel.z = combined.z
-- apply friction
m.vel.x = m.vel.x * physics.friction
m.vel.z = m.vel.z * physics.friction
m.vel.y = 0.0
-- apply slope
m.vel.x = m.vel.x + physics.force * floorNormal.x
m.vel.z = m.vel.z + physics.force * floorNormal.z
-- apply vanilla forces
local velBeforeVanilla = { x = m.vel.x, y = m.vel.y, z = m.vel.z }
mario_update_moving_sand(m)
mario_update_windy_ground(m)
m.vel.x = m.vel.x * 0.2 + velBeforeVanilla.x * 0.8
m.vel.y = m.vel.y * 0.2 + velBeforeVanilla.y * 0.8
m.vel.z = m.vel.z * 0.2 + velBeforeVanilla.z * 0.8
end
function update_race_shell_speed(m)
local maxTargetSpeed = 0
local targetSpeed = 0
local startForwardVel = m.forwardVel
-- brake
if (m.controller.buttonDown & B_BUTTON) ~= 0 then
m.forwardVel = m.forwardVel * 0.9
end
-- set water level
if m.floorHeight < m.waterLevel then
m.floorHeight = m.waterLevel
m.floor = get_water_surface_pseudo_floor()
m.floor.originOffset = m.waterLevel -- Negative origin offset
end
-- set max target speed
if m.floor ~= nil and m.floor.type == SURFACE_SLOW then
maxTargetSpeed = 48.0
else
maxTargetSpeed = 64.0
end
-- set target speed
targetSpeed = m.intendedMag * 2.0
if targetSpeed > maxTargetSpeed then
targetSpeed = maxTargetSpeed
end
if targetSpeed < 18.0 then
targetSpeed = 18.0
end
-- set speed
if m.forwardVel <= 0.0 then
m.forwardVel = 1.1
elseif m.forwardVel <= targetSpeed + 1.1 then
m.forwardVel = m.forwardVel + 1.1
elseif m.forwardVel > targetSpeed - 1.5 then
m.forwardVel = m.forwardVel - 1.5
elseif m.floor ~= nil and m.floor.normal.y >= 0.95 then
m.forwardVel = m.forwardVel - 1.1
end
if m.forwardVel > 64.0 then
if m.forwardVel > startForwardVel - 3.0 then
m.forwardVel = startForwardVel - 3.0
end
end
local turnSpeed = 0x800
if (m.controller.buttonDown & B_BUTTON) ~= 0 then turnSpeed = 0x650 end
m.faceAngle.y = m.intendedYaw - approach_s32(convert_s16(m.intendedYaw - m.faceAngle.y), 0, turnSpeed, turnSpeed)
race_apply_slope_accel(m)
end
function act_race_shell_ground(m)
if m.actionTimer < 5 then m.actionTimer = m.actionTimer + 1 end
local startYaw = m.faceAngle.y
-- enforce min velocities
if m.forwardVel == 0 then m.forwardVel = 1 end
if vec3f_length(m.vel) == 0 then m.vel.x = 1 end
-- jump
if (m.input & INPUT_A_PRESSED) ~= 0 then
m.vel.x = m.vel.x * 0.9
m.vel.z = m.vel.z * 0.9
return set_mario_action(m, ACT_RIDING_SHELL_JUMP, 0)
end
-- update physics
update_race_shell_speed(m)
-- set animation
if m.actionArg == 0 then
set_mario_animation(m, MARIO_ANIM_START_RIDING_SHELL)
else
set_mario_animation(m, MARIO_ANIM_RIDING_SHELL)
end
local gs = perform_ground_step(m)
if gs == GROUND_STEP_LEFT_GROUND then
m.vel.y = (m.pos.y - gExtraMarioState[m.playerIndex].lastY)
return set_mario_action(m, ACT_RIDING_SHELL_FALL, 0)
elseif gs == GROUND_STEP_HIT_WALL then
-- check if the wall is in the facing direction
local castDir = {
x = sins(m.faceAngle.y) * 200,
y = 0,
z = coss(m.faceAngle.y) * 200
}
local info = collision_find_surface_on_ray(
m.pos.x, m.pos.y + 100, m.pos.z,
castDir.x, castDir.y, castDir.z)
if info.surface ~= nil then
mario_stop_riding_object(m)
play_sound(SOUND_ACTION_BONK, m.marioObj.header.gfx.cameraToObject)
m.particleFlags = m.particleFlags | PARTICLE_VERTICAL_STAR
m.forwardVel = 0
set_mario_action(m, ACT_BACKWARD_GROUND_KB, 0)
end
end
tilt_body_ground_shell(m, startYaw)
if m.floor.type == SURFACE_BURNING then
play_sound(SOUND_MOVING_RIDING_SHELL_LAVA, m.marioObj.header.gfx.cameraToObject)
else
play_sound(SOUND_MOVING_TERRAIN_RIDING_SHELL, m.marioObj.header.gfx.cameraToObject)
end
adjust_sound_for_speed(m)
reset_rumble_timers(m)
gExtraMarioState[m.playerIndex].lastY = m.pos.y
return 0
end
function act_race_shell_air(m)
if m.actionTimer < 5 then m.actionTimer = m.actionTimer + 1 end
play_mario_sound(m, SOUND_ACTION_TERRAIN_JUMP, 0)
set_mario_animation(m, MARIO_ANIM_JUMP_RIDING_SHELL)
if m.vel.y > 65 then m.vel.y = 65 end
local mSpeed = m.forwardVel / 128.0 * gGlobalSyncTable.speed
if mSpeed > 100 * gGlobalSyncTable.speed then mSpeed = 100 * gGlobalSyncTable.speed end
local mDir = {
x = sins(m.intendedYaw),
y = 0,
z = coss(m.intendedYaw)
}
-- apply direction
local parallel = vec3f_project(mDir, m.vel)
local perpendicular = { x = mDir.x - parallel.x, y = mDir.y - parallel.y, z = mDir.z - parallel.z }
local parallelMag = vec3f_length(parallel)
if parallelMag < mSpeed then parallelMag = mSpeed / parallelMag end
local combined = {
x = parallel.x * parallelMag + perpendicular.x * 0.95,
y = parallel.y * parallelMag + perpendicular.y * 0.95,
z = parallel.z * parallelMag + perpendicular.z * 0.95,
}
m.vel.x = m.vel.x + mSpeed * mDir.x
m.vel.z = m.vel.z + mSpeed * mDir.z
-- apply rotation
m.faceAngle.y = m.intendedYaw - approach_s32(convert_s16(m.intendedYaw - m.faceAngle.y), 0, 0x300, 0x300)
local step = perform_air_step(m, 0)
if step == AIR_STEP_LANDED then
set_mario_action(m, ACT_RIDING_SHELL_GROUND, 1)
elseif step == AIR_STEP_HIT_WALL then
mario_set_forward_vel(m, 0.0)
elseif step == AIR_STEP_HIT_LAVA_WALL then
lava_boost_on_wall(m)
end
m.marioObj.header.gfx.pos.y = m.marioObj.header.gfx.pos.y + 42.0
gExtraMarioState[m.playerIndex].lastY = m.pos.y
return 0
end
hook_mario_action(ACT_RIDING_SHELL_GROUND, act_race_shell_ground)
hook_mario_action(ACT_RIDING_SHELL_JUMP, act_race_shell_air)
hook_mario_action(ACT_RIDING_SHELL_FALL, act_race_shell_air)