wowlab_engine_domain/pool/
spell_gate.rs1use std::hash::Hash;
2
3use wowlab_types::sim::FastSet;
4
5use super::base::Pool;
6
7#[derive(Clone, Copy, Debug, Eq, PartialEq)]
9#[non_exhaustive]
10pub enum SpellGate {
11 ReactionDelay,
12 TargetHealth,
13 ActiveAuraRestriction,
15}
16
17impl SpellGate {
18 const fn blocker(self) -> SpellGateBlockers {
19 match self {
20 Self::ReactionDelay => SpellGateBlockers::REACTION_DELAY,
21 Self::TargetHealth => SpellGateBlockers::TARGET_HEALTH,
22 Self::ActiveAuraRestriction => SpellGateBlockers::ACTIVE_AURA_RESTRICTION,
23 }
24 }
25}
26
27bitflags::bitflags! {
28 #[derive(Clone, Copy, Debug, Default)]
29 struct SpellGateBlockers: u8 {
30 const REACTION_DELAY = 1 << 0;
31 const TARGET_HEALTH = 1 << 1;
32 const ACTIVE_AURA_RESTRICTION = 1 << 2;
33 }
34}
35
36#[derive(Clone, Copy, Debug)]
37struct SpellGateState {
38 base_enabled: bool,
39 blockers: SpellGateBlockers,
40}
41
42#[derive(Clone, Copy, Debug)]
43pub struct SpellGateUpdate {
44 pub base_enabled: bool,
45 pub available: bool,
46}
47
48#[derive(Clone, Debug)]
49pub struct SpellGatePool<K> {
50 state: Pool<K, SpellGateState>,
51 aura_state_exceptions: FastSet<K>,
52}
53
54impl<K> SpellGatePool<K>
55where
56 K: Copy + Eq + Hash,
57{
58 #[must_use]
59 pub fn new() -> Self {
60 Self::default()
61 }
62
63 pub fn set(&mut self, key: K, gate: SpellGate, update: SpellGateUpdate) -> bool {
64 let state = self.state.get_or_insert_with(key, || SpellGateState {
65 base_enabled: update.base_enabled,
66 blockers: SpellGateBlockers::empty(),
67 });
68
69 if update.available {
70 state.blockers.remove(gate.blocker());
71 } else {
72 state.blockers.insert(gate.blocker());
73 }
74
75 state.base_enabled && state.blockers.is_empty()
76 }
77
78 pub fn set_aura_state_exception(&mut self, key: K, active: bool) {
79 if active {
80 self.aura_state_exceptions.insert(key);
81 } else {
82 self.aura_state_exceptions.remove(&key);
83 }
84 }
85
86 pub fn ignores_aura_state(&self, key: &K) -> bool {
87 self.aura_state_exceptions.contains(key)
88 }
89
90 pub fn reset(&mut self) -> Vec<(K, bool)> {
91 self.aura_state_exceptions.clear();
92
93 self.state
94 .drain()
95 .map(|(key, state)| (key, state.base_enabled))
96 .collect()
97 }
98}
99
100impl<K> Default for SpellGatePool<K> {
101 fn default() -> Self {
102 Self {
103 state: Pool::default(),
104 aura_state_exceptions: FastSet::default(),
105 }
106 }
107}
108
109#[cfg(test)]
110#[path = "spell_gate/tests.rs"]
111mod tests;