wowlab_engine_combat/systems/buffs/
traversal.rs1use super::{
2 ActorId, ActorView, BuffEffect, CombatState, DenseBuffer, EnemyIdx, SpellEffectAttributes,
3};
4
5pub(crate) fn dbc_effect_points(
6 state: &CombatState,
7 source_spell_id: u32,
8 effect_index: u8,
9 stacks: f64,
10) -> f64 {
11 let attributes = SpellEffectAttributes::from_dbc(state.config.game_data.effect_attributes(
12 wowlab_types::sim::SpellIdx::from_raw(source_spell_id),
13 effect_index,
14 ));
15
16 if attributes.contains(SpellEffectAttributes::SUPPRESS_POINTS_STACKING) {
17 1.0
18 } else {
19 stacks
20 }
21}
22
23pub(crate) fn for_each_active_aura_effect(
24 state: &CombatState,
25 buf: &DenseBuffer,
26 mut f: impl FnMut(f64, &BuffEffect),
27) {
28 for_each_active_actor_aura_effect(ActorView::new(state, buf, ActorId::Player), &mut f);
29}
30
31pub(crate) fn for_each_active_actor_aura_effect(
32 view: ActorView<'_>,
33 mut f: impl FnMut(f64, &BuffEffect),
34) {
35 let ActorView { state, buf, actor } = view;
36
37 if actor == ActorId::Player {
38 for driver in &state.defs.passive_driver_effects {
39 tracing::trace!(
41 driver_spell_id = driver.driver_spell_id,
42 ?driver.effect,
43 "passive driver effect applied"
44 );
45 f(1.0, &driver.effect);
46 }
47 }
48
49 for key in buf.aura_keys() {
50 if key.affected() != actor {
51 continue;
52 }
53
54 let Some(slot) = buf.aura(key).filter(|slot| slot.is_occupied()) else {
55 continue;
56 };
57 let Some(local) = state.aura_local_for_key(key) else {
58 continue;
59 };
60 let aura = &state.defs.auras[local.as_usize()];
62 let stacks_f = f64::from(slot.stacks);
63
64 for effect in aura.effects.iter().flatten() {
65 trace_content_damage_mult(aura.aura_id, stacks_f, effect);
66 f(stacks_f, effect);
67 }
68 }
69}
70
71fn trace_content_damage_mult(aura_id: u32, stacks: f64, effect: &BuffEffect) {
76 if !matches!(
77 effect,
78 BuffEffect::DamageMult(..)
79 | BuffEffect::DamageMultStacking { .. }
80 | BuffEffect::DamageMultSpells(..)
81 | BuffEffect::DamageMultSpellsActive(..)
82 | BuffEffect::DamageMultSpellsLinear(..)
83 ) {
84 return;
85 }
86
87 tracing::trace!(
88 aura_id,
89 stacks,
90 scaled = ?effect.scaled(stacks),
91 "content aura damage multiplier applied"
92 );
93}
94
95pub(crate) fn for_each_active_target_aura_effect(
96 state: &CombatState,
97 buf: &DenseBuffer,
98 target: EnemyIdx,
99 mut f: impl FnMut(f64, &BuffEffect),
100) {
101 for key in buf.aura_keys() {
102 if key.affected() != ActorId::Enemy(target) {
103 continue;
104 }
105
106 let Some(slot) = buf.aura(key).filter(|slot| slot.is_occupied()) else {
107 continue;
108 };
109 let Some(local) = state.aura_local_for_key(key) else {
110 continue;
111 };
112 let aura = &state.defs.auras[local.as_usize()];
114 let stacks_f = f64::from(slot.stacks);
115
116 for effect in aura.effects.iter().flatten() {
117 f(stacks_f, effect);
118 }
119 }
120}