wowlab_engine_content/hooks/arcane_mage/
handler.rs1use 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 ) -> Self {
25 let mut built = parts.into_built();
26
27 apply_arcane_max_mana(&mut built, params);
28 register_arcane(&mut built, params);
29
30 Self {
31 inner: CombatHandler::from_built(built),
32 fight_duration_ms: wowlab_types::numeric::f64_to_u32_saturating_trunc(params.fight_duration_secs * MS_PER_SECOND),
33 }
34 }
35}
36
37crate::hooks::define_spec_handler! {
38impl ArcaneHandler(self, inner) {
39 fn on_sim_start(&mut self, ctx: &mut SimContext) {
40 self.inner.on_sim_start(ctx);
41 if self
42 .inner
43 .state()
44 .spec_config::<ArcaneConfig>()
45 .is_some_and(|cfg| cfg.arcane_familiar)
46 {
47 self.inner
48 .with_hook_ctx(&mut *ctx.telemetry, wowlab_engine_combat::HookCtxRequest::targetless(wowlab_types::sim::SimTime::ZERO), |precombat| {
49 let _ = precombat.summon_guardian(
50 GuardianSpec::new_inheriting_owner(
51 REPORTED_SPELL::ARCANE_FAMILIAR,
52 self.fight_duration_ms.saturating_add(1),
53 )
54 .ability(
55 GuardianAbility::new(
56 ARCANE_FAMILIAR_PERIOD_MS,
57 arcane_familiar_action,
58 )
59 .first_action_delay(ARCANE_FAMILIAR_PERIOD_MS)
60 .hasted_actions(),
61 ),
62 );
63 });
64 }
65 }
66
67}
68}