wowlab_engine_domain/dbc/passives/
resource.rs1use std::{collections::HashSet, hash::BuildHasher};
2
3use super::{
4 AuraSubtypeKind, ModifierFold, ModifierOperation, ModifierPropertyKind, PassiveQuery,
5 SpellDataFlat, aura_kind, aura_subtype_semantic, effect_targets_spell, fold_flat_pct_modifiers,
6 modified_effect_base_points, modifier_property_kind, pct_to_mult, power_cost_is_available,
7};
8
9#[must_use]
11pub fn passive_resource_cost<S>(
12 query: PassiveQuery<'_>,
13 resource_type: i32,
14 base_cost: f64,
15 active_aura_spell_ids: &HashSet<i32, S>,
16 modifiers: &crate::dbc::PowerModifiers,
17) -> f64
18where
19 S: BuildHasher,
20{
21 let PassiveQuery { passives, spell } = query;
22 let Some(cost_index) = spell.power_costs.iter().position(|cost| {
23 cost.power_type == resource_type && power_cost_is_available(cost, active_aura_spell_ids)
24 }) else {
25 return base_cost;
26 };
27 let property = match cost_index {
28 0 => ModifierPropertyKind::ResourceCost1,
29 1 => ModifierPropertyKind::ResourceCost2,
30 2 => ModifierPropertyKind::ResourceCost3,
31 _ => return base_cost,
32 };
33
34 fold_flat_pct_modifiers(
35 passives,
36 base_cost,
37 ModifierFold::FlatAndPercent,
38 |source, ranks, modifier| {
39 if modifier_property_kind(modifier) != Some(property)
40 || !effect_targets_spell(modifier, source, spell)
41 {
42 return None;
43 }
44
45 let amount = modified_effect_base_points(
46 PassiveQuery {
47 passives,
48 spell: source,
49 },
50 modifier.index,
51 modifier.base_points,
52 ) * ranks;
53 let is_flat = aura_subtype_semantic(modifier.aura)
54 .and_then(|semantic| semantic.modifier)
55 .is_some_and(|(operation, _)| operation == ModifierOperation::Flat);
56
57 Some(if is_flat {
58 crate::dbc::decode::scale_power_amount(amount, resource_type, modifiers)
59 } else {
60 amount
61 })
62 },
63 )
64 .max(0.0)
65}
66
67pub type RankedPassive = (SpellDataFlat, f64);
69
70#[must_use]
72pub fn passive_mana_regen_multiplier(passives: &[RankedPassive]) -> f64 {
73 passives.iter().fold(1.0, |multiplier, (spell, ranks)| {
74 spell
75 .effects
76 .iter()
77 .filter(|effect| aura_kind(effect) == Some(AuraSubtypeKind::ModManaRegenPercent))
78 .fold(multiplier, |value, effect| {
79 value * pct_to_mult(effect.base_points * ranks)
80 })
81 })
82}