Skip to main content

wowlab_engine_combat/state/
ground_effect.rs

1use wowlab_types::sim::SpatialTransform;
2
3use super::{DamageEffectRef, RuntimeDamageDef};
4use crate::systems::DamageFlags;
5
6/// Stable authored identity for one finalized location-locked effect.
7#[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/// Construction-time description of one location-locked damage sequence.
17#[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    /// Cold test/introspection constructor for non-generated fixture identities.
79    #[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    /// Cold test/introspection constructor for data-timed fixture identities.
108    #[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}