diff --git a/src/aim/target_ui.rs b/src/aim/target_ui.rs index de55ff1..e90ba78 100644 --- a/src/aim/target_ui.rs +++ b/src/aim/target_ui.rs @@ -153,6 +153,7 @@ fn sync( new_state = Some(BackpackHead { head: head.0, health: hp.health(), + ammo: 1., }); } } diff --git a/src/backpack/mod.rs b/src/backpack/mod.rs index 18d5dd4..bdfd3dc 100644 --- a/src/backpack/mod.rs +++ b/src/backpack/mod.rs @@ -5,16 +5,29 @@ use bevy::prelude::*; pub use backpack_ui::BackpackAction; -#[derive(Clone, Copy, Debug, PartialEq)] +#[derive(Clone, Copy, Debug, PartialEq, Reflect)] pub struct BackpackHead { pub head: usize, pub health: f32, + pub ammo: f32, } impl BackpackHead { + pub fn new(head: usize) -> Self { + Self { + head, + health: 1.0, + ammo: 1.0, + } + } + pub fn damage(&self) -> f32 { 1. - self.health } + + pub fn ammo_used(&self) -> f32 { + 1. - self.ammo + } } #[derive(Resource, Default)] @@ -37,6 +50,7 @@ fn setup(mut commands: Commands) { .map(|i| BackpackHead { head: i, health: 1., + ammo: 1., }) .collect(), }); diff --git a/src/heads_ui.rs b/src/heads_ui.rs index 5f2079d..2385dd8 100644 --- a/src/heads_ui.rs +++ b/src/heads_ui.rs @@ -6,7 +6,7 @@ use crate::{ sounds::PlaySound, }; use bevy::prelude::*; -use bevy_ui_gradients::{AngularColorStop, BackgroundGradient, ConicGradient, Position}; +use bevy_ui_gradients::{AngularColorStop, BackgroundGradient, ConicGradient, Gradient, Position}; use std::f32::consts::PI; pub static HEAD_COUNT: usize = 18; @@ -35,9 +35,10 @@ pub struct HeadsImages { pub heads: Vec>, } -#[derive(Resource, Default)] +#[derive(Resource, Default, Reflect)] +#[reflect(Resource)] pub struct ActiveHeads { - heads: [Option; 5], + heads: [Option; 5], current_slot: usize, } @@ -46,8 +47,13 @@ pub struct HeadChanged(pub usize); pub fn plugin(app: &mut App) { app.register_type::(); + app.register_type::(); + app.add_systems(OnEnter(GameState::Playing), setup); - app.add_systems(Update, update.run_if(in_state(GameState::Playing))); + app.add_systems( + Update, + (update, update_ammo, update_health).run_if(in_state(GameState::Playing)), + ); app.add_observer(on_select_active_head); app.add_observer(on_swap_backpack); } @@ -82,7 +88,13 @@ fn setup(mut commands: Commands, asset_server: Res, assets: Res, mut gradients: Query<(&mut BackgroundGradient, &HeadImage)>) { + if res.is_changed() { + for (mut gradient, HeadImage(head)) in gradients.iter_mut() { + if let Some(head) = res.heads[*head] { + let ammo_used = head.ammo_used(); + let Gradient::Conic(gradient) = &mut gradient.0[0] else { + continue; + }; + let angle = PI * 2. * ammo_used; + gradient.stops[1].angle = Some(angle); + gradient.stops[2].angle = Some(angle); + } + } + } +} + +fn update_health(res: Res, mut query: Query<(&mut Node, &HeadDamage)>) { + if res.is_changed() { + for (mut node, HeadDamage(head)) in query.iter_mut() { + node.height = + Val::Percent(res.heads[*head].map(|head| head.damage()).unwrap_or(0.) * 100.); + } + } +} + fn on_select_active_head( trigger: Trigger, mut commands: Commands, @@ -217,7 +254,7 @@ fn on_select_active_head( } commands.trigger(PlaySound::Selection); - commands.trigger(HeadChanged(res.heads[res.current_slot].unwrap())); + commands.trigger(HeadChanged(res.heads[res.current_slot].unwrap().head)); } fn on_swap_backpack( @@ -233,16 +270,13 @@ fn on_swap_backpack( let current_active_slot = res.current_slot; let current_active_head = res.heads[current_active_slot]; - res.heads[current_active_slot] = Some(head.head); + res.heads[current_active_slot] = Some(*head); if let Some(old_active) = current_active_head { - backpack.heads[backpack_slot] = BackpackHead { - head: old_active, - health: 1., - }; + backpack.heads[backpack_slot] = old_active; } else { backpack.heads.remove(backpack_slot); } - commands.trigger(HeadChanged(res.heads[res.current_slot].unwrap())); + commands.trigger(HeadChanged(res.heads[res.current_slot].unwrap().head)); }