Game stats that reset every frame, inspired by immediate mode GUI.
gamedev bevy stats
0
fork

Configure Feed

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

Moved all tests into tests directory.

+541 -555
+1 -73
immediate_stats/src/bevy.rs
··· 1 - #[cfg(feature = "bevy_butler")] 2 - pub mod butler; 3 - 4 1 use crate::StatContainer; 2 + use crate::modifier::Modifier; 5 3 use crate::stat::Stat; 6 - use crate::stat::modifier::Modifier; 7 4 use bevy_app::{App, Plugin}; 8 5 use bevy_ecs::component::Mutable; 9 6 use bevy_ecs::prelude::ReflectComponent; ··· 40 37 res.reset_modifiers(); 41 38 } 42 39 } 43 - 44 - #[cfg(test)] 45 - mod tests { 46 - use super::*; 47 - use crate::stat::Stat; 48 - use bevy_ecs::prelude::World; 49 - use immediate_stats_macros::StatContainer; 50 - 51 - #[derive(Component, Resource, StatContainer, PartialEq, Debug, Clone)] 52 - struct Health(Stat); 53 - 54 - #[test] 55 - fn reset_component() { 56 - let mut world = World::new(); 57 - let system = world.register_system(reset_component_modifiers::<Health>); 58 - 59 - let entity = world 60 - .spawn(Health(Stat { 61 - base: 100, 62 - bonus: 50, 63 - multiplier: 2.0, 64 - })) 65 - .id(); 66 - 67 - world.run_system(system).unwrap(); 68 - 69 - assert_eq!( 70 - world.get::<Health>(entity), 71 - Some(Health(Stat::new(100))).as_ref() 72 - ); 73 - } 74 - 75 - #[test] 76 - fn pause_component() { 77 - let mut world = World::new(); 78 - let system = world.register_system(reset_component_modifiers::<Health>); 79 - 80 - let health = Health(Stat { 81 - base: 100, 82 - bonus: 50, 83 - multiplier: 2.0, 84 - }); 85 - 86 - let entity = world.spawn((health.clone(), PauseStatReset)).id(); 87 - 88 - world.run_system(system).unwrap(); 89 - 90 - assert_eq!(world.get::<Health>(entity), Some(health).as_ref()); 91 - } 92 - 93 - #[test] 94 - fn reset_resource() { 95 - let mut world = World::new(); 96 - let system = world.register_system(reset_resource_modifiers::<Health>); 97 - 98 - world.insert_resource(Health(Stat { 99 - base: 100, 100 - bonus: 50, 101 - multiplier: 2.0, 102 - })); 103 - 104 - world.run_system(system).unwrap(); 105 - 106 - assert_eq!( 107 - world.get_resource::<Health>(), 108 - Some(Health(Stat::new(100))).as_ref() 109 - ); 110 - } 111 - }
-60
immediate_stats/src/bevy/butler.rs
··· 1 - #[cfg(test)] 2 - mod tests { 3 - use crate as immediate_stats; 4 - use crate::StatContainer; 5 - use crate::stat::Stat; 6 - use bevy_app::App; 7 - use bevy_butler::*; 8 - use bevy_ecs::prelude::*; 9 - 10 - #[butler_plugin] 11 - struct MyPlugin; 12 - 13 - #[derive(Resource, Component, StatContainer, Default, PartialEq, Debug)] 14 - #[add_component(plugin = MyPlugin)] 15 - #[add_resource(plugin = MyPlugin)] 16 - struct Health(Stat); 17 - 18 - #[test] 19 - fn reset_component_auto() { 20 - let mut app = App::new(); 21 - 22 - app.add_plugins(MyPlugin); 23 - 24 - let entity = app 25 - .world_mut() 26 - .spawn(Health(Stat { 27 - base: 100, 28 - bonus: 50, 29 - multiplier: 2.0, 30 - })) 31 - .id(); 32 - 33 - app.update(); 34 - 35 - assert_eq!( 36 - app.world().get::<Health>(entity), 37 - Some(Health(Stat::new(100))).as_ref() 38 - ); 39 - } 40 - 41 - #[test] 42 - fn reset_resource_auto() { 43 - let mut app = App::new(); 44 - 45 - app.add_plugins(MyPlugin); 46 - 47 - app.insert_resource(Health(Stat { 48 - base: 100, 49 - bonus: 50, 50 - multiplier: 2.0, 51 - })); 52 - 53 - app.update(); 54 - 55 - assert_eq!( 56 - app.world().get_resource::<Health>(), 57 - Some(Health(Stat::new(100))).as_ref() 58 - ); 59 - } 60 - }
+2 -167
immediate_stats/src/lib.rs
··· 2 2 3 3 #[cfg(feature = "bevy")] 4 4 pub mod bevy; 5 + pub mod modifier; 5 6 pub mod stat; 6 7 7 8 // Todo Move into internal module called `__internal` like Bevy Butler. ··· 11 12 12 13 #[cfg(feature = "bevy")] 13 14 pub use bevy::*; 15 + pub use modifier::*; 14 16 pub use stat::*; 15 17 16 18 /// Types that contain stats that need to be reset. ··· 23 25 /// Resets all stat bonuses to zero, and stat multipliers to one. 24 26 fn reset_modifiers(&mut self); 25 27 } 26 - 27 - #[cfg(test)] 28 - mod tests { 29 - use super::*; 30 - use crate::stat::Stat; 31 - use immediate_stats_macros::StatContainer; 32 - 33 - #[derive(StatContainer, PartialEq, Debug)] 34 - struct Movement { 35 - speed: Stat, 36 - other: bool, 37 - } 38 - 39 - #[test] 40 - fn reset() { 41 - for base in 0..10 { 42 - let mut movement = Movement { 43 - speed: Stat { 44 - base, 45 - bonus: 3, 46 - multiplier: 1.5, 47 - }, 48 - other: true, 49 - }; 50 - 51 - movement.reset_modifiers(); 52 - 53 - assert_eq!( 54 - movement, 55 - Movement { 56 - speed: Stat::new(base), 57 - other: true 58 - } 59 - ); 60 - } 61 - } 62 - 63 - #[derive(StatContainer, PartialEq, Debug)] 64 - struct MaxHealth(Stat, bool); 65 - 66 - #[test] 67 - fn reset_tuple_struct() { 68 - for base in 0..10 { 69 - let mut max_health = MaxHealth( 70 - Stat { 71 - base, 72 - bonus: 3, 73 - multiplier: 1.5, 74 - }, 75 - true, 76 - ); 77 - 78 - max_health.reset_modifiers(); 79 - 80 - assert_eq!(max_health.0, Stat::new(base)); 81 - } 82 - } 83 - 84 - #[derive(StatContainer, PartialEq, Debug)] 85 - struct Health { 86 - #[stat] 87 - max: MaxHealth, 88 - current: i32, 89 - } 90 - 91 - #[test] 92 - fn reset_with_attribute() { 93 - for base in 0..10 { 94 - let mut health = Health { 95 - max: MaxHealth( 96 - Stat { 97 - base, 98 - bonus: 3, 99 - multiplier: 1.5, 100 - }, 101 - true, 102 - ), 103 - current: base, 104 - }; 105 - 106 - health.reset_modifiers(); 107 - 108 - assert_eq!(health.max.0, Stat::new(base)); 109 - } 110 - } 111 - 112 - #[derive(StatContainer, PartialEq, Debug)] 113 - struct PartialReset { 114 - #[stat_ignore] 115 - ignored: Stat, 116 - reset: Stat, 117 - } 118 - 119 - #[test] 120 - fn reset_ignored() { 121 - for base in 0..10 { 122 - let stat = Stat { 123 - base, 124 - bonus: 3, 125 - multiplier: 1.5, 126 - }; 127 - 128 - let mut partial = PartialReset { 129 - ignored: stat, 130 - reset: stat, 131 - }; 132 - 133 - partial.reset_modifiers(); 134 - 135 - assert_eq!(partial.ignored, stat); 136 - assert_eq!(partial.reset, Stat::new(base)); 137 - } 138 - } 139 - 140 - #[derive(StatContainer, PartialEq, Debug)] 141 - enum EnumStat { 142 - Named { 143 - stat: Stat, 144 - other: u8, 145 - }, 146 - Unnamed(Stat, u8), 147 - #[expect(dead_code)] 148 - Other, 149 - } 150 - 151 - #[test] 152 - fn reset_enum_named() { 153 - for base in 0..10 { 154 - let mut stat = EnumStat::Named { 155 - stat: Stat { 156 - base, 157 - bonus: 3, 158 - multiplier: 1.5, 159 - }, 160 - other: 0, 161 - }; 162 - 163 - stat.reset_modifiers(); 164 - 165 - assert_eq!( 166 - stat, 167 - EnumStat::Named { 168 - stat: Stat::new(base), 169 - other: 0, 170 - } 171 - ); 172 - } 173 - } 174 - 175 - #[test] 176 - fn reset_enum_unnamed() { 177 - for base in 0..10 { 178 - let mut stat = EnumStat::Unnamed( 179 - Stat { 180 - base, 181 - bonus: 3, 182 - multiplier: 1.5, 183 - }, 184 - 0, 185 - ); 186 - 187 - stat.reset_modifiers(); 188 - 189 - assert_eq!(stat, EnumStat::Unnamed(Stat::new(base), 0)); 190 - } 191 - } 192 - }
+68
immediate_stats/src/modifier.rs
··· 1 + use std::ops::{AddAssign, DivAssign, MulAssign, SubAssign}; 2 + 3 + /// Modifier values that can be applied to a [`super::Stat`]. 4 + #[derive(PartialEq, Debug, Copy, Clone)] 5 + #[cfg_attr( 6 + feature = "bevy", 7 + derive(bevy_reflect::Reflect), 8 + reflect(PartialEq, Debug, Clone) 9 + )] 10 + pub struct Modifier { 11 + /// Added to `base` of a [`super::Stat`] during calculation. 12 + pub bonus: i32, 13 + /// Multiplies the `base` of a [`super::Stat`] during calculation. 14 + pub multiplier: f32, 15 + } 16 + 17 + impl Modifier { 18 + pub fn new(bonus: i32, multiplier: f32) -> Self { 19 + Self { bonus, multiplier } 20 + } 21 + 22 + pub fn from_bonus(bonus: i32) -> Self { 23 + Self { 24 + bonus, 25 + ..Self::default() 26 + } 27 + } 28 + 29 + pub fn from_multiplier(multiplier: f32) -> Self { 30 + Self { 31 + multiplier, 32 + ..Self::default() 33 + } 34 + } 35 + } 36 + 37 + impl Default for Modifier { 38 + fn default() -> Self { 39 + Self { 40 + bonus: 0, 41 + multiplier: 1.0, 42 + } 43 + } 44 + } 45 + 46 + impl AddAssign<i32> for Modifier { 47 + fn add_assign(&mut self, rhs: i32) { 48 + self.bonus += rhs; 49 + } 50 + } 51 + 52 + impl SubAssign<i32> for Modifier { 53 + fn sub_assign(&mut self, rhs: i32) { 54 + self.bonus -= rhs; 55 + } 56 + } 57 + 58 + impl MulAssign<f32> for Modifier { 59 + fn mul_assign(&mut self, rhs: f32) { 60 + self.multiplier *= rhs; 61 + } 62 + } 63 + 64 + impl DivAssign<f32> for Modifier { 65 + fn div_assign(&mut self, rhs: f32) { 66 + self.multiplier /= rhs; 67 + } 68 + }
+1 -130
immediate_stats/src/stat.rs
··· 1 - pub mod modifier; 2 - 3 1 use crate::StatContainer; 4 - use crate::stat::modifier::Modifier; 2 + use crate::modifier::Modifier; 5 3 use std::ops::{AddAssign, DivAssign, MulAssign, SubAssign}; 6 4 7 5 /// A stat that [resets] to a base value every iteration. ··· 116 114 self.multiplier /= rhs; 117 115 } 118 116 } 119 - 120 - #[cfg(test)] 121 - mod tests { 122 - use super::*; 123 - 124 - #[test] 125 - fn reset() { 126 - for i in 0..10 { 127 - let mut stat = Stat { 128 - base: i, 129 - bonus: 4, 130 - multiplier: 1.5, 131 - }; 132 - stat.reset_modifiers(); 133 - 134 - assert_eq!(stat, Stat::new(i)); 135 - } 136 - } 137 - 138 - #[test] 139 - fn add() { 140 - let mut stat = Stat::new(10); 141 - stat += 5; 142 - assert_eq!( 143 - stat, 144 - Stat { 145 - base: 10, 146 - bonus: 5, 147 - multiplier: 1.0, 148 - } 149 - ); 150 - } 151 - 152 - #[test] 153 - fn subtract() { 154 - let mut stat = Stat::new(10); 155 - stat -= 5; 156 - assert_eq!( 157 - stat, 158 - Stat { 159 - base: 10, 160 - bonus: -5, 161 - multiplier: 1.0, 162 - } 163 - ); 164 - } 165 - 166 - #[test] 167 - fn multiply() { 168 - let mut stat = Stat::new(10); 169 - stat *= 2.0; 170 - assert_eq!( 171 - stat, 172 - Stat { 173 - base: 10, 174 - bonus: 0, 175 - multiplier: 2.0, 176 - } 177 - ); 178 - } 179 - 180 - #[test] 181 - fn divide() { 182 - let mut stat = Stat::new(10); 183 - stat /= 2.0; 184 - assert_eq!( 185 - stat, 186 - Stat { 187 - base: 10, 188 - bonus: 0, 189 - multiplier: 0.5, 190 - } 191 - ); 192 - } 193 - 194 - #[test] 195 - fn default_total() { 196 - for i in 0..10 { 197 - assert_eq!(Stat::new(i).total(), i); 198 - } 199 - } 200 - 201 - #[test] 202 - fn total() { 203 - assert_eq!( 204 - Stat { 205 - base: 10, 206 - bonus: 4, 207 - multiplier: 1.5, 208 - } 209 - .total(), 210 - 21 211 - ) 212 - } 213 - 214 - #[test] 215 - fn total_no_bonus() { 216 - assert_eq!(Stat::new(20).with_multiplier(0.5).total(), 10); 217 - } 218 - 219 - #[test] 220 - fn total_no_multiplier() { 221 - assert_eq!(Stat::new(2).with_bonus(1).total(), 3); 222 - } 223 - 224 - #[test] 225 - fn total_with_modifier() { 226 - assert_eq!(Stat::new(5).with_modifier(Modifier::new(1, 0.5)).total(), 3); 227 - } 228 - 229 - #[test] 230 - fn apply() { 231 - let mut stat = Stat::new(10); 232 - 233 - stat.apply(Modifier::new(2, 2.0)); 234 - stat.apply(Modifier::new(3, 4.0)); 235 - 236 - assert_eq!( 237 - stat, 238 - Stat { 239 - base: 10, 240 - bonus: 5, 241 - multiplier: 8.0, 242 - } 243 - ) 244 - } 245 - }
-125
immediate_stats/src/stat/modifier.rs
··· 1 - use std::ops::{AddAssign, DivAssign, MulAssign, SubAssign}; 2 - 3 - /// Modifier values that can be applied to a [`super::Stat`]. 4 - #[derive(PartialEq, Debug, Copy, Clone)] 5 - #[cfg_attr( 6 - feature = "bevy", 7 - derive(bevy_reflect::Reflect), 8 - reflect(PartialEq, Debug, Clone) 9 - )] 10 - pub struct Modifier { 11 - /// Added to `base` of a [`super::Stat`] during calculation. 12 - pub bonus: i32, 13 - /// Multiplies the `base` of a [`super::Stat`] during calculation. 14 - pub multiplier: f32, 15 - } 16 - 17 - impl Modifier { 18 - pub fn new(bonus: i32, multiplier: f32) -> Self { 19 - Self { bonus, multiplier } 20 - } 21 - 22 - pub fn from_bonus(bonus: i32) -> Self { 23 - Self { 24 - bonus, 25 - ..Self::default() 26 - } 27 - } 28 - 29 - pub fn from_multiplier(multiplier: f32) -> Self { 30 - Self { 31 - multiplier, 32 - ..Self::default() 33 - } 34 - } 35 - } 36 - 37 - impl Default for Modifier { 38 - fn default() -> Self { 39 - Self { 40 - bonus: 0, 41 - multiplier: 1.0, 42 - } 43 - } 44 - } 45 - 46 - impl AddAssign<i32> for Modifier { 47 - fn add_assign(&mut self, rhs: i32) { 48 - self.bonus += rhs; 49 - } 50 - } 51 - 52 - impl SubAssign<i32> for Modifier { 53 - fn sub_assign(&mut self, rhs: i32) { 54 - self.bonus -= rhs; 55 - } 56 - } 57 - 58 - impl MulAssign<f32> for Modifier { 59 - fn mul_assign(&mut self, rhs: f32) { 60 - self.multiplier *= rhs; 61 - } 62 - } 63 - 64 - impl DivAssign<f32> for Modifier { 65 - fn div_assign(&mut self, rhs: f32) { 66 - self.multiplier /= rhs; 67 - } 68 - } 69 - 70 - #[cfg(test)] 71 - mod tests { 72 - use super::*; 73 - 74 - #[test] 75 - fn add() { 76 - let mut modifier = Modifier::default(); 77 - modifier += 5; 78 - assert_eq!( 79 - modifier, 80 - Modifier { 81 - bonus: 5, 82 - multiplier: 1.0, 83 - } 84 - ); 85 - } 86 - 87 - #[test] 88 - fn subtract() { 89 - let mut modifier = Modifier::default(); 90 - modifier -= 5; 91 - assert_eq!( 92 - modifier, 93 - Modifier { 94 - bonus: -5, 95 - multiplier: 1.0, 96 - } 97 - ); 98 - } 99 - 100 - #[test] 101 - fn multiply() { 102 - let mut modifier = Modifier::default(); 103 - modifier *= 2.0; 104 - assert_eq!( 105 - modifier, 106 - Modifier { 107 - bonus: 0, 108 - multiplier: 2.0, 109 - } 110 - ); 111 - } 112 - 113 - #[test] 114 - fn divide() { 115 - let mut modifier = Modifier::default(); 116 - modifier /= 2.0; 117 - assert_eq!( 118 - modifier, 119 - Modifier { 120 - bonus: 0, 121 - multiplier: 0.5, 122 - } 123 - ); 124 - } 125 - }
+66
immediate_stats/tests/bevy.rs
··· 1 + #![cfg(feature = "bevy")] 2 + //! Tests the reset systems and `PauseStatReset`. 3 + 4 + use bevy_ecs::prelude::*; 5 + use immediate_stats::*; 6 + 7 + #[derive(Component, Resource, StatContainer, PartialEq, Debug, Clone)] 8 + struct Health(Stat); 9 + 10 + #[test] 11 + fn reset_component() { 12 + let mut world = World::new(); 13 + let system = world.register_system(reset_component_modifiers::<Health>); 14 + 15 + let entity = world 16 + .spawn(Health(Stat { 17 + base: 100, 18 + bonus: 50, 19 + multiplier: 2.0, 20 + })) 21 + .id(); 22 + 23 + world.run_system(system).unwrap(); 24 + 25 + assert_eq!( 26 + world.get::<Health>(entity), 27 + Some(Health(Stat::new(100))).as_ref() 28 + ); 29 + } 30 + 31 + #[test] 32 + fn pause_component() { 33 + let mut world = World::new(); 34 + let system = world.register_system(reset_component_modifiers::<Health>); 35 + 36 + let health = Health(Stat { 37 + base: 100, 38 + bonus: 50, 39 + multiplier: 2.0, 40 + }); 41 + 42 + let entity = world.spawn((health.clone(), PauseStatReset)).id(); 43 + 44 + world.run_system(system).unwrap(); 45 + 46 + assert_eq!(world.get::<Health>(entity), Some(health).as_ref()); 47 + } 48 + 49 + #[test] 50 + fn reset_resource() { 51 + let mut world = World::new(); 52 + let system = world.register_system(reset_resource_modifiers::<Health>); 53 + 54 + world.insert_resource(Health(Stat { 55 + base: 100, 56 + bonus: 50, 57 + multiplier: 2.0, 58 + })); 59 + 60 + world.run_system(system).unwrap(); 61 + 62 + assert_eq!( 63 + world.get_resource::<Health>(), 64 + Some(Health(Stat::new(100))).as_ref() 65 + ); 66 + }
+60
immediate_stats/tests/bevy_butler.rs
··· 1 + #![cfg(feature = "bevy_butler")] 2 + //! Tests the `add_component` attribute for automatic system registration. 3 + 4 + use crate::StatContainer; 5 + use crate::stat::Stat; 6 + use bevy_app::App; 7 + use bevy_butler::*; 8 + use bevy_ecs::prelude::*; 9 + use immediate_stats::*; 10 + 11 + #[butler_plugin] 12 + struct MyPlugin; 13 + 14 + #[derive(Resource, Component, StatContainer, Default, PartialEq, Debug)] 15 + #[add_component(plugin = MyPlugin)] 16 + #[add_resource(plugin = MyPlugin)] 17 + struct Health(Stat); 18 + 19 + #[test] 20 + fn reset_component_auto() { 21 + let mut app = App::new(); 22 + 23 + app.add_plugins(MyPlugin); 24 + 25 + let entity = app 26 + .world_mut() 27 + .spawn(Health(Stat { 28 + base: 100, 29 + bonus: 50, 30 + multiplier: 2.0, 31 + })) 32 + .id(); 33 + 34 + app.update(); 35 + 36 + assert_eq!( 37 + app.world().get::<Health>(entity), 38 + Some(Health(Stat::new(100))).as_ref() 39 + ); 40 + } 41 + 42 + #[test] 43 + fn reset_resource_auto() { 44 + let mut app = App::new(); 45 + 46 + app.add_plugins(MyPlugin); 47 + 48 + app.insert_resource(Health(Stat { 49 + base: 100, 50 + bonus: 50, 51 + multiplier: 2.0, 52 + })); 53 + 54 + app.update(); 55 + 56 + assert_eq!( 57 + app.world().get_resource::<Health>(), 58 + Some(Health(Stat::new(100))).as_ref() 59 + ); 60 + }
+163
immediate_stats/tests/derive.rs
··· 1 + //! Tests the basic `StatContainer` derive with no extra features. 2 + 3 + use immediate_stats::*; 4 + 5 + #[derive(StatContainer, PartialEq, Debug)] 6 + struct Movement { 7 + speed: Stat, 8 + other: bool, 9 + } 10 + 11 + #[test] 12 + fn reset() { 13 + for base in 0..10 { 14 + let mut movement = Movement { 15 + speed: Stat { 16 + base, 17 + bonus: 3, 18 + multiplier: 1.5, 19 + }, 20 + other: true, 21 + }; 22 + 23 + movement.reset_modifiers(); 24 + 25 + assert_eq!( 26 + movement, 27 + Movement { 28 + speed: Stat::new(base), 29 + other: true 30 + } 31 + ); 32 + } 33 + } 34 + 35 + #[derive(StatContainer, PartialEq, Debug)] 36 + struct MaxHealth(Stat, bool); 37 + 38 + #[test] 39 + fn reset_tuple_struct() { 40 + for base in 0..10 { 41 + let mut max_health = MaxHealth( 42 + Stat { 43 + base, 44 + bonus: 3, 45 + multiplier: 1.5, 46 + }, 47 + true, 48 + ); 49 + 50 + max_health.reset_modifiers(); 51 + 52 + assert_eq!(max_health.0, Stat::new(base)); 53 + } 54 + } 55 + 56 + #[derive(StatContainer, PartialEq, Debug)] 57 + struct Health { 58 + #[stat] 59 + max: MaxHealth, 60 + current: i32, 61 + } 62 + 63 + #[test] 64 + fn reset_with_attribute() { 65 + for base in 0..10 { 66 + let mut health = Health { 67 + max: MaxHealth( 68 + Stat { 69 + base, 70 + bonus: 3, 71 + multiplier: 1.5, 72 + }, 73 + true, 74 + ), 75 + current: base, 76 + }; 77 + 78 + health.reset_modifiers(); 79 + 80 + assert_eq!(health.max.0, Stat::new(base)); 81 + } 82 + } 83 + 84 + #[derive(StatContainer, PartialEq, Debug)] 85 + struct PartialReset { 86 + #[stat_ignore] 87 + ignored: Stat, 88 + reset: Stat, 89 + } 90 + 91 + #[test] 92 + fn reset_ignored() { 93 + for base in 0..10 { 94 + let stat = Stat { 95 + base, 96 + bonus: 3, 97 + multiplier: 1.5, 98 + }; 99 + 100 + let mut partial = PartialReset { 101 + ignored: stat, 102 + reset: stat, 103 + }; 104 + 105 + partial.reset_modifiers(); 106 + 107 + assert_eq!(partial.ignored, stat); 108 + assert_eq!(partial.reset, Stat::new(base)); 109 + } 110 + } 111 + 112 + #[derive(StatContainer, PartialEq, Debug)] 113 + enum EnumStat { 114 + Named { 115 + stat: Stat, 116 + other: u8, 117 + }, 118 + Unnamed(Stat, u8), 119 + #[expect(dead_code)] 120 + Other, 121 + } 122 + 123 + #[test] 124 + fn reset_enum_named() { 125 + for base in 0..10 { 126 + let mut stat = EnumStat::Named { 127 + stat: Stat { 128 + base, 129 + bonus: 3, 130 + multiplier: 1.5, 131 + }, 132 + other: 0, 133 + }; 134 + 135 + stat.reset_modifiers(); 136 + 137 + assert_eq!( 138 + stat, 139 + EnumStat::Named { 140 + stat: Stat::new(base), 141 + other: 0, 142 + } 143 + ); 144 + } 145 + } 146 + 147 + #[test] 148 + fn reset_enum_unnamed() { 149 + for base in 0..10 { 150 + let mut stat = EnumStat::Unnamed( 151 + Stat { 152 + base, 153 + bonus: 3, 154 + multiplier: 1.5, 155 + }, 156 + 0, 157 + ); 158 + 159 + stat.reset_modifiers(); 160 + 161 + assert_eq!(stat, EnumStat::Unnamed(Stat::new(base), 0)); 162 + } 163 + }
+55
immediate_stats/tests/modifier.rs
··· 1 + //! Tests the various methods of `Modifier`. 2 + 3 + use immediate_stats::*; 4 + 5 + #[test] 6 + fn add() { 7 + let mut modifier = Modifier::default(); 8 + modifier += 5; 9 + assert_eq!( 10 + modifier, 11 + Modifier { 12 + bonus: 5, 13 + multiplier: 1.0, 14 + } 15 + ); 16 + } 17 + 18 + #[test] 19 + fn subtract() { 20 + let mut modifier = Modifier::default(); 21 + modifier -= 5; 22 + assert_eq!( 23 + modifier, 24 + Modifier { 25 + bonus: -5, 26 + multiplier: 1.0, 27 + } 28 + ); 29 + } 30 + 31 + #[test] 32 + fn multiply() { 33 + let mut modifier = Modifier::default(); 34 + modifier *= 2.0; 35 + assert_eq!( 36 + modifier, 37 + Modifier { 38 + bonus: 0, 39 + multiplier: 2.0, 40 + } 41 + ); 42 + } 43 + 44 + #[test] 45 + fn divide() { 46 + let mut modifier = Modifier::default(); 47 + modifier /= 2.0; 48 + assert_eq!( 49 + modifier, 50 + Modifier { 51 + bonus: 0, 52 + multiplier: 0.5, 53 + } 54 + ); 55 + }
+125
immediate_stats/tests/stat.rs
··· 1 + //! Tests the various methods of `Stat`. 2 + 3 + use immediate_stats::*; 4 + 5 + #[test] 6 + fn reset() { 7 + for i in 0..10 { 8 + let mut stat = Stat { 9 + base: i, 10 + bonus: 4, 11 + multiplier: 1.5, 12 + }; 13 + stat.reset_modifiers(); 14 + 15 + assert_eq!(stat, Stat::new(i)); 16 + } 17 + } 18 + 19 + #[test] 20 + fn add() { 21 + let mut stat = Stat::new(10); 22 + stat += 5; 23 + assert_eq!( 24 + stat, 25 + Stat { 26 + base: 10, 27 + bonus: 5, 28 + multiplier: 1.0, 29 + } 30 + ); 31 + } 32 + 33 + #[test] 34 + fn subtract() { 35 + let mut stat = Stat::new(10); 36 + stat -= 5; 37 + assert_eq!( 38 + stat, 39 + Stat { 40 + base: 10, 41 + bonus: -5, 42 + multiplier: 1.0, 43 + } 44 + ); 45 + } 46 + 47 + #[test] 48 + fn multiply() { 49 + let mut stat = Stat::new(10); 50 + stat *= 2.0; 51 + assert_eq!( 52 + stat, 53 + Stat { 54 + base: 10, 55 + bonus: 0, 56 + multiplier: 2.0, 57 + } 58 + ); 59 + } 60 + 61 + #[test] 62 + fn divide() { 63 + let mut stat = Stat::new(10); 64 + stat /= 2.0; 65 + assert_eq!( 66 + stat, 67 + Stat { 68 + base: 10, 69 + bonus: 0, 70 + multiplier: 0.5, 71 + } 72 + ); 73 + } 74 + 75 + #[test] 76 + fn default_total() { 77 + for i in 0..10 { 78 + assert_eq!(Stat::new(i).total(), i); 79 + } 80 + } 81 + 82 + #[test] 83 + fn total() { 84 + assert_eq!( 85 + Stat { 86 + base: 10, 87 + bonus: 4, 88 + multiplier: 1.5, 89 + } 90 + .total(), 91 + 21 92 + ) 93 + } 94 + 95 + #[test] 96 + fn total_no_bonus() { 97 + assert_eq!(Stat::new(20).with_multiplier(0.5).total(), 10); 98 + } 99 + 100 + #[test] 101 + fn total_no_multiplier() { 102 + assert_eq!(Stat::new(2).with_bonus(1).total(), 3); 103 + } 104 + 105 + #[test] 106 + fn total_with_modifier() { 107 + assert_eq!(Stat::new(5).with_modifier(Modifier::new(1, 0.5)).total(), 3); 108 + } 109 + 110 + #[test] 111 + fn apply() { 112 + let mut stat = Stat::new(10); 113 + 114 + stat.apply(Modifier::new(2, 2.0)); 115 + stat.apply(Modifier::new(3, 4.0)); 116 + 117 + assert_eq!( 118 + stat, 119 + Stat { 120 + base: 10, 121 + bonus: 5, 122 + multiplier: 8.0, 123 + } 124 + ) 125 + }