Skip to main content

wowlab_engine_combat/systems/damage_pipeline/
leech.rs

1//! Leech healing produced by finalized outgoing damage.
2
3use wowlab_engine_telemetry::DamageEvent;
4use wowlab_types::{
5    constants::HUNDRED,
6    sim::{ActorId, SpellIdx},
7};
8
9use super::school_of;
10use crate::{
11    context::CombatCtx,
12    state::BuffEffect,
13    systems::{HealRequest, buffs, deal_heal},
14};
15
16pub(super) fn apply_leech_healing(
17    ctx: &mut CombatCtx<'_>,
18    event: &DamageEvent,
19    actual_damage: f64,
20) {
21    if actual_damage <= f64::EPSILON || matches!(ctx.source, ActorId::Enemy(_)) {
22        return;
23    }
24
25    let mut leech_percent = ctx.state.config.base_stats.stats.leech;
26
27    buffs::for_each_active_actor_aura_effect(ctx.view().for_actor(ctx.source), |stacks, effect| {
28        if let BuffEffect::LeechPercent(percent) = effect {
29            leech_percent += percent * stacks;
30        }
31    });
32    let spell = SpellIdx::from_raw(event.spell_id);
33    let health_leech_fraction = (1..=ctx.state.config.game_data.max_effect_index(spell))
34        .find(|&effect_index| {
35            wowlab_engine_domain::dbc::spell_effect_is(
36                ctx.state.config.game_data.effect_type(spell, effect_index),
37                wowlab_engine_domain::dbc::SpellEffectKind::HealthLeech,
38            )
39        })
40        .map_or(0.0, |effect_index| {
41            let amplitude = ctx.state.config.game_data.amplitude(spell, effect_index);
42
43            buffs::active_effect_amplitude(ctx.view().for_actor(ctx.source), spell, amplitude)
44                .max(0.0)
45        });
46    let fraction = leech_percent.max(0.0) / HUNDRED + health_leech_fraction;
47
48    if fraction <= f64::EPSILON {
49        return;
50    }
51
52    let school = school_of(ctx.state, event.spell_id);
53    let _ = deal_heal(
54        ctx.state,
55        ctx.buf,
56        ctx.rng,
57        HealRequest {
58            source: ctx.source,
59            target: ctx.source,
60            base: actual_damage * fraction,
61            percent_of_max: 0.0,
62            school,
63            periodic: event.is_periodic,
64            may_crit: false,
65            at: ctx.now,
66        },
67    );
68}