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:
+13
-28
@@ -5,52 +5,43 @@ use super::{
|
||||
use crate::fighter::FighterFacingDirection;
|
||||
use crate::fighter::animation::AnimKind;
|
||||
use crate::fighter::state::FighterState;
|
||||
use crate::fighter::state::ground::GroundedStateCommon;
|
||||
use crate::input::FighterCommands::{SmashMoveLeft, SmashMoveRight};
|
||||
|
||||
#[derive(Debug, Clone, Hash)]
|
||||
pub struct DashState {
|
||||
direction: FighterFacingDirection,
|
||||
pub ground_common: GroundedStateCommon,
|
||||
}
|
||||
|
||||
impl DashState {
|
||||
pub fn new(direction: FighterFacingDirection, ground_common: GroundedStateCommon) -> Self {
|
||||
Self {
|
||||
direction,
|
||||
ground_common,
|
||||
}
|
||||
pub fn new(direction: FighterFacingDirection) -> Self {
|
||||
Self { direction }
|
||||
}
|
||||
}
|
||||
|
||||
impl FighterStateImpl for DashState {
|
||||
const NAME: &'static str = "Dash";
|
||||
fn check_interrupt(&self, ctx: &mut InterruptContext) -> Option<FighterState> {
|
||||
let ground = &self.ground_common;
|
||||
let attributes = ctx.fighter_attributes;
|
||||
|
||||
// A reverse dash can interrupt before IASA
|
||||
if let Some(direction) =
|
||||
check_smash_input_with_dir(ctx).filter(|direction| *direction != self.direction)
|
||||
{
|
||||
return Some(FighterState::Dash(DashState::new(
|
||||
direction,
|
||||
ground.clone(),
|
||||
)));
|
||||
return Some(FighterState::Dash(DashState::new(direction)));
|
||||
}
|
||||
|
||||
if let Some(state) = ground::grounded_movement_common_interrupts(ctx, ground) {
|
||||
if let Some(state) = ground::grounded_movement_common_interrupts(ctx) {
|
||||
return Some(state);
|
||||
}
|
||||
|
||||
if ctx.is_current_animation_finished() {
|
||||
return run::check_input(ctx, ground)
|
||||
.or_else(|| walk::check_input(ctx, ground))
|
||||
.or_else(|| wait::check_input(ctx, ground));
|
||||
return run::check_input(ctx)
|
||||
.or_else(|| walk::check_input(ctx))
|
||||
.or_else(|| wait::check_input(ctx));
|
||||
}
|
||||
|
||||
if ctx.get_current_animation_frame() > attributes.dash_acceleration_duration {
|
||||
return run::check_input(ctx, ground);
|
||||
return run::check_input(ctx);
|
||||
}
|
||||
|
||||
None
|
||||
@@ -106,12 +97,10 @@ impl FighterStateImpl for DashState {
|
||||
&mut self,
|
||||
state_context: &mut CollisionContext,
|
||||
) -> Option<FighterState> {
|
||||
ground::collision_interrupt(state_context, &mut self.ground_common, true)
|
||||
ground::collision_interrupt(state_context, true)
|
||||
}
|
||||
|
||||
fn is_visually_grounded<'a>(
|
||||
&'a self,
|
||||
) -> bool {
|
||||
|
||||
fn is_visually_grounded<'a>(&'a self) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
@@ -126,10 +115,6 @@ fn check_smash_input_with_dir(state_context: &InterruptContext) -> Option<Fighte
|
||||
}
|
||||
}
|
||||
|
||||
pub fn check_input(
|
||||
state_context: &InterruptContext,
|
||||
ground_common: &GroundedStateCommon,
|
||||
) -> Option<FighterState> {
|
||||
check_smash_input_with_dir(state_context)
|
||||
.map(|dir| FighterState::Dash(DashState::new(dir, ground_common.clone())))
|
||||
pub fn check_input(state_context: &InterruptContext) -> Option<FighterState> {
|
||||
check_smash_input_with_dir(state_context).map(|dir| FighterState::Dash(DashState::new(dir)))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user