Add waveland snapping
CI / production-build (pull_request) Successful in 11m11s
CI / build-and-test (pull_request) Failing after 1m38s

This commit is contained in:
2026-10-13 22:49:56 +02:00
parent 472a0b6a19
commit 5be69cab52
5 changed files with 44 additions and 17 deletions
+24 -11
View File
@@ -1,17 +1,9 @@
use crate::{
fighter::{
FighterInvulnerabilityState,
animation::AnimKind,
state::{
CollisionContext, EnterContext, FighterState, FighterStateImpl, InterruptContext,
UpdateContext,
air::{self, AirborneStateCommon},
fall::FallState,
land::LandingType,
FighterInvulnerabilityState, animation::AnimKind, state::{
CollisionContext, EnterContext, FighterState, FighterStateImpl, InterruptContext, UpdateContext, air::{self, AirborneStateCommon}, fall::FallState, land::{LandingState, LandingType},
},
},
input,
math::vec::FGVec2,
}, input, math::vec::FGVec2, stage::line::{StageLineID, StagePolyLineSegmentType},
};
#[derive(Debug, Clone, Hash)]
@@ -52,6 +44,27 @@ impl FighterStateImpl for AirDodgeState {
&mut self,
state_context: &mut CollisionContext,
) -> Option<FighterState> {
let can_wavesnap = self.direction.y.is_zero() || self.direction.y.is_negative();
if can_wavesnap {
for (poly_idx, poly) in state_context.stage_collision.stage_polys.iter().enumerate() {
for (segment_idx, segment) in poly.segments.iter().enumerate() {
if !matches!(segment.segment_type, StagePolyLineSegmentType::Floor) {
continue;
}
let bottom_point = state_context.translation.0 + state_context.ecb.get_bottom_point();
let point_in_segment = segment.segment.closest_point(bottom_point);
let dist_to_segment = point_in_segment.distance(bottom_point);
if dist_to_segment <= state_context.waveland_snap_distance {
state_context.ecb.bottom = point_in_segment;
state_context.ecb.rebase_onto_bottom();
state_context.surface.land(StageLineID { polygon: poly_idx, segment: segment_idx }, state_context.ledge_info);
return Some(FighterState::Land(LandingState::create(LandingType::Special)));
}
}
}
}
air::collision_interrupt(state_context, LandingType::Special, false)
}
+3
View File
@@ -260,6 +260,7 @@ pub struct CollisionContext<'a> {
pub ledge_info: &'a mut FighterLedgeInformation,
pub fighter_ledge_collision_box: FGRect,
pub downward_stick_threshold: FGi32,
pub waveland_snap_distance: FGi32,
pub(crate) ecb_advanced: bool,
}
@@ -503,6 +504,7 @@ impl<'w, 's> FighterFrameQueryItem<'w, 's> {
downward_stick_threshold: game_settings.input_common.run_stick_threshold,
fighter_ledge_collision_box,
ecb_advanced: false,
waveland_snap_distance: game_settings.fighter_common.waveland_snap_distance,
}
}
}
@@ -891,6 +893,7 @@ mod tests {
},
downward_stick_threshold: FGi32::ONE,
ecb_advanced: false,
waveland_snap_distance: FGi32::ZERO,
};
assert!(context.air_collide_with_ledges().is_none());