1#![allow(non_snake_case, dead_code)]
4use wowlab_types::{combat::ResourceType, game::SpecId};
5use wowlab_engine_domain::dbc::ProcAttributes;
6use wowlab_engine_combat::{
7 BuiltCombatSystem, AuraDefinitionDraft, LocalAuraIdx, LocalSpellIdx,
8 SpellDefinitionDraft,
9};
10use wowlab_engine_ports::{
11 DeclaredSpecMetadata, SpecDescriptor, SpecHandler, HeroTalentTreeDesc,
12 DeclaredServerProcEntry,
13};
14use wowlab_engine_gamedata::ResolvedGameData;
15pub(crate) mod SPELL {
16 pub(crate) const STORMSTRIKE: u32 = 17364;
18 pub(crate) const LAVA_LASH: u32 = 60103;
20 pub(crate) const CRASH_LIGHTNING: u32 = 187_874;
22 pub(crate) const LIGHTNING_BOLT: u32 = 188_196;
24 pub(crate) const CHAIN_LIGHTNING: u32 = 188_443;
26 pub(crate) const FLAME_SHOCK: u32 = 188_389;
28 pub(crate) const FROST_SHOCK: u32 = 196_840;
30 pub(crate) const SUNDERING: u32 = 197_214;
32 pub(crate) const DOOM_WINDS: u32 = 384_352;
34 pub(crate) const ASCENDANCE: u32 = 114_051;
36 pub(crate) const TEMPEST: u32 = 452_201;
38 pub(crate) const PRIMORDIAL_WAVE: u32 = 375_982;
40 pub(crate) const VOLTAIC_BLAZE: u32 = 470_057;
42 pub(crate) const SKYFURY: u32 = 462_854;
44 pub(crate) const LIGHTNING_SHIELD: u32 = 192_106;
46 pub(crate) const STORMSTRIKE_MH: u32 = 32175;
48 pub(crate) const STORMSTRIKE_OFFHAND: u32 = 32176;
50 pub(crate) const SUNDERING_SPLITSTREAM: u32 = 467_283;
52 pub(crate) const STORMBLAST: u32 = 390_287;
54 pub(crate) const CRASH_LIGHTNING_UNLEASHED: u32 = 1_252_431;
56 pub(crate) const PRIMORDIAL_STORM: u32 = 1_218_090;
58 pub(crate) const PRIMORDIAL_FIRE: u32 = 1_218_113;
60 pub(crate) const PRIMORDIAL_FROST: u32 = 1_218_116;
62 pub(crate) const PRIMORDIAL_LIGHTNING: u32 = 1_218_118;
64 pub(crate) const SURGING_TOTEM: u32 = 444_995;
66 pub(crate) const TREMOR: u32 = 455_622;
68 pub(crate) const SURGING_BOLT: u32 = 458_267;
70 pub(crate) const SEARING_BOLT: u32 = 3606;
72 pub(crate) const SEARING_VOLLEY: u32 = 458_147;
74 pub(crate) const WINDFURY_WEAPON: u32 = 33757;
76 pub(crate) const FLAMETONGUE_WEAPON: u32 = 318_038;
78 pub(crate) const WINDFURY_ATTACK: u32 = 25504;
80 pub(crate) const FLAMETONGUE_ATTACK: u32 = 10444;
82 pub(crate) const FLAMETONGUE_ATTACK_IMBUEMENT_MASTERY: u32 = 467_386;
84 pub(crate) const MAELSTROM_WEAPON_DRIVER: u32 = 187_880;
86 pub(crate) const HOT_HAND_DRIVER: u32 = 201_900;
88 pub(crate) const STORMSURGE_DRIVER: u32 = 201_845;
90}
91pub(crate) mod AURA {
92 pub(crate) const ASCENDANCE: u32 = 114_051;
94 pub(crate) const DOOM_WINDS: u32 = 466_772;
96 pub(crate) const STORM_UNLEASHED: u32 = 1_262_830;
98 pub(crate) const CRASH_LIGHTNING: u32 = 1_252_415;
100 pub(crate) const CONVERGING_STORMS: u32 = 198_300;
102 pub(crate) const MOLTEN_WEAPON: u32 = 224_125;
104 pub(crate) const CRACKLING_SURGE: u32 = 224_127;
106 pub(crate) const TEMPEST: u32 = 454_015;
108 pub(crate) const UNLIMITED_POWER: u32 = 454_394;
110 pub(crate) const FLAME_SHOCK: u32 = 188_389;
112 pub(crate) const LIGHTNING_SHIELD: u32 = 192_106;
114 pub(crate) const PRIMORDIAL_STORM: u32 = 1_218_125;
116 pub(crate) const OVERFLOWING_MAELSTROM: u32 = 384_143;
118 pub(crate) const LASHING_FLAMES: u32 = 334_168;
120 pub(crate) const SKYFURY: u32 = 462_854;
122 pub(crate) const SKYFURY_HIGHLIGHT: u32 = 462_854;
124 pub(crate) const THORIM_S_INVOCATION: u32 = 384_444;
126 pub(crate) const LIVELY_TOTEMS: u32 = 461_242;
128 pub(crate) const AMPLIFICATION_CORE: u32 = 456_369;
130 pub(crate) const SURGING_TOTEM: u32 = 1_221_347;
132 pub(crate) const WHIRLING_FIRE: u32 = 453_405;
134 pub(crate) const WHIRLING_EARTH: u32 = 453_406;
136 pub(crate) const WHIRLING_AIR: u32 = 453_409;
138 pub(crate) const TOTEMIC_REBOUND: u32 = 458_269;
140 pub(crate) const MAELSTROM_WEAPON: u32 = 344_179;
142 pub(crate) const HOT_HAND: u32 = 215_785;
144 pub(crate) const STORMSURGE: u32 = 201_846;
146}
147pub(crate) mod TALENT {
148 pub(crate) const ASCENDANCE: u32 = 114_051;
150 pub(crate) const ASHEN_CATALYST: u32 = 390_370;
152 pub(crate) const CRASH_LIGHTNING: u32 = 187_874;
154 pub(crate) const DEEPLY_ROOTED_ELEMENTS: u32 = 378_270;
156 pub(crate) const DOOM_WINDS: u32 = 384_352;
158 pub(crate) const ELEMENTAL_ASSAULT: u32 = 210_853;
160 pub(crate) const ELEMENTAL_BLAST: u32 = 117_014;
162 pub(crate) const ELEMENTAL_TEMPO: u32 = 1_250_364;
164 pub(crate) const ELEMENTAL_WEAPONS: u32 = 384_355;
166 pub(crate) const FERAL_SPIRIT: u32 = 469_314;
168 pub(crate) const FLAMETONGUE_WEAPON: u32 = 318_038;
170 pub(crate) const FORCEFUL_WINDS: u32 = 262_647;
172 pub(crate) const HOT_HAND: u32 = 201_900;
174 pub(crate) const IMBUEMENT_MASTERY: u32 = 445_028;
176 pub(crate) const LAVA_LASH: u32 = 60103;
178 pub(crate) const LIVELY_TOTEMS: u32 = 445_034;
180 pub(crate) const MAELSTROM_WEAPON: u32 = 187_880;
182 pub(crate) const OVERFLOWING_MAELSTROM: u32 = 384_143;
184 pub(crate) const PRIMORDIAL_STORM: u32 = 1_218_047;
186 pub(crate) const RAGING_MAELSTROM: u32 = 384_149;
188 pub(crate) const SPLITSTREAM: u32 = 445_035;
190 pub(crate) const STORMBLAST: u32 = 319_930;
192 pub(crate) const STORMFLURRY: u32 = 344_357;
194 pub(crate) const STORMS_WRATH: u32 = 392_352;
196 pub(crate) const STORM_UNLEASHED: u32 = 1_262_713;
198 pub(crate) const STORM_UNLEASHED_REPEATS: u32 = 1_252_373;
200 pub(crate) const SUNDERING: u32 = 197_214;
202 pub(crate) const THORIMS_INVOCATION: u32 = 384_444;
204 pub(crate) const TOTEMIC_MOMENTUM: u32 = 1_260_644;
206 pub(crate) const UNRULY_WINDS: u32 = 390_288;
208 pub(crate) const VOLTAIC_BLAZE: u32 = 470_057;
210 pub(crate) const WINDFURY_WEAPON: u32 = 33757;
212}
213pub(crate) mod REPORTED_SPELL {
214 pub(crate) const CRASH_LIGHTNING_PROC: u32 = 195_592;
216 pub(crate) const CRASH_LIGHTNING_UNLEASHED: u32 = 1_252_431;
218 pub(crate) const DOOM_WINDS_DAMAGE: u32 = 469_270;
220 pub(crate) const ELEMENTAL_WEAPONS_MODIFIER: u32 = 408_390;
222 pub(crate) const FLAMETONGUE_ATTACK_IMBUEMENT_MASTERY: u32 = 467_386;
224 pub(crate) const PRIMORDIAL_FIRE: u32 = 1_218_113;
226 pub(crate) const PRIMORDIAL_FROST: u32 = 1_218_116;
228 pub(crate) const PRIMORDIAL_LIGHTNING: u32 = 1_218_118;
230 pub(crate) const SEARING_VOLLEY: u32 = 458_147;
232 pub(crate) const STORMBLAST: u32 = 390_287;
234 pub(crate) const SUNDERING_SPLITSTREAM: u32 = 467_283;
236 pub(crate) const VOLTAIC_BLAZE_DAMAGE: u32 = 1_259_101;
238}
239pub(crate) mod HERO {
240 pub(crate) mod STORMBRINGER {
241 pub(crate) mod SPELL {
242 pub(crate) const TEMPEST: u32 = 452_201;
244 }
245 pub(crate) mod AURA {
246 pub(crate) const ARC_DISCHARGE: u32 = 470_532;
248 pub(crate) const AWAKENING_STORMS: u32 = 455_129;
250 pub(crate) const STORM_SWELL: u32 = 455_089;
252 pub(crate) const TEMPEST: u32 = 454_015;
254 pub(crate) const UNLIMITED_POWER: u32 = 454_394;
256 }
257 }
258 pub(crate) mod TOTEMIC {
259 pub(crate) mod SPELL {
260 pub(crate) const SURGING_TOTEM: u32 = 444_995;
262 }
263 pub(crate) mod AURA {
264 pub(crate) const AMPLIFICATION_CORE: u32 = 456_369;
266 pub(crate) const LIVELY_TOTEMS: u32 = 461_242;
268 pub(crate) const SURGING_TOTEM: u32 = 1_221_347;
270 pub(crate) const TOTEMIC_REBOUND: u32 = 458_269;
272 pub(crate) const WHIRLING_AIR: u32 = 453_409;
274 pub(crate) const WHIRLING_EARTH: u32 = 453_406;
276 pub(crate) const WHIRLING_FIRE: u32 = 453_405;
278 }
279 }
280}
281static HERO_TREE_STORMBRINGER_SPELLS: &[(&str, u32)] = &[("TEMPEST", 452_201)];
282static HERO_TREE_STORMBRINGER_AURAS: &[(&str, u32)] = &[
283 ("ARC_DISCHARGE", 470_532),
284 ("AWAKENING_STORMS", 455_129),
285 ("STORM_SWELL", 455_089),
286 ("TEMPEST", 454_015),
287 ("UNLIMITED_POWER", 454_394),
288];
289static HERO_TREE_TOTEMIC_SPELLS: &[(&str, u32)] = &[("SURGING_TOTEM", 444_995)];
290static HERO_TREE_TOTEMIC_AURAS: &[(&str, u32)] = &[
291 ("AMPLIFICATION_CORE", 456_369),
292 ("LIVELY_TOTEMS", 461_242),
293 ("SURGING_TOTEM", 1_221_347),
294 ("TOTEMIC_REBOUND", 458_269),
295 ("WHIRLING_AIR", 453_409),
296 ("WHIRLING_EARTH", 453_406),
297 ("WHIRLING_FIRE", 453_405),
298];
299pub(crate) const AURA_ASCENDANCE: LocalAuraIdx = LocalAuraIdx::new(0);
300pub(crate) const AURA_DOOM_WINDS: LocalAuraIdx = LocalAuraIdx::new(1);
301pub(crate) const AURA_STORM_UNLEASHED: LocalAuraIdx = LocalAuraIdx::new(2);
302pub(crate) const AURA_CRASH_LIGHTNING: LocalAuraIdx = LocalAuraIdx::new(3);
303pub(crate) const AURA_CONVERGING_STORMS: LocalAuraIdx = LocalAuraIdx::new(4);
304pub(crate) const AURA_MOLTEN_WEAPON: LocalAuraIdx = LocalAuraIdx::new(5);
305pub(crate) const AURA_CRACKLING_SURGE: LocalAuraIdx = LocalAuraIdx::new(6);
306pub(crate) const AURA_TEMPEST: LocalAuraIdx = LocalAuraIdx::new(7);
307pub(crate) const AURA_UNLIMITED_POWER: LocalAuraIdx = LocalAuraIdx::new(8);
308pub(crate) const AURA_FLAME_SHOCK: LocalAuraIdx = LocalAuraIdx::new(9);
309pub(crate) const AURA_LIGHTNING_SHIELD: LocalAuraIdx = LocalAuraIdx::new(10);
310pub(crate) const AURA_PRIMORDIAL_STORM: LocalAuraIdx = LocalAuraIdx::new(11);
311pub(crate) const AURA_OVERFLOWING_MAELSTROM: LocalAuraIdx = LocalAuraIdx::new(12);
312pub(crate) const AURA_LASHING_FLAMES: LocalAuraIdx = LocalAuraIdx::new(13);
313pub(crate) const AURA_SKYFURY: LocalAuraIdx = LocalAuraIdx::new(14);
314pub(crate) const AURA_SKYFURY_HIGHLIGHT: LocalAuraIdx = LocalAuraIdx::new(15);
315pub(crate) const AURA_THORIM_S_INVOCATION: LocalAuraIdx = LocalAuraIdx::new(16);
316pub(crate) const AURA_LIVELY_TOTEMS: LocalAuraIdx = LocalAuraIdx::new(17);
317pub(crate) const AURA_AMPLIFICATION_CORE: LocalAuraIdx = LocalAuraIdx::new(18);
318pub(crate) const AURA_SURGING_TOTEM: LocalAuraIdx = LocalAuraIdx::new(19);
319pub(crate) const AURA_WHIRLING_FIRE: LocalAuraIdx = LocalAuraIdx::new(20);
320pub(crate) const AURA_WHIRLING_EARTH: LocalAuraIdx = LocalAuraIdx::new(21);
321pub(crate) const AURA_WHIRLING_AIR: LocalAuraIdx = LocalAuraIdx::new(22);
322pub(crate) const AURA_TOTEMIC_REBOUND: LocalAuraIdx = LocalAuraIdx::new(23);
323pub(crate) const AURA_MAELSTROM_WEAPON: LocalAuraIdx = LocalAuraIdx::new(24);
324pub(crate) const AURA_HOT_HAND: LocalAuraIdx = LocalAuraIdx::new(25);
325pub(crate) const AURA_STORMSURGE: LocalAuraIdx = LocalAuraIdx::new(26);
326pub(crate) const AURA_COUNT: usize = 27;
327const _: () = assert!(
328 AURA_COUNT == 27, "AURA index ABI: count changed -- update positional hook consumers"
329);
330pub(crate) const SPELL_STORMSTRIKE: LocalSpellIdx = LocalSpellIdx::new(0);
331pub(crate) const SPELL_LAVA_LASH: LocalSpellIdx = LocalSpellIdx::new(1);
332pub(crate) const SPELL_CRASH_LIGHTNING: LocalSpellIdx = LocalSpellIdx::new(2);
333pub(crate) const SPELL_LIGHTNING_BOLT: LocalSpellIdx = LocalSpellIdx::new(3);
334pub(crate) const SPELL_CHAIN_LIGHTNING: LocalSpellIdx = LocalSpellIdx::new(4);
335pub(crate) const SPELL_FLAME_SHOCK: LocalSpellIdx = LocalSpellIdx::new(5);
336pub(crate) const SPELL_FROST_SHOCK: LocalSpellIdx = LocalSpellIdx::new(6);
337pub(crate) const SPELL_SUNDERING: LocalSpellIdx = LocalSpellIdx::new(7);
338pub(crate) const SPELL_DOOM_WINDS: LocalSpellIdx = LocalSpellIdx::new(8);
339pub(crate) const SPELL_ASCENDANCE: LocalSpellIdx = LocalSpellIdx::new(9);
340pub(crate) const SPELL_TEMPEST: LocalSpellIdx = LocalSpellIdx::new(10);
341pub(crate) const SPELL_PRIMORDIAL_WAVE: LocalSpellIdx = LocalSpellIdx::new(11);
342pub(crate) const SPELL_VOLTAIC_BLAZE: LocalSpellIdx = LocalSpellIdx::new(12);
343pub(crate) const SPELL_SKYFURY: LocalSpellIdx = LocalSpellIdx::new(13);
344pub(crate) const SPELL_LIGHTNING_SHIELD: LocalSpellIdx = LocalSpellIdx::new(14);
345pub(crate) const SPELL_STORMSTRIKE_MH: LocalSpellIdx = LocalSpellIdx::new(15);
346pub(crate) const SPELL_STORMSTRIKE_OFFHAND: LocalSpellIdx = LocalSpellIdx::new(16);
347pub(crate) const SPELL_SUNDERING_SPLITSTREAM: LocalSpellIdx = LocalSpellIdx::new(17);
348pub(crate) const SPELL_STORMBLAST: LocalSpellIdx = LocalSpellIdx::new(18);
349pub(crate) const SPELL_CRASH_LIGHTNING_UNLEASHED: LocalSpellIdx = LocalSpellIdx::new(19);
350pub(crate) const SPELL_PRIMORDIAL_STORM: LocalSpellIdx = LocalSpellIdx::new(20);
351pub(crate) const SPELL_PRIMORDIAL_FIRE: LocalSpellIdx = LocalSpellIdx::new(21);
352pub(crate) const SPELL_PRIMORDIAL_FROST: LocalSpellIdx = LocalSpellIdx::new(22);
353pub(crate) const SPELL_PRIMORDIAL_LIGHTNING: LocalSpellIdx = LocalSpellIdx::new(23);
354pub(crate) const SPELL_SURGING_TOTEM: LocalSpellIdx = LocalSpellIdx::new(24);
355pub(crate) const SPELL_TREMOR: LocalSpellIdx = LocalSpellIdx::new(25);
356pub(crate) const SPELL_SURGING_BOLT: LocalSpellIdx = LocalSpellIdx::new(26);
357pub(crate) const SPELL_SEARING_BOLT: LocalSpellIdx = LocalSpellIdx::new(27);
358pub(crate) const SPELL_SEARING_VOLLEY: LocalSpellIdx = LocalSpellIdx::new(28);
359pub(crate) const SPELL_WINDFURY_WEAPON: LocalSpellIdx = LocalSpellIdx::new(29);
360pub(crate) const SPELL_FLAMETONGUE_WEAPON: LocalSpellIdx = LocalSpellIdx::new(30);
361pub(crate) const SPELL_WINDFURY_ATTACK: LocalSpellIdx = LocalSpellIdx::new(31);
362pub(crate) const SPELL_FLAMETONGUE_ATTACK: LocalSpellIdx = LocalSpellIdx::new(32);
363pub(crate) const SPELL_FLAMETONGUE_ATTACK_IMBUEMENT_MASTERY: LocalSpellIdx = LocalSpellIdx::new(
364 33,
365);
366pub(crate) const SPELL_MAELSTROM_WEAPON_DRIVER: LocalSpellIdx = LocalSpellIdx::new(34);
367pub(crate) const SPELL_HOT_HAND_DRIVER: LocalSpellIdx = LocalSpellIdx::new(35);
368pub(crate) const SPELL_STORMSURGE_DRIVER: LocalSpellIdx = LocalSpellIdx::new(36);
369pub(crate) const SPELL_COUNT: usize = 37;
370const _: () = assert!(
371 SPELL_COUNT == 37,
372 "SPELL index ABI: count changed -- update positional hook consumers"
373);
374pub(crate) mod EFFECT {
375 pub(crate) const ASHEN_CATALYST_CDR: (u32, u8) = (390_370, 1);
377 pub(crate) const CHAIN_LIGHTNING_DAMAGE: (u32, u8) = (188_443, 1);
379 pub(crate) const CRASH_LIGHTNING_DAMAGE: (u32, u8) = (1_252_415, 1);
381 pub(crate) const CRASH_LIGHTNING_UNLEASHED_DAMAGE: (u32, u8) = (1_252_431, 1);
383 pub(crate) const ELEMENTAL_TEMPO_CDR: (u32, u8) = (1_250_364, 3);
385 pub(crate) const ELEMENTAL_WEAPONS_BONUS: (u32, u8) = (384_355, 1);
387 pub(crate) const ELEMENTAL_WEAPONS_DIRECT: (u32, u8) = (408_390, 1);
389 pub(crate) const ELEMENTAL_WEAPONS_PERIODIC: (u32, u8) = (408_390, 2);
391 pub(crate) const FLAMETONGUE_ATTACK_DAMAGE: (u32, u8) = (10444, 1);
393 pub(crate) const LAVA_LASH_DAMAGE: (u32, u8) = (60103, 1);
395 pub(crate) const LIGHTNING_BOLT_DAMAGE: (u32, u8) = (188_196, 1);
397 pub(crate) const PRIMORDIAL_FIRE_DAMAGE: (u32, u8) = (1_218_113, 1);
399 pub(crate) const PRIMORDIAL_FROST_DAMAGE: (u32, u8) = (1_218_116, 1);
401 pub(crate) const PRIMORDIAL_LIGHTNING_DAMAGE: (u32, u8) = (1_218_118, 1);
403 pub(crate) const SEARING_BOLT_DAMAGE: (u32, u8) = (3606, 1);
405 pub(crate) const SEARING_VOLLEY_DAMAGE: (u32, u8) = (458_147, 1);
407 pub(crate) const SPLITSTREAM_DAMAGE: (u32, u8) = (445_035, 1);
409 pub(crate) const STORMBLAST_BONUS: (u32, u8) = (319_930, 1);
411 pub(crate) const STORMSTRIKE_MH_DAMAGE: (u32, u8) = (32175, 1);
413 pub(crate) const STORMSTRIKE_OH_DAMAGE: (u32, u8) = (32176, 1);
415 pub(crate) const STORMSURGE_MASTERY: (u32, u8) = (77223, 3);
417 pub(crate) const STORM_UNLEASHED_CHANCE: (u32, u8) = (1_262_713, 1);
419 pub(crate) const SUNDERING_SPLITSTREAM_DAMAGE: (u32, u8) = (467_283, 1);
421 pub(crate) const SURGING_BOLT_DAMAGE: (u32, u8) = (458_267, 1);
423 pub(crate) const TOTEMIC_MOMENTUM_BONUS: (u32, u8) = (1_260_644, 1);
425 pub(crate) const TREMOR_DAMAGE: (u32, u8) = (455_622, 1);
427 pub(crate) const VOLTAIC_BLAZE_MAELSTROM_STACKS: (u32, u8) = (470_057, 2);
429 pub(crate) const WINDFURY_ATTACK_DAMAGE: (u32, u8) = (25504, 1);
431 pub(crate) const WINDFURY_MASTERY: (u32, u8) = (77223, 4);
433 pub(crate) const WINDFURY_PROC: (u32, u8) = (319_773, 1);
435 pub(crate) const TOTEMIC_REBOUND_RPPM_DRIVER: (u32, u8) = (445_025, 1);
437}
438static REPORTED_SPELLS: &[(&str, u32)] = &[
439 ("crash_lightning_proc", 195_592),
440 ("crash_lightning_unleashed", 1_252_431),
441 ("doom_winds_damage", 469_270),
442 ("elemental_weapons_modifier", 408_390),
443 ("flametongue_attack_imbuement_mastery", 467_386),
444 ("primordial_fire", 1_218_113),
445 ("primordial_frost", 1_218_116),
446 ("primordial_lightning", 1_218_118),
447 ("searing_volley", 458_147),
448 ("stormblast", 390_287),
449 ("sundering_splitstream", 467_283),
450 ("voltaic_blaze_damage", 1_259_101),
451];
452static DECLARED_SPELL_IDS: &[u32] = &[
453 17364, 60103, 187_874, 188_196, 188_443, 188_389, 196_840, 197_214, 384_352, 114_051,
454 452_201, 375_982, 470_057, 462_854, 192_106, 32175, 32176, 467_283, 390_287,
455 1_252_431, 1_218_090, 1_218_113, 1_218_116, 1_218_118, 444_995, 455_622, 458_267,
456 3606, 458_147, 33757, 318_038, 25504, 10444, 467_386, 187_880, 201_900, 201_845,
457 114_051, 466_772, 1_262_830, 1_252_415, 198_300, 224_125, 224_127, 454_015, 454_394,
458 188_389, 192_106, 1_218_125, 384_143, 334_168, 462_854, 462_854, 384_444, 461_242,
459 456_369, 1_221_347, 453_405, 453_406, 453_409, 458_269, 344_179, 215_785, 201_846,
460 6603, 6603, 3606, 10444, 25504, 32175, 32176, 60103, 77223, 188_196, 188_389,
461 188_443, 195_592, 197_214, 319_773, 319_930, 384_355, 390_287, 390_370, 408_390,
462 445_025, 445_035, 454_394, 455_593, 455_622, 458_147, 458_267, 466_772, 467_283,
463 467_386, 469_270, 470_057, 1_218_113, 1_218_116, 1_218_118, 1_250_364, 1_252_415,
464 1_252_431, 1_259_101, 1_260_644, 1_262_713, 195_592, 1_252_431, 469_270, 408_390,
465 467_386, 1_218_113, 1_218_116, 1_218_118, 458_147, 390_287, 467_283, 1_259_101,
466 452_201, 470_532, 455_129, 455_089, 454_015, 454_394, 444_995, 456_369, 461_242,
467 1_221_347, 458_269, 453_409, 453_406, 453_405,
468];
469static DECLARED_AURA_IDS: &[u32] = &[
470 114_051, 466_772, 1_262_830, 1_252_415, 198_300, 224_125, 224_127, 454_015, 454_394,
471 188_389, 192_106, 1_218_125, 384_143, 334_168, 462_854, 462_854, 384_444, 461_242,
472 456_369, 1_221_347, 453_405, 453_406, 453_409, 458_269, 344_179, 215_785, 201_846,
473 470_532, 455_129, 455_089, 454_015, 454_394, 456_369, 461_242, 1_221_347, 458_269,
474 453_409, 453_406, 453_405,
475];
476static TALENTS: &[(&str, u32)] = &[
477 ("ASCENDANCE", TALENT::ASCENDANCE),
478 ("ASHEN_CATALYST", TALENT::ASHEN_CATALYST),
479 ("CRASH_LIGHTNING", TALENT::CRASH_LIGHTNING),
480 ("DEEPLY_ROOTED_ELEMENTS", TALENT::DEEPLY_ROOTED_ELEMENTS),
481 ("DOOM_WINDS", TALENT::DOOM_WINDS),
482 ("ELEMENTAL_ASSAULT", TALENT::ELEMENTAL_ASSAULT),
483 ("ELEMENTAL_BLAST", TALENT::ELEMENTAL_BLAST),
484 ("ELEMENTAL_TEMPO", TALENT::ELEMENTAL_TEMPO),
485 ("ELEMENTAL_WEAPONS", TALENT::ELEMENTAL_WEAPONS),
486 ("FERAL_SPIRIT", TALENT::FERAL_SPIRIT),
487 ("FLAMETONGUE_WEAPON", TALENT::FLAMETONGUE_WEAPON),
488 ("FORCEFUL_WINDS", TALENT::FORCEFUL_WINDS),
489 ("HOT_HAND", TALENT::HOT_HAND),
490 ("IMBUEMENT_MASTERY", TALENT::IMBUEMENT_MASTERY),
491 ("LAVA_LASH", TALENT::LAVA_LASH),
492 ("LIVELY_TOTEMS", TALENT::LIVELY_TOTEMS),
493 ("MAELSTROM_WEAPON", TALENT::MAELSTROM_WEAPON),
494 ("OVERFLOWING_MAELSTROM", TALENT::OVERFLOWING_MAELSTROM),
495 ("PRIMORDIAL_STORM", TALENT::PRIMORDIAL_STORM),
496 ("RAGING_MAELSTROM", TALENT::RAGING_MAELSTROM),
497 ("SPLITSTREAM", TALENT::SPLITSTREAM),
498 ("STORMBLAST", TALENT::STORMBLAST),
499 ("STORMFLURRY", TALENT::STORMFLURRY),
500 ("STORMS_WRATH", TALENT::STORMS_WRATH),
501 ("STORM_UNLEASHED", TALENT::STORM_UNLEASHED),
502 ("STORM_UNLEASHED_REPEATS", TALENT::STORM_UNLEASHED_REPEATS),
503 ("SUNDERING", TALENT::SUNDERING),
504 ("THORIMS_INVOCATION", TALENT::THORIMS_INVOCATION),
505 ("TOTEMIC_MOMENTUM", TALENT::TOTEMIC_MOMENTUM),
506 ("UNRULY_WINDS", TALENT::UNRULY_WINDS),
507 ("VOLTAIC_BLAZE", TALENT::VOLTAIC_BLAZE),
508 ("WINDFURY_WEAPON", TALENT::WINDFURY_WEAPON),
509];
510pub(crate) mod ENHANCEMENT_SHAMAN {
511 pub(crate) const STORMSTRIKE_CASTS: u32 = 0;
512 pub(crate) const LAVA_LASH_CASTS: u32 = 1;
513 pub(crate) const CRASH_LIGHTNING_CASTS: u32 = 2;
514 pub(crate) const LIGHTNING_BOLT_CASTS: u32 = 3;
515 pub(crate) const DOOM_WINDS_CASTS: u32 = 4;
516 pub(crate) const ASCENDANCE_CASTS: u32 = 5;
517 pub(crate) const TEMPEST_CASTS: u32 = 6;
518 pub(crate) const MAELSTROM_WEAPON_CONSUMED: u32 = 7;
519}
520fn aura_ascendance(
521 a: AuraDefinitionDraft,
522 data: &ResolvedGameData,
523) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
524 a.on_player()
525 .apply_base_from_data(data, 114_051)?
526 .max_stacks(
527 data.require_aura_max_stacks(wowlab_types::sim::SpellIdx::from_raw(114_051))?,
528 )
529 .damage_multiplier(1.2)
530}
531fn aura_doom_winds(
532 a: AuraDefinitionDraft,
533 data: &ResolvedGameData,
534) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
535 a.on_player()
536 .apply_base_from_data(data, 466_772)?
537 .max_stacks(
538 data.require_aura_max_stacks(wowlab_types::sim::SpellIdx::from_raw(466_772))?,
539 )
540 .periodic_damage_from_spell(
541 wowlab_engine_combat::validated_milliseconds(
542 data.period(wowlab_types::sim::SpellIdx::from_raw(466_772), 3),
543 466_772,
544 "periodic_damage.tick_ms",
545 )?,
546 wowlab_engine_combat::DamagePayload::new(
547 469_270,
548 ((data.ap_coef(wowlab_types::sim::SpellIdx::from_raw(469_270), 1))
549 * 10.0)
550 .round() / 10.0,
551 wowlab_engine_combat::DamageFlags::empty(),
552 ),
553 )
554 .apply_periodic_behavior_from_data(data, 466_772)
555}
556fn aura_storm_unleashed(
557 a: AuraDefinitionDraft,
558 data: &ResolvedGameData,
559) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
560 Ok(
561 a
562 .on_player()
563 .apply_base_from_data(data, 1_262_830)?
564 .max_stacks(
565 data
566 .require_aura_max_stacks(
567 wowlab_types::sim::SpellIdx::from_raw(1_262_830),
568 )?,
569 ),
570 )
571}
572fn aura_crash_lightning(
573 a: AuraDefinitionDraft,
574 data: &ResolvedGameData,
575) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
576 Ok(
577 a
578 .on_player()
579 .apply_base_from_data(data, 1_252_415)?
580 .max_stacks(
581 data
582 .require_aura_max_stacks(
583 wowlab_types::sim::SpellIdx::from_raw(1_252_415),
584 )?,
585 )
586 .async_stacks(),
587 )
588}
589fn aura_converging_storms(
590 a: AuraDefinitionDraft,
591 data: &ResolvedGameData,
592) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
593 Ok(
594 a
595 .on_player()
596 .apply_base_from_data(data, 198_300)?
597 .max_stacks(
598 data
599 .require_aura_max_stacks(
600 wowlab_types::sim::SpellIdx::from_raw(198_300),
601 )?,
602 ),
603 )
604}
605fn aura_molten_weapon(
606 a: AuraDefinitionDraft,
607 data: &ResolvedGameData,
608) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
609 Ok(
610 a
611 .on_player()
612 .apply_base_from_data(data, 224_125)?
613 .max_stacks(
614 data
615 .require_aura_max_stacks(
616 wowlab_types::sim::SpellIdx::from_raw(224_125),
617 )?,
618 ),
619 )
620}
621fn aura_crackling_surge(
622 a: AuraDefinitionDraft,
623 data: &ResolvedGameData,
624) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
625 Ok(
626 a
627 .on_player()
628 .apply_base_from_data(data, 224_127)?
629 .max_stacks(
630 data
631 .require_aura_max_stacks(
632 wowlab_types::sim::SpellIdx::from_raw(224_127),
633 )?,
634 ),
635 )
636}
637fn aura_tempest(
638 a: AuraDefinitionDraft,
639 data: &ResolvedGameData,
640) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
641 Ok(
642 a
643 .on_player()
644 .apply_base_from_data(data, 454_015)?
645 .max_stacks(
646 data
647 .require_aura_max_stacks(
648 wowlab_types::sim::SpellIdx::from_raw(454_015),
649 )?,
650 ),
651 )
652}
653fn aura_unlimited_power(
654 a: AuraDefinitionDraft,
655 data: &ResolvedGameData,
656) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
657 a.on_player()
658 .apply_base_from_data(data, 454_394)?
659 .max_stacks(
660 data.require_aura_max_stacks(wowlab_types::sim::SpellIdx::from_raw(454_394))?,
661 )
662 .haste_per_stack(
663 (data.base_points(wowlab_types::sim::SpellIdx::from_raw(454_394), 1)) * 2.0,
664 )
665}
666fn aura_flame_shock(
667 a: AuraDefinitionDraft,
668 data: &ResolvedGameData,
669) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
670 a.on_target()
671 .apply_base_from_data(data, 188_389)?
672 .max_stacks(
673 data.require_aura_max_stacks(wowlab_types::sim::SpellIdx::from_raw(188_389))?,
674 )
675 .periodic_damage(
676 wowlab_engine_combat::validated_milliseconds(
677 data.period(wowlab_types::sim::SpellIdx::from_raw(188_389), 2),
678 188_389,
679 "periodic_damage.tick_ms",
680 )?,
681 ((data.sp_coef(wowlab_types::sim::SpellIdx::from_raw(188_389), 2)) * 10000.0)
682 .round() / 10000.0,
683 wowlab_engine_combat::DamageFlags::empty(),
684 )
685 .apply_periodic_behavior_from_data(data, 188_389)
686}
687fn aura_lightning_shield(
688 a: AuraDefinitionDraft,
689 data: &ResolvedGameData,
690) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
691 Ok(
692 a
693 .on_player()
694 .apply_base_from_data(data, 192_106)?
695 .max_stacks(
696 data
697 .require_aura_max_stacks(
698 wowlab_types::sim::SpellIdx::from_raw(192_106),
699 )?,
700 ),
701 )
702}
703fn aura_primordial_storm(
704 a: AuraDefinitionDraft,
705 data: &ResolvedGameData,
706) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
707 Ok(
708 a
709 .on_player()
710 .apply_base_from_data(data, 1_218_125)?
711 .max_stacks(
712 data
713 .require_aura_max_stacks(
714 wowlab_types::sim::SpellIdx::from_raw(1_218_125),
715 )?,
716 ),
717 )
718}
719fn aura_overflowing_maelstrom(
720 a: AuraDefinitionDraft,
721 data: &ResolvedGameData,
722) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
723 Ok(
724 a
725 .on_player()
726 .apply_base_from_data(data, 384_143)?
727 .max_stacks(
728 data
729 .require_aura_max_stacks(
730 wowlab_types::sim::SpellIdx::from_raw(384_143),
731 )?,
732 ),
733 )
734}
735fn aura_lashing_flames(
736 a: AuraDefinitionDraft,
737 data: &ResolvedGameData,
738) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
739 Ok(
740 a
741 .on_target()
742 .apply_base_from_data(data, 334_168)?
743 .max_stacks(
744 data
745 .require_aura_max_stacks(
746 wowlab_types::sim::SpellIdx::from_raw(334_168),
747 )?,
748 ),
749 )
750}
751fn aura_skyfury(
752 a: AuraDefinitionDraft,
753 data: &ResolvedGameData,
754) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
755 Ok(
756 a
757 .on_player()
758 .apply_base_from_data(data, 462_854)?
759 .max_stacks(
760 data
761 .require_aura_max_stacks(
762 wowlab_types::sim::SpellIdx::from_raw(462_854),
763 )?,
764 ),
765 )
766}
767fn aura_skyfury_highlight(
768 a: AuraDefinitionDraft,
769 data: &ResolvedGameData,
770) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
771 Ok(
772 a
773 .on_player()
774 .apply_base_from_data(data, 462_854)?
775 .max_stacks(
776 data
777 .require_aura_max_stacks(
778 wowlab_types::sim::SpellIdx::from_raw(462_854),
779 )?,
780 ),
781 )
782}
783fn aura_thorim_s_invocation(
784 a: AuraDefinitionDraft,
785 data: &ResolvedGameData,
786) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
787 Ok(
788 a
789 .on_player()
790 .apply_base_from_data(data, 384_444)?
791 .max_stacks(
792 data
793 .require_aura_max_stacks(
794 wowlab_types::sim::SpellIdx::from_raw(384_444),
795 )?,
796 ),
797 )
798}
799fn aura_lively_totems(
800 a: AuraDefinitionDraft,
801 data: &ResolvedGameData,
802) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
803 Ok(
804 a
805 .on_player()
806 .apply_base_from_data(data, 461_242)?
807 .max_stacks(
808 data
809 .require_aura_max_stacks(
810 wowlab_types::sim::SpellIdx::from_raw(461_242),
811 )?,
812 ),
813 )
814}
815fn aura_amplification_core(
816 a: AuraDefinitionDraft,
817 data: &ResolvedGameData,
818) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
819 Ok(
820 a
821 .on_player()
822 .apply_base_from_data(data, 456_369)?
823 .max_stacks(
824 data
825 .require_aura_max_stacks(
826 wowlab_types::sim::SpellIdx::from_raw(456_369),
827 )?,
828 ),
829 )
830}
831fn aura_surging_totem(
832 a: AuraDefinitionDraft,
833 data: &ResolvedGameData,
834) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
835 Ok(
836 a
837 .on_player()
838 .apply_base_from_data(data, 1_221_347)?
839 .max_stacks(
840 data
841 .require_aura_max_stacks(
842 wowlab_types::sim::SpellIdx::from_raw(1_221_347),
843 )?,
844 )
845 .periodic_hook(
846 wowlab_engine_combat::validated_milliseconds(
847 data.period(wowlab_types::sim::SpellIdx::from_raw(455_593), 1),
848 1_221_347,
849 "periodic_hook.tick_ms",
850 )?,
851 )
852 .apply_periodic_behavior_from_data(data, 455_593)?
853 .hasted_periodic()
854 .tick_hook(crate::hooks::enhancement_shaman::surging_totem_pulse_hook),
855 )
856}
857fn aura_whirling_fire(
858 a: AuraDefinitionDraft,
859 data: &ResolvedGameData,
860) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
861 Ok(
862 a
863 .on_player()
864 .apply_base_from_data(data, 453_405)?
865 .max_stacks(
866 data
867 .require_aura_max_stacks(
868 wowlab_types::sim::SpellIdx::from_raw(453_405),
869 )?,
870 ),
871 )
872}
873fn aura_whirling_earth(
874 a: AuraDefinitionDraft,
875 data: &ResolvedGameData,
876) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
877 Ok(
878 a
879 .on_player()
880 .apply_base_from_data(data, 453_406)?
881 .max_stacks(
882 data
883 .require_aura_max_stacks(
884 wowlab_types::sim::SpellIdx::from_raw(453_406),
885 )?,
886 ),
887 )
888}
889fn aura_whirling_air(
890 a: AuraDefinitionDraft,
891 data: &ResolvedGameData,
892) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
893 Ok(
894 a
895 .on_player()
896 .apply_base_from_data(data, 453_409)?
897 .max_stacks(
898 data
899 .require_aura_max_stacks(
900 wowlab_types::sim::SpellIdx::from_raw(453_409),
901 )?,
902 ),
903 )
904}
905fn aura_totemic_rebound(
906 a: AuraDefinitionDraft,
907 data: &ResolvedGameData,
908) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
909 Ok(
910 a
911 .on_player()
912 .apply_base_from_data(data, 458_269)?
913 .max_stacks(
914 data
915 .require_aura_max_stacks(
916 wowlab_types::sim::SpellIdx::from_raw(458_269),
917 )?,
918 ),
919 )
920}
921fn aura_maelstrom_weapon(
922 a: AuraDefinitionDraft,
923 data: &ResolvedGameData,
924) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
925 Ok(
926 a
927 .on_player()
928 .apply_base_from_data(data, 344_179)?
929 .max_stacks(
930 data
931 .require_aura_max_stacks(
932 wowlab_types::sim::SpellIdx::from_raw(344_179),
933 )?,
934 ),
935 )
936}
937fn aura_hot_hand(
938 a: AuraDefinitionDraft,
939 data: &ResolvedGameData,
940) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
941 Ok(
942 a
943 .on_player()
944 .apply_base_from_data(data, 215_785)?
945 .max_stacks(
946 data
947 .require_aura_max_stacks(
948 wowlab_types::sim::SpellIdx::from_raw(215_785),
949 )?,
950 ),
951 )
952}
953fn aura_stormsurge(
954 a: AuraDefinitionDraft,
955 data: &ResolvedGameData,
956) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
957 Ok(
958 a
959 .on_player()
960 .apply_base_from_data(data, 201_846)?
961 .max_stacks(
962 data
963 .require_aura_max_stacks(
964 wowlab_types::sim::SpellIdx::from_raw(201_846),
965 )?,
966 ),
967 )
968}
969fn spell_stormstrike(
970 s: SpellDefinitionDraft,
971 data: &ResolvedGameData,
972) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
973 Ok(
974 s
975 .apply_base_from_data(data, 17364)?
976 .without_primary_data_damage()
977 .trigger_program_predicate(
978 1,
979 crate::hooks::enhancement_shaman::hook_owned_damage_trigger_disabled,
980 )
981 .trigger_program_predicate(
982 2,
983 crate::hooks::enhancement_shaman::hook_owned_damage_trigger_disabled,
984 )
985 .apply_aoe_from_data(data)
986 .on_cast(crate::hooks::enhancement_shaman::stormstrike_hook),
987 )
988}
989fn spell_lava_lash(
990 s: SpellDefinitionDraft,
991 data: &ResolvedGameData,
992) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
993 Ok(
994 s
995 .apply_base_from_data(data, 60103)?
996 .apply_aoe_from_data(data)
997 .on_cast(crate::hooks::enhancement_shaman::lava_lash_hook),
998 )
999}
1000fn spell_crash_lightning(
1001 s: SpellDefinitionDraft,
1002 data: &ResolvedGameData,
1003) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1004 Ok(
1005 s
1006 .apply_base_from_data(data, 187_874)?
1007 .applies_aura(AURA_CRASH_LIGHTNING)
1008 .apply_aoe_from_data(data)
1009 .on_cast(crate::hooks::enhancement_shaman::crash_lightning_hook)
1010 .cooldown_bypass_when_aura(AURA::STORM_UNLEASHED),
1011 )
1012}
1013fn spell_lightning_bolt(
1014 s: SpellDefinitionDraft,
1015 data: &ResolvedGameData,
1016) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1017 Ok(
1018 s
1019 .apply_base_from_data(data, 188_196)?
1020 .cast_time(
1021 wowlab_engine_combat::validated_milliseconds(
1022 0.0,
1023 188_196,
1024 "spell.cast_time_ms",
1025 )?,
1026 )
1027 .apply_aoe_from_data(data)
1028 .on_cast(crate::hooks::enhancement_shaman::lightning_bolt_hook),
1029 )
1030}
1031fn spell_chain_lightning(
1032 s: SpellDefinitionDraft,
1033 data: &ResolvedGameData,
1034) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1035 Ok(
1036 s
1037 .apply_base_from_data(data, 188_443)?
1038 .apply_aoe_from_data(data)
1039 .on_cast(crate::hooks::enhancement_shaman::chain_lightning_hook),
1040 )
1041}
1042fn spell_flame_shock(
1043 s: SpellDefinitionDraft,
1044 data: &ResolvedGameData,
1045) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1046 Ok(
1047 s
1048 .apply_base_from_data(data, 188_389)?
1049 .applies_inferred_aura(AURA_FLAME_SHOCK, 188_389)
1050 .apply_aoe_from_data(data),
1051 )
1052}
1053fn spell_frost_shock(
1054 s: SpellDefinitionDraft,
1055 data: &ResolvedGameData,
1056) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1057 Ok(s.apply_base_from_data(data, 196_840)?.apply_aoe_from_data(data))
1058}
1059fn spell_sundering(
1060 s: SpellDefinitionDraft,
1061 data: &ResolvedGameData,
1062) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1063 Ok(
1064 s
1065 .apply_base_from_data(data, 197_214)?
1066 .damage_ap(
1067 data.ap_coef(wowlab_types::sim::SpellIdx::from_raw(197_214), 1),
1068 wowlab_engine_combat::DamageFlags::empty(),
1069 )
1070 .applies_aura(AURA_PRIMORDIAL_STORM)
1071 .apply_aoe_from_data(data)
1072 .on_cast(crate::hooks::enhancement_shaman::sundering_hook),
1073 )
1074}
1075fn spell_doom_winds(
1076 s: SpellDefinitionDraft,
1077 data: &ResolvedGameData,
1078) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1079 Ok(
1080 s
1081 .apply_base_from_data(data, 384_352)?
1082 .without_primary_data_damage()
1083 .apply_aoe_from_data(data)
1084 .on_cast(crate::hooks::enhancement_shaman::doom_winds_hook),
1085 )
1086}
1087fn spell_ascendance(
1088 s: SpellDefinitionDraft,
1089 data: &ResolvedGameData,
1090) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1091 Ok(
1092 s
1093 .apply_base_from_data(data, 114_051)?
1094 .applies_inferred_aura(AURA_ASCENDANCE, 114_051)
1095 .apply_aoe_from_data(data)
1096 .on_cast(crate::hooks::enhancement_shaman::ascendance_hook),
1097 )
1098}
1099fn spell_tempest(
1100 s: SpellDefinitionDraft,
1101 data: &ResolvedGameData,
1102) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1103 Ok(
1104 s
1105 .apply_base_from_data(data, 452_201)?
1106 .applies_aura(AURA_TEMPEST)
1107 .apply_aoe_from_data(data),
1108 )
1109}
1110fn spell_primordial_wave(
1111 s: SpellDefinitionDraft,
1112 data: &ResolvedGameData,
1113) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1114 Ok(s.apply_base_from_data(data, 375_982)?.apply_aoe_from_data(data))
1115}
1116fn spell_voltaic_blaze(
1117 s: SpellDefinitionDraft,
1118 data: &ResolvedGameData,
1119) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1120 Ok(
1121 s
1122 .apply_base_from_data(data, 470_057)?
1123 .damage_sp_from_data(
1124 wowlab_engine_domain::dbc::EffectLookup::new(
1125 data,
1126 wowlab_types::sim::EffectRef::new(
1127 wowlab_types::sim::SpellIdx::from_raw(1_259_101),
1128 1,
1129 ),
1130 ),
1131 )?
1132 .applies_aura(AURA_FLAME_SHOCK)
1133 .guaranteed_crit()
1134 .apply_aoe_from_data(data)
1135 .on_cast(crate::hooks::enhancement_shaman::voltaic_blaze_hook),
1136 )
1137}
1138fn spell_skyfury(
1139 s: SpellDefinitionDraft,
1140 data: &ResolvedGameData,
1141) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1142 Ok(
1143 s
1144 .apply_base_from_data(data, 462_854)?
1145 .applies_inferred_aura(AURA_SKYFURY, 462_854)
1146 .apply_aoe_from_data(data),
1147 )
1148}
1149fn spell_lightning_shield(
1150 s: SpellDefinitionDraft,
1151 data: &ResolvedGameData,
1152) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1153 Ok(
1154 s
1155 .apply_base_from_data(data, 192_106)?
1156 .applies_inferred_aura(AURA_LIGHTNING_SHIELD, 192_106)
1157 .apply_aoe_from_data(data),
1158 )
1159}
1160fn spell_stormstrike_mh(
1161 s: SpellDefinitionDraft,
1162 data: &ResolvedGameData,
1163) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1164 Ok(s.apply_base_from_data(data, 32175)?.apply_aoe_from_data(data))
1165}
1166fn spell_stormstrike_offhand(
1167 s: SpellDefinitionDraft,
1168 data: &ResolvedGameData,
1169) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1170 Ok(s.apply_base_from_data(data, 32176)?.apply_aoe_from_data(data))
1171}
1172fn spell_sundering_splitstream(
1173 s: SpellDefinitionDraft,
1174 data: &ResolvedGameData,
1175) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1176 Ok(s.apply_base_from_data(data, 467_283)?.apply_aoe_from_data(data))
1177}
1178fn spell_stormblast(
1179 s: SpellDefinitionDraft,
1180 data: &ResolvedGameData,
1181) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1182 Ok(s.apply_base_from_data(data, 390_287)?.apply_aoe_from_data(data))
1183}
1184fn spell_crash_lightning_unleashed(
1185 s: SpellDefinitionDraft,
1186 data: &ResolvedGameData,
1187) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1188 Ok(s.apply_base_from_data(data, 1_252_431)?.apply_aoe_from_data(data))
1189}
1190fn spell_primordial_storm(
1191 s: SpellDefinitionDraft,
1192 data: &ResolvedGameData,
1193) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1194 Ok(
1195 s
1196 .apply_base_from_data(data, 1_218_090)?
1197 .without_primary_data_damage()
1198 .trigger_program_predicate(
1199 1,
1200 crate::hooks::enhancement_shaman::hook_owned_damage_trigger_disabled,
1201 )
1202 .trigger_program_predicate(
1203 2,
1204 crate::hooks::enhancement_shaman::hook_owned_damage_trigger_disabled,
1205 )
1206 .trigger_program_predicate(
1207 3,
1208 crate::hooks::enhancement_shaman::hook_owned_damage_trigger_disabled,
1209 )
1210 .applies_inferred_aura(AURA_PRIMORDIAL_STORM, 1_218_125)
1211 .apply_aoe_from_data(data)
1212 .on_cast(crate::hooks::enhancement_shaman::primordial_storm_hook),
1213 )
1214}
1215fn spell_primordial_fire(
1216 s: SpellDefinitionDraft,
1217 data: &ResolvedGameData,
1218) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1219 Ok(s.apply_base_from_data(data, 1_218_113)?.apply_aoe_from_data(data))
1220}
1221fn spell_primordial_frost(
1222 s: SpellDefinitionDraft,
1223 data: &ResolvedGameData,
1224) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1225 Ok(s.apply_base_from_data(data, 1_218_116)?.apply_aoe_from_data(data))
1226}
1227fn spell_primordial_lightning(
1228 s: SpellDefinitionDraft,
1229 data: &ResolvedGameData,
1230) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1231 Ok(s.apply_base_from_data(data, 1_218_118)?.apply_aoe_from_data(data))
1232}
1233fn spell_surging_totem(
1234 s: SpellDefinitionDraft,
1235 data: &ResolvedGameData,
1236) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1237 Ok(
1238 s
1239 .apply_base_from_data(data, 444_995)?
1240 .applies_aura(AURA_SURGING_TOTEM)
1241 .apply_aoe_from_data(data)
1242 .on_cast(crate::hooks::enhancement_shaman::surging_totem_hook),
1243 )
1244}
1245fn spell_tremor(
1246 s: SpellDefinitionDraft,
1247 data: &ResolvedGameData,
1248) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1249 Ok(s.apply_base_from_data(data, 455_622)?.apply_aoe_from_data(data))
1250}
1251fn spell_surging_bolt(
1252 s: SpellDefinitionDraft,
1253 data: &ResolvedGameData,
1254) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1255 Ok(s.apply_base_from_data(data, 458_267)?.apply_aoe_from_data(data))
1256}
1257fn spell_searing_bolt(
1258 s: SpellDefinitionDraft,
1259 data: &ResolvedGameData,
1260) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1261 Ok(s.apply_base_from_data(data, 3606)?.apply_aoe_from_data(data))
1262}
1263fn spell_searing_volley(
1264 s: SpellDefinitionDraft,
1265 data: &ResolvedGameData,
1266) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1267 Ok(s.apply_base_from_data(data, 458_147)?.apply_aoe_from_data(data))
1268}
1269fn spell_windfury_weapon(
1270 s: SpellDefinitionDraft,
1271 data: &ResolvedGameData,
1272) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1273 Ok(s.apply_base_from_data(data, 33757)?.apply_aoe_from_data(data))
1274}
1275fn spell_flametongue_weapon(
1276 s: SpellDefinitionDraft,
1277 data: &ResolvedGameData,
1278) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1279 Ok(s.apply_base_from_data(data, 318_038)?.apply_aoe_from_data(data))
1280}
1281fn spell_windfury_attack(
1282 s: SpellDefinitionDraft,
1283 data: &ResolvedGameData,
1284) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1285 Ok(s.apply_base_from_data(data, 25504)?.apply_aoe_from_data(data))
1286}
1287fn spell_flametongue_attack(
1288 s: SpellDefinitionDraft,
1289 data: &ResolvedGameData,
1290) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1291 Ok(s.apply_base_from_data(data, 10444)?.apply_aoe_from_data(data))
1292}
1293fn spell_flametongue_attack_imbuement_mastery(
1294 s: SpellDefinitionDraft,
1295 data: &ResolvedGameData,
1296) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1297 Ok(s.apply_base_from_data(data, 467_386)?.apply_aoe_from_data(data))
1298}
1299fn spell_maelstrom_weapon_driver(
1300 s: SpellDefinitionDraft,
1301 data: &ResolvedGameData,
1302) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1303 Ok(s.apply_base_from_data(data, 187_880)?.apply_aoe_from_data(data))
1304}
1305fn spell_hot_hand_driver(
1306 s: SpellDefinitionDraft,
1307 data: &ResolvedGameData,
1308) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1309 Ok(s.apply_base_from_data(data, 201_900)?.apply_aoe_from_data(data))
1310}
1311fn spell_stormsurge_driver(
1312 s: SpellDefinitionDraft,
1313 data: &ResolvedGameData,
1314) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1315 Ok(s.apply_base_from_data(data, 201_845)?.apply_aoe_from_data(data))
1316}
1317pub(crate) fn build_combat_system(
1318 params: &wowlab_engine_ports::HandlerParams<'_>,
1319) -> Result<BuiltCombatSystem, wowlab_engine_ports::EngineError> {
1320 let builder = BuiltCombatSystem::builder(params.stats.clone())
1321 .spec_id(SpecId::Enhancement)
1322 .hero_talent_trees(DECLARED_METADATA.hero_talent_trees)
1323 .mastery_spell(77223)
1324 .mastery_hook(crate::hooks::enhancement_shaman::mastery)
1325 .resource(
1326 "maelstrom",
1327 150.0,
1328 params
1329 .game_data
1330 .power_regen_for_max(11, 150.0)
1331 .ok_or_else(|| {
1332 wowlab_engine_ports::EngineError::spec_construction(
1333 "missing power-type power_regen_for_max for type_id 11",
1334 )
1335 })?,
1336 )
1337 .resource_type_id(11)
1338 .resource_start(
1339 params
1340 .game_data
1341 .power_default(11)
1342 .ok_or_else(|| {
1343 wowlab_engine_ports::EngineError::spec_construction(
1344 "missing power-type power_default for type_id 11",
1345 )
1346 })?,
1347 )
1348 .aura("ascendance", AURA::ASCENDANCE, |a| aura_ascendance(a, ¶ms.game_data))
1349 .aura("doom_winds", AURA::DOOM_WINDS, |a| aura_doom_winds(a, ¶ms.game_data))
1350 .aura(
1351 "storm_unleashed",
1352 AURA::STORM_UNLEASHED,
1353 |a| aura_storm_unleashed(a, ¶ms.game_data),
1354 )
1355 .aura(
1356 "crash_lightning",
1357 AURA::CRASH_LIGHTNING,
1358 |a| aura_crash_lightning(a, ¶ms.game_data),
1359 )
1360 .aura(
1361 "converging_storms",
1362 AURA::CONVERGING_STORMS,
1363 |a| aura_converging_storms(a, ¶ms.game_data),
1364 )
1365 .aura(
1366 "molten_weapon",
1367 AURA::MOLTEN_WEAPON,
1368 |a| aura_molten_weapon(a, ¶ms.game_data),
1369 )
1370 .aura(
1371 "crackling_surge",
1372 AURA::CRACKLING_SURGE,
1373 |a| aura_crackling_surge(a, ¶ms.game_data),
1374 )
1375 .aura("tempest", AURA::TEMPEST, |a| aura_tempest(a, ¶ms.game_data))
1376 .aura(
1377 "unlimited_power",
1378 AURA::UNLIMITED_POWER,
1379 |a| aura_unlimited_power(a, ¶ms.game_data),
1380 )
1381 .aura(
1382 "flame_shock",
1383 AURA::FLAME_SHOCK,
1384 |a| aura_flame_shock(a, ¶ms.game_data),
1385 )
1386 .aura(
1387 "lightning_shield",
1388 AURA::LIGHTNING_SHIELD,
1389 |a| aura_lightning_shield(a, ¶ms.game_data),
1390 )
1391 .aura(
1392 "primordial_storm",
1393 AURA::PRIMORDIAL_STORM,
1394 |a| aura_primordial_storm(a, ¶ms.game_data),
1395 )
1396 .aura(
1397 "overflowing_maelstrom",
1398 AURA::OVERFLOWING_MAELSTROM,
1399 |a| aura_overflowing_maelstrom(a, ¶ms.game_data),
1400 )
1401 .aura(
1402 "lashing_flames",
1403 AURA::LASHING_FLAMES,
1404 |a| aura_lashing_flames(a, ¶ms.game_data),
1405 )
1406 .aura("skyfury", AURA::SKYFURY, |a| aura_skyfury(a, ¶ms.game_data))
1407 .aura(
1408 "skyfury_highlight",
1409 AURA::SKYFURY_HIGHLIGHT,
1410 |a| aura_skyfury_highlight(a, ¶ms.game_data),
1411 )
1412 .aura(
1413 "thorims_invocation",
1414 AURA::THORIM_S_INVOCATION,
1415 |a| aura_thorim_s_invocation(a, ¶ms.game_data),
1416 )
1417 .aura(
1418 "lively_totems",
1419 AURA::LIVELY_TOTEMS,
1420 |a| aura_lively_totems(a, ¶ms.game_data),
1421 )
1422 .aura(
1423 "amplification_core",
1424 AURA::AMPLIFICATION_CORE,
1425 |a| aura_amplification_core(a, ¶ms.game_data),
1426 )
1427 .aura(
1428 "surging_totem",
1429 AURA::SURGING_TOTEM,
1430 |a| aura_surging_totem(a, ¶ms.game_data),
1431 )
1432 .aura(
1433 "whirling_fire",
1434 AURA::WHIRLING_FIRE,
1435 |a| aura_whirling_fire(a, ¶ms.game_data),
1436 )
1437 .aura(
1438 "whirling_earth",
1439 AURA::WHIRLING_EARTH,
1440 |a| aura_whirling_earth(a, ¶ms.game_data),
1441 )
1442 .aura(
1443 "whirling_air",
1444 AURA::WHIRLING_AIR,
1445 |a| aura_whirling_air(a, ¶ms.game_data),
1446 )
1447 .aura(
1448 "totemic_rebound",
1449 AURA::TOTEMIC_REBOUND,
1450 |a| aura_totemic_rebound(a, ¶ms.game_data),
1451 )
1452 .aura(
1453 "maelstrom_weapon",
1454 AURA::MAELSTROM_WEAPON,
1455 |a| aura_maelstrom_weapon(a, ¶ms.game_data),
1456 )
1457 .aura("hot_hand", AURA::HOT_HAND, |a| aura_hot_hand(a, ¶ms.game_data))
1458 .aura("stormsurge", AURA::STORMSURGE, |a| aura_stormsurge(a, ¶ms.game_data))
1459 .spell(
1460 "stormstrike",
1461 SPELL::STORMSTRIKE,
1462 |s| spell_stormstrike(s, ¶ms.game_data),
1463 )
1464 .spell("lava_lash", SPELL::LAVA_LASH, |s| spell_lava_lash(s, ¶ms.game_data))
1465 .spell(
1466 "crash_lightning",
1467 SPELL::CRASH_LIGHTNING,
1468 |s| spell_crash_lightning(s, ¶ms.game_data),
1469 )
1470 .spell(
1471 "lightning_bolt",
1472 SPELL::LIGHTNING_BOLT,
1473 |s| spell_lightning_bolt(s, ¶ms.game_data),
1474 )
1475 .spell(
1476 "chain_lightning",
1477 SPELL::CHAIN_LIGHTNING,
1478 |s| spell_chain_lightning(s, ¶ms.game_data),
1479 )
1480 .spell(
1481 "flame_shock",
1482 SPELL::FLAME_SHOCK,
1483 |s| spell_flame_shock(s, ¶ms.game_data),
1484 )
1485 .spell(
1486 "frost_shock",
1487 SPELL::FROST_SHOCK,
1488 |s| spell_frost_shock(s, ¶ms.game_data),
1489 )
1490 .spell("sundering", SPELL::SUNDERING, |s| spell_sundering(s, ¶ms.game_data))
1491 .spell(
1492 "doom_winds",
1493 SPELL::DOOM_WINDS,
1494 |s| spell_doom_winds(s, ¶ms.game_data),
1495 )
1496 .spell(
1497 "ascendance",
1498 SPELL::ASCENDANCE,
1499 |s| spell_ascendance(s, ¶ms.game_data),
1500 )
1501 .spell("tempest", SPELL::TEMPEST, |s| spell_tempest(s, ¶ms.game_data))
1502 .spell(
1503 "primordial_wave",
1504 SPELL::PRIMORDIAL_WAVE,
1505 |s| spell_primordial_wave(s, ¶ms.game_data),
1506 )
1507 .spell(
1508 "voltaic_blaze",
1509 SPELL::VOLTAIC_BLAZE,
1510 |s| spell_voltaic_blaze(s, ¶ms.game_data),
1511 )
1512 .spell("skyfury", SPELL::SKYFURY, |s| spell_skyfury(s, ¶ms.game_data))
1513 .spell(
1514 "lightning_shield",
1515 SPELL::LIGHTNING_SHIELD,
1516 |s| spell_lightning_shield(s, ¶ms.game_data),
1517 )
1518 .spell(
1519 "stormstrike_mh",
1520 SPELL::STORMSTRIKE_MH,
1521 |s| spell_stormstrike_mh(s, ¶ms.game_data),
1522 )
1523 .spell(
1524 "stormstrike_offhand",
1525 SPELL::STORMSTRIKE_OFFHAND,
1526 |s| spell_stormstrike_offhand(s, ¶ms.game_data),
1527 )
1528 .spell(
1529 "sundering_splitstream",
1530 SPELL::SUNDERING_SPLITSTREAM,
1531 |s| spell_sundering_splitstream(s, ¶ms.game_data),
1532 )
1533 .spell(
1534 "stormblast",
1535 SPELL::STORMBLAST,
1536 |s| spell_stormblast(s, ¶ms.game_data),
1537 )
1538 .spell(
1539 "crash_lightning_unleashed",
1540 SPELL::CRASH_LIGHTNING_UNLEASHED,
1541 |s| spell_crash_lightning_unleashed(s, ¶ms.game_data),
1542 )
1543 .spell(
1544 "primordial_storm",
1545 SPELL::PRIMORDIAL_STORM,
1546 |s| spell_primordial_storm(s, ¶ms.game_data),
1547 )
1548 .spell(
1549 "primordial_fire",
1550 SPELL::PRIMORDIAL_FIRE,
1551 |s| spell_primordial_fire(s, ¶ms.game_data),
1552 )
1553 .spell(
1554 "primordial_frost",
1555 SPELL::PRIMORDIAL_FROST,
1556 |s| spell_primordial_frost(s, ¶ms.game_data),
1557 )
1558 .spell(
1559 "primordial_lightning",
1560 SPELL::PRIMORDIAL_LIGHTNING,
1561 |s| spell_primordial_lightning(s, ¶ms.game_data),
1562 )
1563 .spell(
1564 "surging_totem",
1565 SPELL::SURGING_TOTEM,
1566 |s| spell_surging_totem(s, ¶ms.game_data),
1567 )
1568 .spell("tremor", SPELL::TREMOR, |s| spell_tremor(s, ¶ms.game_data))
1569 .spell(
1570 "surging_bolt",
1571 SPELL::SURGING_BOLT,
1572 |s| spell_surging_bolt(s, ¶ms.game_data),
1573 )
1574 .spell(
1575 "searing_bolt",
1576 SPELL::SEARING_BOLT,
1577 |s| spell_searing_bolt(s, ¶ms.game_data),
1578 )
1579 .spell(
1580 "searing_volley",
1581 SPELL::SEARING_VOLLEY,
1582 |s| spell_searing_volley(s, ¶ms.game_data),
1583 )
1584 .spell(
1585 "windfury_weapon",
1586 SPELL::WINDFURY_WEAPON,
1587 |s| spell_windfury_weapon(s, ¶ms.game_data),
1588 )
1589 .spell(
1590 "flametongue_weapon",
1591 SPELL::FLAMETONGUE_WEAPON,
1592 |s| spell_flametongue_weapon(s, ¶ms.game_data),
1593 )
1594 .spell(
1595 "windfury_attack",
1596 SPELL::WINDFURY_ATTACK,
1597 |s| spell_windfury_attack(s, ¶ms.game_data),
1598 )
1599 .spell(
1600 "flametongue_attack",
1601 SPELL::FLAMETONGUE_ATTACK,
1602 |s| spell_flametongue_attack(s, ¶ms.game_data),
1603 )
1604 .spell(
1605 "flametongue_attack_imbuement_mastery",
1606 SPELL::FLAMETONGUE_ATTACK_IMBUEMENT_MASTERY,
1607 |s| spell_flametongue_attack_imbuement_mastery(s, ¶ms.game_data),
1608 )
1609 .spell(
1610 "maelstrom_weapon_driver",
1611 SPELL::MAELSTROM_WEAPON_DRIVER,
1612 |s| spell_maelstrom_weapon_driver(s, ¶ms.game_data),
1613 )
1614 .spell(
1615 "hot_hand_driver",
1616 SPELL::HOT_HAND_DRIVER,
1617 |s| spell_hot_hand_driver(s, ¶ms.game_data),
1618 )
1619 .spell(
1620 "stormsurge_driver",
1621 SPELL::STORMSURGE_DRIVER,
1622 |s| spell_stormsurge_driver(s, ¶ms.game_data),
1623 )
1624 .auto_attack(|a| {
1625 a
1626 .spell_id(6603)
1627 .swing_ms(2600)
1628 .apply_base_from_data(¶ms.game_data)
1629 .on_swing(crate::hooks::enhancement_shaman::swing_hook)
1630 })
1631 .auto_attack(|a| {
1632 a
1633 .spell_id(6603)
1634 .swing_ms(2600)
1635 .apply_base_from_data(¶ms.game_data)
1636 .on_swing(crate::hooks::enhancement_shaman::swing_hook)
1637 })
1638 .game_data(params.game_data.clone())
1639 .talent_spell_ids(TALENTS)
1640 .talent_selections(params.talent_selections)
1641 .set_bonus_auras(params.set_bonus_auras)
1642 .encounter(params.encounter.clone());
1643 let builder = crate::generated::items::register_equipped(
1644 builder,
1645 ¶ms.game_data,
1646 params.equipped_items,
1647 )?;
1648
1649 builder
1650 .build(params.rotation)
1651 .map_err(wowlab_engine_ports::EngineError::rotation_compile)
1652}
1653fn new_handler(
1654 params: wowlab_engine_ports::HandlerParams<'_>,
1655) -> Result<Box<dyn SpecHandler>, wowlab_engine_ports::EngineError> {
1656 let handler = crate::composition::compose_handler(
1657 build_combat_system,
1658 ¶ms,
1659 crate::hooks::enhancement_shaman::EnhancementHandler::try_new,
1660 )?;
1661
1662 Ok(Box::new(handler))
1663}
1664static DECLARED_METADATA: DeclaredSpecMetadata = DeclaredSpecMetadata {
1665 primary_resource: ResourceType::Maelstrom,
1666 secondary_resource: None,
1667 spell_ids: DECLARED_SPELL_IDS,
1668 aura_ids: DECLARED_AURA_IDS,
1669 server_proc_entries: &[
1670 DeclaredServerProcEntry {
1671 spell_id: 198_300,
1672 attributes: ProcAttributes::USE_STACKS_FOR_CHARGES.bits(),
1673 },
1674 ],
1675 talents: TALENTS,
1676 rotation_field_schema: &[],
1677 metrics_plugin_id: None,
1678 hero_talent_trees: &[
1679 HeroTalentTreeDesc {
1680 name: "Stormbringer",
1681 spells: HERO_TREE_STORMBRINGER_SPELLS,
1682 auras: HERO_TREE_STORMBRINGER_AURAS,
1683 },
1684 HeroTalentTreeDesc {
1685 name: "Totemic",
1686 spells: HERO_TREE_TOTEMIC_SPELLS,
1687 auras: HERO_TREE_TOTEMIC_AURAS,
1688 },
1689 ],
1690 reported_spells: REPORTED_SPELLS,
1691 masked_passive_effects: &[],
1692 passive_effect_overrides: &[
1693 wowlab_engine_ports::DeclaredPassiveEffectOverride {
1694 spell_id: 1_251_026,
1695 effect: 2,
1696 source: Some((1_251_026, 2)),
1697 value: 0.0,
1698 multiplier: 0.5,
1699 },
1700 ],
1701};
1702pub(super) const SPEC_DESCRIPTOR: SpecDescriptor = SpecDescriptor {
1703 spec_id: SpecId::Enhancement,
1704 display_name: "Enhancement Shaman",
1705 metadata: DECLARED_METADATA,
1706 handler_factory: new_handler,
1707};
1708wowlab_engine_combat::smoke_test!(build_combat_system);