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