use crate::{ fighter::{FighterInvulnerabilityState, baked_animation::BakedFighterAnimations}, game_settings::GameSettings, materials::fighter_material::{FighterMaterial, FighterMesh}, }; use bevy::prelude::*; #[derive(Component, Clone)] pub struct FighterAnimations { /// The single animation source for gameplay and the visual skeleton. pub baked: Handle, } #[derive(Clone, Copy, Default, PartialEq)] pub enum LastKnownInvulnerabilityState { #[default] Vulnerable, Intangible, Invulnerable, } impl From<&FighterInvulnerabilityState> for LastKnownInvulnerabilityState { fn from(value: &FighterInvulnerabilityState) -> Self { match value { FighterInvulnerabilityState::Vulnerable => Self::Vulnerable, FighterInvulnerabilityState::Invulnerable { .. } => Self::Invulnerable, FighterInvulnerabilityState::Intangible { .. } => Self::Intangible, } } } #[derive(Component, Clone, Default)] pub struct FighterInvulnerabilityVisualState { pub last_known_state: LastKnownInvulnerabilityState, pub frames_in_state: u32, } pub fn update_status_colors( mut fighters: Query<( &FighterInvulnerabilityState, &mut FighterInvulnerabilityVisualState, )>, meshes: Query<(&FighterMesh, &MeshMaterial3d)>, mut materials: ResMut>, game_settings: Res, ) { for (invuln_state, mut invuln_state_visual) in &mut fighters { let curr_state = invuln_state.into(); let last_known_state = invuln_state_visual.last_known_state; if curr_state != last_known_state { invuln_state_visual.last_known_state = curr_state; invuln_state_visual.frames_in_state = 0; } } for (mesh, mat) in meshes { let (_, invuln_state_visual) = fighters .get(mesh.fighter) .expect("Material should have relevant fighter available"); let status_color = match invuln_state_visual.last_known_state { LastKnownInvulnerabilityState::Vulnerable => bevy::color::palettes::css::WHITE.into(), LastKnownInvulnerabilityState::Invulnerable => { game_settings.fighter_common.intangible_color } LastKnownInvulnerabilityState::Intangible => { game_settings.fighter_common.intangible_color } }; let intensity = match invuln_state_visual.last_known_state { LastKnownInvulnerabilityState::Vulnerable => 0.0, LastKnownInvulnerabilityState::Invulnerable | LastKnownInvulnerabilityState::Intangible => { let cycle_frames = invuln_state_visual.frames_in_state % game_settings.fighter_common.intangible_pulse_duration; 1.0 - cycle_frames as f32 / ((game_settings.fighter_common.intangible_pulse_duration) as f32) } }; let mut material = materials .get_mut(mat.id()) .expect("Material should exist here..."); material .extension .update_status_color(status_color.into(), intensity); } for (_, mut invuln_state_visual) in fighters { invuln_state_visual.frames_in_state = invuln_state_visual.frames_in_state.saturating_add(1); } }