Skip to main content

wowlab_engine_combat/pipeline/
cdr.rs

1use wowlab_types::game::{CdrCondition, CdrEffect};
2
3use crate::{
4    context::CombatCtx,
5    state::{LocalAuraIdx, LocalSpellIdx, SpellData},
6    systems::{is_aura_active, reduce_cooldown, reset_cooldown},
7};
8
9pub(super) fn process_cdr_effects(ctx: &mut CombatCtx<'_>, spell: &SpellData) {
10    for i in 0..spell.cooldown.cdr_count as usize {
11        // #t(rust_unchecked_indexing) i bounded by cdr_count which is <= MAX_CDR_EFFECTS
12        apply_cdr_effect(ctx, spell.cooldown.cdr_effects[i]);
13    }
14}
15
16fn apply_cdr_effect(ctx: &mut CombatCtx<'_>, effect: CdrEffect) {
17    let spell_local = LocalSpellIdx::new(effect.target_spell_local);
18    let reduce = |ctx: &mut CombatCtx<'_>| {
19        reduce_cooldown(ctx.state, ctx.buf, spell_local, effect.amount_ms, ctx.now);
20    };
21
22    match effect.condition {
23        CdrCondition::Always => reduce(ctx),
24        CdrCondition::ProcChance { chance } => {
25            if (ctx.rng)() < chance {
26                reduce(ctx);
27            }
28        }
29        CdrCondition::WhileAuraActive { aura_local } => {
30            if is_aura_active(
31                &ctx.view(),
32                LocalAuraIdx::new(aura_local),
33                ctx.source,
34                Some(ctx.target),
35            ) {
36                reduce(ctx);
37            }
38        }
39        CdrCondition::ResetWhileAura { aura_local } => {
40            if is_aura_active(
41                &ctx.view(),
42                LocalAuraIdx::new(aura_local),
43                ctx.source,
44                Some(ctx.target),
45            ) {
46                reset_cooldown(ctx.state, ctx.buf, spell_local);
47            }
48        }
49        _ => unreachable!("the engine and canonical CDR condition contract must stay in sync"),
50    }
51}