Skip to main content

wowlab_engine_content/hooks/demonology_warlock/
handler.rs

1use wowlab_engine_combat::GuardianOps as _;
2use wowlab_engine_combat::AuraOps as _;
3use wowlab_engine_combat::{CombatHandler, GuardianAbility, GuardianSpec};
4use wowlab_engine_ports::{HandlerParams, SimContext};
5
6use wowlab_types::constants::MS_PER_SECOND;
7
8use crate::generated::specs::demonology_warlock::{
9    AURA, AURA_INNER_DEMONS, REPORTED_SPELL, TALENT,
10};
11
12use super::{
13    config::{apply_demonic_calling, register_demonology_config},
14    hooks::{
15        felguard_controller_action, inner_demons_action, FELGUARD_CONTROLLER_TICK_MS,
16        INNER_DEMONS_PERIOD_MS,
17    },
18};
19
20#[derive(Debug)]
21pub(crate) struct DemonologyHandler {
22    inner: CombatHandler,
23    inner_demons: bool,
24    fight_duration_ms: u32,
25}
26
27impl DemonologyHandler {
28    /// Finishes the specialization handler from the shared-content composition stage.
29    pub(crate) fn new(
30        parts: crate::composition::ContentHandlerParts,
31        params: &HandlerParams<'_>,
32    ) -> Self {
33        let mut built = parts.into_built();
34        let inner_demons = params.talent_ranks(TALENT::INNER_DEMONS) > 0;
35
36        apply_demonic_calling(&mut built, params.talent_ranks(TALENT::DEMONIC_CALLING));
37        register_demonology_config(&mut built, params);
38
39        Self {
40            inner: CombatHandler::from_built(built),
41            inner_demons,
42            fight_duration_ms: wowlab_types::numeric::f64_to_u32_saturating_trunc(params.fight_duration_secs * MS_PER_SECOND),
43        }
44    }
45}
46
47crate::hooks::define_spec_handler! {
48impl DemonologyHandler(self, inner) {
49    fn on_sim_start(&mut self, ctx: &mut SimContext) {
50        self.inner.on_sim_start(ctx);
51        let duration_ms = self.fight_duration_ms.saturating_add(1);
52        self.inner
53            .with_hook_ctx(&mut *ctx.telemetry, wowlab_engine_combat::HookCtxRequest::targetless(wowlab_types::sim::SimTime::ZERO), |precombat| {
54            let _ = precombat.summon_guardian(
55                GuardianSpec::new_inheriting_owner(
56                    REPORTED_SPELL::LEGION_STRIKE,
57                    duration_ms,
58                )
59                .ability(
60                    GuardianAbility::new(
61                        FELGUARD_CONTROLLER_TICK_MS,
62                        felguard_controller_action,
63                    )
64                    .first_action_delay(FELGUARD_CONTROLLER_TICK_MS),
65                ),
66            );
67            });
68        if !self.inner_demons {
69            return;
70        }
71
72        self.inner
73            .with_hook_ctx(&mut *ctx.telemetry, wowlab_engine_combat::HookCtxRequest::targetless(wowlab_types::sim::SimTime::ZERO), |precombat| {
74                let first_spawn_ms = wowlab_types::numeric::f64_to_u32_saturating_trunc(
75                    (precombat.rng())() * f64::from(INNER_DEMONS_PERIOD_MS),
76                );
77                precombat.apply_aura(AURA_INNER_DEMONS.raw());
78                let _ = precombat.summon_guardian(
79                    GuardianSpec::new_inheriting_owner(AURA::INNER_DEMONS, duration_ms).ability(
80                        GuardianAbility::new(INNER_DEMONS_PERIOD_MS, inner_demons_action)
81                            .first_action_delay(first_spawn_ms),
82                    ),
83                );
84            });
85    }
86
87}
88}