medic healing ability
This commit is contained in:
76
src/abilities/healing.rs
Normal file
76
src/abilities/healing.rs
Normal file
@@ -0,0 +1,76 @@
|
||||
use bevy::prelude::*;
|
||||
|
||||
use crate::{
|
||||
GameState, global_observer, heads::ActiveHeads, heads_database::HeadsDatabase,
|
||||
hitpoints::Hitpoints, loading_assets::AudioAssets,
|
||||
};
|
||||
|
||||
#[derive(Component)]
|
||||
struct Healing(Entity);
|
||||
|
||||
#[derive(Event, Debug)]
|
||||
pub enum HealingStateChanged {
|
||||
Started,
|
||||
Stopped,
|
||||
}
|
||||
|
||||
pub fn plugin(app: &mut App) {
|
||||
app.add_systems(Update, update.run_if(in_state(GameState::Playing)));
|
||||
|
||||
global_observer!(app, on_heal_start_stop);
|
||||
}
|
||||
|
||||
fn on_heal_start_stop(
|
||||
trigger: Trigger<HealingStateChanged>,
|
||||
mut cmds: Commands,
|
||||
assets: Res<AudioAssets>,
|
||||
query: Query<&Healing>,
|
||||
) {
|
||||
if matches!(trigger.event(), HealingStateChanged::Started) {
|
||||
let e = cmds
|
||||
.spawn((
|
||||
Name::new("sfx-heal"),
|
||||
AudioPlayer::new(assets.healing.clone()),
|
||||
PlaybackSettings {
|
||||
mode: bevy::audio::PlaybackMode::Loop,
|
||||
..Default::default()
|
||||
},
|
||||
))
|
||||
.id();
|
||||
cmds.entity(trigger.target())
|
||||
.add_child(e)
|
||||
.insert(Healing(e));
|
||||
} else {
|
||||
if let Ok(healing) = query.single() {
|
||||
cmds.entity(healing.0).despawn();
|
||||
}
|
||||
cmds.entity(trigger.target()).remove::<Healing>();
|
||||
}
|
||||
}
|
||||
|
||||
fn update(
|
||||
mut query: Query<(&mut ActiveHeads, &mut Hitpoints), With<Healing>>,
|
||||
time: Res<Time>,
|
||||
heads_db: Res<HeadsDatabase>,
|
||||
) {
|
||||
for (mut heads, mut hitpoints) in query.iter_mut() {
|
||||
let Some(current) = heads.current() else {
|
||||
continue;
|
||||
};
|
||||
|
||||
let head = heads_db.head_stats(current.head);
|
||||
|
||||
if current.last_use + (1. / head.aps) > time.elapsed_secs() {
|
||||
continue;
|
||||
}
|
||||
|
||||
let medic_hp = hitpoints.get().0;
|
||||
if medic_hp > 0 {
|
||||
if let Some(health) = heads.medic_heal(2, time.elapsed_secs()) {
|
||||
hitpoints.set_health(health);
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
mod arrow;
|
||||
mod gun;
|
||||
mod healing;
|
||||
mod missile;
|
||||
mod thrown;
|
||||
|
||||
@@ -15,6 +16,7 @@ use crate::{
|
||||
sounds::PlaySound,
|
||||
};
|
||||
use bevy::prelude::*;
|
||||
use healing::HealingStateChanged;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Event, Reflect)]
|
||||
@@ -34,6 +36,7 @@ pub enum HeadAbility {
|
||||
Thrown,
|
||||
Gun,
|
||||
Missile,
|
||||
Medic,
|
||||
}
|
||||
|
||||
#[derive(Debug, Reflect, Clone, Copy)]
|
||||
@@ -88,8 +91,12 @@ pub fn plugin(app: &mut App) {
|
||||
app.add_plugins(thrown::plugin);
|
||||
app.add_plugins(arrow::plugin);
|
||||
app.add_plugins(missile::plugin);
|
||||
app.add_plugins(healing::plugin);
|
||||
|
||||
app.add_systems(Update, update.run_if(in_state(GameState::Playing)));
|
||||
app.add_systems(
|
||||
Update,
|
||||
(update, update_heal_ability).run_if(in_state(GameState::Playing)),
|
||||
);
|
||||
|
||||
global_observer!(app, on_trigger_state);
|
||||
}
|
||||
@@ -136,6 +143,16 @@ fn update(
|
||||
return;
|
||||
};
|
||||
|
||||
let head = heads_db.head_stats(state.head);
|
||||
|
||||
if matches!(head.ability, HeadAbility::None | HeadAbility::Medic) {
|
||||
return;
|
||||
}
|
||||
|
||||
active_heads.use_ammo(time.elapsed_secs());
|
||||
|
||||
res.cooldown = time.elapsed_secs() + (1. / head.aps);
|
||||
|
||||
let trigger_state = TriggerData {
|
||||
dir,
|
||||
rot,
|
||||
@@ -145,18 +162,39 @@ fn update(
|
||||
head: state.head,
|
||||
};
|
||||
|
||||
active_heads.use_ammo(time.elapsed_secs());
|
||||
|
||||
let head = heads_db.head_stats(state.head);
|
||||
|
||||
res.cooldown = time.elapsed_secs() + (1. / head.aps);
|
||||
|
||||
match head.ability {
|
||||
HeadAbility::Thrown => commands.trigger(TriggerThrow(trigger_state)),
|
||||
HeadAbility::Gun => commands.trigger(TriggerGun(trigger_state)),
|
||||
HeadAbility::Missile => commands.trigger(TriggerMissile(trigger_state)),
|
||||
HeadAbility::Arrow => commands.trigger(TriggerArrow(trigger_state)),
|
||||
HeadAbility::None => (),
|
||||
_ => panic!("Unhandled head ability"),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
fn update_heal_ability(
|
||||
res: Res<TriggerStateRes>,
|
||||
mut commands: Commands,
|
||||
active_heads: Single<(Entity, &ActiveHeads), With<Player>>,
|
||||
heads_db: Res<HeadsDatabase>,
|
||||
) {
|
||||
if res.is_changed() {
|
||||
let Some(state) = active_heads.1.current() else {
|
||||
return;
|
||||
};
|
||||
|
||||
let player = active_heads.0;
|
||||
|
||||
let head = heads_db.head_stats(state.head);
|
||||
|
||||
if !matches!(head.ability, HeadAbility::Medic) {
|
||||
return;
|
||||
}
|
||||
|
||||
if res.active {
|
||||
commands.trigger_targets(HealingStateChanged::Started, player);
|
||||
} else {
|
||||
commands.trigger_targets(HealingStateChanged::Stopped, player);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user