wowlab_engine_content/hooks/elemental_shaman/
elementals.rs1use 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}