1use std::ops::Mul;
9
10use super::time::Ticks;
11
12#[derive(Copy, Clone, PartialEq, Eq, Debug)]
17#[non_exhaustive]
18pub enum BaseEffectType {
19 Weak { magnitude: u16 },
20 Strong { magnitude: u16 },
21}
22
23impl BaseEffectType {
24 fn magnitude(&self) -> u16 {
25 match *self {
26 BaseEffectType::Weak { magnitude } => magnitude,
27 BaseEffectType::Strong { magnitude } => magnitude,
28 }
29 }
30}
31
32impl Mul<f32> for BaseEffectType {
33 type Output = BaseEffectType;
34
35 fn mul(self, rhs: f32) -> Self::Output {
36 let mg = (self.magnitude() as f32 * rhs) as u16;
37 match self {
38 BaseEffectType::Weak { .. } => BaseEffectType::Weak { magnitude: mg },
39 BaseEffectType::Strong { .. } => BaseEffectType::Strong { magnitude: mg },
40 }
41 }
42}
43
44impl Default for BaseEffectType {
45 fn default() -> Self {
46 BaseEffectType::Weak { magnitude: 0 }
47 }
48}
49
50#[derive(Copy, Clone, PartialEq, Debug, Default)]
55pub struct BaseEffect {
56 pub kind: BaseEffectType,
58 pub scheduling: Replay,
60 pub envelope: Envelope,
63}
64
65impl BaseEffect {
66 pub(super) fn magnitude_at(&self, ticks: Ticks) -> BaseEffectType {
68 if let Some(wrapped) = self.scheduling.wrap(ticks) {
69 let att =
70 self.scheduling.at(wrapped) * self.envelope.at(wrapped, self.scheduling.play_for);
71 self.kind * att
72 } else {
73 self.kind * 0.0
74 }
75 }
76}
77
78#[derive(Copy, Clone, PartialEq, Debug, Default)]
80pub struct Envelope {
82 pub attack_length: Ticks,
83 pub attack_level: f32,
84 pub fade_length: Ticks,
85 pub fade_level: f32,
86}
87
88impl Envelope {
89 pub(super) fn at(&self, ticks: Ticks, dur: Ticks) -> f32 {
90 debug_assert!(self.fade_length < dur);
91 debug_assert!(self.attack_length + self.fade_length < dur);
92
93 if ticks < self.attack_length {
94 self.attack_level
95 + ticks.0 as f32 * (1.0 - self.attack_level) / self.attack_length.0 as f32
96 } else if ticks + self.fade_length > dur {
97 1.0 + (ticks + self.fade_length - dur).0 as f32 * (self.fade_level - 1.0)
98 / self.fade_length.0 as f32
99 } else {
100 1.0
101 }
102 }
103}
104
105#[derive(Copy, Clone, PartialEq, Eq, Debug)]
114pub struct Replay {
115 pub after: Ticks,
117 pub play_for: Ticks,
119 pub with_delay: Ticks,
121}
122
123impl Replay {
124 pub(super) fn at(&self, ticks: Ticks) -> f32 {
125 if ticks >= self.play_for {
126 0.0
127 } else {
128 1.0
129 }
130 }
131
132 pub fn dur(&self) -> Ticks {
134 self.play_for + self.with_delay
135 }
136
137 fn wrap(&self, ticks: Ticks) -> Option<Ticks> {
139 ticks.checked_sub(self.after).map(|t| t % self.dur())
140 }
141}
142
143impl Default for Replay {
144 fn default() -> Self {
145 Replay {
146 after: Ticks(0),
147 play_for: Ticks(1),
148 with_delay: Ticks(0),
149 }
150 }
151}