wowlab_engine_gamedata/game_data/
builder.rs1use std::sync::Arc;
6
7use wowlab_types::{
8 data::WeaponStats,
9 sim::{EffectRef, SpellIdx},
10};
11
12use super::{
13 AuraProps, ConsumableSpells, PowerTypeProps, ResolvedCurves, ResolvedGameData,
14 ResolvedGameDataInner, ResolvedGameTables, SpellProps,
15};
16
17#[derive(Debug)]
19pub struct ResolvedGameDataBuilder {
20 inner: ResolvedGameDataInner,
21}
22
23macro_rules! effect_insert {
24 (effect $ty:ty; $($method:ident => $field:ident),+ $(,)?) => {
25 $(
26 pub fn $method(&mut self, effect: EffectRef, value: $ty) {
27 self.inner
28 .effects.values
29 .entry(effect)
30 .or_default()
31 .$field = value;
32 }
33 )+
34 };
35 (parts $ty:ty; $($method:ident => $field:ident),+ $(,)?) => {
36 $(
37 pub fn $method(&mut self, spell_id: SpellIdx, effect_index: u8, value: $ty) {
38 self.inner
39 .effects.values
40 .entry(EffectRef::new(spell_id, effect_index))
41 .or_default()
42 .$field = value;
43 }
44 )+
45 };
46}
47
48impl ResolvedGameDataBuilder {
49 pub(crate) fn new() -> Self {
50 Self {
51 inner: ResolvedGameDataInner::default(),
52 }
53 }
54
55 pub fn insert_implicit_targets(&mut self, effect: EffectRef, target_a: i32, target_b: i32) {
56 let values = self.inner.effects.values.entry(effect).or_default();
57
58 values.implicit_target_a = target_a;
59 values.implicit_target_b = target_b;
60 }
61
62 pub fn insert_effect_class_mask(
64 &mut self,
65 spell_id: SpellIdx,
66 effect_index: u8,
67 mask: [i32; super::CLASS_FAMILY_FLAGS],
68 ) {
69 self.inner
70 .effects
71 .values
72 .entry(EffectRef::new(spell_id, effect_index))
73 .or_default()
74 .class_mask = mask;
75 }
76
77 pub fn insert_school_mask(&mut self, spell_id: SpellIdx, school_mask: i32) {
78 self.inner
79 .effects
80 .school_masks
81 .insert(spell_id, school_mask);
82 }
83
84 pub fn insert_spell_props(&mut self, spell_id: SpellIdx, props: SpellProps) {
85 self.inner
86 .spells
87 .props
88 .insert(spell_id, super::normalize_spell_modifier_defaults(props));
89 }
90
91 pub fn insert_server_proc_attributes(&mut self, spell_id: SpellIdx, attributes: u32) -> bool {
93 let Some(props) = self.inner.spells.props.get_mut(&spell_id) else {
94 return false;
95 };
96
97 props.proc_attributes = attributes;
98
99 true
100 }
101
102 pub fn insert_aura_props(&mut self, spell_id: SpellIdx, props: AuraProps) {
103 self.inner.spells.aura_props.insert(spell_id, props);
104 }
105
106 pub fn insert_power_type(&mut self, type_id: i32, props: PowerTypeProps) {
107 self.inner.spells.power_types.insert(type_id, props);
108 }
109
110 pub fn power_type_mut(&mut self, type_id: i32) -> Option<&mut PowerTypeProps> {
112 self.inner.spells.power_types.get_mut(&type_id)
113 }
114
115 pub fn insert_spell_override(&mut self, overridden_id: SpellIdx, replacement_id: SpellIdx) {
116 self.inner
117 .spells
118 .overrides
119 .insert(overridden_id, replacement_id);
120 }
121
122 pub fn insert_spell_learn(&mut self, teacher_id: SpellIdx, learned_id: SpellIdx) {
123 let learned = self.inner.spells.learns.entry(teacher_id).or_default();
124
125 if !learned.contains(&learned_id) {
126 learned.push(learned_id);
127 }
128 }
129
130 pub fn insert_spell_labels(&mut self, spell_id: SpellIdx, labels: Vec<i32>) {
132 self.inner.spells.labels.insert(spell_id, labels);
133 }
134
135 pub fn insert_spell_class_flags(
137 &mut self,
138 spell_id: SpellIdx,
139 class_set: i32,
140 class_mask: [i32; super::CLASS_FAMILY_FLAGS],
141 ) {
142 self.inner.spells.class_flags.insert(
143 spell_id,
144 super::SpellClassFlags {
145 class_set,
146 class_mask,
147 },
148 );
149 }
150
151 pub fn set_armor_constant(&mut self, value: f64) {
152 self.inner.environment.armor_constant = value;
153 }
154
155 pub fn set_creature_armor(&mut self, value: f64) {
156 self.inner.environment.creature_armor = value;
157 }
158
159 pub fn set_target_armor_mult(&mut self, value: f64) {
160 self.inner.environment.target_armor_mult = value;
161 }
162
163 pub fn set_armor_constant_mod(&mut self, value: f64) {
164 self.inner.environment.armor_constant_mod = value;
165 }
166
167 pub fn set_main_hand(&mut self, value: WeaponStats) {
168 self.inner.environment.main_hand = value;
169 }
170
171 pub fn set_off_hand(&mut self, value: Option<WeaponStats>) {
172 self.inner.environment.off_hand = value;
173 }
174
175 pub fn set_curves(&mut self, value: ResolvedCurves) {
176 self.inner.scaling.curves = value;
177 }
178
179 pub fn set_game_tables(&mut self, value: ResolvedGameTables) {
180 self.inner.scaling.game_tables = value;
181 }
182
183 pub fn set_level(&mut self, value: u32) {
184 self.inner.scaling.level = value;
185 }
186
187 pub fn set_auto_attack_damage_mult(&mut self, value: f64) {
188 self.inner.passives.auto_attack_damage_mult = value;
189 }
190
191 pub fn set_pet_damage_mult(&mut self, value: f64) {
192 self.inner.passives.pet_damage_mult = value;
193 }
194
195 pub fn set_guardian_damage_mult(&mut self, value: f64) {
196 self.inner.passives.guardian_damage_mult = value;
197 }
198
199 pub fn set_specialization_spells(&mut self, value: Vec<SpellIdx>) {
200 self.inner.spells.specialization = value;
201 }
202
203 pub fn set_folded_passive_spells(&mut self, value: Vec<SpellIdx>) {
204 self.inner.passives.folded_spells = value;
205 }
206
207 pub fn set_class_target_debuffs(&mut self, value: Vec<SpellIdx>) {
208 self.inner.passives.class_target_debuffs = value;
209 }
210
211 pub fn set_consumable_spells(&mut self, value: ConsumableSpells) {
212 self.inner.environment.consumables = value;
213 }
214
215 pub fn insert_direct_damage_mult(&mut self, spell_id: SpellIdx, mult: f64) {
216 self.inner
217 .passives
218 .direct_damage_mult
219 .insert(spell_id, mult);
220 }
221
222 pub fn insert_direct_damage_flat(
223 &mut self,
224 spell_id: SpellIdx,
225 amount: f64,
226 mastery_coefficient: f64,
227 ) {
228 self.inner
229 .passives
230 .direct_damage_flat
231 .insert(spell_id, amount);
232 self.inner
233 .passives
234 .direct_damage_flat_mastery
235 .insert(spell_id, mastery_coefficient);
236 }
237
238 pub fn insert_periodic_damage_mult(&mut self, spell_id: SpellIdx, mult: f64) {
239 self.inner
240 .passives
241 .periodic_damage_mult
242 .insert(spell_id, mult);
243 }
244
245 pub fn insert_crit_chance_bonus(&mut self, spell_id: SpellIdx, bonus: f64) {
247 self.inner
248 .passives
249 .crit_chance_bonus
250 .insert(spell_id, bonus);
251 }
252
253 pub fn insert_crit_chance_mult(&mut self, spell_id: SpellIdx, mult: f64) {
254 self.inner.passives.crit_chance_mult.insert(spell_id, mult);
255 }
256
257 pub fn insert_pet_stat_inheritance_mult(
259 &mut self,
260 npc_id: u32,
261 attack_power_mult: f64,
262 spell_power_mult: f64,
263 ) {
264 self.inner
265 .passives
266 .pet_attack_power_inheritance
267 .insert(npc_id, attack_power_mult);
268 self.inner
269 .passives
270 .pet_spell_power_inheritance
271 .insert(npc_id, spell_power_mult);
272 }
273
274 pub fn insert_crit_damage_bonus(&mut self, spell_id: SpellIdx, bonus: f64) {
276 self.inner
277 .passives
278 .crit_damage_bonus
279 .insert(spell_id, bonus);
280 }
281
282 pub fn push_crit_damage_per_crit_chance(&mut self, school_mask: i32, percent: f64) {
284 self.inner
285 .passives
286 .crit_damage_per_crit_chance
287 .push((school_mask, percent));
288 }
289
290 pub fn insert_crit_bonus_per_crit_chance(&mut self, spell_id: SpellIdx, percent: f64) {
292 self.inner
293 .passives
294 .crit_bonus_per_crit_chance
295 .insert(spell_id, percent);
296 }
297
298 #[must_use]
299 pub fn build(self) -> ResolvedGameData {
300 ResolvedGameData {
301 inner: Arc::new(self.inner),
302 }
303 }
304
305 effect_insert! {
306 effect i32;
307 insert_scaling_class => scaling_class,
308 insert_chain_targets => chain_targets,
309 insert_effect_type => effect_type,
310 insert_effect_mechanic => effect_mechanic,
311 insert_effect_attributes => effect_attributes,
312 insert_effect_aura => effect_aura,
313 insert_trigger_spell => trigger_spell,
314 insert_effect_misc_value_0 => misc_value_0,
315 insert_effect_misc_value_1 => misc_value_1,
316 insert_shapeshift_form_flags => shapeshift_form_flags,
317 }
318
319 effect_insert! {
320 parts i32;
321 insert_shapeshift_combat_round_time_ms => shapeshift_combat_round_time_ms,
322 }
323
324 effect_insert! {
325 parts f64;
326 insert_ap_coef => ap_coef,
327 insert_sp_coef => sp_coef,
328 insert_base_points => base_points,
329 insert_amplitude => amplitude,
330 insert_period => period,
331 insert_coefficient => coefficient,
332 insert_points_per_resource => points_per_resource,
333 insert_chain_multiplier => chain_multiplier,
334 insert_effect_radius => radius,
335 }
336
337 effect_insert! {
338 effect f64;
339 insert_power_coefficient_mastery_add => power_coefficient_mastery_add,
340 }
341}