Skip to main content

wowlab_engine_content/hooks/arcane_mage/
handler.rs

1use wowlab_engine_combat::GuardianOps as _;
2use wowlab_engine_combat::{CombatHandler, GuardianAbility, GuardianSpec};
3use wowlab_engine_ports::{HandlerParams, SimContext};
4
5use wowlab_types::constants::MS_PER_SECOND;
6
7use crate::generated::specs::arcane_mage::REPORTED_SPELL;
8
9use super::{
10    config::{apply_arcane_max_mana, register_arcane, ArcaneConfig},
11    hooks::{arcane_familiar_action, ARCANE_FAMILIAR_PERIOD_MS},
12};
13
14#[derive(Debug)]
15pub(crate) struct ArcaneHandler {
16    inner: CombatHandler,
17    fight_duration_ms: u32,
18}
19
20impl ArcaneHandler {
21    pub(crate) fn new(
22        parts: crate::composition::ContentHandlerParts,
23        params: &HandlerParams<'_>,
24    ) -> Result<Self, wowlab_engine_ports::EngineError> {
25        let mut parts = parts;
26        let built = parts.draft_mut();
27
28        apply_arcane_max_mana(built, params);
29        register_arcane(built, params);
30
31        let built = parts.finalize()?;
32
33        Ok(Self {
34            inner: CombatHandler::from_built(built),
35            fight_duration_ms: wowlab_types::numeric::f64_to_u32_saturating_trunc(params.fight_duration_secs * MS_PER_SECOND),
36        })
37    }
38}
39
40crate::hooks::define_spec_handler! {
41impl ArcaneHandler(self, inner) {
42    fn on_sim_start(&mut self, ctx: &mut SimContext) {
43        self.inner.on_sim_start(ctx);
44        if self
45            .inner
46            .program()
47            .spec_config::<ArcaneConfig>()
48            .is_some_and(|cfg| cfg.arcane_familiar)
49        {
50            self.inner
51                .with_hook_ctx(&mut *ctx.telemetry, wowlab_engine_combat::HookCtxRequest::targetless(wowlab_types::sim::SimTime::ZERO), |precombat| {
52                    let _ = precombat.summon_guardian(
53                        GuardianSpec::new_inheriting_owner(
54                            REPORTED_SPELL::ARCANE_FAMILIAR,
55                            self.fight_duration_ms.saturating_add(1),
56                        )
57                        .ability(
58                            GuardianAbility::new(
59                                ARCANE_FAMILIAR_PERIOD_MS,
60                                arcane_familiar_action,
61                            )
62                            .first_action_delay(ARCANE_FAMILIAR_PERIOD_MS)
63                            .hasted_actions(),
64                        ),
65                    );
66                });
67        }
68    }
69
70}
71}