1use crate::prelude::*;
2use bevy::prelude::*;
3use std::fmt;
4use std::ops::Range;
5
6
7#[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 });
91}