Skip to main content

wowlab_engine_combat/context/hook/
spells.rs

1use wowlab_engine_domain::pool::SpellGate;
2
3use super::CooldownOps;
4use crate::{context::HookCtx, state::LocalSpellIdx, systems};
5
6impl CooldownOps for HookCtx<'_> {
7    fn spend_spell_charge(&mut self, spell: u8) -> bool {
8        let local = LocalSpellIdx::new(spell);
9        let Some(definition) = self.state.defs.spells.get(local.as_usize()) else {
10            return false;
11        };
12        let Some(cooldown) = self.buf.cooldown(definition.idx()) else {
13            return false;
14        };
15
16        if !definition.is_charged() || cooldown.current_charges <= 0 {
17            return false;
18        }
19
20        systems::start_cooldown(self.state, self.buf, local, self.now);
21
22        true
23    }
24
25    fn reduce_cooldown(&mut self, spell: u8, amount_ms: u32) {
26        systems::reduce_cooldown(
27            self.state,
28            self.buf,
29            LocalSpellIdx::new(spell),
30            amount_ms,
31            self.now,
32        );
33    }
34
35    fn reset_cooldown(&mut self, spell: u8) {
36        systems::reset_cooldown(self.state, self.buf, LocalSpellIdx::new(spell));
37    }
38
39    fn start_cooldown(&mut self, spell: u8) {
40        systems::start_cooldown(self.state, self.buf, LocalSpellIdx::new(spell), self.now);
41    }
42
43    fn set_spell_gate(&mut self, spell: u8, gate: SpellGate, available: bool) {
44        systems::set_spell_gate(
45            self.state,
46            self.buf,
47            LocalSpellIdx::new(spell),
48            gate,
49            available,
50        );
51    }
52
53    fn grant_charges(&mut self, spell: u8, amount: u8) {
54        systems::grant_charges(self.state, self.buf, LocalSpellIdx::new(spell), amount);
55    }
56
57    fn spell_cooldown_ms(&self, spell: u8) -> u32 {
58        self.state
59            .defs
60            .spells
61            .get(usize::from(spell))
62            .map_or(0, |definition| {
63                if definition.cooldown.recharge_ms > 0 {
64                    definition.cooldown.recharge_ms
65                } else {
66                    definition.cooldown.cooldown_duration_ms
67                }
68            })
69    }
70
71    fn spell_cooldown_remaining_ms(&self, spell: u8) -> u32 {
72        let remaining_seconds = self
73            .state
74            .defs
75            .spells
76            .get(usize::from(spell))
77            .and_then(|definition| self.buf.cooldown(definition.idx()))
78            .map_or(0.0, |cooldown| cooldown.ready_at - self.now.as_secs_f64())
79            .max(0.0);
80
81        wowlab_types::numeric::f64_to_u32_saturating_trunc(
82            remaining_seconds.mul_add(wowlab_types::constants::MS_PER_SECOND, 0.0),
83        )
84    }
85
86    fn spell_ready(&self, spell: u8) -> bool {
87        self.state
88            .defs
89            .spells
90            .get(usize::from(spell))
91            .and_then(|definition| self.buf.cooldown(definition.idx()))
92            .is_none_or(|cooldown| cooldown.is_ready(self.now.as_secs_f64()))
93    }
94
95    fn spell_current_charges(&self, spell: u8) -> i32 {
96        self.state
97            .defs
98            .spells
99            .get(usize::from(spell))
100            .and_then(|definition| self.buf.cooldown(definition.idx()))
101            .map_or(0, |cooldown| cooldown.current_charges)
102    }
103}