Skip to main content

wowlab_engine_content/hooks/elemental_shaman/
elementals.rs

1use wowlab_engine_combat::DamageOps as _;
2use wowlab_engine_combat::GuardianOps as _;
3use wowlab_engine_combat::AuraOps as _;
4use wowlab_engine_combat::{DamageFlags, GuardianAbility, GuardianEvent, GuardianSpec, HookCtx};
5use wowlab_types::{constants::HUNDRED};
6
7use crate::generated::specs::elemental_shaman::{
8    AURA_FIRE_ELEMENTAL, AURA_STORM_ELEMENTAL, AURA_WIND_GUST,
9};
10
11pub(super) const STORM_ELEMENTAL_GUARDIAN_TAG: u32 = 262_001;
12const FIRE_ELEMENTAL_GUARDIAN_TAG: u32 = 262_002;
13const STORM_ELEMENTAL_DURATION_MS: u32 = 14_400;
14const FIRE_ELEMENTAL_DURATION_MS: u32 = 24_000;
15const PRIMAL_ELEMENTAL_OWNER_SP_MULT: f64 = 1.8;
16const STORM_ELEMENTAL_ACTION_MS: u32 = 2_000;
17const STORM_ELEMENTAL_FIRST_ACTION_MS: u32 = 500;
18const STORM_ELEMENTAL_MAX_ACTIONS: u16 = 7;
19const STORMFURY_TICKS: i32 = 4;
20const FIRE_ELEMENTAL_ACTION_MS: u32 = 2_500;
21const FIRE_ELEMENTAL_FIRST_ACTION_MS: u32 = 100;
22const FIRE_ELEMENTAL_MAX_ACTIONS: u16 = 11;
23
24fn storm_elemental_action(ctx: &mut HookCtx<'_>, event: GuardianEvent) {
25    match event.action_index {
26        0 => {
27            let coef = ctx.effect_sp_coefficient(crate::generated::specs::elemental_shaman::DAMAGE_EFFECT::CALL_LIGHTNING_DAMAGE)
28                * PRIMAL_ELEMENTAL_OWNER_SP_MULT;
29
30            ctx.deal_damage_sp(crate::generated::specs::elemental_shaman::DAMAGE_SPELL::CALL_LIGHTNING, coef, DamageFlags::PET);
31        }
32        1 => {
33            let coef = ctx.effect_sp_coefficient(crate::generated::specs::elemental_shaman::DAMAGE_EFFECT::STORMFURY_DAMAGE)
34                * PRIMAL_ELEMENTAL_OWNER_SP_MULT;
35            let charged = 1.0
36                + ctx.effect_base_points(crate::generated::specs::elemental_shaman::DAMAGE_EFFECT::CALL_LIGHTNING_DAMAGE_BONUS)
37                    / HUNDRED;
38            let ramp = 1.0 + ctx.effect_base_points(crate::generated::specs::elemental_shaman::DAMAGE_EFFECT::STORMFURY_RAMP) / HUNDRED;
39
40            for tick in 1_i32..=STORMFURY_TICKS {
41                ctx.deal_damage_sp(
42                    crate::generated::specs::elemental_shaman::DAMAGE_SPELL::STORMFURY,
43                    coef * charged * ramp.powi(tick),
44                    DamageFlags::PET,
45                );
46            }
47        }
48        _ => {
49            let coef = ctx.effect_sp_coefficient(crate::generated::specs::elemental_shaman::DAMAGE_EFFECT::WIND_GUST_DAMAGE)
50                * PRIMAL_ELEMENTAL_OWNER_SP_MULT;
51            let charged = 1.0
52                + ctx.effect_base_points(crate::generated::specs::elemental_shaman::DAMAGE_EFFECT::CALL_LIGHTNING_DAMAGE_BONUS)
53                    / HUNDRED;
54
55            ctx.deal_damage_sp(crate::generated::specs::elemental_shaman::DAMAGE_SPELL::WIND_GUST, coef * charged, DamageFlags::PET);
56        }
57    }
58}
59
60fn storm_elemental_demise(ctx: &mut HookCtx<'_>, _event: GuardianEvent) {
61    ctx.expire_aura(AURA_WIND_GUST);
62    ctx.expire_aura(AURA_STORM_ELEMENTAL);
63}
64
65fn fire_elemental_demise(ctx: &mut HookCtx<'_>, _event: GuardianEvent) {
66    ctx.expire_aura(AURA_FIRE_ELEMENTAL);
67}
68
69fn fire_elemental_action(ctx: &mut HookCtx<'_>, event: GuardianEvent) {
70    if event.action_index == 0 {
71        let meteor = ctx.effect_sp_coefficient(crate::generated::specs::elemental_shaman::DAMAGE_EFFECT::METEOR_DAMAGE)
72            * PRIMAL_ELEMENTAL_OWNER_SP_MULT;
73        let immolate = ctx.effect_sp_coefficient(crate::generated::specs::elemental_shaman::DAMAGE_EFFECT::IMMOLATE_DAMAGE)
74            * PRIMAL_ELEMENTAL_OWNER_SP_MULT;
75
76        ctx.deal_damage_sp(crate::generated::specs::elemental_shaman::DAMAGE_SPELL::METEOR, meteor, DamageFlags::PET);
77        ctx.deal_damage_sp(crate::generated::specs::elemental_shaman::DAMAGE_SPELL::IMMOLATE, immolate, DamageFlags::PET);
78    } else {
79        let blast = ctx.effect_sp_coefficient(crate::generated::specs::elemental_shaman::DAMAGE_EFFECT::FIRE_BLAST_DAMAGE)
80            * PRIMAL_ELEMENTAL_OWNER_SP_MULT;
81
82        ctx.deal_damage_sp(crate::generated::specs::elemental_shaman::DAMAGE_SPELL::FIRE_BLAST, blast, DamageFlags::PET);
83    }
84
85    let tick = ctx.effect_sp_coefficient(crate::generated::specs::elemental_shaman::DAMAGE_EFFECT::IMMOLATE_PERIODIC_DAMAGE)
86        * PRIMAL_ELEMENTAL_OWNER_SP_MULT;
87
88    ctx.deal_damage_sp(crate::generated::specs::elemental_shaman::DAMAGE_SPELL::IMMOLATE, tick, DamageFlags::PET);
89}
90
91pub(super) fn summon_storm_elemental(ctx: &mut HookCtx<'_>) {
92    ctx.apply_aura(AURA_STORM_ELEMENTAL);
93    let _ = ctx.summon_guardian(
94        GuardianSpec::new_inheriting_owner(
95            STORM_ELEMENTAL_GUARDIAN_TAG,
96            STORM_ELEMENTAL_DURATION_MS,
97        )
98        .ability(
99            GuardianAbility::new(STORM_ELEMENTAL_ACTION_MS, storm_elemental_action)
100                .first_action_delay(STORM_ELEMENTAL_FIRST_ACTION_MS)
101                .hasted_actions()
102                .max_actions(STORM_ELEMENTAL_MAX_ACTIONS)
103                .ends_guardian(),
104        )
105        .on_demise(storm_elemental_demise),
106    );
107}
108
109pub(super) fn summon_fire_elemental(ctx: &mut HookCtx<'_>) {
110    ctx.apply_aura(AURA_FIRE_ELEMENTAL);
111    let _ = ctx.summon_guardian(
112        GuardianSpec::new_inheriting_owner(FIRE_ELEMENTAL_GUARDIAN_TAG, FIRE_ELEMENTAL_DURATION_MS)
113            .ability(
114                GuardianAbility::new(FIRE_ELEMENTAL_ACTION_MS, fire_elemental_action)
115                    .first_action_delay(FIRE_ELEMENTAL_FIRST_ACTION_MS)
116                    .hasted_actions()
117                    .max_actions(FIRE_ELEMENTAL_MAX_ACTIONS)
118                    .ends_guardian(),
119            )
120            .on_demise(fire_elemental_demise),
121    );
122}