wowlab_engine_combat/builder/aura_builder/
from_data.rs1use wowlab_engine_domain::dbc::{
2 AuraSubtypeKind, EffectLookup, LiveDamageModifierKind, ModifierPropertyKind, aura_subtype_is,
3 aura_subtype_is_any, live_damage_modifier, modifier_property_is,
4};
5
6use super::{
7 AuraDefinitionDraft, apply_active_stat_effect, apply_actor_scope_from_data,
8 apply_automatic_periodic_effect, apply_critical_modifier_effect, apply_effect_points_modifier,
9 apply_non_passive_effect, apply_spell_modifier_effect, apply_timing_modifier_effect,
10};
11use crate::{
12 BuilderError,
13 state::{BuffEffect, DamageSource},
14};
15
16fn apply_foldable_effects(
18 mut aura: AuraDefinitionDraft,
19 lookup: EffectLookup<'_>,
20 folded_passive: bool,
21) -> Result<AuraDefinitionDraft, BuilderError> {
22 if folded_passive {
23 return Ok(aura);
24 }
25
26 aura = apply_effect_points_modifier(aura, lookup)?;
27 aura = apply_spell_modifier_effect(aura, lookup)?;
28 aura = apply_timing_modifier_effect(aura, lookup)?;
29 aura = apply_critical_modifier_effect(aura, lookup)?;
30 aura = apply_active_stat_effect(aura, lookup)?;
31 let spell_id = lookup.effect.spell.as_u32();
32 let effect_index = lookup.effect.effect_index;
33 let subtype = lookup.effect_aura();
34
35 if aura_subtype_is_any(
36 subtype,
37 &[
38 AuraSubtypeKind::AddPercentModifier,
39 AuraSubtypeKind::AddPercentLabelModifier,
40 ],
41 ) && modifier_property_is(lookup.effect_misc_value_0(), ModifierPropertyKind::Cooldown)
42 {
43 aura = aura.push_effect(BuffEffect::CooldownDurationPercent {
44 percent: lookup.base_points(),
45 source_spell_id: spell_id,
46 effect_index,
47 })?;
48 }
49
50 let subtype = lookup.effect_aura();
51
52 if aura_subtype_is(subtype, AuraSubtypeKind::SpellReflection) {
53 aura = aura.push_effect(BuffEffect::SpellReflection(
54 wowlab_engine_domain::dbc::SpellSchoolMask::CHAOS,
55 ))?;
56 } else if aura_subtype_is(subtype, AuraSubtypeKind::SpellReflectionSchool) {
57 aura = aura.push_effect(BuffEffect::SpellReflection(
58 wowlab_engine_domain::dbc::SpellSchoolMask::from_dbc(lookup.effect_misc_value_0()),
59 ))?;
60 } else if aura_subtype_is(subtype, AuraSubtypeKind::DeflectSpells) {
61 aura = aura.push_effect(BuffEffect::SpellDeflectChance(lookup.base_points()))?;
62 }
63
64 Ok(aura)
65}
66
67fn apply_damage_taken_effects(
68 mut aura: AuraDefinitionDraft,
69 lookup: EffectLookup<'_>,
70) -> Result<AuraDefinitionDraft, BuilderError> {
71 let spell_id = lookup.effect.spell.as_u32();
72 let effect_index = lookup.effect.effect_index;
73 let subtype = lookup.effect_aura();
74 let source = if aura_subtype_is(subtype, AuraSubtypeKind::ModDamageTakenFromCaster) {
75 Some(DamageSource::Player)
76 } else if aura_subtype_is(subtype, AuraSubtypeKind::ModDamageTakenFromCasterGuardian) {
77 Some(DamageSource::Guardian)
78 } else if aura_subtype_is(subtype, AuraSubtypeKind::ModDamageTakenFromCasterPet) {
79 Some(DamageSource::Pet)
80 } else {
81 None
82 };
83
84 if let Some(source) = source {
85 aura = aura.push_effect(BuffEffect::DamageTakenFromSource(
86 lookup.base_points(),
87 source,
88 ))?;
89 }
90
91 if live_damage_modifier(subtype, lookup.effect_misc_value_0())
92 == Some(LiveDamageModifierKind::DamageTakenFromCasterSpells)
93 {
94 aura = aura.push_effect(BuffEffect::DamageTakenFromSourceSpells {
95 percent: lookup.base_points(),
96 source_spell_id: spell_id,
97 effect_index,
98 source: DamageSource::Player,
99 })?;
100 }
101
102 Ok(aura)
103}
104
105pub(super) fn apply_base_effect(
106 aura: AuraDefinitionDraft,
107 lookup: EffectLookup<'_>,
108 folded_passive: bool,
109) -> Result<AuraDefinitionDraft, BuilderError> {
110 let spell_id = lookup.effect.spell.as_u32();
111 let effect_index = lookup.effect.effect_index;
112 let mut aura = apply_actor_scope_from_data(aura, lookup);
113
114 if aura.crowd_control.is_none()
115 && let Some(subtype) = wowlab_engine_domain::dbc::aura_subtype_kind(lookup.effect_aura())
116 {
117 aura.crowd_control = wowlab_engine_domain::dbc::crowd_control_semantic(subtype);
118 }
119
120 if aura_subtype_is(lookup.effect_aura(), AuraSubtypeKind::Shapeshift) {
121 aura.shapeshift_form = lookup.effect_misc_value_0();
122 aura.shapeshift_form_flags = lookup
123 .data
124 .shapeshift_form_flags(lookup.effect.spell, effect_index);
125 aura.shapeshift_combat_round_time_ms = u32::try_from(
126 lookup
127 .data
128 .shapeshift_combat_round_time_ms(lookup.effect.spell, effect_index),
129 )
130 .unwrap_or(0);
131 }
132
133 if aura_subtype_is(lookup.effect_aura(), AuraSubtypeKind::TriggerSpellOnExpire)
134 && let Some(trigger) = lookup.trigger_spell()
135 {
136 aura = aura.trigger_spell_on_expire(trigger.as_u32(), lookup.effect_misc_value_0() > 0);
137 }
138
139 if aura_subtype_is_any(
140 lookup.effect_aura(),
141 &[
142 AuraSubtypeKind::ModTimeRate,
143 AuraSubtypeKind::ModTimeRateLabel,
144 ],
145 ) {
146 aura = aura.push_effect(BuffEffect::AuraTimeRateFromEffect {
147 percent: lookup.base_points(),
148 source_spell_id: spell_id,
149 effect_index,
150 })?;
151 }
152
153 let aura = apply_automatic_periodic_effect(aura, lookup)?;
154 let aura = apply_non_passive_effect(aura, lookup)?;
155 let aura = apply_foldable_effects(aura, lookup, folded_passive)?;
156
157 apply_damage_taken_effects(aura, lookup)
158}