Skip to main content

wowlab_engine_content/
composition.rs

1//! Canonical composition of generated combat systems with shared and specialization content.
2
3#[cfg(test)]
4use wowlab_engine_combat::CombatHandler;
5use wowlab_engine_combat::{BuiltCombatSystem, CombatSystemDraft};
6use wowlab_engine_ports::{EngineError, HandlerParams};
7
8use crate::{
9    racials::racial_spec,
10    raid_buffs::{
11        PrecombatBuffSpec, augment_rune_spec, bloodlust_spec, flask_spec, register_external_buffs,
12        register_precombat_buffs, tempered_potion_spec,
13    },
14    weapon_enchants::register_weapon_enchant_procs,
15};
16
17#[derive(Debug)]
18pub(crate) struct ContentHandlerParts<'a> {
19    draft: CombatSystemDraft,
20    rotation: &'a wowlab_types::sim::Rotation,
21}
22
23impl ContentHandlerParts<'_> {
24    pub(crate) fn draft_mut(&mut self) -> &mut CombatSystemDraft {
25        &mut self.draft
26    }
27
28    pub(crate) fn finalize(self) -> Result<BuiltCombatSystem, EngineError> {
29        self.draft.finalize(self.rotation)
30    }
31
32    #[cfg(test)]
33    pub(crate) fn into_handler(self) -> Result<CombatHandler, EngineError> {
34        self.finalize().map(CombatHandler::from_built)
35    }
36}
37
38pub(crate) fn compose_handler<T>(
39    build_system: for<'a> fn(&HandlerParams<'a>) -> Result<CombatSystemDraft, EngineError>,
40    params: &HandlerParams<'_>,
41    finish: impl FnOnce(ContentHandlerParts<'_>, &HandlerParams<'_>) -> Result<T, EngineError>,
42) -> Result<T, EngineError> {
43    let mut draft = build_system(params)?;
44
45    register_shared_content(&mut draft, params)?;
46
47    finish(
48        ContentHandlerParts {
49            draft,
50            rotation: params.rotation,
51        },
52        params,
53    )
54}
55
56fn register_shared_content(
57    draft: &mut CombatSystemDraft,
58    params: &HandlerParams<'_>,
59) -> Result<(), EngineError> {
60    draft.set_bug_toggles(wowlab_engine_ports::resolve_bug_toggles(&params.bugs)?);
61    draft.set_cast_latency(params.cast_latency);
62    draft.set_raid_events(params.raid_events);
63    draft.set_external_buffs(params.external_buffs);
64
65    let mut precombat = Vec::<PrecombatBuffSpec>::new();
66
67    if params.bloodlust {
68        precombat.push(bloodlust_spec());
69    }
70
71    if params.pre_pot_tempered {
72        precombat.push(tempered_potion_spec());
73    }
74
75    if params.flask {
76        precombat.push(flask_spec());
77    }
78
79    if params.augment_rune {
80        precombat.push(augment_rune_spec());
81    }
82
83    if let Some(racial) = racial_spec(params.race) {
84        precombat.push(racial);
85    }
86
87    register_precombat_buffs(draft, &params.game_data, &precombat)?;
88    register_external_buffs(draft, &params.game_data, params.external_buffs)?;
89    register_weapon_enchant_procs(draft, params.weapon_enchant_procs)?;
90
91    crate::expansion_traits::register(draft, params)
92}
93
94#[cfg(test)]
95mod tests;