An experimental, status effects-as-entities system for Bevy.
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Added `TimerMergeMode`.

Not yet implemented.

+72 -16
+2 -1
bevy_status_effects/src/lib.rs
··· 11 11 use bevy_ecs::world::DeferredWorld; 12 12 use bevy_reflect::prelude::ReflectDefault; 13 13 14 - use crate::timer::{Delay, Lifetime}; 14 + use crate::timer::{Delay, Lifetime, TimerMergeMode}; 15 15 pub use bevy_app::Startup; 16 16 use bevy_reflect::{Reflect, reflect_trait}; 17 17 pub use bevy_status_effects_macros::StatusEffect; ··· 25 25 .register_type::<EffectedBy>() 26 26 .register_type::<Lifetime>() 27 27 .register_type::<Delay>() 28 + .register_type::<TimerMergeMode>() 28 29 .add_systems( 29 30 PreUpdate, 30 31 (timer::despawn_finished_lifetimes, timer::tick_delay).chain(),
+70 -15
bevy_status_effects/src/timer.rs
··· 4 4 use bevy_time::{Time, Timer, TimerMode}; 5 5 use std::time::Duration; 6 6 7 + pub trait EffectTimer: Sized { 8 + fn new(duration: Duration) -> Self; 9 + 10 + fn from_seconds(seconds: f32) -> Self { 11 + Self::new(Duration::from_secs_f32(seconds)) 12 + } 13 + 14 + fn with_mode(self, mode: TimerMergeMode) -> Self; 15 + } 16 + 7 17 /// Despawns the entity when the timer finishes. 8 18 #[derive(Component, Reflect, Eq, PartialEq, Debug, Clone)] 9 19 #[reflect(Component, PartialEq, Debug, Clone)] 10 - pub struct Lifetime(pub Timer); 20 + pub struct Lifetime { 21 + pub timer: Timer, 22 + pub mode: TimerMergeMode, 23 + } 24 + 25 + impl EffectTimer for Lifetime { 26 + fn new(duration: Duration) -> Self { 27 + Self { 28 + timer: Timer::new(duration, TimerMode::Once), 29 + ..Self::default() 30 + } 31 + } 11 32 12 - impl Lifetime { 13 - pub fn new(duration: Duration) -> Self { 14 - Self(Timer::new(duration, TimerMode::Once)) 33 + fn with_mode(mut self, mode: TimerMergeMode) -> Self { 34 + self.mode = mode; 35 + self 15 36 } 37 + } 16 38 17 - pub fn from_seconds(seconds: f32) -> Self { 18 - Self::new(Duration::from_secs_f32(seconds)) 39 + impl Default for Lifetime { 40 + fn default() -> Self { 41 + Self { 42 + timer: Timer::default(), 43 + mode: TimerMergeMode::Max, 44 + } 19 45 } 20 46 } 21 47 22 48 /// Repeating timer used for the delay between effect applications. 23 49 #[derive(Component, Reflect, Eq, PartialEq, Debug, Clone)] 24 50 #[reflect(Component, PartialEq, Debug, Clone)] 25 - pub struct Delay(pub Timer); 51 + pub struct Delay { 52 + pub timer: Timer, 53 + pub mode: TimerMergeMode, 54 + } 55 + 56 + impl EffectTimer for Delay { 57 + fn new(duration: Duration) -> Self { 58 + Self { 59 + timer: Timer::new(duration, TimerMode::Repeating), 60 + ..Self::default() 61 + } 62 + } 26 63 27 - impl Delay { 28 - pub fn new(duration: Duration) -> Self { 29 - Self(Timer::new(duration, TimerMode::Repeating)) 64 + fn with_mode(mut self, mode: TimerMergeMode) -> Self { 65 + self.mode = mode; 66 + self 30 67 } 68 + } 31 69 32 - pub fn from_seconds(seconds: f32) -> Self { 33 - Self::new(Duration::from_secs_f32(seconds)) 70 + impl Default for Delay { 71 + fn default() -> Self { 72 + Self { 73 + timer: Timer::default(), 74 + mode: TimerMergeMode::Fraction, 75 + } 34 76 } 35 77 } 36 78 79 + #[derive(Reflect, Eq, PartialEq, Debug, Copy, Clone)] 80 + #[reflect(PartialEq, Debug, Clone)] 81 + pub enum TimerMergeMode { 82 + /// The new effect's time will be used, ignoring the old one. 83 + Replace, 84 + /// The old effect's time will be used, ignoring the new one. 85 + Inherit, 86 + /// The new timer is used, but with the same fraction of the old timer's elapsed time. 87 + Fraction, 88 + /// The timer with the larger time remaining will be used. 89 + Max, 90 + } 91 + 37 92 pub(super) fn despawn_finished_lifetimes( 38 93 mut commands: Commands, 39 94 time: Res<Time>, 40 95 mut query: Query<(Entity, &mut Lifetime)>, 41 96 ) { 42 97 for (entity, mut lifetime) in &mut query { 43 - lifetime.0.tick(time.delta()); 98 + lifetime.timer.tick(time.delta()); 44 99 45 - if lifetime.0.finished() { 100 + if lifetime.timer.finished() { 46 101 commands.entity(entity).despawn(); 47 102 } 48 103 } ··· 50 105 51 106 pub(super) fn tick_delay(time: Res<Time>, mut query: Query<&mut Delay>) { 52 107 for mut delay in &mut query { 53 - delay.0.tick(time.delta()); 108 + delay.timer.tick(time.delta()); 54 109 } 55 110 }