wowlab_engine_combat/systems/buffs/
totals.rs1use super::{
2 ActorId, ActorView, BuffEffect, BuffTotals, CombatState, DenseBuffer, EnemyIdx,
3 for_each_active_actor_aura_effect,
4};
5
6#[must_use]
8pub fn accumulate_buffs(
9 state: &CombatState,
10 buf: &DenseBuffer,
11 target: Option<EnemyIdx>,
12) -> BuffTotals {
13 accumulate_actor_buffs(ActorView::new(state, buf, ActorId::Player), target)
14}
15
16pub(crate) fn accumulate_actor_buffs(view: ActorView<'_>, target: Option<EnemyIdx>) -> BuffTotals {
17 let ActorView { state, buf, .. } = view;
18 let mut totals = BuffTotals::default();
19
20 for_each_active_actor_aura_effect(view, |stacks, effect| {
21 if let BuffEffect::DynamicDamageMult(resolve) = effect {
22 totals.damage_mult *= resolve(state, buf, target).powf(stacks);
23 } else if let BuffEffect::DynamicRegenPercent(resolve) = effect {
24 totals.regen_pct += resolve(state, buf) * stacks;
25 } else {
26 totals.add(effect.scaled(stacks));
27 }
28 });
29
30 totals
31}
32
33pub(crate) fn accumulate_actor_only_buffs(
34 view: ActorView<'_>,
35 target: Option<EnemyIdx>,
36) -> BuffTotals {
37 let ActorView { state, buf, actor } = view;
38 let mut totals = BuffTotals::default();
39
40 for key in buf.aura_keys() {
41 if key.affected() != actor
42 || buf.aura(key).is_none_or(|slot| !slot.is_occupied())
43 || buf.aura_keys().any(|owner_key| {
44 owner_key.aura() == key.aura()
45 && owner_key.affected() == ActorId::Player
46 && buf
47 .aura(owner_key)
48 .is_some_and(wowlab_engine_domain::rotation::AuraSlot::is_occupied)
49 })
50 {
51 continue;
52 }
53
54 let Some(local) = state.aura_local_for_key(key) else {
55 continue;
56 };
57 let aura = &state.defs.auras[local.as_usize()];
59 let stacks = f64::from(buf.aura(key).map_or(0, |slot| slot.stacks));
60
61 for effect in aura.effects.iter().flatten() {
62 if let BuffEffect::DynamicDamageMult(resolve) = effect {
63 totals.damage_mult *= resolve(state, buf, target).powf(stacks);
64 } else if let BuffEffect::DynamicRegenPercent(resolve) = effect {
65 totals.regen_pct += resolve(state, buf) * stacks;
66 } else {
67 totals.add(effect.scaled(stacks));
68 }
69 }
70 }
71
72 totals
73}