1#![allow(non_snake_case, dead_code)]
4use wowlab_types::{combat::ResourceType, game::SpecId};
5use wowlab_engine_combat::{
6 BuiltCombatSystem, AuraDefinitionDraft, LocalAuraIdx, LocalSpellIdx,
7 SpellDefinitionDraft,
8};
9use wowlab_engine_ports::{
10 DeclaredSpecMetadata, SpecDescriptor, SpecHandler, HeroTalentTreeDesc,
11};
12use wowlab_engine_gamedata::ResolvedGameData;
13pub(crate) mod SPELL {
14 pub(crate) const LIGHTNING_BOLT: u32 = 188_196;
16 pub(crate) const CHAIN_LIGHTNING: u32 = 188_443;
18 pub(crate) const LAVA_BURST: u32 = 51505;
20 pub(crate) const EARTH_SHOCK: u32 = 8042;
22 pub(crate) const ELEMENTAL_BLAST: u32 = 117_014;
24 pub(crate) const EARTHQUAKE: u32 = 61882;
26 pub(crate) const FLAME_SHOCK: u32 = 188_389;
28 pub(crate) const FROST_SHOCK: u32 = 196_840;
30 pub(crate) const TEMPEST: u32 = 452_201;
32 pub(crate) const STORMKEEPER: u32 = 191_634;
34 pub(crate) const ASCENDANCE: u32 = 1_219_480;
36 pub(crate) const ANCESTRAL_SWIFTNESS: u32 = 443_454;
38 pub(crate) const FLAMETONGUE_WEAPON: u32 = 318_038;
40 pub(crate) const THUNDERSTRIKE_WARD: u32 = 462_757;
42 pub(crate) const LIGHTNING_SHIELD: u32 = 192_106;
44 pub(crate) const FIRE_ELEMENTAL: u32 = 188_592;
46 pub(crate) const FIRE_BLAST: u32 = 57984;
48 pub(crate) const METEOR: u32 = 117_588;
50 pub(crate) const IMMOLATE: u32 = 118_297;
52 pub(crate) const WIND_GUST: u32 = 157_331;
54 pub(crate) const CALL_LIGHTNING: u32 = 157_348;
56 pub(crate) const STORMFURY: u32 = 269_005;
58 pub(crate) const LIGHTNING_BOLT_OVERLOAD: u32 = 45284;
60 pub(crate) const CHAIN_LIGHTNING_OVERLOAD: u32 = 45297;
62 pub(crate) const LAVA_BURST_OVERLOAD: u32 = 285_466;
64 pub(crate) const ELEMENTAL_BLAST_OVERLOAD: u32 = 120_588;
66 pub(crate) const TEMPEST_OVERLOAD: u32 = 463_351;
68 pub(crate) const STORMS_EYE: u32 = 1_235_840;
70 pub(crate) const LIGHTNING_ROD_DAMAGE: u32 = 197_568;
72 pub(crate) const SKYFURY: u32 = 462_854;
74}
75pub(crate) mod AURA {
76 pub(crate) const ASCENDANCE: u32 = 1_219_480;
78 pub(crate) const STORMKEEPER: u32 = 191_634;
80 pub(crate) const MASTER_OF_THE_ELEMENTS: u32 = 260_734;
82 pub(crate) const LAVA_SURGE: u32 = 77762;
84 pub(crate) const TEMPEST: u32 = 454_015;
86 pub(crate) const THUNDEROUS_VELOCITY: u32 = 1_272_101;
88 pub(crate) const POWER_OF_THE_MAELSTROM: u32 = 191_877;
90 pub(crate) const UNLIMITED_POWER: u32 = 454_394;
92 pub(crate) const ELEMENTAL_BLAST_CRIT: u32 = 118_522;
94 pub(crate) const ELEMENTAL_BLAST_HASTE: u32 = 173_183;
96 pub(crate) const ELEMENTAL_BLAST_MASTERY: u32 = 173_184;
98 pub(crate) const ANCESTRAL_SWIFTNESS: u32 = 443_454;
100 pub(crate) const FLAME_SHOCK: u32 = 188_389;
102 pub(crate) const LIGHTNING_ROD: u32 = 210_689;
104 pub(crate) const PURGING_FLAMES: u32 = 1_259_491;
106 pub(crate) const LIGHTNING_SHIELD: u32 = 192_106;
108 pub(crate) const THUNDERSTRIKE_WARD: u32 = 462_757;
110 pub(crate) const IMPROVED_FLAMETONGUE_WEAPON: u32 = 382_027;
112 pub(crate) const ECHOES_OF_GREAT_SUNDERING: u32 = 384_088;
114 pub(crate) const WIND_GUST: u32 = 263_806;
116 pub(crate) const FIRE_ELEMENTAL: u32 = 188_592;
118 pub(crate) const STORM_ELEMENTAL: u32 = 157_299;
120 pub(crate) const STORMS_EYE: u32 = 1_239_315;
122 pub(crate) const SKYFURY: u32 = 462_854;
124 pub(crate) const SKYFURY_HIGHLIGHT: u32 = 462_854;
126}
127pub(crate) mod TALENT {
128 pub(crate) const AFTERSHOCK: u32 = 273_221;
130 pub(crate) const ANCESTRAL_SWIFTNESS: u32 = 443_454;
132 pub(crate) const ARC_DISCHARGE: u32 = 455_096;
134 pub(crate) const ASCENDANCE: u32 = 114_050;
136 pub(crate) const AWAKENING_STORMS: u32 = 455_129;
138 pub(crate) const CALL_OF_FIRE: u32 = 378_255;
140 pub(crate) const ELEMENTAL_BLAST: u32 = 117_014;
142 pub(crate) const ELEMENTAL_UNITY: u32 = 462_866;
144 pub(crate) const FEEDBACK_LOOP_3: u32 = 1_270_064;
146 pub(crate) const FIRE_ELEMENTAL: u32 = 188_592;
148 pub(crate) const FLAMETONGUE_WEAPON: u32 = 318_038;
150 pub(crate) const FURY_OF_THE_STORMS: u32 = 191_717;
152 pub(crate) const FUSION_OF_ELEMENTS: u32 = 462_840;
154 pub(crate) const INFERNO_ARC: u32 = 1_259_047;
156 pub(crate) const LIGHTNING_CAPACITOR: u32 = 462_862;
158 pub(crate) const LIGHTNING_ROD: u32 = 210_689;
160 pub(crate) const MASTER_OF_THE_ELEMENTS: u32 = 16166;
162 pub(crate) const MOUNTAINS_WILL_FALL: u32 = 381_726;
164 pub(crate) const POWER_OF_THE_MAELSTROM: u32 = 191_861;
166 pub(crate) const PRIMAL_ELEMENTALIST: u32 = 117_013;
168 pub(crate) const PRIMORDIAL_CAPACITY: u32 = 443_448;
170 pub(crate) const SEARING_FLAMES: u32 = 381_782;
172 pub(crate) const STORMKEEPER: u32 = 191_634;
174 pub(crate) const STORMWELL: u32 = 1_264_762;
176 pub(crate) const STORM_ELEMENTAL: u32 = 157_299;
178 pub(crate) const SUPERCHARGE: u32 = 455_110;
180 pub(crate) const SWELLING_MAELSTROM: u32 = 381_707;
182 pub(crate) const TEMPEST_TALENT: u32 = 454_009;
184 pub(crate) const THUNDERSTRIKE_WARD: u32 = 462_757;
186 pub(crate) const UNLIMITED_POWER: u32 = 454_391;
188 pub(crate) const VOLTAIC_BLAZE: u32 = 1_259_101;
190}
191pub(crate) mod SET_BONUS {
192 pub(crate) const MID1_ELEMENTAL_2PC: u32 = 1_264_862;
194 pub(crate) const MID1_ELEMENTAL_4PC: u32 = 1_264_863;
196 pub(crate) const TWW3_STORMBRINGER_2PC: u32 = 1_236_408;
198 pub(crate) const TWW3_STORMBRINGER_4PC: u32 = 1_236_409;
200}
201pub(crate) mod HERO {
202 pub(crate) mod STORMBRINGER {
203 pub(crate) mod SPELL {
204 pub(crate) const TEMPEST: u32 = 452_201;
206 pub(crate) const TEMPEST_OVERLOAD: u32 = 463_351;
208 }
209 pub(crate) mod AURA {
210 pub(crate) const ARC_DISCHARGE: u32 = 470_532;
212 pub(crate) const AWAKENING_STORMS: u32 = 455_129;
214 pub(crate) const STORM_SWELL: u32 = 455_089;
216 pub(crate) const TEMPEST: u32 = 454_015;
218 pub(crate) const UNLIMITED_POWER: u32 = 454_394;
220 }
221 }
222 pub(crate) mod FARSEER {
223 pub(crate) mod SPELL {
224 pub(crate) const ANCESTRAL_SWIFTNESS: u32 = 443_454;
226 pub(crate) const CALL_OF_THE_ANCESTORS: u32 = 447_244;
228 }
229 pub(crate) mod AURA {
230 pub(crate) const ANCESTRAL_SWIFTNESS: u32 = 443_454;
232 pub(crate) const CALL_OF_THE_ANCESTORS: u32 = 447_244;
234 pub(crate) const PRIMORDIAL_CAPACITY: u32 = 443_448;
236 }
237 }
238 pub(crate) mod TOTEMIC {
239 pub(crate) mod SPELL {
240 pub(crate) const SURGING_TOTEM: u32 = 1_221_347;
242 }
243 pub(crate) mod AURA {
244 pub(crate) const AMPLIFICATION_CORE: u32 = 456_369;
246 pub(crate) const LIVELY_TOTEMS: u32 = 461_242;
248 pub(crate) const SURGING_TOTEM: u32 = 1_221_347;
250 pub(crate) const TOTEMIC_REBOUND: u32 = 458_269;
252 }
253 }
254}
255static HERO_TREE_STORMBRINGER_SPELLS: &[(&str, u32)] = &[
256 ("TEMPEST", 452_201),
257 ("TEMPEST_OVERLOAD", 463_351),
258];
259static HERO_TREE_STORMBRINGER_AURAS: &[(&str, u32)] = &[
260 ("ARC_DISCHARGE", 470_532),
261 ("AWAKENING_STORMS", 455_129),
262 ("STORM_SWELL", 455_089),
263 ("TEMPEST", 454_015),
264 ("UNLIMITED_POWER", 454_394),
265];
266static HERO_TREE_FARSEER_SPELLS: &[(&str, u32)] = &[
267 ("ANCESTRAL_SWIFTNESS", 443_454),
268 ("CALL_OF_THE_ANCESTORS", 447_244),
269];
270static HERO_TREE_FARSEER_AURAS: &[(&str, u32)] = &[
271 ("ANCESTRAL_SWIFTNESS", 443_454),
272 ("CALL_OF_THE_ANCESTORS", 447_244),
273 ("PRIMORDIAL_CAPACITY", 443_448),
274];
275static HERO_TREE_TOTEMIC_SPELLS: &[(&str, u32)] = &[("SURGING_TOTEM", 1_221_347)];
276static HERO_TREE_TOTEMIC_AURAS: &[(&str, u32)] = &[
277 ("AMPLIFICATION_CORE", 456_369),
278 ("LIVELY_TOTEMS", 461_242),
279 ("SURGING_TOTEM", 1_221_347),
280 ("TOTEMIC_REBOUND", 458_269),
281];
282pub(crate) const AURA_ASCENDANCE: LocalAuraIdx = LocalAuraIdx::new(0);
283pub(crate) const AURA_STORMKEEPER: LocalAuraIdx = LocalAuraIdx::new(1);
284pub(crate) const AURA_MASTER_OF_THE_ELEMENTS: LocalAuraIdx = LocalAuraIdx::new(2);
285pub(crate) const AURA_LAVA_SURGE: LocalAuraIdx = LocalAuraIdx::new(3);
286pub(crate) const AURA_TEMPEST: LocalAuraIdx = LocalAuraIdx::new(4);
287pub(crate) const AURA_THUNDEROUS_VELOCITY: LocalAuraIdx = LocalAuraIdx::new(5);
288pub(crate) const AURA_POWER_OF_THE_MAELSTROM: LocalAuraIdx = LocalAuraIdx::new(6);
289pub(crate) const AURA_UNLIMITED_POWER: LocalAuraIdx = LocalAuraIdx::new(7);
290pub(crate) const AURA_ELEMENTAL_BLAST_CRIT: LocalAuraIdx = LocalAuraIdx::new(8);
291pub(crate) const AURA_ELEMENTAL_BLAST_HASTE: LocalAuraIdx = LocalAuraIdx::new(9);
292pub(crate) const AURA_ELEMENTAL_BLAST_MASTERY: LocalAuraIdx = LocalAuraIdx::new(10);
293pub(crate) const AURA_ANCESTRAL_SWIFTNESS: LocalAuraIdx = LocalAuraIdx::new(11);
294pub(crate) const AURA_FLAME_SHOCK: LocalAuraIdx = LocalAuraIdx::new(12);
295pub(crate) const AURA_LIGHTNING_ROD: LocalAuraIdx = LocalAuraIdx::new(13);
296pub(crate) const AURA_PURGING_FLAMES: LocalAuraIdx = LocalAuraIdx::new(14);
297pub(crate) const AURA_LIGHTNING_SHIELD: LocalAuraIdx = LocalAuraIdx::new(15);
298pub(crate) const AURA_THUNDERSTRIKE_WARD: LocalAuraIdx = LocalAuraIdx::new(16);
299pub(crate) const AURA_IMPROVED_FLAMETONGUE_WEAPON: LocalAuraIdx = LocalAuraIdx::new(17);
300pub(crate) const AURA_ECHOES_OF_GREAT_SUNDERING: LocalAuraIdx = LocalAuraIdx::new(18);
301pub(crate) const AURA_WIND_GUST: LocalAuraIdx = LocalAuraIdx::new(19);
302pub(crate) const AURA_FIRE_ELEMENTAL: LocalAuraIdx = LocalAuraIdx::new(20);
303pub(crate) const AURA_STORM_ELEMENTAL: LocalAuraIdx = LocalAuraIdx::new(21);
304pub(crate) const AURA_STORMS_EYE: LocalAuraIdx = LocalAuraIdx::new(22);
305pub(crate) const AURA_SKYFURY: LocalAuraIdx = LocalAuraIdx::new(23);
306pub(crate) const AURA_SKYFURY_HIGHLIGHT: LocalAuraIdx = LocalAuraIdx::new(24);
307pub(crate) const AURA_COUNT: usize = 25;
308const _: () = assert!(
309 AURA_COUNT == 25, "AURA index ABI: count changed -- update positional hook consumers"
310);
311pub(crate) const SPELL_LIGHTNING_BOLT: LocalSpellIdx = LocalSpellIdx::new(0);
312pub(crate) const SPELL_CHAIN_LIGHTNING: LocalSpellIdx = LocalSpellIdx::new(1);
313pub(crate) const SPELL_LAVA_BURST: LocalSpellIdx = LocalSpellIdx::new(2);
314pub(crate) const SPELL_EARTH_SHOCK: LocalSpellIdx = LocalSpellIdx::new(3);
315pub(crate) const SPELL_ELEMENTAL_BLAST: LocalSpellIdx = LocalSpellIdx::new(4);
316pub(crate) const SPELL_EARTHQUAKE: LocalSpellIdx = LocalSpellIdx::new(5);
317pub(crate) const SPELL_FLAME_SHOCK: LocalSpellIdx = LocalSpellIdx::new(6);
318pub(crate) const SPELL_FROST_SHOCK: LocalSpellIdx = LocalSpellIdx::new(7);
319pub(crate) const SPELL_TEMPEST: LocalSpellIdx = LocalSpellIdx::new(8);
320pub(crate) const SPELL_STORMKEEPER: LocalSpellIdx = LocalSpellIdx::new(9);
321pub(crate) const SPELL_ASCENDANCE: LocalSpellIdx = LocalSpellIdx::new(10);
322pub(crate) const SPELL_ANCESTRAL_SWIFTNESS: LocalSpellIdx = LocalSpellIdx::new(11);
323pub(crate) const SPELL_FLAMETONGUE_WEAPON: LocalSpellIdx = LocalSpellIdx::new(12);
324pub(crate) const SPELL_THUNDERSTRIKE_WARD: LocalSpellIdx = LocalSpellIdx::new(13);
325pub(crate) const SPELL_LIGHTNING_SHIELD: LocalSpellIdx = LocalSpellIdx::new(14);
326pub(crate) const SPELL_FIRE_ELEMENTAL: LocalSpellIdx = LocalSpellIdx::new(15);
327pub(crate) const SPELL_FIRE_BLAST: LocalSpellIdx = LocalSpellIdx::new(16);
328pub(crate) const SPELL_METEOR: LocalSpellIdx = LocalSpellIdx::new(17);
329pub(crate) const SPELL_IMMOLATE: LocalSpellIdx = LocalSpellIdx::new(18);
330pub(crate) const SPELL_WIND_GUST: LocalSpellIdx = LocalSpellIdx::new(19);
331pub(crate) const SPELL_CALL_LIGHTNING: LocalSpellIdx = LocalSpellIdx::new(20);
332pub(crate) const SPELL_STORMFURY: LocalSpellIdx = LocalSpellIdx::new(21);
333pub(crate) const SPELL_LIGHTNING_BOLT_OVERLOAD: LocalSpellIdx = LocalSpellIdx::new(22);
334pub(crate) const SPELL_CHAIN_LIGHTNING_OVERLOAD: LocalSpellIdx = LocalSpellIdx::new(23);
335pub(crate) const SPELL_LAVA_BURST_OVERLOAD: LocalSpellIdx = LocalSpellIdx::new(24);
336pub(crate) const SPELL_ELEMENTAL_BLAST_OVERLOAD: LocalSpellIdx = LocalSpellIdx::new(25);
337pub(crate) const SPELL_TEMPEST_OVERLOAD: LocalSpellIdx = LocalSpellIdx::new(26);
338pub(crate) const SPELL_STORMS_EYE: LocalSpellIdx = LocalSpellIdx::new(27);
339pub(crate) const SPELL_LIGHTNING_ROD_DAMAGE: LocalSpellIdx = LocalSpellIdx::new(28);
340pub(crate) const SPELL_SKYFURY: LocalSpellIdx = LocalSpellIdx::new(29);
341pub(crate) const SPELL_COUNT: usize = 30;
342const _: () = assert!(
343 SPELL_COUNT == 30,
344 "SPELL index ABI: count changed -- update positional hook consumers"
345);
346pub(crate) mod EFFECT {
347 pub(crate) const CALL_LIGHTNING_DAMAGE: (u32, u8) = (157_348, 1);
349 pub(crate) const CALL_LIGHTNING_DAMAGE_BONUS: (u32, u8) = (157_348, 2);
351 pub(crate) const CHAIN_LIGHTNING_OVERLOAD: (u32, u8) = (45297, 1);
353 pub(crate) const ELEMENTAL_BLAST_DAMAGE: (u32, u8) = (117_014, 1);
355 pub(crate) const ELEMENTAL_BLAST_OVERLOAD: (u32, u8) = (120_588, 1);
357 pub(crate) const EARTHQUAKE_DAMAGE: (u32, u8) = (77478, 1);
359 pub(crate) const EARTHQUAKE_TIMING: (u32, u8) = (61882, 2);
361 pub(crate) const FEEDBACK_LOOP_BONUS: (u32, u8) = (1_270_064, 1);
363 pub(crate) const FIRE_BLAST_DAMAGE: (u32, u8) = (57984, 1);
365 pub(crate) const FUSION_OF_ELEMENTS_BONUS: (u32, u8) = (462_840, 1);
367 pub(crate) const IMMOLATE_DAMAGE: (u32, u8) = (118_297, 1);
369 pub(crate) const IMMOLATE_PERIODIC_DAMAGE: (u32, u8) = (118_297, 2);
371 pub(crate) const LAVA_BURST_OVERLOAD: (u32, u8) = (285_466, 1);
373 pub(crate) const LIGHTNING_BOLT_OVERLOAD: (u32, u8) = (45284, 1);
375 pub(crate) const MASTERY_DIRECT_DAMAGE: (u32, u8) = (168_534, 3);
377 pub(crate) const MASTERY_PERIODIC_DAMAGE: (u32, u8) = (168_534, 4);
379 pub(crate) const MASTERY_PET_DAMAGE: (u32, u8) = (168_534, 5);
381 pub(crate) const METEOR_DAMAGE: (u32, u8) = (117_588, 1);
383 pub(crate) const MID1_STORMKEEPER_BONUS: (u32, u8) = (1_264_863, 2);
385 pub(crate) const MOUNTAINS_WILL_FALL_BONUS: (u32, u8) = (381_726, 1);
387 pub(crate) const STORMFURY_DAMAGE: (u32, u8) = (269_005, 1);
389 pub(crate) const STORMS_EYE_DAMAGE: (u32, u8) = (1_235_840, 2);
391 pub(crate) const TEMPEST_OVERLOAD: (u32, u8) = (463_351, 1);
393 pub(crate) const WIND_GUST_DAMAGE: (u32, u8) = (157_331, 1);
395 pub(crate) const OVERLOAD_CHANCE: (u32, u8) = (168_534, 1);
397 pub(crate) const OVERLOAD_PENALTY: (u32, u8) = (168_534, 2);
399 pub(crate) const SUPERCHARGE_CHANCE: (u32, u8) = (455_110, 1);
401 pub(crate) const AFTERSHOCK_CHANCE: (u32, u8) = (273_221, 1);
403 pub(crate) const TEMPEST_TALENT_CHANCE: (u32, u8) = (454_009, 1);
405 pub(crate) const AWAKENING_STORMS_CHANCE: (u32, u8) = (455_129, 3);
407 pub(crate) const POWER_OF_THE_MAELSTROM_CHANCE: (u32, u8) = (191_861, 1);
409 pub(crate) const LAVA_BURST_DAMAGE: (u32, u8) = (285_452, 1);
411 pub(crate) const LIGHTNING_ROD_PERCENT: (u32, u8) = (210_689, 2);
413 pub(crate) const STORMFURY_RAMP: (u32, u8) = (157_375, 2);
415 pub(crate) const STORMKEEPER_DAMAGE: (u32, u8) = (191_634, 2);
417 pub(crate) const STORMKEEPER_TIER_DAMAGE: (u32, u8) = (191_634, 4);
419 pub(crate) const ELEMENTAL_UNITY_FIRE: (u32, u8) = (462_866, 1);
421 pub(crate) const ELEMENTAL_UNITY_STORM: (u32, u8) = (462_866, 3);
423 pub(crate) const FIRE_ELEMENTAL_UNITY: (u32, u8) = (188_592, 4);
425 pub(crate) const FIRE_ELEMENTAL_UNITY_PERIODIC: (u32, u8) = (188_592, 5);
427 pub(crate) const STORM_ELEMENTAL_UNITY: (u32, u8) = (157_299, 3);
429 pub(crate) const STORM_ELEMENTAL_UNITY_PET: (u32, u8) = (157_299, 4);
431 pub(crate) const LIGHTNING_CAPACITOR_DAMAGE: (u32, u8) = (462_862, 3);
433 pub(crate) const IMPROVED_FLAMETONGUE_DAMAGE: (u32, u8) = (382_028, 1);
435 pub(crate) const STORMWELL_SK_MAELSTROM: (u32, u8) = (1_264_762, 2);
437}
438static REPORTED_SPELLS: &[(&str, u32)] = &[];
439static DECLARED_SPELL_IDS: &[u32] = &[
440 188_196, 188_443, 51505, 8042, 117_014, 61882, 188_389, 196_840, 452_201, 191_634,
441 1_219_480, 443_454, 318_038, 462_757, 192_106, 188_592, 57984, 117_588, 118_297,
442 157_331, 157_348, 269_005, 45284, 45297, 285_466, 120_588, 463_351, 1_235_840,
443 197_568, 462_854, 1_219_480, 191_634, 260_734, 77762, 454_015, 1_272_101, 191_877,
444 454_394, 118_522, 173_183, 173_184, 443_454, 188_389, 210_689, 1_259_491, 192_106,
445 462_757, 382_027, 384_088, 263_806, 188_592, 157_299, 1_239_315, 462_854, 462_854,
446 16166, 45284, 45297, 57984, 61882, 77478, 117_014, 117_588, 118_297, 120_588,
447 157_299, 157_331, 157_348, 157_375, 168_534, 188_592, 191_634, 191_861, 192_106,
448 210_689, 269_005, 273_221, 285_452, 285_466, 381_726, 382_028, 454_009, 455_110,
449 455_129, 462_840, 462_862, 462_866, 463_351, 1_219_480, 1_235_840, 1_264_762,
450 1_264_863, 1_270_064, 452_201, 463_351, 470_532, 455_129, 455_089, 454_015, 454_394,
451 443_454, 447_244, 443_454, 447_244, 443_448, 1_221_347, 456_369, 461_242, 1_221_347,
452 458_269,
453];
454static DECLARED_AURA_IDS: &[u32] = &[
455 1_219_480, 191_634, 260_734, 77762, 454_015, 1_272_101, 191_877, 454_394, 118_522,
456 173_183, 173_184, 443_454, 188_389, 210_689, 1_259_491, 192_106, 462_757, 382_027,
457 384_088, 263_806, 188_592, 157_299, 1_239_315, 462_854, 462_854, 470_532, 455_129,
458 455_089, 454_015, 454_394, 443_454, 447_244, 443_448, 456_369, 461_242, 1_221_347,
459 458_269,
460];
461static TALENTS: &[(&str, u32)] = &[
462 ("AFTERSHOCK", TALENT::AFTERSHOCK),
463 ("ANCESTRAL_SWIFTNESS", TALENT::ANCESTRAL_SWIFTNESS),
464 ("ARC_DISCHARGE", TALENT::ARC_DISCHARGE),
465 ("ASCENDANCE", TALENT::ASCENDANCE),
466 ("AWAKENING_STORMS", TALENT::AWAKENING_STORMS),
467 ("CALL_OF_FIRE", TALENT::CALL_OF_FIRE),
468 ("ELEMENTAL_BLAST", TALENT::ELEMENTAL_BLAST),
469 ("ELEMENTAL_UNITY", TALENT::ELEMENTAL_UNITY),
470 ("FEEDBACK_LOOP_3", TALENT::FEEDBACK_LOOP_3),
471 ("FIRE_ELEMENTAL", TALENT::FIRE_ELEMENTAL),
472 ("FLAMETONGUE_WEAPON", TALENT::FLAMETONGUE_WEAPON),
473 ("FURY_OF_THE_STORMS", TALENT::FURY_OF_THE_STORMS),
474 ("FUSION_OF_ELEMENTS", TALENT::FUSION_OF_ELEMENTS),
475 ("INFERNO_ARC", TALENT::INFERNO_ARC),
476 ("LIGHTNING_CAPACITOR", TALENT::LIGHTNING_CAPACITOR),
477 ("LIGHTNING_ROD", TALENT::LIGHTNING_ROD),
478 ("MASTER_OF_THE_ELEMENTS", TALENT::MASTER_OF_THE_ELEMENTS),
479 ("MOUNTAINS_WILL_FALL", TALENT::MOUNTAINS_WILL_FALL),
480 ("POWER_OF_THE_MAELSTROM", TALENT::POWER_OF_THE_MAELSTROM),
481 ("PRIMAL_ELEMENTALIST", TALENT::PRIMAL_ELEMENTALIST),
482 ("PRIMORDIAL_CAPACITY", TALENT::PRIMORDIAL_CAPACITY),
483 ("SEARING_FLAMES", TALENT::SEARING_FLAMES),
484 ("STORMKEEPER", TALENT::STORMKEEPER),
485 ("STORMWELL", TALENT::STORMWELL),
486 ("STORM_ELEMENTAL", TALENT::STORM_ELEMENTAL),
487 ("SUPERCHARGE", TALENT::SUPERCHARGE),
488 ("SWELLING_MAELSTROM", TALENT::SWELLING_MAELSTROM),
489 ("TEMPEST_TALENT", TALENT::TEMPEST_TALENT),
490 ("THUNDERSTRIKE_WARD", TALENT::THUNDERSTRIKE_WARD),
491 ("UNLIMITED_POWER", TALENT::UNLIMITED_POWER),
492 ("VOLTAIC_BLAZE", TALENT::VOLTAIC_BLAZE),
493];
494pub(crate) mod ELEMENTAL_SHAMAN {
495 pub(crate) const LIGHTNING_BOLT_CASTS: u32 = 0;
496 pub(crate) const LAVA_BURST_CASTS: u32 = 1;
497 pub(crate) const EARTH_SHOCK_CASTS: u32 = 2;
498 pub(crate) const ELEMENTAL_BLAST_CASTS: u32 = 3;
499 pub(crate) const STORMKEEPER_CASTS: u32 = 4;
500 pub(crate) const ASCENDANCE_CASTS: u32 = 5;
501 pub(crate) const FLAME_SHOCK_UPTIME_MS: u32 = 6;
502 pub(crate) const TEMPEST_CASTS: u32 = 7;
503}
504fn aura_ascendance(
505 a: AuraDefinitionDraft,
506 data: &ResolvedGameData,
507) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
508 a.on_player()
509 .apply_base_from_data(data, 1_219_480)?
510 .max_stacks(
511 data
512 .require_aura_max_stacks(
513 wowlab_types::sim::SpellIdx::from_raw(1_219_480),
514 )?,
515 )
516 .damage_percent_spells(
517 data.base_points(wowlab_types::sim::SpellIdx::from_raw(1_219_480), 8),
518 &[45284, 45297, 285_466, 120_588, 463_351],
519 )
520}
521fn aura_stormkeeper(
522 a: AuraDefinitionDraft,
523 data: &ResolvedGameData,
524) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
525 Ok(
526 a
527 .on_player()
528 .apply_base_from_data(data, 191_634)?
529 .max_stacks(
530 wowlab_engine_combat::validated_max_stacks(
531 1.0,
532 191_634,
533 "aura.max_stacks",
534 )?,
535 ),
536 )
537}
538fn aura_master_of_the_elements(
539 a: AuraDefinitionDraft,
540 data: &ResolvedGameData,
541) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
542 a.on_player()
543 .apply_base_from_data(data, 260_734)?
544 .max_stacks(
545 data.require_aura_max_stacks(wowlab_types::sim::SpellIdx::from_raw(260_734))?,
546 )
547 .damage_multiplier(
548 ((data.base_points(wowlab_types::sim::SpellIdx::from_raw(16166), 2)) * 0.01)
549 + 1.0,
550 )
551}
552fn aura_lava_surge(
553 a: AuraDefinitionDraft,
554 data: &ResolvedGameData,
555) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
556 Ok(
557 a
558 .on_player()
559 .apply_base_from_data(data, 77762)?
560 .max_stacks(
561 data
562 .require_aura_max_stacks(
563 wowlab_types::sim::SpellIdx::from_raw(77762),
564 )?,
565 ),
566 )
567}
568fn aura_tempest(
569 a: AuraDefinitionDraft,
570 data: &ResolvedGameData,
571) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
572 Ok(
573 a
574 .on_player()
575 .apply_base_from_data(data, 454_015)?
576 .max_stacks(
577 data
578 .require_aura_max_stacks(
579 wowlab_types::sim::SpellIdx::from_raw(454_015),
580 )?,
581 ),
582 )
583}
584fn aura_thunderous_velocity(
585 a: AuraDefinitionDraft,
586 data: &ResolvedGameData,
587) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
588 Ok(
589 a
590 .on_player()
591 .apply_base_from_data(data, 1_272_101)?
592 .max_stacks(
593 data
594 .require_aura_max_stacks(
595 wowlab_types::sim::SpellIdx::from_raw(1_272_101),
596 )?,
597 ),
598 )
599}
600fn aura_power_of_the_maelstrom(
601 a: AuraDefinitionDraft,
602 data: &ResolvedGameData,
603) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
604 Ok(
605 a
606 .on_player()
607 .apply_base_from_data(data, 191_877)?
608 .max_stacks(
609 data
610 .require_aura_max_stacks(
611 wowlab_types::sim::SpellIdx::from_raw(191_877),
612 )?,
613 ),
614 )
615}
616fn aura_unlimited_power(
617 a: AuraDefinitionDraft,
618 data: &ResolvedGameData,
619) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
620 Ok(
621 a
622 .on_player()
623 .apply_base_from_data(data, 454_394)?
624 .max_stacks(
625 data
626 .require_aura_max_stacks(
627 wowlab_types::sim::SpellIdx::from_raw(454_394),
628 )?,
629 ),
630 )
631}
632fn aura_elemental_blast_crit(
633 a: AuraDefinitionDraft,
634 data: &ResolvedGameData,
635) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
636 Ok(
637 a
638 .on_player()
639 .apply_base_from_data(data, 118_522)?
640 .max_stacks(
641 data
642 .require_aura_max_stacks(
643 wowlab_types::sim::SpellIdx::from_raw(118_522),
644 )?,
645 ),
646 )
647}
648fn aura_elemental_blast_haste(
649 a: AuraDefinitionDraft,
650 data: &ResolvedGameData,
651) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
652 Ok(
653 a
654 .on_player()
655 .apply_base_from_data(data, 173_183)?
656 .max_stacks(
657 data
658 .require_aura_max_stacks(
659 wowlab_types::sim::SpellIdx::from_raw(173_183),
660 )?,
661 ),
662 )
663}
664fn aura_elemental_blast_mastery(
665 a: AuraDefinitionDraft,
666 data: &ResolvedGameData,
667) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
668 Ok(
669 a
670 .on_player()
671 .apply_base_from_data(data, 173_184)?
672 .max_stacks(
673 data
674 .require_aura_max_stacks(
675 wowlab_types::sim::SpellIdx::from_raw(173_184),
676 )?,
677 ),
678 )
679}
680fn aura_ancestral_swiftness(
681 a: AuraDefinitionDraft,
682 data: &ResolvedGameData,
683) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
684 Ok(
685 a
686 .on_player()
687 .apply_base_from_data(data, 443_454)?
688 .max_stacks(
689 data
690 .require_aura_max_stacks(
691 wowlab_types::sim::SpellIdx::from_raw(443_454),
692 )?,
693 ),
694 )
695}
696fn aura_flame_shock(
697 a: AuraDefinitionDraft,
698 data: &ResolvedGameData,
699) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
700 a.on_target()
701 .apply_base_from_data(data, 188_389)?
702 .max_stacks(
703 data.require_aura_max_stacks(wowlab_types::sim::SpellIdx::from_raw(188_389))?,
704 )
705 .crit_chance_spells(100.0, &[51505, 285_466])
706}
707fn aura_lightning_rod(
708 a: AuraDefinitionDraft,
709 data: &ResolvedGameData,
710) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
711 Ok(
712 a
713 .on_target()
714 .apply_base_from_data(data, 210_689)?
715 .max_stacks(
716 data
717 .require_aura_max_stacks(
718 wowlab_types::sim::SpellIdx::from_raw(210_689),
719 )?,
720 ),
721 )
722}
723fn aura_purging_flames(
724 a: AuraDefinitionDraft,
725 data: &ResolvedGameData,
726) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
727 Ok(
728 a
729 .on_player()
730 .apply_base_from_data(data, 1_259_491)?
731 .max_stacks(
732 data
733 .require_aura_max_stacks(
734 wowlab_types::sim::SpellIdx::from_raw(1_259_491),
735 )?,
736 ),
737 )
738}
739fn aura_lightning_shield(
740 a: AuraDefinitionDraft,
741 data: &ResolvedGameData,
742) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
743 a.on_player()
744 .apply_base_from_data(data, 192_106)?
745 .max_stacks(
746 data.require_aura_max_stacks(wowlab_types::sim::SpellIdx::from_raw(192_106))?,
747 )
748 .primary_pct_per_stack(
749 data.base_points(wowlab_types::sim::SpellIdx::from_raw(192_106), 4),
750 )
751}
752fn aura_thunderstrike_ward(
753 a: AuraDefinitionDraft,
754 data: &ResolvedGameData,
755) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
756 Ok(
757 a
758 .on_player()
759 .apply_base_from_data(data, 462_757)?
760 .max_stacks(
761 data
762 .require_aura_max_stacks(
763 wowlab_types::sim::SpellIdx::from_raw(462_757),
764 )?,
765 ),
766 )
767}
768fn aura_improved_flametongue_weapon(
769 a: AuraDefinitionDraft,
770 data: &ResolvedGameData,
771) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
772 Ok(
773 a
774 .on_player()
775 .apply_base_from_data(data, 382_027)?
776 .max_stacks(
777 data
778 .require_aura_max_stacks(
779 wowlab_types::sim::SpellIdx::from_raw(382_027),
780 )?,
781 ),
782 )
783}
784fn aura_echoes_of_great_sundering(
785 a: AuraDefinitionDraft,
786 data: &ResolvedGameData,
787) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
788 Ok(
789 a
790 .on_player()
791 .apply_base_from_data(data, 384_088)?
792 .max_stacks(
793 data
794 .require_aura_max_stacks(
795 wowlab_types::sim::SpellIdx::from_raw(384_088),
796 )?,
797 ),
798 )
799}
800fn aura_wind_gust(
801 a: AuraDefinitionDraft,
802 data: &ResolvedGameData,
803) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
804 Ok(
805 a
806 .on_player()
807 .apply_base_from_data(data, 263_806)?
808 .max_stacks(
809 data
810 .require_aura_max_stacks(
811 wowlab_types::sim::SpellIdx::from_raw(263_806),
812 )?,
813 ),
814 )
815}
816fn aura_fire_elemental(
817 a: AuraDefinitionDraft,
818 data: &ResolvedGameData,
819) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
820 Ok(
821 a
822 .on_player()
823 .apply_base_from_data(data, 188_592)?
824 .max_stacks(
825 data
826 .require_aura_max_stacks(
827 wowlab_types::sim::SpellIdx::from_raw(188_592),
828 )?,
829 ),
830 )
831}
832fn aura_storm_elemental(
833 a: AuraDefinitionDraft,
834 data: &ResolvedGameData,
835) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
836 a.on_player()
837 .duration_ms(
838 wowlab_engine_combat::validated_milliseconds(
839 (((f64::from(
840 data
841 .require_aura_duration_ms(
842 wowlab_types::sim::SpellIdx::from_raw(157_299),
843 )?,
844 )) * 1.028_571_428_571_428_5) * 1.0)
845 .round() / 1.0,
846 157_299,
847 "aura.duration_ms",
848 )?,
849 )
850 .apply_periodic_effect_from_data(data, 157_299)?
851 .apply_duration_behavior_from_data(data, 157_299)?
852 .apply_timing_modifiers_from_data(data, 157_299)?
853 .max_stacks(
854 data.require_aura_max_stacks(wowlab_types::sim::SpellIdx::from_raw(157_299))?,
855 )
856 .apply_periodic_behavior_from_data(data, 157_299)
857}
858fn aura_storms_eye(
859 a: AuraDefinitionDraft,
860 data: &ResolvedGameData,
861) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
862 Ok(
863 a
864 .on_player()
865 .apply_base_from_data(data, 1_239_315)?
866 .max_stacks(
867 data
868 .require_aura_max_stacks(
869 wowlab_types::sim::SpellIdx::from_raw(1_239_315),
870 )?,
871 ),
872 )
873}
874fn aura_skyfury(
875 a: AuraDefinitionDraft,
876 data: &ResolvedGameData,
877) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
878 Ok(
879 a
880 .on_player()
881 .apply_base_from_data(data, 462_854)?
882 .max_stacks(
883 data
884 .require_aura_max_stacks(
885 wowlab_types::sim::SpellIdx::from_raw(462_854),
886 )?,
887 ),
888 )
889}
890fn aura_skyfury_highlight(
891 a: AuraDefinitionDraft,
892 data: &ResolvedGameData,
893) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
894 Ok(
895 a
896 .on_player()
897 .apply_base_from_data(data, 462_854)?
898 .max_stacks(
899 data
900 .require_aura_max_stacks(
901 wowlab_types::sim::SpellIdx::from_raw(462_854),
902 )?,
903 ),
904 )
905}
906fn spell_lightning_bolt(
907 s: SpellDefinitionDraft,
908 data: &ResolvedGameData,
909) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
910 Ok(
911 s
912 .apply_base_from_data(data, 188_196)?
913 .gain(6.0)
914 .apply_aoe_from_data(data)
915 .on_cast(crate::hooks::elemental_shaman::lightning_bolt_hook),
916 )
917}
918fn spell_chain_lightning(
919 s: SpellDefinitionDraft,
920 data: &ResolvedGameData,
921) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
922 Ok(
923 s
924 .apply_base_from_data(data, 188_443)?
925 .gain(2.0)
926 .apply_aoe_from_data(data)
927 .on_cast(crate::hooks::elemental_shaman::chain_lightning_hook),
928 )
929}
930fn spell_lava_burst(
931 s: SpellDefinitionDraft,
932 data: &ResolvedGameData,
933) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
934 Ok(
935 s
936 .apply_base_from_data(data, 51505)?
937 .apply_aoe_from_data(data)
938 .on_cast(crate::hooks::elemental_shaman::lava_burst_hook),
939 )
940}
941fn spell_earth_shock(
942 s: SpellDefinitionDraft,
943 data: &ResolvedGameData,
944) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
945 Ok(s.apply_base_from_data(data, 8042)?.apply_aoe_from_data(data))
946}
947fn spell_elemental_blast(
948 s: SpellDefinitionDraft,
949 data: &ResolvedGameData,
950) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
951 Ok(
952 s
953 .apply_base_from_data(data, 117_014)?
954 .apply_aoe_from_data(data)
955 .on_cast(crate::hooks::elemental_shaman::elemental_blast_hook)
956 .cost_free_when_aura(443_454),
957 )
958}
959fn spell_earthquake(
960 s: SpellDefinitionDraft,
961 data: &ResolvedGameData,
962) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
963 Ok(
964 s
965 .apply_base_from_data(data, 61882)?
966 .apply_aoe_from_data(data)
967 .on_cast(crate::hooks::elemental_shaman::earthquake_hook),
968 )
969}
970fn spell_flame_shock(
971 s: SpellDefinitionDraft,
972 data: &ResolvedGameData,
973) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
974 Ok(
975 s
976 .apply_base_from_data(data, 188_389)?
977 .gain(3.0)
978 .applies_inferred_aura(AURA_FLAME_SHOCK, 188_389)
979 .apply_aoe_from_data(data),
980 )
981}
982fn spell_frost_shock(
983 s: SpellDefinitionDraft,
984 data: &ResolvedGameData,
985) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
986 Ok(s.apply_base_from_data(data, 196_840)?.apply_aoe_from_data(data))
987}
988fn spell_tempest(
989 s: SpellDefinitionDraft,
990 data: &ResolvedGameData,
991) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
992 Ok(
993 s
994 .apply_base_from_data(data, 452_201)?
995 .apply_aoe_from_data(data)
996 .on_cast(crate::hooks::elemental_shaman::tempest_hook),
997 )
998}
999fn spell_stormkeeper(
1000 s: SpellDefinitionDraft,
1001 data: &ResolvedGameData,
1002) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1003 Ok(
1004 s
1005 .apply_base_from_data(data, 191_634)?
1006 .cast_time(
1007 wowlab_engine_combat::validated_milliseconds(
1008 0.0,
1009 191_634,
1010 "spell.cast_time_ms",
1011 )?,
1012 )
1013 .gain(10.0)
1014 .applies_inferred_aura(AURA_STORMKEEPER, 191_634)
1015 .apply_aoe_from_data(data)
1016 .on_cast(crate::hooks::elemental_shaman::stormkeeper_hook),
1017 )
1018}
1019fn spell_ascendance(
1020 s: SpellDefinitionDraft,
1021 data: &ResolvedGameData,
1022) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1023 Ok(
1024 s
1025 .apply_base_from_data(data, 1_219_480)?
1026 .applies_inferred_aura(AURA_ASCENDANCE, 1_219_480)
1027 .apply_aoe_from_data(data)
1028 .on_cast(crate::hooks::elemental_shaman::ascendance_hook),
1029 )
1030}
1031fn spell_ancestral_swiftness(
1032 s: SpellDefinitionDraft,
1033 data: &ResolvedGameData,
1034) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1035 Ok(
1036 s
1037 .apply_base_from_data(data, 443_454)?
1038 .applies_inferred_aura(AURA_ANCESTRAL_SWIFTNESS, 443_454)
1039 .apply_aoe_from_data(data),
1040 )
1041}
1042fn spell_flametongue_weapon(
1043 s: SpellDefinitionDraft,
1044 data: &ResolvedGameData,
1045) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1046 Ok(s.apply_base_from_data(data, 318_038)?.apply_aoe_from_data(data))
1047}
1048fn spell_thunderstrike_ward(
1049 s: SpellDefinitionDraft,
1050 data: &ResolvedGameData,
1051) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1052 Ok(
1053 s
1054 .apply_base_from_data(data, 462_757)?
1055 .applies_inferred_aura(AURA_THUNDERSTRIKE_WARD, 462_757)
1056 .apply_aoe_from_data(data),
1057 )
1058}
1059fn spell_lightning_shield(
1060 s: SpellDefinitionDraft,
1061 data: &ResolvedGameData,
1062) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1063 Ok(
1064 s
1065 .apply_base_from_data(data, 192_106)?
1066 .applies_inferred_aura(AURA_LIGHTNING_SHIELD, 192_106)
1067 .apply_aoe_from_data(data),
1068 )
1069}
1070fn spell_fire_elemental(
1071 s: SpellDefinitionDraft,
1072 data: &ResolvedGameData,
1073) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1074 Ok(
1075 s
1076 .apply_base_from_data(data, 188_592)?
1077 .applies_inferred_aura(AURA_FIRE_ELEMENTAL, 188_592)
1078 .apply_aoe_from_data(data),
1079 )
1080}
1081fn spell_fire_blast(
1082 s: SpellDefinitionDraft,
1083 data: &ResolvedGameData,
1084) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1085 Ok(s.apply_base_from_data(data, 57984)?.apply_aoe_from_data(data))
1086}
1087fn spell_meteor(
1088 s: SpellDefinitionDraft,
1089 data: &ResolvedGameData,
1090) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1091 Ok(s.apply_base_from_data(data, 117_588)?.apply_aoe_from_data(data))
1092}
1093fn spell_immolate(
1094 s: SpellDefinitionDraft,
1095 data: &ResolvedGameData,
1096) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1097 Ok(s.apply_base_from_data(data, 118_297)?.apply_aoe_from_data(data))
1098}
1099fn spell_wind_gust(
1100 s: SpellDefinitionDraft,
1101 data: &ResolvedGameData,
1102) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1103 Ok(s.apply_base_from_data(data, 157_331)?.apply_aoe_from_data(data))
1104}
1105fn spell_call_lightning(
1106 s: SpellDefinitionDraft,
1107 data: &ResolvedGameData,
1108) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1109 Ok(s.apply_base_from_data(data, 157_348)?.apply_aoe_from_data(data))
1110}
1111fn spell_stormfury(
1112 s: SpellDefinitionDraft,
1113 data: &ResolvedGameData,
1114) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1115 Ok(s.apply_base_from_data(data, 269_005)?.apply_aoe_from_data(data))
1116}
1117fn spell_lightning_bolt_overload(
1118 s: SpellDefinitionDraft,
1119 data: &ResolvedGameData,
1120) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1121 Ok(s.apply_base_from_data(data, 45284)?.apply_aoe_from_data(data))
1122}
1123fn spell_chain_lightning_overload(
1124 s: SpellDefinitionDraft,
1125 data: &ResolvedGameData,
1126) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1127 Ok(s.apply_base_from_data(data, 45297)?.apply_aoe_from_data(data))
1128}
1129fn spell_lava_burst_overload(
1130 s: SpellDefinitionDraft,
1131 data: &ResolvedGameData,
1132) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1133 Ok(s.apply_base_from_data(data, 285_466)?.apply_aoe_from_data(data))
1134}
1135fn spell_elemental_blast_overload(
1136 s: SpellDefinitionDraft,
1137 data: &ResolvedGameData,
1138) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1139 Ok(s.apply_base_from_data(data, 120_588)?.apply_aoe_from_data(data))
1140}
1141fn spell_tempest_overload(
1142 s: SpellDefinitionDraft,
1143 data: &ResolvedGameData,
1144) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1145 Ok(s.apply_base_from_data(data, 463_351)?.apply_aoe_from_data(data))
1146}
1147fn spell_storms_eye(
1148 s: SpellDefinitionDraft,
1149 data: &ResolvedGameData,
1150) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1151 Ok(
1152 s
1153 .apply_base_from_data(data, 1_235_840)?
1154 .applies_inferred_aura(AURA_STORMS_EYE, 1_239_315)
1155 .apply_aoe_from_data(data),
1156 )
1157}
1158fn spell_lightning_rod_damage(
1159 s: SpellDefinitionDraft,
1160 data: &ResolvedGameData,
1161) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1162 Ok(s.apply_base_from_data(data, 197_568)?.apply_aoe_from_data(data))
1163}
1164fn spell_skyfury(
1165 s: SpellDefinitionDraft,
1166 data: &ResolvedGameData,
1167) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1168 Ok(
1169 s
1170 .apply_base_from_data(data, 462_854)?
1171 .applies_inferred_aura(AURA_SKYFURY, 462_854)
1172 .apply_aoe_from_data(data),
1173 )
1174}
1175pub(crate) fn build_combat_system(
1176 params: &wowlab_engine_ports::HandlerParams<'_>,
1177) -> Result<BuiltCombatSystem, wowlab_engine_ports::EngineError> {
1178 let builder = BuiltCombatSystem::builder(params.stats.clone())
1179 .spec_id(SpecId::Elemental)
1180 .hero_talent_trees(DECLARED_METADATA.hero_talent_trees)
1181 .mastery_spell(168_534)
1182 .mastery_hook(crate::hooks::elemental_shaman::mastery)
1183 .resource(
1184 "maelstrom",
1185 params
1186 .game_data
1187 .power_max(11)
1188 .ok_or_else(|| {
1189 wowlab_engine_ports::EngineError::spec_construction(
1190 "missing power-type power_max for type_id 11",
1191 )
1192 })?,
1193 params
1194 .game_data
1195 .power_regen_for_max(
1196 11,
1197 params
1198 .game_data
1199 .power_max(11)
1200 .ok_or_else(|| {
1201 wowlab_engine_ports::EngineError::spec_construction(
1202 "missing power-type power_max for type_id 11",
1203 )
1204 })?,
1205 )
1206 .ok_or_else(|| {
1207 wowlab_engine_ports::EngineError::spec_construction(
1208 "missing power-type power_regen_for_max for type_id 11",
1209 )
1210 })?,
1211 )
1212 .resource_type_id(11)
1213 .resource_start(
1214 params
1215 .game_data
1216 .power_default(11)
1217 .ok_or_else(|| {
1218 wowlab_engine_ports::EngineError::spec_construction(
1219 "missing power-type power_default for type_id 11",
1220 )
1221 })?,
1222 )
1223 .aura("ascendance", AURA::ASCENDANCE, |a| aura_ascendance(a, ¶ms.game_data))
1224 .aura(
1225 "stormkeeper",
1226 AURA::STORMKEEPER,
1227 |a| aura_stormkeeper(a, ¶ms.game_data),
1228 )
1229 .aura(
1230 "master_of_the_elements",
1231 AURA::MASTER_OF_THE_ELEMENTS,
1232 |a| aura_master_of_the_elements(a, ¶ms.game_data),
1233 )
1234 .aura("lava_surge", AURA::LAVA_SURGE, |a| aura_lava_surge(a, ¶ms.game_data))
1235 .aura("tempest", AURA::TEMPEST, |a| aura_tempest(a, ¶ms.game_data))
1236 .aura(
1237 "thunderous_velocity",
1238 AURA::THUNDEROUS_VELOCITY,
1239 |a| aura_thunderous_velocity(a, ¶ms.game_data),
1240 )
1241 .aura(
1242 "power_of_the_maelstrom",
1243 AURA::POWER_OF_THE_MAELSTROM,
1244 |a| aura_power_of_the_maelstrom(a, ¶ms.game_data),
1245 )
1246 .aura(
1247 "unlimited_power",
1248 AURA::UNLIMITED_POWER,
1249 |a| aura_unlimited_power(a, ¶ms.game_data),
1250 )
1251 .aura(
1252 "elemental_blast_crit",
1253 AURA::ELEMENTAL_BLAST_CRIT,
1254 |a| aura_elemental_blast_crit(a, ¶ms.game_data),
1255 )
1256 .aura(
1257 "elemental_blast_haste",
1258 AURA::ELEMENTAL_BLAST_HASTE,
1259 |a| aura_elemental_blast_haste(a, ¶ms.game_data),
1260 )
1261 .aura(
1262 "elemental_blast_mastery",
1263 AURA::ELEMENTAL_BLAST_MASTERY,
1264 |a| aura_elemental_blast_mastery(a, ¶ms.game_data),
1265 )
1266 .aura(
1267 "ancestral_swiftness",
1268 AURA::ANCESTRAL_SWIFTNESS,
1269 |a| aura_ancestral_swiftness(a, ¶ms.game_data),
1270 )
1271 .aura(
1272 "flame_shock",
1273 AURA::FLAME_SHOCK,
1274 |a| aura_flame_shock(a, ¶ms.game_data),
1275 )
1276 .aura(
1277 "lightning_rod",
1278 AURA::LIGHTNING_ROD,
1279 |a| aura_lightning_rod(a, ¶ms.game_data),
1280 )
1281 .aura(
1282 "purging_flames",
1283 AURA::PURGING_FLAMES,
1284 |a| aura_purging_flames(a, ¶ms.game_data),
1285 )
1286 .aura(
1287 "lightning_shield",
1288 AURA::LIGHTNING_SHIELD,
1289 |a| aura_lightning_shield(a, ¶ms.game_data),
1290 )
1291 .aura(
1292 "thunderstrike_ward",
1293 AURA::THUNDERSTRIKE_WARD,
1294 |a| aura_thunderstrike_ward(a, ¶ms.game_data),
1295 )
1296 .aura(
1297 "improved_flametongue_weapon",
1298 AURA::IMPROVED_FLAMETONGUE_WEAPON,
1299 |a| aura_improved_flametongue_weapon(a, ¶ms.game_data),
1300 )
1301 .aura(
1302 "echoes_of_great_sundering",
1303 AURA::ECHOES_OF_GREAT_SUNDERING,
1304 |a| aura_echoes_of_great_sundering(a, ¶ms.game_data),
1305 )
1306 .aura("wind_gust", AURA::WIND_GUST, |a| aura_wind_gust(a, ¶ms.game_data))
1307 .aura(
1308 "fire_elemental",
1309 AURA::FIRE_ELEMENTAL,
1310 |a| aura_fire_elemental(a, ¶ms.game_data),
1311 )
1312 .aura(
1313 "storm_elemental",
1314 AURA::STORM_ELEMENTAL,
1315 |a| aura_storm_elemental(a, ¶ms.game_data),
1316 )
1317 .aura("storms_eye", AURA::STORMS_EYE, |a| aura_storms_eye(a, ¶ms.game_data))
1318 .aura("skyfury", AURA::SKYFURY, |a| aura_skyfury(a, ¶ms.game_data))
1319 .aura(
1320 "skyfury_highlight",
1321 AURA::SKYFURY_HIGHLIGHT,
1322 |a| aura_skyfury_highlight(a, ¶ms.game_data),
1323 )
1324 .spell(
1325 "lightning_bolt",
1326 SPELL::LIGHTNING_BOLT,
1327 |s| spell_lightning_bolt(s, ¶ms.game_data),
1328 )
1329 .spell(
1330 "chain_lightning",
1331 SPELL::CHAIN_LIGHTNING,
1332 |s| spell_chain_lightning(s, ¶ms.game_data),
1333 )
1334 .spell(
1335 "lava_burst",
1336 SPELL::LAVA_BURST,
1337 |s| spell_lava_burst(s, ¶ms.game_data),
1338 )
1339 .spell(
1340 "earth_shock",
1341 SPELL::EARTH_SHOCK,
1342 |s| spell_earth_shock(s, ¶ms.game_data),
1343 )
1344 .spell(
1345 "elemental_blast",
1346 SPELL::ELEMENTAL_BLAST,
1347 |s| spell_elemental_blast(s, ¶ms.game_data),
1348 )
1349 .spell(
1350 "earthquake",
1351 SPELL::EARTHQUAKE,
1352 |s| spell_earthquake(s, ¶ms.game_data),
1353 )
1354 .spell(
1355 "flame_shock",
1356 SPELL::FLAME_SHOCK,
1357 |s| spell_flame_shock(s, ¶ms.game_data),
1358 )
1359 .spell(
1360 "frost_shock",
1361 SPELL::FROST_SHOCK,
1362 |s| spell_frost_shock(s, ¶ms.game_data),
1363 )
1364 .spell("tempest", SPELL::TEMPEST, |s| spell_tempest(s, ¶ms.game_data))
1365 .spell(
1366 "stormkeeper",
1367 SPELL::STORMKEEPER,
1368 |s| spell_stormkeeper(s, ¶ms.game_data),
1369 )
1370 .spell(
1371 "ascendance",
1372 SPELL::ASCENDANCE,
1373 |s| spell_ascendance(s, ¶ms.game_data),
1374 )
1375 .spell(
1376 "ancestral_swiftness",
1377 SPELL::ANCESTRAL_SWIFTNESS,
1378 |s| spell_ancestral_swiftness(s, ¶ms.game_data),
1379 )
1380 .spell(
1381 "flametongue_weapon",
1382 SPELL::FLAMETONGUE_WEAPON,
1383 |s| spell_flametongue_weapon(s, ¶ms.game_data),
1384 )
1385 .spell(
1386 "thunderstrike_ward",
1387 SPELL::THUNDERSTRIKE_WARD,
1388 |s| spell_thunderstrike_ward(s, ¶ms.game_data),
1389 )
1390 .spell(
1391 "lightning_shield",
1392 SPELL::LIGHTNING_SHIELD,
1393 |s| spell_lightning_shield(s, ¶ms.game_data),
1394 )
1395 .spell(
1396 "fire_elemental",
1397 SPELL::FIRE_ELEMENTAL,
1398 |s| spell_fire_elemental(s, ¶ms.game_data),
1399 )
1400 .spell(
1401 "fire_blast",
1402 SPELL::FIRE_BLAST,
1403 |s| spell_fire_blast(s, ¶ms.game_data),
1404 )
1405 .spell("meteor", SPELL::METEOR, |s| spell_meteor(s, ¶ms.game_data))
1406 .spell("immolate", SPELL::IMMOLATE, |s| spell_immolate(s, ¶ms.game_data))
1407 .spell("wind_gust", SPELL::WIND_GUST, |s| spell_wind_gust(s, ¶ms.game_data))
1408 .spell(
1409 "call_lightning",
1410 SPELL::CALL_LIGHTNING,
1411 |s| spell_call_lightning(s, ¶ms.game_data),
1412 )
1413 .spell("stormfury", SPELL::STORMFURY, |s| spell_stormfury(s, ¶ms.game_data))
1414 .spell(
1415 "lightning_bolt_overload",
1416 SPELL::LIGHTNING_BOLT_OVERLOAD,
1417 |s| spell_lightning_bolt_overload(s, ¶ms.game_data),
1418 )
1419 .spell(
1420 "chain_lightning_overload",
1421 SPELL::CHAIN_LIGHTNING_OVERLOAD,
1422 |s| spell_chain_lightning_overload(s, ¶ms.game_data),
1423 )
1424 .spell(
1425 "lava_burst_overload",
1426 SPELL::LAVA_BURST_OVERLOAD,
1427 |s| spell_lava_burst_overload(s, ¶ms.game_data),
1428 )
1429 .spell(
1430 "elemental_blast_overload",
1431 SPELL::ELEMENTAL_BLAST_OVERLOAD,
1432 |s| spell_elemental_blast_overload(s, ¶ms.game_data),
1433 )
1434 .spell(
1435 "tempest_overload",
1436 SPELL::TEMPEST_OVERLOAD,
1437 |s| spell_tempest_overload(s, ¶ms.game_data),
1438 )
1439 .spell(
1440 "storms_eye",
1441 SPELL::STORMS_EYE,
1442 |s| spell_storms_eye(s, ¶ms.game_data),
1443 )
1444 .spell(
1445 "lightning_rod_damage",
1446 SPELL::LIGHTNING_ROD_DAMAGE,
1447 |s| spell_lightning_rod_damage(s, ¶ms.game_data),
1448 )
1449 .spell("skyfury", SPELL::SKYFURY, |s| spell_skyfury(s, ¶ms.game_data))
1450 .game_data(params.game_data.clone())
1451 .talent_spell_ids(TALENTS)
1452 .talent_selections(params.talent_selections)
1453 .set_bonus_auras(params.set_bonus_auras)
1454 .encounter(params.encounter.clone());
1455 let builder = crate::generated::items::register_equipped(
1456 builder,
1457 ¶ms.game_data,
1458 params.equipped_items,
1459 )?;
1460
1461 builder
1462 .build(params.rotation)
1463 .map_err(wowlab_engine_ports::EngineError::rotation_compile)
1464}
1465fn new_handler(
1466 params: wowlab_engine_ports::HandlerParams<'_>,
1467) -> Result<Box<dyn SpecHandler>, wowlab_engine_ports::EngineError> {
1468 let handler = crate::composition::compose_handler(
1469 build_combat_system,
1470 ¶ms,
1471 |parts, params| Ok(
1472 crate::hooks::elemental_shaman::ElementalHandler::new(parts, params),
1473 ),
1474 )?;
1475
1476 Ok(Box::new(handler))
1477}
1478static DECLARED_METADATA: DeclaredSpecMetadata = DeclaredSpecMetadata {
1479 primary_resource: ResourceType::Maelstrom,
1480 secondary_resource: None,
1481 spell_ids: DECLARED_SPELL_IDS,
1482 aura_ids: DECLARED_AURA_IDS,
1483 server_proc_entries: &[],
1484 talents: TALENTS,
1485 rotation_field_schema: &[],
1486 metrics_plugin_id: None,
1487 hero_talent_trees: &[
1488 HeroTalentTreeDesc {
1489 name: "Stormbringer",
1490 spells: HERO_TREE_STORMBRINGER_SPELLS,
1491 auras: HERO_TREE_STORMBRINGER_AURAS,
1492 },
1493 HeroTalentTreeDesc {
1494 name: "Farseer",
1495 spells: HERO_TREE_FARSEER_SPELLS,
1496 auras: HERO_TREE_FARSEER_AURAS,
1497 },
1498 HeroTalentTreeDesc {
1499 name: "Totemic",
1500 spells: HERO_TREE_TOTEMIC_SPELLS,
1501 auras: HERO_TREE_TOTEMIC_AURAS,
1502 },
1503 ],
1504 reported_spells: REPORTED_SPELLS,
1505 masked_passive_effects: &[],
1506 passive_effect_overrides: &[],
1507};
1508pub(super) const SPEC_DESCRIPTOR: SpecDescriptor = SpecDescriptor {
1509 spec_id: SpecId::Elemental,
1510 display_name: "Elemental Shaman",
1511 metadata: DECLARED_METADATA,
1512 handler_factory: new_handler,
1513};
1514wowlab_engine_combat::smoke_test!(build_combat_system);