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>
This commit was merged in pull request #60.
This commit is contained in:
@@ -7,7 +7,7 @@ use crate::{
|
||||
InterruptContext, UpdateContext,
|
||||
air::{self, AirborneStateCommon},
|
||||
fall::FallState,
|
||||
ground::{GroundedStateCommon, collision_interrupt},
|
||||
ground::collision_interrupt,
|
||||
land::LandingType,
|
||||
wait::WaitState,
|
||||
},
|
||||
@@ -17,7 +17,7 @@ use crate::{
|
||||
|
||||
#[derive(Clone, Debug, Hash)]
|
||||
pub enum HitstopStateKind {
|
||||
Grounded(GroundedStateCommon),
|
||||
Grounded,
|
||||
Airborne,
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ impl FighterStateImpl for HitstunState {
|
||||
|
||||
fn name(&self) -> String {
|
||||
let hitstop_kind = match self.hitstop_kind {
|
||||
HitstopStateKind::Grounded(_) => "Grounded",
|
||||
HitstopStateKind::Grounded => "Grounded",
|
||||
HitstopStateKind::Airborne => "Airborne",
|
||||
};
|
||||
|
||||
@@ -58,14 +58,10 @@ impl FighterStateImpl for HitstunState {
|
||||
fn check_interrupt(&self, state_context: &mut InterruptContext) -> Option<FighterState> {
|
||||
if state_context.get_current_animation_frame() > self.hit_reaction.hitstun_frames {
|
||||
match &self.hitstop_kind {
|
||||
HitstopStateKind::Grounded(grounded_state_common) => {
|
||||
Some(FighterState::Wait(WaitState {
|
||||
grounded_common: grounded_state_common.clone(),
|
||||
}))
|
||||
}
|
||||
HitstopStateKind::Airborne => {
|
||||
Some(FighterState::Fall(FallState::new(AirborneStateCommon::default())))
|
||||
}
|
||||
HitstopStateKind::Grounded => Some(FighterState::Wait(WaitState)),
|
||||
HitstopStateKind::Airborne => Some(FighterState::Fall(FallState::new(
|
||||
AirborneStateCommon::default(),
|
||||
))),
|
||||
}
|
||||
} else {
|
||||
None
|
||||
@@ -85,8 +81,9 @@ impl FighterStateImpl for HitstunState {
|
||||
}
|
||||
|
||||
match self.hitstop_kind {
|
||||
HitstopStateKind::Grounded(_) => {}
|
||||
HitstopStateKind::Grounded => {}
|
||||
HitstopStateKind::Airborne => {
|
||||
ctx.surface.leave_ground();
|
||||
air::integrate_gravity(ctx.velocity, ctx.fighter_attributes, false);
|
||||
}
|
||||
}
|
||||
@@ -103,7 +100,7 @@ impl FighterStateImpl for HitstunState {
|
||||
|
||||
fn on_enter(&mut self, state_context: &mut EnterContext) {
|
||||
let animation = match self.hitstop_kind {
|
||||
HitstopStateKind::Grounded(_) => AnimKind::FlinchGround,
|
||||
HitstopStateKind::Grounded => AnimKind::FlinchGround,
|
||||
HitstopStateKind::Airborne => AnimKind::FlinchAir,
|
||||
};
|
||||
state_context.play_animation(animation, false);
|
||||
@@ -116,9 +113,7 @@ impl FighterStateImpl for HitstunState {
|
||||
state_context: &mut CollisionContext,
|
||||
) -> Option<FighterState> {
|
||||
match &mut self.hitstop_kind {
|
||||
HitstopStateKind::Grounded(grounded_state_common) => {
|
||||
collision_interrupt(state_context, grounded_state_common, true)
|
||||
}
|
||||
HitstopStateKind::Grounded => collision_interrupt(state_context, true),
|
||||
HitstopStateKind::Airborne => {
|
||||
air::collision_interrupt(state_context, LandingType::Normal)
|
||||
}
|
||||
@@ -127,7 +122,7 @@ impl FighterStateImpl for HitstunState {
|
||||
|
||||
fn is_visually_grounded<'a>(&'a self) -> bool {
|
||||
match self.hitstop_kind {
|
||||
HitstopStateKind::Grounded(_) => true,
|
||||
HitstopStateKind::Grounded => true,
|
||||
HitstopStateKind::Airborne => false,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user