Skip to main content

wowlab_engine_content/hooks/shared/
hunter.rs

1use wowlab_engine_combat::{AuraOps as _, HookCtx, LocalAuraIdx, ProcOps as _};
2
3pub(crate) type HowlEffect = fn(&mut HookCtx<'_>);
4
5const HOWL_STAGE_COUNT: usize = 3;
6const FINAL_HOWL_STAGE: usize = HOWL_STAGE_COUNT - 1;
7
8#[derive(Clone, Copy, Debug)]
9pub(crate) struct PackLeaderHowl {
10    pub wyvern_ready: LocalAuraIdx,
11    pub boar_ready: LocalAuraIdx,
12    pub bear_ready: LocalAuraIdx,
13    pub on_wyvern: HowlEffect,
14    pub on_boar: HowlEffect,
15    pub on_bear: HowlEffect,
16    pub on_consumed: HowlEffect,
17    pub consume_all: bool,
18}
19
20pub(crate) fn apply_next_howl_ready(
21    ctx: &mut HookCtx<'_>,
22    driver_spell_id: u32,
23    ready_auras: [LocalAuraIdx; HOWL_STAGE_COUNT],
24) {
25    let stage_count = u32::try_from(HOWL_STAGE_COUNT).expect("howl stage count fits in u32");
26    let stage = usize::try_from(ctx.proc_counter(driver_spell_id) % stage_count)
27        .expect("howl stage index fits in usize");
28    let Some(ready_aura) = ready_auras.get(stage).copied() else {
29        return;
30    };
31
32    ctx.apply_aura(ready_aura.raw());
33
34    if stage == FINAL_HOWL_STAGE {
35        ctx.reset_proc_counter(driver_spell_id);
36    } else {
37        ctx.add_proc_counter(driver_spell_id, 1);
38    }
39}
40
41pub(crate) fn consume_howl(ctx: &mut HookCtx<'_>, howl: PackLeaderHowl) {
42    let mut consumed = false;
43
44    for (ready, effect) in [
45        (howl.wyvern_ready, howl.on_wyvern),
46        (howl.boar_ready, howl.on_boar),
47        (howl.bear_ready, howl.on_bear),
48    ] {
49        if ctx.consume_aura(ready.raw()) {
50            effect(ctx);
51            consumed = true;
52
53            if !howl.consume_all {
54                break;
55            }
56        }
57    }
58
59    if consumed {
60        (howl.on_consumed)(ctx);
61    }
62}