use crate::{fighter::{FighterInvulnerabilityState, animation::AnimKind, state::{FighterState, FighterStateImpl, air::AirborneStateCommon, fall::FallState}}, math::vec::FGVec2}; #[derive(Debug, Clone, Hash)] pub struct AngelState { frames_remaining: u32 } impl AngelState { pub fn new(duration: u32) -> Self { Self { frames_remaining: duration } } } impl FighterStateImpl for AngelState { const NAME: &'static str = "Angel"; fn check_interrupt(&self, state_context: &mut super::InterruptContext) -> Option { let moved_sideways = !state_context.input.get_last_frame().movement.x.is_zero(); let moved_vertically = !state_context.input.get_last_frame().movement.y.is_zero(); if self.frames_remaining == 0 || moved_sideways || moved_vertically { Some(FighterState::Fall(FallState::new(AirborneStateCommon::default()))) } else { None } } fn update(&mut self, _state_context: &mut super::UpdateContext) { self.frames_remaining = self.frames_remaining.saturating_sub(1); } fn is_visually_grounded<'a>(&'a self) -> bool { false } fn on_enter(&mut self, state_context: &mut super::EnterContext) { state_context.play_animation(AnimKind::Wait, true); state_context.velocity.0 = FGVec2::ZERO; *state_context.vulnerability = FighterInvulnerabilityState::Invulnerable { frames_remaining: Some(state_context.game_settings.fighter_common.angel_platform_invulnerability_duration) }; } fn check_collision_interrupt( &mut self, _state_context: &mut super::CollisionContext, ) -> Option { None } fn surface_policy(&self) -> super::SurfacePolicy { super::SurfacePolicy::Airborne(crate::fighter::surface::EcbLockPolicy::Clear) } }