Initial work on ledge & improved baking of root motion. (#90)
CI / build-and-test (push) Successful in 2m15s
CI / production-build (push) Successful in 12m24s

Reviewed-on: #90
Co-authored-by: Álex Román Núñez <eirexe@eirteam.moe>
This commit was merged in pull request #90.
This commit is contained in:
2026-10-12 20:58:27 +00:00
committed by EIREXE
parent 0642a9234b
commit 9b974d0dd6
22 changed files with 1094 additions and 141 deletions
+40 -1
View File
@@ -2,6 +2,7 @@
//! ECS types so it stays cheap to reason about and to unit-test — it has to be
//! bit-for-bit deterministic for rollback.
use crate::fighter::state::air_dodge::AirDodgeState;
use crate::fighter::state::{
CollisionContext, FighterState, InterruptContext, air, crouch, dash, fall, ground_attack, turn, wait, walk,
};
@@ -9,6 +10,7 @@ use crate::fighter::{
FighterAttributes, FighterTranslation, FighterVelocity,
};
use crate::game_settings::GameSettings;
use crate::input::FighterInput;
use crate::math::int::{FGWide, FGi32};
use crate::math::vec::FGVec2;
use crate::stage::line::{StageLineID, StagePoly, StagePolyLineSegment, StagePolyLineSegmentType};
@@ -245,7 +247,8 @@ mod tests {
use super::*;
use crate::fighter::ecb::FighterPreviousECB;
use crate::fighter::{FighterECB, FighterPreviousTranslation, FighterSurfaceState};
use crate::stage::line::StagePolyType;
use crate::math::rect::FGRect;
use crate::stage::line::StagePolyType;
use crate::input::FighterInput;
fn two_segment_floor() -> StagePoly {
@@ -357,6 +360,7 @@ mod tests {
fn grounded_collision_updates_surface_segment() {
let stage_collision = crate::stage::line::StageCollision {
stage_polys: vec![two_segment_floor()],
..crate::stage::line::StageCollision::default()
};
let mut surface = FighterSurfaceState::Grounded {
line_id: StageLineID {
@@ -387,6 +391,11 @@ mod tests {
leave_ground_ecb_lock_duration: 10,
presentation_snap: &mut presentation_snap,
downward_stick_threshold: FGi32::ONE,
fighter_ledge_collision_box: FGRect {
origin: FGVec2::ZERO,
end: FGVec2::ZERO,
},
ledge_grab_lockout_active: false,
};
assert!(matches!(
@@ -412,6 +421,7 @@ mod tests {
(FGVec2::lit("10", "0"), StagePolyLineSegmentType::Floor),
],
)],
..crate::stage::line::StageCollision::default()
};
let mut surface = FighterSurfaceState::Grounded {
line_id: StageLineID {
@@ -442,6 +452,11 @@ mod tests {
leave_ground_ecb_lock_duration: 10,
presentation_snap: &mut presentation_snap,
downward_stick_threshold: FGi32::ONE,
fighter_ledge_collision_box: FGRect {
origin: FGVec2::ZERO,
end: FGVec2::ZERO,
},
ledge_grab_lockout_active: false,
};
assert!(matches!(
@@ -477,3 +492,27 @@ pub fn grounded_movement_standstill_common_interrupts(
None
}
}
pub fn perform_wavedash(input: &FighterInput, game_settings: &GameSettings) -> FighterState {
// If aiming sideways and in the deadzone, do a perfect wavedash
// TODO: Improve this so we don't have to go through the airborne state first
let mut wavedash_dir =
input
.get_last_frame()
.movement
.normalize_or_zero();
let movement = input.get_last_frame().movement;
if movement.y.is_zero() && !movement.x.is_zero() {
wavedash_dir.y =
-game_settings.input_common.stick_deadzone - FGi32::lit("-0.01");
wavedash_dir.x = movement.x.signum();
}
if wavedash_dir == FGVec2::ZERO {
wavedash_dir = FGVec2::lit("0.0", "-1.0");
}
FighterState::AirDodge(AirDodgeState {
direction: wavedash_dir.normalize_or_zero(),
})
}