Fix various minor issues (#74)
CI / production-build (push) Canceled after 0s
CI / build-and-test (push) Canceled after 29s

Reviewed-on: #74
Co-authored-by: Álex Román Núñez <eirexe@eirteam.moe>
This commit was merged in pull request #74.
This commit is contained in:
2026-09-28 15:08:39 +00:00
committed by EIREXE
parent e02dff58e5
commit ccf2657d29
10 changed files with 36 additions and 16 deletions
+17 -2
View File
@@ -45,7 +45,7 @@ pub fn air_collide_with_stage(
ecb: &FighterECB, ecb: &FighterECB,
stage_collision: &StageCollision, stage_collision: &StageCollision,
ignored_polys: &[usize], ignored_polys: &[usize],
ignore_soft_platforms: bool, can_ignore_soft_platforms: bool,
) -> Option<AirCollisionWithStageResult> { ) -> Option<AirCollisionWithStageResult> {
let ray_segment = FGSegment2d::new( let ray_segment = FGSegment2d::new(
prev_translation.0 + prev_ecb.get_bottom_point(), prev_translation.0 + prev_ecb.get_bottom_point(),
@@ -58,7 +58,7 @@ pub fn air_collide_with_stage(
.enumerate() .enumerate()
.filter(|(poly_idx, poly)| { .filter(|(poly_idx, poly)| {
!ignored_polys.contains(poly_idx) !ignored_polys.contains(poly_idx)
&& !(ignore_soft_platforms && matches!(poly.poly_type, StagePolyType::Platform)) && !(can_ignore_soft_platforms && matches!(poly.poly_type, StagePolyType::Platform))
}) })
.filter_map(|(poly_idx, poly)| { .filter_map(|(poly_idx, poly)| {
poly.intersect_ray(ray_segment).map(|intersect_result| { poly.intersect_ray(ray_segment).map(|intersect_result| {
@@ -176,6 +176,21 @@ mod tests {
true, true,
) )
.is_none()); .is_none());
assert_eq!(
air_collide_with_stage(
&previous_translation,
&translation,
&previous_ecb,
&ecb,
&stage_collision,
&[],
false,
)
.expect("air dodges still collide with soft platforms")
.hit_position,
FGVec2::lit("0", "0")
);
} }
#[test] #[test]
+2 -1
View File
@@ -115,8 +115,9 @@ pub fn update_standard_motion(
pub fn collision_interrupt( pub fn collision_interrupt(
ctx: &mut CollisionContext, ctx: &mut CollisionContext,
landing_type: LandingType, landing_type: LandingType,
can_ignore_soft_platforms: bool,
) -> Option<FighterState> { ) -> Option<FighterState> {
let res = ctx.air_collide_with_stage()?; let res = ctx.air_collide_with_stage(can_ignore_soft_platforms)?;
let diff = res.hit_position - ctx.translation.0; let diff = res.hit_position - ctx.translation.0;
ctx.ecb.bottom -= diff; ctx.ecb.bottom -= diff;
ctx.ecb.top -= diff; ctx.ecb.top -= diff;
+1 -1
View File
@@ -45,7 +45,7 @@ impl FighterStateImpl for AirDodgeState {
&mut self, &mut self,
state_context: &mut CollisionContext, state_context: &mut CollisionContext,
) -> Option<FighterState> { ) -> Option<FighterState> {
air::collision_interrupt(state_context, LandingType::Special) air::collision_interrupt(state_context, LandingType::Special, false)
} }
fn on_enter(&mut self, state_context: &mut EnterContext) { fn on_enter(&mut self, state_context: &mut EnterContext) {
+1
View File
@@ -38,6 +38,7 @@ impl FighterStateImpl for FallState {
air::collision_interrupt( air::collision_interrupt(
state_context, state_context,
crate::fighter::state::land::LandingType::Normal, crate::fighter::state::land::LandingType::Normal,
true,
) )
} }
+3 -3
View File
@@ -11,8 +11,7 @@ use crate::{
land::LandingType, land::LandingType,
wait::WaitState, wait::WaitState,
}, },
}, }, math::{int::FGi32, vec::FGVec2},
math::int::FGi32,
}; };
#[derive(Clone, Debug, Hash)] #[derive(Clone, Debug, Hash)]
@@ -103,6 +102,7 @@ impl FighterStateImpl for HitstunState {
HitstopStateKind::Airborne => AnimKind::FlinchAir, HitstopStateKind::Airborne => AnimKind::FlinchAir,
}; };
state_context.play_animation(animation, false); state_context.play_animation(animation, false);
state_context.velocity.0 = FGVec2::ZERO;
} }
fn on_exit(&mut self, _state_context: &mut ExitContext) {} fn on_exit(&mut self, _state_context: &mut ExitContext) {}
@@ -114,7 +114,7 @@ impl FighterStateImpl for HitstunState {
match &mut self.hitstop_kind { match &mut self.hitstop_kind {
HitstopStateKind::Grounded => collision_interrupt(state_context, true), HitstopStateKind::Grounded => collision_interrupt(state_context, true),
HitstopStateKind::Airborne => { HitstopStateKind::Airborne => {
air::collision_interrupt(state_context, LandingType::Normal) air::collision_interrupt(state_context, LandingType::Normal, false)
} }
} }
} }
+1
View File
@@ -180,6 +180,7 @@ impl FighterStateImpl for JumpState {
air::collision_interrupt( air::collision_interrupt(
state_context, state_context,
crate::fighter::state::land::LandingType::Normal, crate::fighter::state::land::LandingType::Normal,
true,
) )
} }
+3 -2
View File
@@ -214,10 +214,11 @@ pub struct CollisionContext<'a> {
impl CollisionContext<'_> { impl CollisionContext<'_> {
pub fn air_collide_with_stage( pub fn air_collide_with_stage(
&self, &self,
can_ignore_soft_platforms: bool,
) -> Option<crate::fighter::collision::AirCollisionWithStageResult> { ) -> Option<crate::fighter::collision::AirCollisionWithStageResult> {
let ignored_polys = self.surface.ignored_polygon_ids(); let ignored_polys = self.surface.ignored_polygon_ids();
let ignore_soft_platforms = let ignore_soft_platforms = can_ignore_soft_platforms
self.input.get_last_frame().movement.y <= -self.downward_stick_threshold; && self.input.get_last_frame().movement.y <= -self.downward_stick_threshold;
crate::fighter::collision::air_collide_with_stage( crate::fighter::collision::air_collide_with_stage(
self.prev_translation, self.prev_translation,
self.translation, self.translation,
+1
View File
@@ -46,6 +46,7 @@ impl FighterStateImpl for PlatformPassState {
air::collision_interrupt( air::collision_interrupt(
state_context, state_context,
crate::fighter::state::land::LandingType::Normal, crate::fighter::state::land::LandingType::Normal,
true,
) )
} }
+2 -2
View File
@@ -3,7 +3,7 @@ use super::{
ground, wait, ground, wait,
}; };
use crate::fighter::animation::AnimKind; use crate::fighter::animation::AnimKind;
use crate::fighter::state::FighterState; use crate::fighter::state::{self, FighterState};
#[derive(Debug, Clone, Hash)] #[derive(Debug, Clone, Hash)]
pub struct WalkState; pub struct WalkState;
@@ -14,7 +14,7 @@ impl FighterStateImpl for WalkState {
if let Some(state) = ground::grounded_movement_common_interrupts(state_context) { if let Some(state) = ground::grounded_movement_common_interrupts(state_context) {
return Some(state); return Some(state);
} }
wait::check_input(state_context).or_else(|| dash::check_input(state_context)) wait::check_input(state_context).or_else(|| dash::check_input(state_context)).or_else(|| state::ground_attack::check_interrupt(state_context))
} }
fn on_enter(&mut self, state_context: &mut EnterContext) { fn on_enter(&mut self, state_context: &mut EnterContext) {
+5 -5
View File
@@ -117,7 +117,7 @@ pub fn register_common_types(engine: &mut rhai::Engine) {
.register_fn("knockback_normal", KnockbackType::make_normal) .register_fn("knockback_normal", KnockbackType::make_normal)
.register_fn("knockback_fixed", KnockbackType::make_fixed) .register_fn("knockback_fixed", KnockbackType::make_fixed)
.register_type_with_name::<AttackAngle>("Angle") .register_type_with_name::<AttackAngle>("Angle")
.register_fn("angle", AttackAngle::make_normal) .register_fn("angle", |str: &str| AttackAngle::make_normal(FGi32::lit(str)))
.register_fn("angle_sakurai", AttackAngle::make_sakurai) .register_fn("angle_sakurai", AttackAngle::make_sakurai)
.register_type_with_name::<Knockback>("Knockback") .register_type_with_name::<Knockback>("Knockback")
.register_fn("knockback", Knockback::lit) .register_fn("knockback", Knockback::lit)
@@ -261,18 +261,18 @@ pub fn compile_script(text: &str) -> Result<FighterAttackScript, String> {
mod tests { mod tests {
use super::*; use super::*;
const HITBOX: &str = "hitbox(0, \"hand_l\", damage(\"1\"), vec3(\"0\", \"0\", \"0\"), fg32(\"1\"), angle(fg32(\"0\")), knockback_normal(), knockback(\"1\"), fg32(\"1\"));"; const HITBOX: &str = "hitbox(0, \"hand_l\", damage(\"1\"), vec3(\"0\", \"0\", \"0\"), fg32(\"1\"), angle(\"0\"), knockback_normal(), knockback(\"1\"), fg32(\"1\"));";
#[test] #[test]
fn compiled_hitboxes_are_sorted_by_authored_id() { fn compiled_hitboxes_are_sorted_by_authored_id() {
let script = compile_script( let script = compile_script(
r#" r#"
frame(1); frame(1);
hitbox(20, "hand_l", damage("1"), vec3("0", "0", "0"), fg32("1"), angle(fg32("0")), knockback_normal(), knockback("1"), fg32("1")); hitbox(20, "hand_l", damage("1"), vec3("0", "0", "0"), fg32("1"), angle("0"), knockback_normal(), knockback("1"), fg32("1"));
frame(2); frame(2);
hitbox(3, "hand_l", damage("2"), vec3("0", "0", "0"), fg32("1"), angle(fg32("0")), knockback_normal(), knockback("1"), fg32("1")); hitbox(3, "hand_l", damage("2"), vec3("0", "0", "0"), fg32("1"), angle("0"), knockback_normal(), knockback("1"), fg32("1"));
frame(3); frame(3);
hitbox(10, "hand_l", damage("3"), vec3("0", "0", "0"), fg32("1"), angle(fg32("0")), knockback_normal(), knockback("1"), fg32("1")); hitbox(10, "hand_l", damage("3"), vec3("0", "0", "0"), fg32("1"), angle("0"), knockback_normal(), knockback("1"), fg32("1"));
frame(4); frame(4);
"#, "#,
) )