Files
shinespark/src/fighter/state/land.rs
T
EIREXE d521461625
CI / build-and-test (push) Successful in 1m28s
CI / production-build (push) Successful in 11m59s
Add authoritative fighter surface state (#60)
## Summary
- add a rollback-tracked `FighterSurfaceState` as the single source of truth for stage contact
- move active stage line ownership out of individual grounded fighter states
- update landing, airborne motion, ledge departure, hit reactions, and debug save states to maintain surface contact
- add tests for contact lifecycle, connected-segment traversal, and ledge departure

Reviewed-on: #60
Co-authored-by: Álex Román Núñez <eirexe@eirteam.moe>
2026-09-25 10:45:27 +00:00

73 lines
2.0 KiB
Rust

use crate::fighter::{
animation::AnimKind,
state::{
CollisionContext, EnterContext, FighterState, FighterStateImpl, InterruptContext,
UpdateContext, dash,
ground::{self, grounded_movement_standstill_common_interrupts},
walk,
},
};
#[derive(Debug, Clone, Hash)]
pub enum LandingType {
Normal,
Special,
}
#[derive(Debug, Clone, Hash)]
pub struct LandingState {
pub landing_type: LandingType,
}
impl LandingState {
pub fn create(landing_type: LandingType) -> Self {
Self { landing_type }
}
}
impl FighterStateImpl for LandingState {
const NAME: &'static str = "Landing";
fn check_interrupt(&self, state_context: &mut InterruptContext) -> Option<FighterState> {
if state_context.is_current_animation_finished() {
grounded_movement_standstill_common_interrupts(state_context)
} else if state_context.get_current_animation_frame()
>= state_context.fighter_attributes.landing_iasa
&& let LandingType::Normal = self.landing_type
{
dash::check_input(state_context).or_else(|| {
ground::grounded_movement_common_interrupts(state_context)
.or_else(|| walk::check_input(state_context))
})
} else {
None
}
}
fn update(&mut self, state_context: &mut UpdateContext) {
ground::update_friction_motion(state_context);
}
fn check_collision_interrupt(
&mut self,
state_context: &mut CollisionContext,
) -> Option<FighterState> {
ground::collision_interrupt(state_context, true)
}
fn on_enter(&mut self, state_context: &mut EnterContext) {
match self.landing_type {
LandingType::Normal => {
state_context.play_animation(AnimKind::Landing, false);
}
LandingType::Special => {
state_context.play_animation(AnimKind::LandingSpecial, false);
}
};
}
fn is_visually_grounded<'a>(&'a self) -> bool {
true
}
}