Skip to content

Instantly share code, notes, and snippets.

@benhall-7
Last active November 19, 2022 05:31
Show Gist options
  • Save benhall-7/9c039809eaea892419fb7bbc0913256f to your computer and use it in GitHub Desktop.
Save benhall-7/9c039809eaea892419fb7bbc0913256f to your computer and use it in GitHub Desktop.
Readable Lua interpretation of the gliding statuses from Brawl
PARAMS = {
max_angle = 80,
min_angle = -70,
glide_start_speed_y = 0.75,
glide_start_accel_y = 1,
glide_start_speed_x_mul = 1,
power_start = 1.7,
power_rate = 0.04,
max_speed = 2.2,
end_speed = 0.7,
gravity_accel = 0.03,
gravity_max = 0.6,
unk_angle_1 = 15,
descent_angle = -25,
descent_accel = 0.03,
unk_14 = 0.15,
stick_threshold = 0.25,
angle_accel_hi = 0.55,
angle_accel_lw = 0.75,
angle_speed_max = 7,
angle_speed_unk = 1
}
kinetic_utility = {
-- resets and enables the kinetic energy type
reset_enable_energy = function(energy_id, modules, some_id, speed_vec)
energy = modules.kinetic_energy:get_energy(energy_id)
energy:reset_energy(some_id, speed_vec)
energy.enabled = true
end,
-- clears and disables the kinetic energy type
clear_unable_energy = function(energy_id)
energy = modules.kinetic_energy:get_energy(energy_id)
energy:clear_energy(energy_id)
energy.enabled = false
end
}
function initStatus_glide(modules)
if modules.status_module:get_status_kind() == 0x85 then
local lr = modules.posture_module:lr()
local sum_speed_vec = modules.kinetic_module:get_sum_speed(KINETIC_ENERGY_ATTRIBUTE_MAIN)
modules.work_module.set_float(PARAMS.power_start, FIGHTER_STATUS_GLIDE_WORK_FLOAT_POWER)
modules.work_module.set_float(-sum_speed_vec.y, FIGHTER_STATUS_GLIDE_WORK_FLOAT_GRAVITY)
-- idk what the 22 means exactly, but it's used for a jump table,
-- so each number might behave differently (up to 22 in Brawl)
kinetic_utility.reset_enable_energy(KINETIC_ENERGY_STOP, modules, 22, {
x = 1.7,
y = 0
})
kinetic_utility.clear_unable_energy(KINETIC_ENERGY_CONTROLLER)
kinetic_utility.clear_unable_energy(KINETIC_ENERGY_GRAVITY)
kinetic_utility.clear_unable_energy(KINETIC_ENERGY_MOTION)
-- animation ID, start frame, rate, 4 bools
modules.motion_module:change_motion(58, 90, 0, false, false, false, false)
-- partial anim slot 1, wing animation ID, bone ID, start frame, rate, 2 bools
modules.motion_module:add_partial_animation(1, 59, 44, 0, 1, false, false)
end
end
function execStatus_glide(modules)
if modules.status_module:get_status_kind() == 0x85 then
local lr = modules.posture_module:lr()
local kinetic_module = modules.kinetic_module
local kinetic_energy_stop = kinetic_module:get_kinetic_energy_descriptor(KINETIC_ENERGY_STOP)
local angle = modules.work_module:get_float(FIGHTER_STATUS_GLIDE_WORK_FLOAT_ANGLE)
local angle_speed = modules.work_module:get_float(FIGHTER_STATUS_GLIDE_WORK_FLOAT_ANGLE_SPEED)
local stick_angle = modules.control_module:get_stick_angle()
-- we want to make stick_angle respective to the direction we're facing
-- and also convert to degrees
-- tbh, the way they chose is confusing to look at, but it works
if lr <= 0 then
-- facing left
local above_or_below = -1
if stick_angle > 0 then
above_or_below = 1
end
stick_angle = (180 * above_or_below) - (stick_angle * 180 / math.pi)
else
stick_angle = stick_angle * 180 / math.pi
end
local stick_x = module.control_module:get_stick_x()
local stick_y = module.control_module:get_stick_y()
local stick_mag = math.sqrt(stick_x * stick_x + stick_y * stick_y)
if stick_mag <= PARAMS.stick_threshold then
-- this block doesn't really make sense, and I can't trigger it in a normal match anyway
if modules.work_module:is_flag(FIGHTER_STATUS_GLIDE_FLAG_STOP) then
-- TODO: check if these weird inequalities are mistakes in the decompiler
if angle_speed < 0 then
angle_speed = 0
end
-- trying my best to name these variables here
local max_angle_speed = PARAMS.angle_speed_max
local new_angle_speed = angle_speed + PARAMS.angle_speed_unk
-- changed how it looks compared to the decomp because I think this is what it
-- actually should look like
if new_angle_speed < -max_angle_speed then
new_angle_speed = -max_angle_speed
end
if new_angle_speed > max_angle_speed then
new_angle_speed = max_angle_speed
end
modules.work_module:set_float(new_angle_speed, FIGHTER_STATUS_GLIDE_WORK_FLOAT_ANGLE_SPEED)
angle = angle + new_angle_speed
end
else
local angle_accel
-- pointing forward or down make you rotate down ; pointing backward or up make you rotate up
if stick_angle < 0 then
if stick_angle >= -135 then
angle_accel = -PARAMS.angle_accel_lw
else
angle_accel = PARAMS.angle_accel_hi
end
else
if stick_angle >= 45 then
angle_accel = PARAMS.angle_accel_hi
else
angle_accel = -PARAMS.angle_accel_lw
end
end
local scaled_angle_accel = angle_accel * (stick_mag - PARAMS.stick_threshold) / (1 - PARAMS.stick_threshold)
-- normally multiplying these two wouldn't make sense, but this is basically a sign check:
-- the result is < 0 only if angle_speed and scaled_angle_accel are in opposite directions
if angle_speed * scaled_angle_accel < 0 then
-- this has the interesting affect that when you switch directions, you don't have to
-- "decelerate" your previous turning, you just start at 0 again
angle_speed = 0
end
local max_angle_speed = PARAMS.angle_speed_max
local new_angle_speed = angle_speed + scaled_angle_accel
if new_angle_speed < -max_angle_speed then
new_angle_speed = -max_angle_speed
end
if new_angle_speed > max_angle_speed then
max_angle_speed = new_angle_speed
end
modules.work_module:set_float(max_angle_speed, FIGHTER_STATUS_GLIDE_WORK_FLOAT_ANGLE_SPEED)
angle = angle + max_angle_speed
end
-- now we've exited those angle blocks and we have a new angle value
if angle < PARAMS.min_angle then
angle = PARAMS.min_angle
end
if angle > PARAMS.max_angle then
angle = PARAMS.max_angle
end
-- this is the same flag as before that I couldn't trigger,
-- so consider the first block the real one
if not modules.work_module:is_flag(FIGHTER_STATUS_GLIDE_FLAG_STOP) then
local power = modules.work_module:get_float(FIGHTER_STATUS_GLIDE_WORK_FLOAT_POWER)
power = power - (angle * PARAMS.power_rate / 90)
-- when you're touching a wall, power decreases by 0.01 every frame
if modules.work_module:is_flag(FIGHTER_STATUS_GLIDE_FLAG_TOUCH_GROUND) then
power = power - 0.01
end
if power < 0 then
power = 0
end
if not modules.work_module:is_flag(FIGHTER_STATUS_GLIDE_FLAG_RAPID_FALL) then
local fall_angle = PARAMS.descent_angle
if angle < fall_angle then
power = power + (PARAMS.descent_accel * (fall_angle - angle) / (fall_angle - PARAMS.min_angle))
end
elseif angle > 0 then
modules.work_module:off_flag(FIGHTER_STATUS_GLIDE_FLAG_RAPID_FALL)
end
local unrotated = {
x = power * lr,
y = 0
}
local angled = vec2_rotate(angle * lr * math.pi / 180, unrotated)
local gravity = modules.work_module:get_float(FIGHTER_STATUS_GLIDE_WORK_FLOAT_GRAVITY)
local new_gravity = gravity + PARAMS.gravity_accel
if new_gravity > PARAMS.gravity_max then
new_gravity = PARAMS.gravity_max
end
modules.work_module:set_float(new_gravity, FIGHTER_STATUS_GLIDE_WORK_FLOAT_GRAVITY)
angled.y = angled.y - gravity
local speed = math.sqrt(angled.x * angled.x + angled.y * angled.y)
if speed > PARAMS.max_speed then
local ratio = PARAMS.max_speed / speed
angled.x = angled.x * ratio
angled.y = angled.y * ratio
end
if speed < PARAMS.end_speed or power <= 0 then
modules.work_module:on_flag(FIGHTER_STATUS_GLIDE_FLAG_STOP)
modules.work_module:set_float(0, FIGHTER_STATUS_GLIDE_WORK_FLOAT_ANGLE_SPEED)
end
kinetic_energy_stop.speed_x = angled.x
kinetic_energy_stop.speed_y = angled.y
modules.work_module:set_float(power, FIGHTER_STATUS_GLIDE_WORK_FLOAT_POWER)
else
-- also unable to trigger this
end
modules.motion_module:set_frame(90 - angle)
modules.work_module:set_float(angle, FIGHTER_STATUS_GLIDE_WORK_FLOAT_ANGLE)
end
end
function execFixPosition_glide(modules)
-- checks if you're touching a wall
-- left wall flag is 0x4, right wall is 0x2, so either wall is 0x6
if fighter_util.get_air_ground_touch_info(modules) & 0x6 > 0 then
modules.work_module:on_flag(FIGHTER_STATUS_GLIDE_FLAG_TOUCH_GROUND)
else
modules.work_module:off_flag(FIGHTER_STATUS_GLIDE_FLAG_TOUCH_GROUND)
end
end
function exitStatus_glide(modules)
-- partial anim slot 1
modules.motion_module:remove_partial_anim(1)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment