Implement invulnerability/intangibility and sakurai angle (#78)
CI / build-and-test (push) Successful in 1m22s
CI / production-build (push) Successful in 11m48s

Reviewed-on: #78
Co-authored-by: Álex Román Núñez <eirexe@eirteam.moe>
This commit was merged in pull request #78.
This commit is contained in:
2026-10-03 10:47:00 +00:00
committed by EIREXE
parent aca3886113
commit 02d444f749
8 changed files with 170 additions and 44 deletions
+56 -17
View File
@@ -4,8 +4,16 @@ use bevy_ggrs::prelude::GgrsSchedule;
use super::*;
use crate::{
fighter::{
Fighter, FighterFacingDirection, FighterHitboxes, FighterHitstop, FighterHitstopShake, FighterHitstopShakeKind, FighterHitstopShakeRole, FighterPendingHitReaction, FighterStaleMoveQueue, errors::FighterErrors, manifest::FighterManifest, state::FighterState,
}, game_settings::GameSettings, math::{int::FGi32}, player::Player, schedule::GameplaySet, scripting::FighterAttackScript,
Fighter, FighterFacingDirection, FighterHitboxes, FighterHitstop, FighterHitstopShake,
FighterHitstopShakeKind, FighterHitstopShakeRole, FighterPendingHitReaction,
FighterStaleMoveQueue, FighterSurfaceState, errors::FighterErrors,
manifest::FighterManifest, state::FighterState,
},
game_settings::GameSettings,
math::int::FGi32,
player::Player,
schedule::GameplaySet,
scripting::FighterAttackScript,
};
pub fn resolve_fighter_hits(
@@ -18,7 +26,14 @@ pub fn resolve_fighter_hits(
&mut FighterHitstop,
&mut FighterHitstopShake,
)>,
mut receiver: Query<(&mut FighterDamage, &Fighter, &mut FighterPendingHitReaction, &FighterState)>,
mut receiver: Query<(
&mut FighterDamage,
&Fighter,
&mut FighterPendingHitReaction,
&FighterState,
&FighterInvulnerabilityState,
&FighterSurfaceState,
)>,
attack_scripts: Res<Assets<FighterAttackScript>>,
game_settings: Res<GameSettings>,
fighter_manifests: Res<Assets<FighterManifest>>,
@@ -33,7 +48,14 @@ pub fn resolve_fighter_hits(
.position(|hit| hit.defender != defender)
.map_or(hits.len(), |offset| hit_offset + offset);
let Ok((mut receiver_damage, fighter, mut pending_reaction, receiver_state)) = receiver.get_mut(defender)
let Ok((
mut receiver_damage,
fighter,
mut pending_reaction,
receiver_state,
invuln_state,
receiver_surface_state,
)) = receiver.get_mut(defender)
else {
hit_offset = next_defender;
continue;
@@ -79,10 +101,12 @@ pub fn resolve_fighter_hits(
false,
false,
);
let angle = match &hitbox.angle {
AttackAngle::Normal(angle) => *angle,
AttackAngle::Sakurai => FGi32::lit("32.0"),
};
let angle = hitbox.angle.get_angle(
&knockback,
receiver_surface_state.is_grounded(),
&game_settings,
);
dbg!(knockback, angle);
let launch_angle = if facing_left {
FGi32::lit("180.0") - angle
} else {
@@ -100,15 +124,21 @@ pub fn resolve_fighter_hits(
hitstun_frames: knockback.get_hitstun_frames(&game_settings),
hitstop_frames: hitstop,
kind: HitReactionKind::Flinch,
damage: FighterDamage(attack_damage)
damage: FighterDamage(attack_damage),
},
));
}
receiver_damage.0 += total_damage_received_this_frame;
match invuln_state {
FighterInvulnerabilityState::Vulnerable => {
receiver_damage.0 += total_damage_received_this_frame
}
_ => (),
}
for (attacker_entity, _, reaction) in &reactions {
let Ok((.., _, mut hitstop, mut hitstop_shake)) = attacker.get_mut(*attacker_entity) else {
let Ok((.., _, mut hitstop, mut hitstop_shake)) = attacker.get_mut(*attacker_entity)
else {
continue;
};
@@ -119,7 +149,9 @@ pub fn resolve_fighter_hits(
FighterHitstopShakeKind::Vertical
};
hitstop.remaining_frames = reaction.hitstop_frames.0;
let shake_frames = reaction.hitstop_frames.calculate_shake_frames(&game_settings);
let shake_frames = reaction
.hitstop_frames
.calculate_shake_frames(&game_settings);
hitstop_shake.total_frames = shake_frames;
hitstop_shake.remaining_frames = shake_frames;
hitstop_shake.kind = shake_kind;
@@ -127,16 +159,23 @@ pub fn resolve_fighter_hits(
}
}
pending_reaction.0 = reactions
.into_iter()
.min_by(|(_, port_a, _), (_, port_b, _)| port_a.cmp(port_b))
.map(|(_, _, reaction)| reaction);
match invuln_state {
FighterInvulnerabilityState::Vulnerable => {
pending_reaction.0 = reactions
.into_iter()
.min_by(|(_, port_a, _), (_, port_b, _)| port_a.cmp(port_b))
.map(|(_, _, reaction)| reaction);
}
_ => (),
}
hit_offset = next_defender;
}
for hit in hits {
let Ok((mut stale_move_queue, _facing_direction, mut hitboxes, ..)) = attacker.get_mut(hit.attacker) else {
let Ok((mut stale_move_queue, _facing_direction, mut hitboxes, ..)) =
attacker.get_mut(hit.attacker)
else {
continue;
};