use crate::fighter::{ attack::{AttackKind, update_active_hitbox_list}, state::{ CollisionContext, EnterContext, ExitContext, FighterState, FighterStateImpl, InterruptContext, UpdateContext, ground::GroundedStateCommon, wait::WaitState, }, }; #[derive(Clone, Debug, Hash)] pub struct GroundAttackState { pub attack_kind: AttackKind, pub grounded_common: GroundedStateCommon, } impl FighterStateImpl for GroundAttackState { const NAME: &'static str = "GroundAttack"; fn check_interrupt(&self, state_context: &mut InterruptContext) -> Option { if state_context.is_current_animation_finished() { Some(FighterState::Wait(WaitState { grounded_common: self.grounded_common.clone(), })) } else { None } } fn update(&mut self, state_context: &mut UpdateContext) { let animation_frame = state_context.get_current_animation_frame(); let script = state_context .attack_scripts .get(&state_context.attack_script_assets.scripts[&self.attack_kind]); if let Some(script) = script { update_active_hitbox_list( script, &mut state_context .hitboxes .0 .as_mut() .expect("ground attack must have active hitboxes") .active_hitboxes, animation_frame, ); } } fn on_enter(&mut self, state_context: &mut EnterContext) { state_context.play_animation(self.attack_kind.get_animation(), false); let script = state_context.attack_script_assets.scripts[&self.attack_kind].clone(); state_context.stale_move_queue.push(self.attack_kind); state_context.hitboxes.0 = Some(crate::fighter::FighterActiveAttack { kind: self.attack_kind, script, active_hitboxes: Vec::new(), solved_hitboxes: Vec::new(), hit_fighters: Vec::new(), }); } fn on_exit(&mut self, state_context: &mut ExitContext) { state_context.hitboxes.0 = None; } fn check_collision_interrupt( &mut self, _state_context: &mut CollisionContext, ) -> Option { None } } pub fn check_interrupt( state_context: &InterruptContext, grounded_common: &GroundedStateCommon, ) -> Option { if state_context .input .has_command(crate::input::FighterCommands::Attack) { let attack_kind = state_context .input .get_attack_command_type() .to_attack_kind_grounded(); Some(FighterState::GroundAttack(GroundAttackState { attack_kind, grounded_common: grounded_common.clone(), })) } else { None } }