game_features/
effector.rs

1use crate::*;
2use std::collections::HashMap;
3use std::hash::Hash;
4
5/// Holds the definitions of the stat effectors.
6#[derive(Debug, Clone, Serialize, Deserialize, new)]
7pub struct EffectorDefinitions<K, E: Hash + Eq> {
8    /// The definitions.
9    pub defs: HashMap<E, EffectorDefinition<K, E>>,
10}
11
12impl<K, E: Hash + Eq> Default for EffectorDefinitions<K, E> {
13    fn default() -> Self {
14        Self {
15            defs: HashMap::default(),
16        }
17    }
18}
19
20impl<K: Hash + Eq + Clone, E: Hash + Eq + Clone> From<Vec<EffectorDefinition<K, E>>>
21    for EffectorDefinitions<K, E>
22{
23    fn from(t: Vec<EffectorDefinition<K, E>>) -> Self {
24        let defs = t
25            .into_iter()
26            .map(|s| (s.key.clone(), s))
27            .collect::<HashMap<_, _>>();
28        Self::new(defs)
29    }
30}
31
32/// A collection of currently active effectors.
33#[derive(Debug, Clone, Serialize, Deserialize, new)]
34pub struct EffectorSet<E> {
35    /// The active effectors.
36    pub effectors: Vec<EffectorInstance<E>>,
37}
38
39impl<E> Default for EffectorSet<E> {
40    fn default() -> Self {
41        Self { effectors: vec![] }
42    }
43}
44
45impl<E: Hash + Eq> EffectorSet<E> {
46    /// Applies the effects of this effector to the provided `StatSet`.
47    /// The delta time is used when using effectors that apply directly to
48    /// the base stat value. (WIP)
49    pub fn apply_to<K: Eq + Hash>(
50        self: &Self,
51        effector_defs: &EffectorDefinitions<K, E>,
52        stat_set: &mut StatSet<K>,
53        _delta_time: f32,
54    ) {
55        for s in stat_set.stats.values_mut() {
56            let mut new_value = s.value;
57            let mut multiplicative_multiplier = 1.0;
58            let mut additive_multiplier = 0.0;
59            let mut additive = 0.0;
60            // find effectors affecting this stat
61            for e in self.effectors.iter() {
62                let def = effector_defs
63                    .defs
64                    .get(&e.effector_key)
65                    .expect("Tried to get unknown stat key.");
66
67                // Algo:
68                // - Apply all multiplicative multipliers
69                // - Apply all additive multipliers
70                // - Apply all additives
71
72                // look into the effect of each effector
73                for (key, ty) in def.effects.iter() {
74                    // if any matches
75                    if *key == s.key {
76                        // Apply Effector
77                        match ty {
78                            EffectorType::Additive(v) => additive += v,
79                            EffectorType::AdditiveMultiplier(v) => additive_multiplier += v,
80                            EffectorType::MultiplicativeMultiplier(v) => {
81                                multiplicative_multiplier *= v
82                            }
83                        }
84                    }
85                }
86            }
87            let multiplier = multiplicative_multiplier + additive_multiplier;
88            new_value += additive;
89            new_value *= multiplier;
90            s.value_with_effectors = new_value;
91        }
92    }
93}
94
95/// The definition of a stat effector.
96/// This modifies temporarily the value of a stat.
97#[derive(Debug, Clone, Serialize, Deserialize, new)]
98pub struct EffectorDefinition<K, E> {
99    /// The key of the effector.
100    pub key: E,
101    /// The duration of the effector.
102    /// None means that it does not expire.
103    /// Some(0) means that it is applied only once.
104    /// Some(n) means that it is applied for n seconds.
105    pub duration: Option<f64>,
106    /// The effects that cause this effector.
107    /// Note that effectors can only cause effects on a single stat.
108    /// To affect multiple stats, create multiple effectors.
109    // TODO consider using only a single element here? It almost never happens that
110    // we want to apply multiple changes to the same stat.
111    pub effects: Vec<(K, EffectorType)>,
112}
113
114/// The way this effector modifies the stat.
115#[derive(Debug, Clone, Serialize, Deserialize, new)]
116pub enum EffectorType {
117    /// Adds a value to the base value of the stat.
118    Additive(f64),
119    /// Multiplies the stat by a value.
120    /// Stacks additively with other multipliers affecting this same stat.
121    AdditiveMultiplier(f64),
122    /// Multiplies the stat by a value.
123    /// Stacks multiplicatively with other multipliers affecting this same stat.
124    MultiplicativeMultiplier(f64),
125}
126
127/// An active instance of an effector.
128#[derive(Debug, Clone, Serialize, Deserialize, new)]
129pub struct EffectorInstance<E> {
130    /// The key of the effector.
131    pub effector_key: E,
132    /// The time before this effector expires.
133    pub disable_in: Option<f64>,
134}