Skip to main content

wowlab_engine_domain/dbc/game_data/
triggered_damage.rs

1use 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
10/// Follow a source effect to the first terminal child damage payload.
11///
12/// # Errors
13///
14/// Returns an error when the trigger graph cannot be resolved into supported damage operations.
15pub 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}