Skip to main content

wowlab_parsers/parsers/transform/
expansion_trait.rs

1use wowlab_engine_domain::dbc::TraitTreeIndex;
2use wowlab_types::{
3    data::{ExpansionTraitTreeFlat, TraitEdge},
4    sim::{FastSet, IntMap},
5};
6
7use super::{
8    super::{dbc::DbcData, errors::TransformError},
9    r#trait::{TraitNodeIndexes, build_node_entries_map, build_talent_node, collect_edges},
10};
11
12/// Midnight's class-agnostic Omnium Folio tree (`TraitTree.ID = 1186`).
13pub const OMNIUM_TRAIT_TREE_ID: i32 = 1186;
14pub const OMNIUM_SYSTEM: &str = "omnium";
15pub const MIDNIGHT_EXPANSION_ID: i32 = 11;
16
17pub(super) fn transform_expansion_trait_tree(
18    dbc: &DbcData,
19    expansion_id: i32,
20    system: &str,
21    tree_id: i32,
22) -> Result<ExpansionTraitTreeFlat, TransformError> {
23    let tree_nodes = dbc
24        .trait_node_by_tree
25        .get(&tree_id)
26        .ok_or_else(|| TransformError::trait_tree_not_found(tree_id))?;
27    let node_ids: Vec<i32> = tree_nodes.iter().map(|node| node.ID).collect();
28    let node_id_set: FastSet<i32> = node_ids.iter().copied().collect();
29    let indexes = TraitNodeIndexes {
30        node_entries: build_node_entries_map(dbc, tree_nodes),
31        hero_tree_offsets: IntMap::default(),
32        group_to_tree_index: IntMap::default(),
33        order_index: IntMap::default(),
34        spec_set_to_specs: IntMap::default(),
35    };
36
37    let mut nodes: Vec<_> = tree_nodes
38        .iter()
39        .filter_map(|node| {
40            build_talent_node(
41                dbc,
42                node,
43                &indexes,
44                0,
45                Some(TraitTreeIndex::Expansion as i32),
46            )
47        })
48        .collect();
49
50    nodes.sort_by_key(|node| node.id);
51
52    let mut edges: Vec<_> = collect_edges(dbc, &node_ids, &node_id_set)
53        .into_iter()
54        .map(|edge| TraitEdge {
55            id: edge.ID,
56            from_node_id: edge.LeftTraitNodeID,
57            to_node_id: edge.RightTraitNodeID,
58            visual_style: edge.VisualStyle,
59        })
60        .collect();
61
62    edges.sort_by_key(|edge| edge.id);
63
64    let max_points = dbc
65        .trait_tree_x_trait_currency
66        .get(&tree_id)
67        .into_iter()
68        .flatten()
69        .filter_map(|tree_currency| {
70            dbc.trait_currency_source
71                .get(&tree_currency.TraitCurrencyID)
72        })
73        .flatten()
74        .map(|source| source.Amount)
75        .sum();
76
77    let mut all_node_ids = node_ids;
78
79    all_node_ids.sort_unstable();
80
81    Ok(ExpansionTraitTreeFlat {
82        expansion_id,
83        system: system.to_string(),
84        tree_id,
85        all_node_ids,
86        nodes,
87        edges,
88        max_points,
89    })
90}
91
92/// Transform every expansion-owned tree supported by this client-data snapshot.
93#[must_use]
94pub fn transform_all_expansion_trait_trees(dbc: &DbcData) -> Vec<ExpansionTraitTreeFlat> {
95    transform_expansion_trait_tree(
96        dbc,
97        MIDNIGHT_EXPANSION_ID,
98        OMNIUM_SYSTEM,
99        OMNIUM_TRAIT_TREE_ID,
100    )
101    .into_iter()
102    .collect()
103}