Skip to main content

wowlab_engine_combat/builder/spell_builder/
damage.rs

1use super::{
2    BuilderDamageDef, BuilderError, BuilderSpellEffect, DamageEffectRef, DamageFlags,
3    ResolvedDamageDef, SpellDefinitionDraft, attribute_damage_flags,
4};
5
6impl SpellDefinitionDraft {
7    pub fn damage_flat(mut self, amount: f64) -> Self {
8        self.damage = BuilderDamageDef::Flat(amount);
9        self.base_points = 0.0;
10
11        self
12    }
13
14    pub fn damage_ap(self, coef: f64, flags: DamageFlags) -> Self {
15        self.damage_ap_typed(coef, flags, crate::state::WeaponApType::MainHand)
16    }
17
18    pub fn damage_ap_typed(
19        mut self,
20        coef: f64,
21        flags: DamageFlags,
22        ap_type: crate::state::WeaponApType,
23    ) -> Self {
24        self.damage = BuilderDamageDef::ApCoefficient {
25            coef,
26            is_physical: flags.contains(DamageFlags::PHYSICAL),
27            ap_type,
28        };
29        self.damage_may_crit = !flags.contains(DamageFlags::NO_CRIT);
30        self.damage_attribute_flags = attribute_damage_flags(flags);
31        self.base_points = 0.0;
32
33        self
34    }
35
36    pub fn damage_sp(mut self, coef: f64, flags: DamageFlags) -> Self {
37        self.damage = BuilderDamageDef::SpCoefficient {
38            coef,
39            is_physical: flags.contains(DamageFlags::PHYSICAL),
40        };
41        self.damage_may_crit = !flags.contains(DamageFlags::NO_CRIT);
42        self.damage_attribute_flags = attribute_damage_flags(flags);
43        self.base_points = 0.0;
44
45        self
46    }
47
48    /// Applies a resolved data-driven damage definition.
49    ///
50    /// # Errors
51    ///
52    /// Returns an error when the resolved damage kind has no builder representation.
53    pub fn damage_auto(mut self, def: ResolvedDamageDef) -> Result<Self, BuilderError> {
54        let flags = if def.is_physical {
55            DamageFlags::PHYSICAL
56        } else {
57            DamageFlags::empty()
58        };
59
60        self.damage = BuilderDamageDef::from_resolved(def, 1.0)
61            .ok_or(crate::builder::BuilderErrorKind::UnsupportedDamageKind)?;
62        self.damage_may_crit = true;
63        self.damage_attribute_flags = attribute_damage_flags(flags);
64        self.base_points = crate::state::resolved_damage_base_points(def, 1.0);
65
66        Ok(self)
67    }
68
69    /// Suppress damage inferred by [`Self::apply_base_from_data`].
70    pub fn without_data_damage(mut self) -> Self {
71        self.infer_data_damage = false;
72        self.damage = BuilderDamageDef::None;
73        self.damage_effect = None;
74        self.base_points = 0.0;
75        self.followup_effects
76            .retain(|effect| !matches!(effect, BuilderSpellEffect::Damage { .. }));
77
78        self
79    }
80
81    /// Suppress only the parent's inferred payload while retaining DBC trigger-child damage.
82    pub fn without_primary_data_damage(mut self) -> Self {
83        self.infer_data_damage = true;
84        self.damage = BuilderDamageDef::None;
85        self.damage_effect = None;
86        self.base_points = 0.0;
87
88        self
89    }
90
91    pub(crate) fn damage_effect(mut self, spell_id: u32, effect_index: u8) -> Self {
92        self.damage_effect = Some(DamageEffectRef::new(spell_id, effect_index));
93
94        self
95    }
96}