Last active
November 19, 2022 05:31
-
-
Save benhall-7/9c039809eaea892419fb7bbc0913256f to your computer and use it in GitHub Desktop.
Readable Lua interpretation of the gliding statuses from Brawl
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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