Skip to main content

wowlab_engine_combat/state/defs/
pets.rs

1//! Persistent-pet action-bar definitions and runtime state.
2
3use wowlab_types::sim::SimTime;
4
5use super::LocalAuraIdx;
6use crate::context::HookCtx;
7
8/// Damage/effect callback for one persistent-pet action.
9pub(crate) type PetActionFn = fn(&mut HookCtx<'_>);
10
11/// Owner-stat coefficients used to derive a pet's snapshotted combat stats.
12#[derive(Clone, Copy, Debug, PartialEq)]
13#[must_use]
14pub struct PetOwnerCoefficients {
15    pub armor: f64,
16    pub health: f64,
17    pub attack_power_from_attack_power: f64,
18    pub attack_power_from_spell_power: f64,
19    pub spell_power_from_attack_power: f64,
20    pub spell_power_from_spell_power: f64,
21}
22
23impl PetOwnerCoefficients {
24    pub const fn new() -> Self {
25        Self {
26            armor: 0.0,
27            health: 0.0,
28            attack_power_from_attack_power: 0.0,
29            attack_power_from_spell_power: 0.0,
30            spell_power_from_attack_power: 0.0,
31            spell_power_from_spell_power: 0.0,
32        }
33    }
34
35    /// Explicit owner identity used by definitions whose actors inherit the owner's full pools.
36    pub const fn owner_identity() -> Self {
37        Self::new()
38            .armor(1.0)
39            .health(1.0)
40            .attack_power(1.0, 0.0)
41            .spell_power(0.0, 1.0)
42    }
43
44    pub const fn armor(mut self, coefficient: f64) -> Self {
45        self.armor = coefficient;
46
47        self
48    }
49
50    pub const fn health(mut self, coefficient: f64) -> Self {
51        self.health = coefficient;
52
53        self
54    }
55
56    pub const fn attack_power(mut self, from_attack_power: f64, from_spell_power: f64) -> Self {
57        self.attack_power_from_attack_power = from_attack_power;
58        self.attack_power_from_spell_power = from_spell_power;
59
60        self
61    }
62
63    pub const fn spell_power(mut self, from_attack_power: f64, from_spell_power: f64) -> Self {
64        self.spell_power_from_attack_power = from_attack_power;
65        self.spell_power_from_spell_power = from_spell_power;
66
67        self
68    }
69}
70
71impl Default for PetOwnerCoefficients {
72    fn default() -> Self {
73        Self::new()
74    }
75}
76
77#[derive(Clone, Copy, Debug, Default, PartialEq)]
78pub(crate) struct PetStatSnapshot {
79    pub(crate) attack_power: f64,
80    pub(crate) spell_power: f64,
81    pub(crate) armor: f64,
82    pub(crate) health: f64,
83}
84
85/// A composable eligibility predicate for one persistent-pet ability.
86#[derive(Clone, Copy, Debug, Eq, PartialEq)]
87#[non_exhaustive]
88#[must_use]
89pub(crate) enum PetAbilityCondition {
90    Always,
91    OwnerAuraActive(LocalAuraIdx),
92    OwnerAuraInactive(LocalAuraIdx),
93}
94
95/// One ability in a persistent pet's priority list.
96#[derive(Clone, Copy, Debug)]
97#[must_use]
98pub struct PetAbility {
99    pub(crate) cost: f64,
100    pub(crate) minimum_resource: f64,
101    pub(crate) gcd_ms: Option<u32>,
102    pub(crate) condition: PetAbilityCondition,
103    pub(crate) action: PetActionFn,
104}
105
106impl PetAbility {
107    pub const fn new(cost: f64, minimum_resource: f64, action: PetActionFn) -> Self {
108        Self {
109            cost,
110            minimum_resource,
111            gcd_ms: None,
112            condition: PetAbilityCondition::Always,
113            action,
114        }
115    }
116
117    /// Override the action bar's default global cooldown for this ability.
118    pub const fn gcd_ms(mut self, gcd_ms: u32) -> Self {
119        self.gcd_ms = Some(gcd_ms);
120
121        self
122    }
123
124    pub const fn while_owner_aura_active(mut self, aura: LocalAuraIdx) -> Self {
125        self.condition = PetAbilityCondition::OwnerAuraActive(aura);
126
127        self
128    }
129
130    pub const fn while_owner_aura_inactive(mut self, aura: LocalAuraIdx) -> Self {
131        self.condition = PetAbilityCondition::OwnerAuraInactive(aura);
132
133        self
134    }
135}
136
137/// Resource and global-cooldown rules for a persistent pet's priority list.
138#[derive(Clone, Copy, Debug)]
139#[must_use]
140pub struct PetActionBar {
141    pub(crate) resource_max: f64,
142    pub(crate) resource_initial: f64,
143    pub(crate) resource_regen_per_second: f64,
144    pub(crate) gcd_ms: u32,
145    pub(crate) abilities: &'static [PetAbility],
146    pub(crate) owner_coefficients: PetOwnerCoefficients,
147}
148
149/// Resource model for a persistent pet action bar.
150#[derive(Clone, Copy, Debug)]
151#[must_use]
152pub struct PetResourceModel {
153    max: f64,
154    initial: f64,
155    regen_per_second: f64,
156}
157
158impl PetResourceModel {
159    pub const fn new(max: f64) -> Self {
160        Self {
161            max,
162            initial: max,
163            regen_per_second: 0.0,
164        }
165    }
166
167    pub const fn initial(mut self, initial: f64) -> Self {
168        self.initial = initial;
169
170        self
171    }
172
173    pub const fn regen_per_second(mut self, regen_per_second: f64) -> Self {
174        self.regen_per_second = regen_per_second;
175
176        self
177    }
178}
179
180impl PetActionBar {
181    pub const fn new(
182        resource: PetResourceModel,
183        gcd_ms: u32,
184        abilities: &'static [PetAbility],
185    ) -> Self {
186        Self {
187            resource_max: resource.max,
188            resource_initial: resource.initial,
189            resource_regen_per_second: resource.regen_per_second,
190            gcd_ms,
191            abilities,
192            owner_coefficients: PetOwnerCoefficients::new(),
193        }
194    }
195
196    pub const fn owner_coefficients(mut self, coefficients: PetOwnerCoefficients) -> Self {
197        self.owner_coefficients = coefficients;
198
199        self
200    }
201
202    pub const fn inherit_owner_stats(self) -> Self {
203        self.owner_coefficients(PetOwnerCoefficients::owner_identity())
204    }
205}
206
207#[derive(Clone, Copy, Debug)]
208pub(crate) struct PetActionState {
209    pub(crate) resource: f64,
210    pub(crate) regen_per_second: f64,
211    pub(crate) resource_updated_at: SimTime,
212    pub(crate) gcd_ready_at: SimTime,
213    pub(crate) next_action_at: Option<SimTime>,
214    pub(crate) stat_snapshot: PetStatSnapshot,
215}