beet_sim/stats/
stat.rs

1use crate::prelude::*;
2use bevy::prelude::*;
3use std::fmt;
4use std::ops::Range;
5
6
7/// Stats are continuous values that represent real world phenomena.
8/// For example they can be used to model health or frequency of events.
9/// We deliberately use floating point because it more accurately represents
10/// the continuous nature of the real world, and is required for utility ai.
11#[derive(
12	Component,
13	Reflect,
14	Debug,
15	Default,
16	Clone,
17	Copy,
18	PartialEq,
19	PartialOrd,
20	Deref,
21	DerefMut,
22)]
23pub struct StatValue(pub f32);
24impl Into<StatValue> for f32 {
25	fn into(self) -> StatValue { StatValue(self) }
26}
27impl From<StatValue> for f32 {
28	fn from(value: StatValue) -> f32 { value.0 }
29}
30
31impl fmt::Display for StatValue {
32	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
33		write!(f, "{:.2}", self.0)
34	}
35}
36
37impl StatValue {
38	pub fn new(value: f32) -> Self { Self(value) }
39
40	pub fn find_by_id(
41		entity: Entity,
42		children: Query<&Children>,
43		stats: Query<(&StatId, &StatValue)>,
44		id: StatId,
45	) -> Option<StatValue> {
46		let Some(children) = children.get(entity).ok() else {
47			return None;
48		};
49		for child in children.iter() {
50			if let Ok((stat_id, value)) = stats.get(child) {
51				if *stat_id == id {
52					return Some(*value);
53				}
54			}
55		}
56		None
57	}
58
59	pub fn range(range: Range<f32>) -> Range<StatValue> {
60		StatValue(range.start)..StatValue(range.end)
61	}
62
63
64	pub fn normalize(&self, range: Range<StatValue>) -> f32 {
65		(self.0 - *range.start) / (*range.end - *range.start)
66	}
67}
68
69
70pub fn stat_plugin(app: &mut App) {
71	app.register_type::<StatValue>()
72		.world_mut()
73		.register_component_hooks::<StatValue>()
74		.on_add(|mut world, cx| {
75			let map = world.resource::<StatMap>();
76			let stat_id = world
77				.get::<StatId>(cx.entity)
78				.expect("StatValue requires StatId");
79
80			let hexcode = map
81				.get(stat_id)
82				.expect("StatId must be in StatMap")
83				.emoji_hexcode
84				.clone();
85
86			// world
87			// 	.commands()
88			// 	.entity(entity)
89			// .insert(Emoji::bundle(&hexcode));
90		});
91}