Fix airdodge being able to pass through platforms when holding down.

This commit is contained in:
2026-09-27 17:54:40 +02:00
parent e02dff58e5
commit 527ca3be75
8 changed files with 27 additions and 7 deletions
+17 -2
View File
@@ -45,7 +45,7 @@ pub fn air_collide_with_stage(
ecb: &FighterECB, ecb: &FighterECB,
stage_collision: &StageCollision, stage_collision: &StageCollision,
ignored_polys: &[usize], ignored_polys: &[usize],
ignore_soft_platforms: bool, can_ignore_soft_platforms: bool,
) -> Option<AirCollisionWithStageResult> { ) -> Option<AirCollisionWithStageResult> {
let ray_segment = FGSegment2d::new( let ray_segment = FGSegment2d::new(
prev_translation.0 + prev_ecb.get_bottom_point(), prev_translation.0 + prev_ecb.get_bottom_point(),
@@ -58,7 +58,7 @@ pub fn air_collide_with_stage(
.enumerate() .enumerate()
.filter(|(poly_idx, poly)| { .filter(|(poly_idx, poly)| {
!ignored_polys.contains(poly_idx) !ignored_polys.contains(poly_idx)
&& !(ignore_soft_platforms && matches!(poly.poly_type, StagePolyType::Platform)) && !(can_ignore_soft_platforms && matches!(poly.poly_type, StagePolyType::Platform))
}) })
.filter_map(|(poly_idx, poly)| { .filter_map(|(poly_idx, poly)| {
poly.intersect_ray(ray_segment).map(|intersect_result| { poly.intersect_ray(ray_segment).map(|intersect_result| {
@@ -176,6 +176,21 @@ mod tests {
true, true,
) )
.is_none()); .is_none());
assert_eq!(
air_collide_with_stage(
&previous_translation,
&translation,
&previous_ecb,
&ecb,
&stage_collision,
&[],
false,
)
.expect("air dodges still collide with soft platforms")
.hit_position,
FGVec2::lit("0", "0")
);
} }
#[test] #[test]
+2 -1
View File
@@ -115,8 +115,9 @@ pub fn update_standard_motion(
pub fn collision_interrupt( pub fn collision_interrupt(
ctx: &mut CollisionContext, ctx: &mut CollisionContext,
landing_type: LandingType, landing_type: LandingType,
can_ignore_soft_platforms: bool,
) -> Option<FighterState> { ) -> Option<FighterState> {
let res = ctx.air_collide_with_stage()?; let res = ctx.air_collide_with_stage(can_ignore_soft_platforms)?;
let diff = res.hit_position - ctx.translation.0; let diff = res.hit_position - ctx.translation.0;
ctx.ecb.bottom -= diff; ctx.ecb.bottom -= diff;
ctx.ecb.top -= diff; ctx.ecb.top -= diff;
+1 -1
View File
@@ -45,7 +45,7 @@ impl FighterStateImpl for AirDodgeState {
&mut self, &mut self,
state_context: &mut CollisionContext, state_context: &mut CollisionContext,
) -> Option<FighterState> { ) -> Option<FighterState> {
air::collision_interrupt(state_context, LandingType::Special) air::collision_interrupt(state_context, LandingType::Special, false)
} }
fn on_enter(&mut self, state_context: &mut EnterContext) { fn on_enter(&mut self, state_context: &mut EnterContext) {
+1
View File
@@ -38,6 +38,7 @@ impl FighterStateImpl for FallState {
air::collision_interrupt( air::collision_interrupt(
state_context, state_context,
crate::fighter::state::land::LandingType::Normal, crate::fighter::state::land::LandingType::Normal,
true,
) )
} }
+1 -1
View File
@@ -114,7 +114,7 @@ impl FighterStateImpl for HitstunState {
match &mut self.hitstop_kind { match &mut self.hitstop_kind {
HitstopStateKind::Grounded => collision_interrupt(state_context, true), HitstopStateKind::Grounded => collision_interrupt(state_context, true),
HitstopStateKind::Airborne => { HitstopStateKind::Airborne => {
air::collision_interrupt(state_context, LandingType::Normal) air::collision_interrupt(state_context, LandingType::Normal, false)
} }
} }
} }
+1
View File
@@ -180,6 +180,7 @@ impl FighterStateImpl for JumpState {
air::collision_interrupt( air::collision_interrupt(
state_context, state_context,
crate::fighter::state::land::LandingType::Normal, crate::fighter::state::land::LandingType::Normal,
true,
) )
} }
+3 -2
View File
@@ -214,10 +214,11 @@ pub struct CollisionContext<'a> {
impl CollisionContext<'_> { impl CollisionContext<'_> {
pub fn air_collide_with_stage( pub fn air_collide_with_stage(
&self, &self,
can_ignore_soft_platforms: bool,
) -> Option<crate::fighter::collision::AirCollisionWithStageResult> { ) -> Option<crate::fighter::collision::AirCollisionWithStageResult> {
let ignored_polys = self.surface.ignored_polygon_ids(); let ignored_polys = self.surface.ignored_polygon_ids();
let ignore_soft_platforms = let ignore_soft_platforms = can_ignore_soft_platforms
self.input.get_last_frame().movement.y <= -self.downward_stick_threshold; && self.input.get_last_frame().movement.y <= -self.downward_stick_threshold;
crate::fighter::collision::air_collide_with_stage( crate::fighter::collision::air_collide_with_stage(
self.prev_translation, self.prev_translation,
self.translation, self.translation,
+1
View File
@@ -46,6 +46,7 @@ impl FighterStateImpl for PlatformPassState {
air::collision_interrupt( air::collision_interrupt(
state_context, state_context,
crate::fighter::state::land::LandingType::Normal, crate::fighter::state::land::LandingType::Normal,
true,
) )
} }