wowlab_engine_combat/state/
ground_effect.rs1use wowlab_types::sim::SpatialTransform;
2
3use super::{DamageEffectRef, RuntimeDamageDef};
4use crate::systems::DamageFlags;
5
6#[derive(Clone, Copy, Debug, Eq, PartialEq)]
8pub struct GroundEffectId(pub(crate) u16);
9
10impl GroundEffectId {
11 pub(crate) const fn index(self) -> usize {
12 self.0 as usize
13 }
14}
15
16#[derive(Clone, Copy, Debug)]
18pub struct GroundEffectDefinition {
19 pub(crate) geometry_effect: crate::DamageEffectId,
20 pub(crate) damage_effect: crate::DamageEffectId,
21 pub(crate) profile_action: crate::DamageActionId,
22 pub(crate) driver_action: Option<crate::DamageActionId>,
23 pub(crate) timing_effect: Option<crate::DamageEffectId>,
24 #[cfg(test)]
25 pub(crate) cold_coordinates: Option<ColdGroundEffectCoordinates>,
26 pub(crate) pulse_count: u8,
27 pub(crate) pulse_period_ms: u32,
28 pub(crate) first_pulse_delay_ms: u32,
29 pub(crate) multiplier: f64,
30 pub(crate) flags: DamageFlags,
31}
32
33impl GroundEffectDefinition {
34 #[must_use]
35 pub const fn new(
36 geometry_effect: crate::DamageEffectId,
37 damage_effect: crate::DamageEffectId,
38 ) -> Self {
39 Self {
40 geometry_effect,
41 damage_effect,
42 profile_action: damage_effect.action(),
43 driver_action: None,
44 timing_effect: None,
45 #[cfg(test)]
46 cold_coordinates: None,
47 pulse_count: 1,
48 pulse_period_ms: 0,
49 first_pulse_delay_ms: 0,
50 multiplier: 1.0,
51 flags: DamageFlags::empty(),
52 }
53 }
54
55 #[must_use]
56 pub const fn from_driver(
57 driver_action: crate::DamageActionId,
58 timing_effect: crate::DamageEffectId,
59 geometry_effect: crate::DamageEffectId,
60 damage_effect: crate::DamageEffectId,
61 ) -> Self {
62 Self {
63 geometry_effect,
64 damage_effect,
65 profile_action: damage_effect.action(),
66 driver_action: Some(driver_action),
67 timing_effect: Some(timing_effect),
68 #[cfg(test)]
69 cold_coordinates: None,
70 pulse_count: 0,
71 pulse_period_ms: 0,
72 first_pulse_delay_ms: 0,
73 multiplier: 1.0,
74 flags: DamageFlags::empty(),
75 }
76 }
77
78 #[cfg(test)]
80 #[must_use]
81 pub const fn cold_from_refs(
82 geometry_effect: DamageEffectRef,
83 damage_effect: DamageEffectRef,
84 ) -> Self {
85 let action = crate::DamageActionId::new(0, damage_effect.spell_id);
86
87 Self {
88 geometry_effect: crate::DamageEffectId::new(action, geometry_effect.effect_index),
89 damage_effect: crate::DamageEffectId::new(action, damage_effect.effect_index),
90 profile_action: action,
91 driver_action: None,
92 timing_effect: None,
93 cold_coordinates: Some(ColdGroundEffectCoordinates {
94 driver_spell_id: None,
95 timing_effect: None,
96 geometry_effect,
97 damage_effect,
98 }),
99 pulse_count: 1,
100 pulse_period_ms: 0,
101 first_pulse_delay_ms: 0,
102 multiplier: 1.0,
103 flags: DamageFlags::empty(),
104 }
105 }
106
107 #[cfg(test)]
109 #[must_use]
110 pub const fn cold_from_driver_refs(
111 driver_spell_id: u32,
112 timing_effect: DamageEffectRef,
113 geometry_effect: DamageEffectRef,
114 damage_effect: DamageEffectRef,
115 ) -> Self {
116 let action = crate::DamageActionId::new(0, damage_effect.spell_id);
117 let driver = crate::DamageActionId::new(0, driver_spell_id);
118
119 Self {
120 geometry_effect: crate::DamageEffectId::new(action, geometry_effect.effect_index),
121 damage_effect: crate::DamageEffectId::new(action, damage_effect.effect_index),
122 profile_action: action,
123 driver_action: Some(driver),
124 timing_effect: Some(crate::DamageEffectId::new(
125 driver,
126 timing_effect.effect_index,
127 )),
128 cold_coordinates: Some(ColdGroundEffectCoordinates {
129 driver_spell_id: Some(driver_spell_id),
130 timing_effect: Some(timing_effect),
131 geometry_effect,
132 damage_effect,
133 }),
134 pulse_count: 0,
135 pulse_period_ms: 0,
136 first_pulse_delay_ms: 0,
137 multiplier: 1.0,
138 flags: DamageFlags::empty(),
139 }
140 }
141
142 #[must_use]
143 pub const fn pulses(mut self, count: u8, period_ms: u32) -> Self {
144 self.pulse_count = count;
145 self.pulse_period_ms = period_ms;
146
147 self
148 }
149
150 #[must_use]
151 pub const fn first_pulse_after(mut self, delay_ms: u32) -> Self {
152 self.first_pulse_delay_ms = delay_ms;
153
154 self
155 }
156
157 #[must_use]
158 pub const fn multiplier(mut self, multiplier: f64) -> Self {
159 self.multiplier = multiplier;
160
161 self
162 }
163
164 #[must_use]
165 pub const fn flags(mut self, flags: DamageFlags) -> Self {
166 self.flags = flags;
167
168 self
169 }
170}
171
172#[derive(Clone, Copy, Debug)]
173#[cfg(test)]
174pub(crate) struct ColdGroundEffectCoordinates {
175 pub(crate) driver_spell_id: Option<u32>,
176 pub(crate) timing_effect: Option<DamageEffectRef>,
177 pub(crate) geometry_effect: DamageEffectRef,
178 pub(crate) damage_effect: DamageEffectRef,
179}
180
181#[derive(Clone, Copy, Debug)]
182pub(crate) struct PendingGroundPulse {
183 pub(crate) binding: crate::state::program::DamageRequestBinding,
184 pub(crate) geometry_effect: DamageEffectRef,
185 pub(crate) damage_effect: DamageEffectRef,
186 pub(crate) profile_spell_id: u32,
187 pub(crate) damage: RuntimeDamageDef,
188 pub(crate) destination: SpatialTransform,
189 pub(crate) flags: DamageFlags,
190}