wowlab_engine_combat/state/defs/
guardians.rs1use wowlab_types::sim::{ActorId, EnemyIdx, PetIdx};
4
5use crate::{context::HookCtx, state::PetOwnerCoefficients};
6
7pub type GuardianActionFn = fn(&mut HookCtx<'_>, GuardianEvent);
8
9#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
11#[must_use]
12pub struct GuardianHandle(pub(crate) u32, pub(crate) u32);
13
14impl GuardianHandle {
15 pub const fn new(slot: u32, generation: u32) -> Self {
16 Self(slot, generation)
17 }
18
19 #[must_use]
20 pub const fn as_u32(&self) -> u32 {
21 self.0
22 }
23
24 #[must_use]
25 pub const fn generation(&self) -> u32 {
26 self.1
27 }
28
29 pub(crate) fn actor(self) -> Option<ActorId> {
30 PetIdx::from_guardian_slot(self.0 as usize).map(ActorId::Pet)
31 }
32}
33
34#[derive(Clone, Copy, Debug, Eq, PartialEq)]
36#[must_use]
37pub struct GuardianEvent {
38 pub handle: GuardianHandle,
39 pub tag: u32,
40 pub ability_index: usize,
41 pub action_index: u16,
42 pub spawned_at: wowlab_types::sim::SimTime,
43 pub expires_at: wowlab_types::sim::SimTime,
44}
45
46#[derive(Clone, Copy, Debug)]
48#[must_use]
49#[expect(
50 clippy::struct_excessive_bools,
51 reason = "guardian cadence, lifetime, and scheduler ownership are independent encounter capabilities"
52)]
53pub struct GuardianAbility {
54 pub(crate) first_action_delay_ms: u32,
55 pub(crate) action_interval_ms: u32,
56 pub(crate) hasted_first_action: bool,
57 pub(crate) hasted_action_interval: bool,
58 pub(crate) max_actions: u16,
59 pub(crate) ends_guardian: bool,
60 pub(crate) self_scheduled: bool,
61 pub(crate) action: GuardianActionFn,
62}
63
64impl GuardianAbility {
65 pub const fn new(action_interval_ms: u32, action: GuardianActionFn) -> Self {
66 Self {
67 first_action_delay_ms: 0,
68 action_interval_ms,
69 hasted_first_action: false,
70 hasted_action_interval: false,
71 max_actions: 0,
72 ends_guardian: false,
73 self_scheduled: true,
74 action,
75 }
76 }
77
78 pub const fn on_demand(action: GuardianActionFn) -> Self {
81 let mut ability = Self::new(0, action);
82
83 ability.self_scheduled = false;
84
85 ability
86 }
87
88 pub const fn first_action_delay(mut self, delay_ms: u32) -> Self {
89 self.first_action_delay_ms = delay_ms;
90
91 self
92 }
93
94 pub const fn hasted_actions(mut self) -> Self {
95 self.hasted_first_action = true;
96 self.hasted_action_interval = true;
97
98 self
99 }
100
101 pub const fn hasted_action_interval(mut self) -> Self {
103 self.hasted_action_interval = true;
104
105 self
106 }
107
108 pub const fn max_actions(mut self, count: u16) -> Self {
110 self.max_actions = count;
111
112 self
113 }
114
115 pub const fn ends_guardian(mut self) -> Self {
117 self.ends_guardian = true;
118
119 self
120 }
121}
122
123#[derive(Clone, Debug)]
125#[must_use]
126pub struct GuardianSpec {
127 pub(crate) tag: u32,
128 pub(crate) npc_id: Option<u32>,
129 pub(crate) duration_ms: u32,
130 pub(crate) abilities: Vec<GuardianAbility>,
131 pub(crate) on_demise: Option<GuardianActionFn>,
132 pub(crate) owner_coefficients: PetOwnerCoefficients,
133}
134
135impl GuardianSpec {
136 pub const fn new(tag: u32, duration_ms: u32) -> Self {
137 Self {
138 tag,
139 npc_id: None,
140 duration_ms,
141 abilities: Vec::new(),
142 on_demise: None,
143 owner_coefficients: PetOwnerCoefficients::new(),
144 }
145 }
146
147 pub const fn new_inheriting_owner(tag: u32, duration_ms: u32) -> Self {
148 Self::new(tag, duration_ms).inherit_owner_stats()
149 }
150
151 pub const fn npc_id(mut self, npc_id: u32) -> Self {
153 self.npc_id = Some(npc_id);
154
155 self
156 }
157
158 pub fn ability(mut self, ability: GuardianAbility) -> Self {
159 self.abilities.push(ability);
160
161 self
162 }
163
164 pub const fn on_demise(mut self, hook: GuardianActionFn) -> Self {
165 self.on_demise = Some(hook);
166
167 self
168 }
169
170 pub const fn owner_coefficients(mut self, coefficients: PetOwnerCoefficients) -> Self {
171 self.owner_coefficients = coefficients;
172
173 self
174 }
175
176 pub const fn inherit_owner_stats(self) -> Self {
177 self.owner_coefficients(PetOwnerCoefficients::owner_identity())
178 }
179}
180
181#[derive(Clone, Copy, Debug)]
182pub(crate) struct GuardianAbilityState {
183 pub(crate) next_action_at: Option<wowlab_types::sim::SimTime>,
184 pub(crate) actions_executed: u16,
185}
186
187#[derive(Clone, Debug)]
188pub(crate) struct GuardianInstance {
189 pub(crate) handle: GuardianHandle,
190 pub(crate) spec: GuardianSpec,
191 pub(crate) spawned_at: wowlab_types::sim::SimTime,
192 pub(crate) expires_at: wowlab_types::sim::SimTime,
193 pub(crate) abilities: Vec<GuardianAbilityState>,
194 pub(crate) source: ActorId,
195 pub(crate) target: EnemyIdx,
196 pub(crate) stat_snapshot: super::PetStatSnapshot,
197}