wowlab_engine_domain/dbc/game_data/
triggered_damage.rs1use wowlab_types::sim::EffectRef;
2
3use super::{
4 super::EffectLookup,
5 damage_def::actual_damage_def,
6 error::TriggerResolveError,
7 trigger_program::{MAX_TRIGGER_DEPTH, TriggerPath, TriggeredDamage},
8};
9
10pub fn resolve_triggered_damage(
16 lookup: EffectLookup<'_>,
17) -> Result<TriggeredDamage, TriggerResolveError> {
18 let data = lookup.data;
19 let EffectRef {
20 spell: source,
21 effect_index,
22 } = lookup.effect;
23 let mut current = lookup
24 .trigger_spell()
25 .ok_or_else(|| TriggerResolveError::missing_edge(source.as_u32(), effect_index))?;
26 let mut path = TriggerPath::new(source);
27
28 for depth in 1..=MAX_TRIGGER_DEPTH {
29 path.enter(current, depth)?;
30
31 if let Some(damage) = actual_damage_def(data, current) {
32 return Ok(TriggeredDamage {
33 spell_id: current,
34 damage,
35 requires_main_hand: data.requires_main_hand(current).unwrap_or(false),
36 requires_off_hand: data.requires_off_hand(current).unwrap_or(false),
37 equipped_item_requirement: data.equipped_item_requirement(current),
38 });
39 }
40
41 let current_id = current.as_u32();
42 let mut children = (1..=data.max_effect_index(current))
43 .filter_map(|index| data.trigger_spell(current, index));
44 let Some(next) = children.next() else {
45 return Err(TriggerResolveError::missing_damage(current_id));
46 };
47
48 if children.next().is_some() {
49 return Err(TriggerResolveError::ambiguous_forward(current_id));
50 }
51
52 current = next;
53 }
54
55 Err(TriggerResolveError::depth_exceeded(source.as_u32()))
56}