wowlab_engine_content/hooks/demonology_warlock/
handler.rs1use wowlab_engine_combat::AuraOps as _;
2use wowlab_engine_combat::GuardianOps 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, DemonologyRuntime},
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 ) -> Result<Self, wowlab_engine_ports::EngineError> {
33 let mut parts = parts;
34 let built = parts.draft_mut();
35 let inner_demons = params.talent_ranks(TALENT::INNER_DEMONS) > 0;
36
37 apply_demonic_calling(built, params.talent_ranks(TALENT::DEMONIC_CALLING));
38 register_demonology_config(built, params);
39 built.set_spec_runtime(DemonologyRuntime::default());
40
41 let built = parts.finalize()?;
42
43 Ok(Self {
44 inner: CombatHandler::from_built(built),
45 inner_demons,
46 fight_duration_ms: wowlab_types::numeric::f64_to_u32_saturating_trunc(
47 params.fight_duration_secs * MS_PER_SECOND,
48 ),
49 })
50 }
51}
52
53crate::hooks::define_spec_handler! {
54impl DemonologyHandler(self, inner) {
55 fn on_sim_start(&mut self, ctx: &mut SimContext) {
56 self.inner.on_sim_start(ctx);
57 let duration_ms = self.fight_duration_ms.saturating_add(1);
58 self.inner
59 .with_hook_ctx(&mut *ctx.telemetry, wowlab_engine_combat::HookCtxRequest::targetless(wowlab_types::sim::SimTime::ZERO), |precombat| {
60 let _ = precombat.summon_guardian(
61 GuardianSpec::new_inheriting_owner(
62 REPORTED_SPELL::LEGION_STRIKE,
63 duration_ms,
64 )
65 .ability(
66 GuardianAbility::new(
67 FELGUARD_CONTROLLER_TICK_MS,
68 felguard_controller_action,
69 )
70 .first_action_delay(FELGUARD_CONTROLLER_TICK_MS),
71 ),
72 );
73 });
74 if !self.inner_demons {
75 return;
76 }
77
78 self.inner
79 .with_hook_ctx(&mut *ctx.telemetry, wowlab_engine_combat::HookCtxRequest::targetless(wowlab_types::sim::SimTime::ZERO), |precombat| {
80 let first_spawn_ms = wowlab_types::numeric::f64_to_u32_saturating_trunc(
81 (precombat.rng())() * f64::from(INNER_DEMONS_PERIOD_MS),
82 );
83 precombat.apply_aura(AURA_INNER_DEMONS);
84 let _ = precombat.summon_guardian(
85 GuardianSpec::new_inheriting_owner(AURA::INNER_DEMONS, duration_ms).ability(
86 GuardianAbility::new(INNER_DEMONS_PERIOD_MS, inner_demons_action)
87 .first_action_delay(first_spawn_ms),
88 ),
89 );
90 });
91 }
92
93}
94}