wowlab_engine_combat/systems/auras/
breaks.rs1use super::{
2 ActorId, AuraBreakTrigger, CombatState, DenseBuffer, HookCtx, SpellAuraInterruptFlags,
3 expire_aura, expire_aura_instance, is_aura_active, refresh_aura_projections,
4};
5
6pub(crate) fn break_auras_on_actor(
7 ctx: &mut HookCtx<'_>,
8 actor: ActorId,
9 trigger: AuraBreakTrigger,
10) {
11 let keys: Vec<_> = ctx
12 .buf
13 .aura_keys()
14 .filter(|key| key.affected() == actor)
15 .filter(|key| {
16 let Some(local) = ctx.state.aura_local_for_key(*key) else {
17 return false;
18 };
19 let aura = ctx.state.defs.auras[local.as_usize()];
21
22 match trigger {
23 AuraBreakTrigger::Action => aura
24 .interrupt_flags
25 .contains(SpellAuraInterruptFlags::ACTION),
26 AuraBreakTrigger::Damage { periodic } => {
27 aura.interrupt_flags
28 .contains(SpellAuraInterruptFlags::DAMAGE)
29 || (!periodic
30 && aura
31 .interrupt_flags
32 .contains(SpellAuraInterruptFlags::NON_PERIODIC_DAMAGE))
33 }
34 }
35 })
36 .collect();
37
38 for key in keys {
39 let Some(local) = ctx.state.aura_local_for_key(key) else {
40 continue;
41 };
42
43 expire_aura_instance(ctx, local, key);
44 }
45}
46
47pub(crate) fn break_auras_without_telemetry(
48 state: &mut CombatState,
49 buf: &mut DenseBuffer,
50 actor: ActorId,
51 periodic_damage: bool,
52) {
53 let keys: Vec<_> = buf
54 .aura_keys()
55 .filter(|key| key.affected() == actor)
56 .filter(|key| {
57 let Some(local) = state.aura_local_for_key(*key) else {
58 return false;
59 };
60 let aura = state.defs.auras[local.as_usize()];
62
63 aura.interrupt_flags
64 .contains(SpellAuraInterruptFlags::DAMAGE)
65 || (!periodic_damage
66 && aura
67 .interrupt_flags
68 .contains(SpellAuraInterruptFlags::NON_PERIODIC_DAMAGE))
69 })
70 .collect();
71
72 for key in keys {
73 if let Some(slot) = buf.aura_mut(key) {
74 slot.remove();
75 }
76
77 state
78 .runtime
79 .health
80 .active_absorbs
81 .retain(|absorb| absorb.key != key);
82 }
83
84 refresh_aura_projections(buf, state.current_target());
85}
86
87pub(crate) fn break_stealth_if_active(ctx: &mut HookCtx<'_>) {
88 let Some(stealth_aura_id) = ctx.state.defs.stealth_aura_id else {
89 return;
90 };
91 let Some(&local) = ctx.state.index.aura_by_id.get(&stealth_aura_id) else {
92 return;
93 };
94
95 if is_aura_active(&ctx.view().combat(), local, ctx.source, ctx.target) {
96 expire_aura(ctx, local);
97 ctx.buf.player_mut().stealthed = 0;
98 }
99}