wowlab_engine_content/hooks/beast_mastery_hunter/
config.rs1use wowlab_engine_combat::{
2 BuffEffect, CombatSystemDraft, DamageEffectRef, DamageReplication, DamageSource,
3};
4use wowlab_engine_domain::dbc::ResolvedGameDataEffectExt as _;
5use wowlab_engine_ports::HandlerParams;
6use wowlab_types::constants::HUNDRED;
7
8use crate::generated::specs::beast_mastery_hunter::{
9 AURA_BEAST_CLEAVE, DAMAGE_EFFECT, EFFECT, SET_BONUS,
10};
11
12#[derive(Clone, Copy, Debug, Default)]
13pub(super) struct BeastMasteryConfig {
14 pub(super) mid2_extra_stomp_mult: f64,
15 pub(super) mid2_cobra_fang: bool,
16 pub(super) cobra_fang_cleave_per_stack: f64,
17 pub(super) cobra_fang_primary_per_stack: f64,
18}
19
20fn target_count(value: f64) -> Result<u8, wowlab_engine_ports::EngineError> {
21 if !value.is_finite()
22 || value < 0.0
23 || value > f64::from(u8::MAX)
24 || value.fract().abs() > f64::EPSILON
25 {
26 return Err(wowlab_engine_ports::EngineError::spec_construction(
27 "Beast Cleave reduced-target count must be an integer from 0 through 255",
28 ));
29 }
30
31 Ok(wowlab_types::numeric::f64_to_u8_saturating_trunc(value))
32}
33
34pub(super) fn register_beast_cleave(
35 built: &mut CombatSystemDraft,
36 params: &HandlerParams<'_>,
37) -> Result<(), wowlab_engine_ports::EngineError> {
38 let data = ¶ms.game_data;
39 let fraction = data.require_effect_base_points(EFFECT::BEAST_CLEAVE_FRACTION)? / HUNDRED;
40 let reduced_targets =
41 target_count(data.require_effect_base_points(EFFECT::BEAST_CLEAVE_REDUCED_TARGETS)?)?;
42
43 for (name, effect) in [
44 ("bm_stampede_damage", DAMAGE_EFFECT::STAMPEDE_DAMAGE),
45 ("bm_stampede_geometry", DAMAGE_EFFECT::STAMPEDE_GEOMETRY),
46 ] {
47 built.register_damage_effect_identity(name, effect);
48 }
49
50 built.set_aura_effect(
51 AURA_BEAST_CLEAVE,
52 BuffEffect::DamageReplication(DamageReplication {
53 fraction,
54 effect: DamageEffectRef::new(
55 EFFECT::BEAST_CLEAVE_DAMAGE.0,
56 EFFECT::BEAST_CLEAVE_DAMAGE.1,
57 ),
58 source: DamageSource::Pet,
59 source_spells: &[],
60 include_magic: false,
61 include_indirect: false,
62 include_primary: false,
63 max_targets: 0,
64 reduced_targets,
65 }),
66 );
67
68 built.set_spec_config(BeastMasteryConfig {
69 mid2_extra_stomp_mult: if params.set_bonus_auras.contains(&SET_BONUS::MID2_BM_2PC) {
70 data.require_effect_base_points(EFFECT::MID2_BM_2PC_EFFECTIVENESS)? / HUNDRED
71 } else {
72 0.0
73 },
74 mid2_cobra_fang: params.set_bonus_auras.contains(&SET_BONUS::MID2_BM_4PC),
75 cobra_fang_cleave_per_stack: data
76 .require_effect_base_points(EFFECT::COBRA_FANG_CLEAVE_PCT)?
77 / HUNDRED,
78 cobra_fang_primary_per_stack: data
79 .require_effect_base_points(EFFECT::COBRA_FANG_PRIMARY_PCT)?
80 / HUNDRED,
81 });
82
83 Ok(())
84}