Skip to main content

wowlab_engine_application/game_data/
resolution_ids.rs

1//! Initial spell and aura closure for recursive game-data resolution.
2
3use std::collections::VecDeque;
4
5use wowlab_engine_ports::{SpellId, TalentSelection};
6use wowlab_types::sim::FastSet;
7
8/// The extra resolution seeds that passive resolution discovered before the recursive closure runs.
9pub(super) struct ResolvedPassiveSeeds<'a> {
10    pub overrides: &'a [(SpellId, SpellId)],
11    pub spec_spells: &'a [u32],
12    pub class_target_debuffs: &'a [u32],
13}
14
15pub(super) fn collect_resolution_ids(
16    spell_ids: &[u32],
17    aura_ids: &[u32],
18    extra_spell_ids: &[u32],
19    talents: &[TalentSelection],
20    seeds: &ResolvedPassiveSeeds<'_>,
21) -> (FastSet<u32>, FastSet<u32>, VecDeque<u32>) {
22    let ResolvedPassiveSeeds {
23        overrides,
24        spec_spells,
25        class_target_debuffs,
26    } = *seeds;
27    let mut all_spell_ids: FastSet<u32> = spell_ids.iter().copied().collect();
28    let mut aura_ids: FastSet<u32> = aura_ids.iter().copied().collect();
29
30    all_spell_ids.extend(talents.iter().map(|talent| talent.spell_id));
31
32    for (_, replacement_id) in overrides {
33        if let Ok(idx) = wowlab_types::sim::SpellIdx::try_from(*replacement_id) {
34            all_spell_ids.insert(idx.as_u32());
35        }
36    }
37
38    for &id in extra_spell_ids {
39        all_spell_ids.insert(id);
40        aura_ids.insert(id);
41    }
42
43    all_spell_ids.extend(spec_spells);
44    // The debuff is applied as an aura, so its duration and stack data must resolve too.
45    aura_ids.extend(class_target_debuffs);
46
47    if all_spell_ids.remove(&0) {
48        tracing::warn!("skipping spell/aura id 0 (placeholder with no game data)");
49    }
50
51    aura_ids.remove(&0);
52    all_spell_ids.extend(aura_ids.iter().copied());
53    let pending = all_spell_ids.iter().copied().collect();
54
55    (aura_ids, all_spell_ids, pending)
56}