use crate::{
components::{PowerBar, PowerLevel, PowerRegeneration},
events::{
ApplyLimitEvent, KnockedOutEvent, LevelUpEvent, LiftLimitEvent, PowerChangeEvent,
ReviveEvent, SpendPowerEvent,
},
limits::{PowerLimit, PowerLimits},
};
use bevy::prelude::*;
pub fn handle_spend_power(
mut events: MessageReader<SpendPowerEvent>,
mut query: Query<(&mut PowerBar, &mut PowerRegeneration, Option<&PowerLimits>)>,
) {
for event in events.read() {
if let Ok((mut power_bar, mut regen, limits)) = query.get_mut(event.entity) {
if power_bar.spend(event.amount) {
regen.reset();
if let Some(limits) = limits {
if limits.any_resets_cooldown() {
regen.reset();
}
}
}
}
}
}
pub fn handle_power_change(
mut events: MessageReader<PowerChangeEvent>,
mut query: Query<&mut PowerBar>,
) {
for event in events.read() {
if let Ok(mut power_bar) = query.get_mut(event.entity) {
if event.amount > 0.0 {
power_bar.add(event.amount);
} else {
power_bar.spend(event.amount.abs());
}
}
}
}
pub fn regenerate_power(
time: Res<Time>,
mut query: Query<(&mut PowerBar, &mut PowerRegeneration)>,
) {
let delta = time.delta_secs();
for (mut power_bar, mut regen) in query.iter_mut() {
if !power_bar.is_knocked_out {
regen.update(delta);
let regen_amount = regen.get_regen_amount(delta);
if regen_amount > 0.0 {
power_bar.add(regen_amount);
}
}
}
}
pub fn handle_apply_limit(
mut events: MessageReader<ApplyLimitEvent>,
mut query: Query<(&mut PowerBar, &mut PowerRegeneration, &mut PowerLimits)>,
mut knocked_out_events: MessageWriter<KnockedOutEvent>,
) {
for event in events.read() {
if let Ok((mut power_bar, mut regen, mut limits)) = query.get_mut(event.entity) {
let new_limit = PowerLimit::new(
event.id,
event.limit_type,
event.color,
event.duration,
event.resets_cooldown,
);
limits.add_limit(new_limit, power_bar.base_max);
let total_reduction = limits.total_reduction();
power_bar.max = (power_bar.base_max - total_reduction).max(0.0);
if power_bar.current > power_bar.max {
power_bar.current = power_bar.max;
}
if power_bar.max <= 0.0 || power_bar.current <= 0.0 {
power_bar.is_knocked_out = true;
knocked_out_events.write(KnockedOutEvent {
entity: event.entity,
});
}
if event.resets_cooldown {
regen.reset();
}
}
}
}
pub fn handle_lift_limit(
mut events: MessageReader<LiftLimitEvent>,
mut query: Query<(&mut PowerBar, &mut PowerLimits)>,
) {
for event in events.read() {
if let Ok((mut power_bar, mut limits)) = query.get_mut(event.entity) {
if limits.remove_limit(event.id) {
let total_reduction = limits.total_reduction();
power_bar.max = (power_bar.base_max - total_reduction).max(0.0);
if power_bar.is_knocked_out && power_bar.max > 0.0 {
power_bar.is_knocked_out = false;
power_bar.current = power_bar.current.min(power_bar.max);
}
}
}
}
}
pub fn update_limit_timers(
time: Res<Time>,
mut query: Query<(Entity, &mut PowerBar, &mut PowerLimits)>,
) {
let delta = time.delta_secs();
for (_entity, mut power_bar, mut limits) in query.iter_mut() {
let removed_ids = limits.update_timers(delta);
if !removed_ids.is_empty() {
let total_reduction = limits.total_reduction();
power_bar.max = (power_bar.base_max - total_reduction).max(0.0);
if power_bar.is_knocked_out && power_bar.max > 0.0 {
power_bar.is_knocked_out = false;
power_bar.current = power_bar.current.min(power_bar.max);
}
}
}
}
pub fn handle_revive(mut events: MessageReader<ReviveEvent>, mut query: Query<&mut PowerBar>) {
for event in events.read() {
if let Ok(mut power_bar) = query.get_mut(event.entity) {
power_bar.revive(event.power_amount);
}
}
}
pub fn handle_level_up(
mut query: Query<(&mut PowerBar, &mut PowerLevel)>,
mut level_up_events: MessageWriter<LevelUpEvent>,
) {
for (mut power_bar, mut power_level) in query.iter_mut() {
if power_level.experience >= power_level.experience_to_next {
let power_bonus = power_level.level_up();
power_bar.base_max += power_bonus;
power_bar.max += power_bonus;
level_up_events.write(LevelUpEvent {
entity: Entity::PLACEHOLDER,
new_level: power_level.level,
power_bonus,
});
}
}
}
pub fn detect_knockout(
mut query: Query<(Entity, &mut PowerBar), Changed<PowerBar>>,
mut knocked_out_events: MessageWriter<KnockedOutEvent>,
) {
for (entity, mut power_bar) in query.iter_mut() {
if !power_bar.is_knocked_out && (power_bar.current <= 0.0 || power_bar.max <= 0.0) {
power_bar.is_knocked_out = true;
power_bar.current = 0.0;
knocked_out_events.write(KnockedOutEvent { entity });
}
}
}
#[derive(SystemSet, Debug, Clone, PartialEq, Eq, Hash)]
pub enum PowerSystemSet {
Input,
Update,
UI,
}