Skip to main content

wowlab_parsers/parsers/transform/loot/
item_bonus.rs

1use wowlab_types::data::{
2    ChallengeModeItemBonusOverride, DelvesSeason, Difficulty, ItemBonusListGroup,
3    ItemBonusSequenceSpell, ItemConversionFlat, ItemGroupIlvlScalingEntry, ItemLevelSelector,
4    ItemLevelSelectorQuality, ItemLevelSelectorQualitySet,
5};
6
7use super::shared::difficulty_kind;
8use crate::parsers::dbc::DbcData;
9
10/// 1:1 transform of `ItemBonusListGroup` rows.
11#[must_use]
12pub fn transform_all_item_bonus_list_groups(dbc: &DbcData) -> Vec<ItemBonusListGroup> {
13    dbc.item_bonus_list_group
14        .values()
15        .map(|row| ItemBonusListGroup {
16            id: row.ID,
17            sequence_spell_id: row.SequenceSpellID,
18            player_condition_id: row.PlayerConditionID,
19            item_extended_cost_id: row.ItemExtendedCostID,
20            item_logical_cost_group_id: row.ItemLogicalCostGroupID,
21            item_group_ilvl_scaling_id: row.ItemGroupIlvlScalingID,
22        })
23        .collect()
24}
25
26/// 1:1 transform of `ItemGroupIlvlScalingEntry` rows.
27#[must_use]
28pub fn transform_all_item_group_ilvl_scaling_entries(
29    dbc: &DbcData,
30) -> Vec<ItemGroupIlvlScalingEntry> {
31    dbc.item_group_ilvl_scaling_entry
32        .values()
33        .flatten()
34        .map(|row| ItemGroupIlvlScalingEntry {
35            id: row.ID,
36            currency_type_id: row.CurrencyTypeID,
37            item_id: row.ItemID,
38            cost_scaling: row.CostScaling,
39            flags: row.Flags,
40            player_condition_id: row.PlayerConditionID,
41            conditional_cost_scaling: row.ConditionalCostScaling,
42            item_group_ilvl_scaling_id: row.ItemGroupIlvlScalingID,
43        })
44        .collect()
45}
46
47/// 1:1 transform of `ItemLevelSelector` rows.
48#[must_use]
49pub fn transform_all_item_level_selectors(dbc: &DbcData) -> Vec<ItemLevelSelector> {
50    dbc.item_level_selector
51        .values()
52        .map(|row| ItemLevelSelector {
53            id: row.ID,
54            min_item_level: row.MinItemLevel,
55            item_level_selector_quality_set_id: row.ItemLevelSelectorQualitySetID,
56            azerite_unlock_mapping_set_id: row.AzeriteUnlockMappingSetID,
57        })
58        .collect()
59}
60
61/// 1:1 transform of `ItemLevelSelectorQualitySet` rows.
62#[must_use]
63pub fn transform_all_item_level_selector_quality_sets(
64    dbc: &DbcData,
65) -> Vec<ItemLevelSelectorQualitySet> {
66    dbc.item_level_selector_quality_set
67        .values()
68        .map(|row| ItemLevelSelectorQualitySet {
69            id: row.ID,
70            ilvl_rare: row.IlvlRare,
71            ilvl_epic: row.IlvlEpic,
72        })
73        .collect()
74}
75
76/// 1:1 transform of `ItemLevelSelectorQuality` rows.
77#[must_use]
78pub fn transform_all_item_level_selector_qualities(dbc: &DbcData) -> Vec<ItemLevelSelectorQuality> {
79    dbc.item_level_selector_quality
80        .values()
81        .map(|row| ItemLevelSelectorQuality {
82            id: row.ID,
83            quality_item_bonus_list_id: row.QualityItemBonusListID,
84            quality: row.Quality,
85            parent_ils_quality_set_id: row.ParentILSQualitySetID,
86        })
87        .collect()
88}
89
90/// Walk every `ItemConversion` row, attach embedded child item IDs from `ItemConversionEntry`, and skip parents with no entries.
91#[must_use]
92pub fn transform_all_item_conversions(dbc: &DbcData) -> Vec<ItemConversionFlat> {
93    dbc.item_conversion
94        .values()
95        .filter_map(|row| {
96            let entries = dbc.item_conversion_entry.get(&row.ID)?;
97
98            if entries.is_empty() {
99                return None;
100            }
101
102            let items: Vec<i32> = entries.iter().map(|e| e.ItemID).collect();
103
104            Some(ItemConversionFlat {
105                id: row.ID,
106                item_bonus_tree_id: row.ItemBonusTreeID,
107                item_logical_cost_group_id: row.ItemLogicalCostGroupID,
108                alternate_item_logical_cost_group_id: row.AlternateItemLogicalCostGroupID,
109                player_condition_id: row.PlayerConditionID,
110                flags: row.Flags,
111                items,
112            })
113        })
114        .collect()
115}
116
117/// 1:1 transform of `ChallengeModeItemBonusOverride` rows.
118#[must_use]
119pub fn transform_all_challenge_mode_item_bonus_overrides(
120    dbc: &DbcData,
121) -> Vec<ChallengeModeItemBonusOverride> {
122    dbc.challenge_mode_item_bonus_override
123        .values()
124        .map(|row| ChallengeModeItemBonusOverride {
125            id: row.ID,
126            item_bonus_tree_group_id: row.ItemBonusTreeGroupID,
127            dst_item_bonus_tree_id: row.DstItemBonusTreeID,
128            value: row.Value,
129            required_time_event_passed: row.RequiredTimeEventPassed,
130            required_time_event_not_passed: row.RequiredTimeEventNotPassed,
131            src_item_bonus_tree_id: row.SrcItemBonusTreeID,
132        })
133        .collect()
134}
135
136/// 1:1 transform of `ItemBonusSequenceSpell` rows.
137#[must_use]
138pub fn transform_all_item_bonus_sequence_spells(dbc: &DbcData) -> Vec<ItemBonusSequenceSpell> {
139    dbc.item_bonus_sequence_spell
140        .values()
141        .map(|row| ItemBonusSequenceSpell {
142            id: row.ID,
143            spell_id: row.SpellID,
144            item_id: row.ItemID,
145        })
146        .collect()
147}
148
149/// 1:1 transform of `DelvesSeason` rows.
150#[must_use]
151pub fn transform_all_delves_seasons(dbc: &DbcData) -> Vec<DelvesSeason> {
152    dbc.delves_season
153        .values()
154        .map(|row| DelvesSeason {
155            id: row.ID,
156            faction_id: row.FactionID,
157        })
158        .collect()
159}
160
161/// 1:1 transform of `Difficulty` rows + derived `kind`.
162#[must_use]
163pub fn transform_all_difficulties(dbc: &DbcData) -> Vec<Difficulty> {
164    dbc.difficulty
165        .values()
166        .map(|row| Difficulty {
167            id: row.ID,
168            name: row.Name_lang.clone().unwrap_or_default(),
169            instance_type: row.InstanceType,
170            order_index: row.OrderIndex,
171            min_players: row.MinPlayers,
172            max_players: row.MaxPlayers,
173            flags: row.Flags,
174            item_context: row.ItemContext,
175            kind: difficulty_kind(row.InstanceType),
176        })
177        .collect()
178}
179
180#[cfg(test)]
181mod tests {
182    use googletest::prelude::*;
183    use wowlab_types::data::DifficultyKind;
184
185    use super::*;
186    use crate::parsers::transform::fixtures::{
187        dbc, difficulty_row, item_conversion_entry_row, item_conversion_row,
188    };
189
190    #[gtest]
191    fn transform_all_item_conversions_attaches_and_drops() -> Result<()> {
192        let mut dbc = dbc();
193
194        dbc.item_conversion.insert(1, item_conversion_row(1));
195        dbc.item_conversion.insert(2, item_conversion_row(2));
196        dbc.item_conversion_entry.insert(
197            1,
198            vec![
199                item_conversion_entry_row(10, 1, 100),
200                item_conversion_entry_row(11, 1, 200),
201            ],
202        );
203
204        let out = transform_all_item_conversions(&dbc);
205
206        verify_that!(out.len(), eq(1))?;
207
208        verify_that!(
209            &out,
210            contains(matches_pattern!(ItemConversionFlat {
211                id: eq(&1),
212                flags: eq(&1),
213                items: eq(&vec![100, 200]),
214                ..
215            }))
216        )
217    }
218
219    #[gtest]
220    fn transform_all_difficulties_derives_kind_and_name() -> Result<()> {
221        let mut dbc = dbc();
222
223        dbc.difficulty.insert(2, difficulty_row(2, 2, None));
224
225        let out = transform_all_difficulties(&dbc);
226
227        verify_that!(
228            &out,
229            contains(matches_pattern!(Difficulty {
230                id: eq(&2),
231                kind: eq(&DifficultyKind::Raid),
232                name: eq(""),
233                ..
234            }))
235        )
236    }
237}