wowlab_engine_content/hooks/demonology_warlock/
handler.rs1use 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 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}