Skip to main content

wowlab_engine_combat/state/defs/
aura.rs

1use super::{
2    AuraOn, BuffEffect, CastHookFn, LocalSpellIdx, MAX_AURA_APPLICATION_EXCLUSIONS,
3    MAX_AURA_BUFF_EFFECTS, PeriodicData, SpellAuraInterruptFlags, SpellEffectRange,
4};
5use crate::state::AuraState;
6
7/// Membership of an aura in a numbered spell group and the rule governing the group.
8#[derive(Clone, Copy, Debug)]
9#[must_use]
10pub struct SpellGroup {
11    pub group_idx: u8,
12    pub rule: wowlab_types::combat::SpellGroupRule,
13}
14
15/// On-crit charge reduction for an auto-attack: roll `chance` to refund a charge of `target`.
16#[derive(Clone, Copy, Debug, PartialEq)]
17#[must_use]
18pub struct CritChargeReduction {
19    pub target: LocalSpellIdx,
20    pub chance: f64,
21}
22
23/// Static definition of an aura (buff/debuff).
24/// `SimC`'s per-tick stat update coordinate.
25#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
26#[non_exhaustive]
27pub enum DynamicTickAction {
28    #[default]
29    None,
30    Update,
31    Snapshot,
32}
33
34/// Whether an aura's periodic tick mutates its stack count.
35#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
36#[non_exhaustive]
37pub enum AuraTickBehavior {
38    #[default]
39    None,
40    Clip,
41    Refresh,
42}
43
44// docref:start auras-aura-data
45#[derive(Clone, Copy, Debug)]
46#[must_use]
47#[expect(
48    clippy::struct_excessive_bools,
49    reason = "runtime aura behavior preserves independent DBC flags"
50)]
51pub struct AuraData {
52    pub aura_id: u32,
53    pub name_idx: u16,
54    pub on: AuraOn,
55    pub propagates_to_pet: bool,
56    pub base_duration_ms: u32,
57    pub doses: u8,
58    pub max_stacks: u8,
59    pub pandemic: bool,
60    pub refresh_behavior: wowlab_types::data::RefreshBehavior,
61    pub duration_hasted: bool,
62    pub shapeshift_form: i32,
63    pub shapeshift_form_flags: i32,
64    /// `SpellShapeshiftForm.CombatRoundTime`; non-zero when the form imposes its own swing period.
65    pub shapeshift_combat_round_time_ms: u32,
66    pub effects: [Option<BuffEffect>; MAX_AURA_BUFF_EFFECTS],
67    pub periodic: Option<PeriodicData>,
68    pub spell_group: Option<SpellGroup>,
69    pub granted_aura_state: Option<AuraState>,
70    pub crowd_control: Option<wowlab_engine_domain::dbc::CrowdControlSemantic>,
71    pub is_snapshot: bool,
72    pub dynamic_tick_action: DynamicTickAction,
73    pub apply_at_max_stacks: bool,
74    pub reverse: bool,
75    pub freeze_stacks: bool,
76    pub tick_behavior: AuraTickBehavior,
77    pub tick_stack_change: u8,
78    pub async_stacks: bool,
79    pub periodic_damage_scales_with_stacks: bool,
80    pub interrupt_flags: SpellAuraInterruptFlags,
81    pub reapply_on_expire: bool,
82    pub application_excluded_auras: [u32; MAX_AURA_APPLICATION_EXCLUSIONS],
83    pub application_followup_aura_id: u32,
84    pub apply_effects: SpellEffectRange,
85    pub apply_profile_spell_id: u32,
86    pub on_consume: SpellEffectRange,
87    pub tick_effects: SpellEffectRange,
88    pub tick_profile_spell_id: u32,
89    pub expire_trigger_spell_id: u32,
90    pub expire_trigger_from_caster: bool,
91    pub on_expire: Option<CastHookFn>,
92    pub on_tick: Option<CastHookFn>,
93}
94// docref:end auras-aura-data
95
96impl AuraData {
97    /// Single-stack, non-periodic player buff carrying `effects` for `duration_ms`.
98    #[inline]
99    pub fn simple_player_buff(
100        aura_id: u32,
101        name_idx: u16,
102        duration_ms: u32,
103        effects: [Option<BuffEffect>; MAX_AURA_BUFF_EFFECTS],
104    ) -> Self {
105        Self {
106            aura_id,
107            name_idx,
108            on: AuraOn::Player,
109            propagates_to_pet: false,
110            base_duration_ms: duration_ms,
111            doses: 1,
112            max_stacks: 1,
113            pandemic: false,
114            refresh_behavior: wowlab_types::data::RefreshBehavior::Duration,
115            duration_hasted: false,
116            shapeshift_form: 0,
117            shapeshift_form_flags: 0,
118            shapeshift_combat_round_time_ms: 0,
119            effects,
120            periodic: None,
121            spell_group: None,
122            granted_aura_state: None,
123            crowd_control: None,
124            is_snapshot: false,
125            dynamic_tick_action: DynamicTickAction::None,
126            apply_at_max_stacks: false,
127            reverse: false,
128            freeze_stacks: false,
129            tick_behavior: AuraTickBehavior::None,
130            tick_stack_change: 1,
131            async_stacks: false,
132            periodic_damage_scales_with_stacks: false,
133            interrupt_flags: SpellAuraInterruptFlags::empty(),
134            reapply_on_expire: false,
135            application_excluded_auras: [0; MAX_AURA_APPLICATION_EXCLUSIONS],
136            application_followup_aura_id: 0,
137            apply_effects: SpellEffectRange::default(),
138            apply_profile_spell_id: 0,
139            on_consume: SpellEffectRange::default(),
140            tick_effects: SpellEffectRange::default(),
141            tick_profile_spell_id: 0,
142            expire_trigger_spell_id: 0,
143            expire_trigger_from_caster: false,
144            on_expire: None,
145            on_tick: None,
146        }
147    }
148}