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 SUMMON_FELHUNTER: u32 = 691;
18 pub(crate) const SUMMON_IMP: u32 = 688;
20 pub(crate) const GRIMOIRE_OF_SACRIFICE: u32 = 108_503;
22 pub(crate) const IMMOLATE: u32 = 348;
24 pub(crate) const INCINERATE: u32 = 29722;
26 pub(crate) const CONFLAGRATE: u32 = 17962;
28 pub(crate) const CHAOS_BOLT: u32 = 116_858;
30 pub(crate) const RAIN_OF_FIRE: u32 = 5740;
32 pub(crate) const SHADOWBURN: u32 = 17877;
34 pub(crate) const SOUL_FIRE: u32 = 6353;
36 pub(crate) const CATACLYSM: u32 = 152_108;
38 pub(crate) const CHANNEL_DEMONFIRE: u32 = 196_447;
40 pub(crate) const CHANNEL_DEMONFIRE_TICK: u32 = 196_448;
42 pub(crate) const HAVOC: u32 = 80240;
44 pub(crate) const SHADOW_BOLT: u32 = 686;
46 pub(crate) const CORRUPTION: u32 = 172;
48 pub(crate) const MALEVOLENCE: u32 = 430_014;
50 pub(crate) const DRAIN_LIFE: u32 = 234_153;
52 pub(crate) const INFERNAL_BOLT: u32 = 434_506;
54 pub(crate) const RUINATION: u32 = 434_635;
56 pub(crate) const SUMMON_INFERNAL: u32 = 1122;
58}
59pub(crate) mod AURA {
60 pub(crate) const IMMOLATE: u32 = 157_736;
62 pub(crate) const BACKDRAFT: u32 = 117_828;
64 pub(crate) const REVERSE_ENTROPY: u32 = 266_030;
66 pub(crate) const REVERSE_ENTROPY_TALENT: u32 = 205_148;
68 pub(crate) const CONFLAGRATION_OF_CHAOS_CONFLAG: u32 = 387_109;
70 pub(crate) const CONFLAGRATION_OF_CHAOS_SHADOWBURN: u32 = 387_109;
72 pub(crate) const FLASHPOINT: u32 = 387_263;
74 pub(crate) const FIENDISH_CRUELTY: u32 = 1_245_664;
76 pub(crate) const FIENDISH_CRUELTY_TALENT: u32 = 1_245_633;
78 pub(crate) const CONFLAGRATION_OF_CHAOS_TALENT: u32 = 387_108;
80 pub(crate) const CHAOTIC_INFERNO: u32 = 1_244_860;
82 pub(crate) const CHAOTIC_INFERNO_TALENT: u32 = 1_244_788;
84 pub(crate) const HAVOC: u32 = 80240;
86 pub(crate) const RITUAL_OF_RUIN: u32 = 387_157;
88 pub(crate) const GRIMOIRE_OF_SACRIFICE: u32 = 196_099;
90 pub(crate) const WITHER: u32 = 445_474;
92 pub(crate) const MALEVOLENCE: u32 = 442_726;
94 pub(crate) const CHANNEL_DEMONFIRE: u32 = 196_447;
96 pub(crate) const RECENTLY_DEMON_HAS_BEEN_SUMMONED_DNT: u32 = 1_288_970;
98 pub(crate) const TRACK_PETS: u32 = 462_599;
100 pub(crate) const INFERNAL_BOLT: u32 = 433_891;
102 pub(crate) const RUINATION: u32 = 433_885;
104 pub(crate) const DIABOLIC_RITUAL_TALENT: u32 = 428_514;
106 pub(crate) const DIABOLIC_RITUAL_OVERLORD: u32 = 431_944;
108 pub(crate) const DIABOLIC_RITUAL_MOTHER: u32 = 432_815;
110 pub(crate) const DIABOLIC_RITUAL_PIT_LORD: u32 = 432_816;
112 pub(crate) const DEMONIC_ART_OVERLORD: u32 = 428_524;
114 pub(crate) const DEMONIC_ART_MOTHER: u32 = 432_794;
116 pub(crate) const DEMONIC_ART_PIT_LORD: u32 = 432_795;
118 pub(crate) const DEMONIC_OCULI: u32 = 1_269_643;
120 pub(crate) const DIABOLIC_OCULI_TALENT: u32 = 1_268_709;
122 pub(crate) const LOOKS_THAT_KILL_TALENT: u32 = 1_268_713;
124 pub(crate) const MINDS_EYES_TALENT: u32 = 1_268_716;
126 pub(crate) const MINDS_EYES: u32 = 1_269_879;
128 pub(crate) const OVERFIEND: u32 = 457_578;
130 pub(crate) const AVATAR_OF_DESTRUCTION_TALENT: u32 = 1_245_089;
132 pub(crate) const EMBERS_OF_NIHILAM_1_TALENT: u32 = 1_265_770;
134 pub(crate) const EMBERS_OF_NIHILAM_2_TALENT: u32 = 1_265_772;
136 pub(crate) const EMBERS_OF_NIHILAM_3_TALENT: u32 = 1_265_774;
138 pub(crate) const VISION_OF_NIHILAM: u32 = 1_265_939;
140 pub(crate) const INFERNAL_EMBERS: u32 = 264_364;
142 pub(crate) const RAIN_OF_CHAOS: u32 = 266_087;
144 pub(crate) const CRASHING_CHAOS: u32 = 417_282;
146}
147pub(crate) mod TALENT {
148 pub(crate) const AVATAR_OF_DESTRUCTION: u32 = 1_245_089;
150 pub(crate) const BACKDRAFT: u32 = 196_406;
152 pub(crate) const CATACLYSM: u32 = 152_108;
154 pub(crate) const CHANNEL_DEMONFIRE: u32 = 196_447;
156 pub(crate) const CHAOS_INCARNATE: u32 = 387_275;
158 pub(crate) const CHAOTIC_INFERNO: u32 = 1_244_788;
160 pub(crate) const CONFLAGRATE: u32 = 17962;
162 pub(crate) const CONFLAGRATION_OF_CHAOS: u32 = 387_108;
164 pub(crate) const CRASHING_CHAOS: u32 = 417_234;
166 pub(crate) const DEMONFIRE_INFUSION: u32 = 1_214_442;
168 pub(crate) const DIABOLIC_EMBERS: u32 = 387_173;
170 pub(crate) const DIABOLIC_OCULI: u32 = 1_268_709;
172 pub(crate) const DIABOLIC_RITUAL: u32 = 428_514;
174 pub(crate) const EMBERSTORM: u32 = 454_744;
176 pub(crate) const EMBERS_OF_NIHILAM_1: u32 = 1_265_770;
178 pub(crate) const EMBERS_OF_NIHILAM_2: u32 = 1_265_772;
180 pub(crate) const EMBERS_OF_NIHILAM_3: u32 = 1_265_774;
182 pub(crate) const FIENDISH_CRUELTY: u32 = 1_245_633;
184 pub(crate) const FIRE_AND_BRIMSTONE: u32 = 196_408;
186 pub(crate) const FLASHPOINT: u32 = 387_259;
188 pub(crate) const GRIMOIRE_OF_SACRIFICE: u32 = 108_503;
190 pub(crate) const HAVOC: u32 = 80240;
192 pub(crate) const IMPROVED_CONFLAGRATE: u32 = 231_793;
194 pub(crate) const INFERNO: u32 = 1_280_483;
196 pub(crate) const INTERNAL_COMBUSTION: u32 = 266_134;
198 pub(crate) const LOOKS_THAT_KILL: u32 = 1_268_713;
200 pub(crate) const MALEVOLENCE: u32 = 430_014;
202 pub(crate) const MAYHEM: u32 = 387_506;
204 pub(crate) const MINDS_EYES: u32 = 1_268_716;
206 pub(crate) const RAGING_DEMONFIRE: u32 = 387_166;
208 pub(crate) const RAIN_OF_CHAOS: u32 = 266_086;
210 pub(crate) const RAIN_OF_FIRE: u32 = 5740;
212 pub(crate) const REVERSE_ENTROPY: u32 = 205_148;
214 pub(crate) const ROARING_BLAZE: u32 = 1_244_310;
216 pub(crate) const SHADOWBURN: u32 = 17877;
218 pub(crate) const SOUL_FIRE: u32 = 6353;
220 pub(crate) const SUMMON_INFERNAL: u32 = 1122;
222}
223pub(crate) mod REPORTED_SPELL {
224 pub(crate) const CHAOS_SALVO: u32 = 432_596;
226 pub(crate) const DIABOLIC_GAZE_1: u32 = 1_269_892;
228 pub(crate) const DIABOLIC_GAZE_2: u32 = 1_269_886;
230 pub(crate) const DIABOLIC_GAZE_3: u32 = 1_269_885;
232 pub(crate) const ECHO_OF_SARGERAS: u32 = 1_265_884;
234 pub(crate) const ECHO_OF_SARGERAS_CB: u32 = 1_277_879;
236 pub(crate) const ECHO_OF_SARGERAS_SB: u32 = 1_265_774;
238 pub(crate) const EYE_EXPLOSION: u32 = 1_269_800;
240 pub(crate) const FELSEEKER: u32 = 434_404;
242 pub(crate) const IMMOLATION: u32 = 20153;
244 pub(crate) const INFERNAL_MELEE: u32 = 111_685;
246 pub(crate) const LASH_OF_PAIN: u32 = 7814;
248 pub(crate) const WICKED_CLEAVE: u32 = 432_120;
250}
251pub(crate) mod HERO {
252 pub(crate) mod HELLCALLER {
253 pub(crate) mod SPELL {
254 pub(crate) const BLACKENED_SOUL_DAMAGE: u32 = 445_736;
256 pub(crate) const BLACKENED_SOUL_TRIGGER: u32 = 445_731;
258 pub(crate) const MALEVOLENCE: u32 = 430_014;
260 pub(crate) const MALEVOLENCE_DAMAGE: u32 = 446_285;
262 pub(crate) const WITHER: u32 = 445_465;
264 pub(crate) const WITHER_DIRECT: u32 = 445_468;
266 }
267 pub(crate) mod AURA {
268 pub(crate) const BLACKENED_SOUL: u32 = 445_731;
270 pub(crate) const MALEVOLENCE_BUFF: u32 = 442_726;
272 pub(crate) const WITHER_DOT: u32 = 445_474;
274 }
275 }
276 pub(crate) mod DIABOLIST {
277 pub(crate) mod SPELL {
278 pub(crate) const INFERNAL_BOLT: u32 = 434_506;
280 pub(crate) const RUINATION: u32 = 434_635;
282 pub(crate) const RUINATION_IMPACT: u32 = 434_636;
284 }
285 pub(crate) mod AURA {
286 pub(crate) const CLOVEN_SOUL: u32 = 434_424;
288 pub(crate) const DEMONIC_ART_MOTHER: u32 = 432_794;
290 pub(crate) const DEMONIC_ART_OVERLORD: u32 = 428_524;
292 pub(crate) const DEMONIC_ART_PIT_LORD: u32 = 432_795;
294 pub(crate) const DEMONIC_OCULI: u32 = 1_269_643;
296 pub(crate) const DIABOLIC_RITUAL_MOTHER: u32 = 432_815;
298 pub(crate) const DIABOLIC_RITUAL_OVERLORD: u32 = 431_944;
300 pub(crate) const DIABOLIC_RITUAL_PIT_LORD: u32 = 432_816;
302 pub(crate) const INFERNAL_BOLT_BUFF: u32 = 433_891;
304 pub(crate) const MINDS_EYES: u32 = 1_269_879;
306 pub(crate) const RUINATION_BUFF: u32 = 433_885;
308 }
309 }
310}
311static HERO_TREE_HELLCALLER_SPELLS: &[(&str, u32)] = &[
312 ("BLACKENED_SOUL_DAMAGE", 445_736),
313 ("BLACKENED_SOUL_TRIGGER", 445_731),
314 ("MALEVOLENCE", 430_014),
315 ("MALEVOLENCE_DAMAGE", 446_285),
316 ("WITHER", 445_465),
317 ("WITHER_DIRECT", 445_468),
318];
319static HERO_TREE_HELLCALLER_AURAS: &[(&str, u32)] = &[
320 ("BLACKENED_SOUL", 445_731),
321 ("MALEVOLENCE_BUFF", 442_726),
322 ("WITHER_DOT", 445_474),
323];
324static HERO_TREE_DIABOLIST_SPELLS: &[(&str, u32)] = &[
325 ("INFERNAL_BOLT", 434_506),
326 ("RUINATION", 434_635),
327 ("RUINATION_IMPACT", 434_636),
328];
329static HERO_TREE_DIABOLIST_AURAS: &[(&str, u32)] = &[
330 ("CLOVEN_SOUL", 434_424),
331 ("DEMONIC_ART_MOTHER", 432_794),
332 ("DEMONIC_ART_OVERLORD", 428_524),
333 ("DEMONIC_ART_PIT_LORD", 432_795),
334 ("DEMONIC_OCULI", 1_269_643),
335 ("DIABOLIC_RITUAL_MOTHER", 432_815),
336 ("DIABOLIC_RITUAL_OVERLORD", 431_944),
337 ("DIABOLIC_RITUAL_PIT_LORD", 432_816),
338 ("INFERNAL_BOLT_BUFF", 433_891),
339 ("MINDS_EYES", 1_269_879),
340 ("RUINATION_BUFF", 433_885),
341];
342pub(crate) const AURA_IMMOLATE: LocalAuraIdx = LocalAuraIdx::new(0);
343pub(crate) const AURA_BACKDRAFT: LocalAuraIdx = LocalAuraIdx::new(1);
344pub(crate) const AURA_REVERSE_ENTROPY: LocalAuraIdx = LocalAuraIdx::new(2);
345pub(crate) const AURA_REVERSE_ENTROPY_TALENT: LocalAuraIdx = LocalAuraIdx::new(3);
346pub(crate) const AURA_CONFLAGRATION_OF_CHAOS_CONFLAG: LocalAuraIdx = LocalAuraIdx::new(
347 4,
348);
349pub(crate) const AURA_CONFLAGRATION_OF_CHAOS_SHADOWBURN: LocalAuraIdx = LocalAuraIdx::new(
350 5,
351);
352pub(crate) const AURA_FLASHPOINT: LocalAuraIdx = LocalAuraIdx::new(6);
353pub(crate) const AURA_FIENDISH_CRUELTY: LocalAuraIdx = LocalAuraIdx::new(7);
354pub(crate) const AURA_FIENDISH_CRUELTY_TALENT: LocalAuraIdx = LocalAuraIdx::new(8);
355pub(crate) const AURA_CONFLAGRATION_OF_CHAOS_TALENT: LocalAuraIdx = LocalAuraIdx::new(9);
356pub(crate) const AURA_CHAOTIC_INFERNO: LocalAuraIdx = LocalAuraIdx::new(10);
357pub(crate) const AURA_CHAOTIC_INFERNO_TALENT: LocalAuraIdx = LocalAuraIdx::new(11);
358pub(crate) const AURA_HAVOC: LocalAuraIdx = LocalAuraIdx::new(12);
359pub(crate) const AURA_RITUAL_OF_RUIN: LocalAuraIdx = LocalAuraIdx::new(13);
360pub(crate) const AURA_GRIMOIRE_OF_SACRIFICE: LocalAuraIdx = LocalAuraIdx::new(14);
361pub(crate) const AURA_WITHER: LocalAuraIdx = LocalAuraIdx::new(15);
362pub(crate) const AURA_MALEVOLENCE: LocalAuraIdx = LocalAuraIdx::new(16);
363pub(crate) const AURA_CHANNEL_DEMONFIRE: LocalAuraIdx = LocalAuraIdx::new(17);
364pub(crate) const AURA_RECENTLY_DEMON_HAS_BEEN_SUMMONED_DNT: LocalAuraIdx = LocalAuraIdx::new(
365 18,
366);
367pub(crate) const AURA_TRACK_PETS: LocalAuraIdx = LocalAuraIdx::new(19);
368pub(crate) const AURA_INFERNAL_BOLT: LocalAuraIdx = LocalAuraIdx::new(20);
369pub(crate) const AURA_RUINATION: LocalAuraIdx = LocalAuraIdx::new(21);
370pub(crate) const AURA_DIABOLIC_RITUAL_TALENT: LocalAuraIdx = LocalAuraIdx::new(22);
371pub(crate) const AURA_DIABOLIC_RITUAL_OVERLORD: LocalAuraIdx = LocalAuraIdx::new(23);
372pub(crate) const AURA_DIABOLIC_RITUAL_MOTHER: LocalAuraIdx = LocalAuraIdx::new(24);
373pub(crate) const AURA_DIABOLIC_RITUAL_PIT_LORD: LocalAuraIdx = LocalAuraIdx::new(25);
374pub(crate) const AURA_DEMONIC_ART_OVERLORD: LocalAuraIdx = LocalAuraIdx::new(26);
375pub(crate) const AURA_DEMONIC_ART_MOTHER: LocalAuraIdx = LocalAuraIdx::new(27);
376pub(crate) const AURA_DEMONIC_ART_PIT_LORD: LocalAuraIdx = LocalAuraIdx::new(28);
377pub(crate) const AURA_DEMONIC_OCULI: LocalAuraIdx = LocalAuraIdx::new(29);
378pub(crate) const AURA_DIABOLIC_OCULI_TALENT: LocalAuraIdx = LocalAuraIdx::new(30);
379pub(crate) const AURA_LOOKS_THAT_KILL_TALENT: LocalAuraIdx = LocalAuraIdx::new(31);
380pub(crate) const AURA_MINDS_EYES_TALENT: LocalAuraIdx = LocalAuraIdx::new(32);
381pub(crate) const AURA_MINDS_EYES: LocalAuraIdx = LocalAuraIdx::new(33);
382pub(crate) const AURA_OVERFIEND: LocalAuraIdx = LocalAuraIdx::new(34);
383pub(crate) const AURA_AVATAR_OF_DESTRUCTION_TALENT: LocalAuraIdx = LocalAuraIdx::new(35);
384pub(crate) const AURA_EMBERS_OF_NIHILAM_1_TALENT: LocalAuraIdx = LocalAuraIdx::new(36);
385pub(crate) const AURA_EMBERS_OF_NIHILAM_2_TALENT: LocalAuraIdx = LocalAuraIdx::new(37);
386pub(crate) const AURA_EMBERS_OF_NIHILAM_3_TALENT: LocalAuraIdx = LocalAuraIdx::new(38);
387pub(crate) const AURA_VISION_OF_NIHILAM: LocalAuraIdx = LocalAuraIdx::new(39);
388pub(crate) const AURA_INFERNAL_EMBERS: LocalAuraIdx = LocalAuraIdx::new(40);
389pub(crate) const AURA_RAIN_OF_CHAOS: LocalAuraIdx = LocalAuraIdx::new(41);
390pub(crate) const AURA_CRASHING_CHAOS: LocalAuraIdx = LocalAuraIdx::new(42);
391pub(crate) const AURA_COUNT: usize = 43;
392const _: () = assert!(
393 AURA_COUNT == 43, "AURA index ABI: count changed -- update positional hook consumers"
394);
395pub(crate) const SPELL_SUMMON_FELHUNTER: LocalSpellIdx = LocalSpellIdx::new(0);
396pub(crate) const SPELL_SUMMON_IMP: LocalSpellIdx = LocalSpellIdx::new(1);
397pub(crate) const SPELL_GRIMOIRE_OF_SACRIFICE: LocalSpellIdx = LocalSpellIdx::new(2);
398pub(crate) const SPELL_IMMOLATE: LocalSpellIdx = LocalSpellIdx::new(3);
399pub(crate) const SPELL_INCINERATE: LocalSpellIdx = LocalSpellIdx::new(4);
400pub(crate) const SPELL_CONFLAGRATE: LocalSpellIdx = LocalSpellIdx::new(5);
401pub(crate) const SPELL_CHAOS_BOLT: LocalSpellIdx = LocalSpellIdx::new(6);
402pub(crate) const SPELL_RAIN_OF_FIRE: LocalSpellIdx = LocalSpellIdx::new(7);
403pub(crate) const SPELL_SHADOWBURN: LocalSpellIdx = LocalSpellIdx::new(8);
404pub(crate) const SPELL_SOUL_FIRE: LocalSpellIdx = LocalSpellIdx::new(9);
405pub(crate) const SPELL_CATACLYSM: LocalSpellIdx = LocalSpellIdx::new(10);
406pub(crate) const SPELL_CHANNEL_DEMONFIRE: LocalSpellIdx = LocalSpellIdx::new(11);
407pub(crate) const SPELL_CHANNEL_DEMONFIRE_TICK: LocalSpellIdx = LocalSpellIdx::new(12);
408pub(crate) const SPELL_HAVOC: LocalSpellIdx = LocalSpellIdx::new(13);
409pub(crate) const SPELL_SHADOW_BOLT: LocalSpellIdx = LocalSpellIdx::new(14);
410pub(crate) const SPELL_CORRUPTION: LocalSpellIdx = LocalSpellIdx::new(15);
411pub(crate) const SPELL_MALEVOLENCE: LocalSpellIdx = LocalSpellIdx::new(16);
412pub(crate) const SPELL_DRAIN_LIFE: LocalSpellIdx = LocalSpellIdx::new(17);
413pub(crate) const SPELL_INFERNAL_BOLT: LocalSpellIdx = LocalSpellIdx::new(18);
414pub(crate) const SPELL_RUINATION: LocalSpellIdx = LocalSpellIdx::new(19);
415pub(crate) const SPELL_SUMMON_INFERNAL: LocalSpellIdx = LocalSpellIdx::new(20);
416pub(crate) const SPELL_COUNT: usize = 21;
417const _: () = assert!(
418 SPELL_COUNT == 21,
419 "SPELL index ABI: count changed -- update positional hook consumers"
420);
421pub(crate) mod EFFECT {
422 pub(crate) const IMMOLATION_DAMAGE: (u32, u8) = (20153, 1);
424 pub(crate) const CHAOS_BOLT_DAMAGE: (u32, u8) = (116_858, 1);
426 pub(crate) const ECHO_OF_SARGERAS_DAMAGE: (u32, u8) = (1_265_884, 1);
428 pub(crate) const LASH_OF_PAIN_DAMAGE: (u32, u8) = (7814, 1);
430 pub(crate) const RAIN_OF_FIRE_DAMAGE: (u32, u8) = (42223, 1);
432 pub(crate) const RAIN_OF_FIRE_TIMING: (u32, u8) = (5740, 3);
434 pub(crate) const WICKED_CLEAVE_DAMAGE: (u32, u8) = (432_120, 1);
436 pub(crate) const CHAOS_SALVO_DAMAGE: (u32, u8) = (432_596, 1);
438 pub(crate) const FELSEEKER_DAMAGE: (u32, u8) = (434_404, 1);
440 pub(crate) const EYE_EXPLOSION_DAMAGE: (u32, u8) = (1_269_800, 1);
442 pub(crate) const DIABOLIC_GAZE_1_DAMAGE: (u32, u8) = (1_269_892, 1);
444 pub(crate) const DIABOLIC_GAZE_2_DAMAGE: (u32, u8) = (1_269_886, 1);
446 pub(crate) const DIABOLIC_GAZE_3_DAMAGE: (u32, u8) = (1_269_885, 1);
448}
449static REPORTED_SPELLS: &[(&str, u32)] = &[
450 ("chaos_salvo", 432_596),
451 ("diabolic_gaze_1", 1_269_892),
452 ("diabolic_gaze_2", 1_269_886),
453 ("diabolic_gaze_3", 1_269_885),
454 ("echo_of_sargeras", 1_265_884),
455 ("echo_of_sargeras_cb", 1_277_879),
456 ("echo_of_sargeras_sb", 1_265_774),
457 ("eye_explosion", 1_269_800),
458 ("felseeker", 434_404),
459 ("immolation", 20153),
460 ("infernal_melee", 111_685),
461 ("lash_of_pain", 7814),
462 ("wicked_cleave", 432_120),
463];
464static DECLARED_SPELL_IDS: &[u32] = &[
465 691, 688, 108_503, 348, 29722, 17962, 116_858, 5740, 17877, 6353, 152_108, 196_447,
466 196_448, 80240, 686, 172, 430_014, 234_153, 434_506, 434_635, 1122, 157_736, 117_828,
467 266_030, 205_148, 387_109, 387_109, 387_263, 1_245_664, 1_245_633, 387_108,
468 1_244_860, 1_244_788, 80240, 387_157, 196_099, 445_474, 442_726, 196_447, 1_288_970,
469 462_599, 433_891, 433_885, 428_514, 431_944, 432_815, 432_816, 428_524, 432_794,
470 432_795, 1_269_643, 1_268_709, 1_268_713, 1_268_716, 1_269_879, 457_578, 1_245_089,
471 1_265_770, 1_265_772, 1_265_774, 1_265_939, 264_364, 266_087, 417_282, 1, 5740, 7814,
472 20153, 42223, 77220, 111_685, 116_858, 157_736, 196_448, 264_364, 264_365, 281_490,
473 432_120, 432_596, 434_404, 434_506, 1_265_772, 1_265_774, 1_265_884, 1_269_800,
474 1_269_879, 1_269_885, 1_269_886, 1_269_892, 1_277_879, 432_596, 1_269_892, 1_269_886,
475 1_269_885, 1_265_884, 1_277_879, 1_265_774, 1_269_800, 434_404, 20153, 111_685, 7814,
476 432_120, 445_736, 445_731, 430_014, 446_285, 445_465, 445_468, 445_731, 442_726,
477 445_474, 434_506, 434_635, 434_636, 434_424, 432_794, 428_524, 432_795, 1_269_643,
478 432_815, 431_944, 432_816, 433_891, 1_269_879, 433_885,
479];
480static DECLARED_AURA_IDS: &[u32] = &[
481 157_736, 117_828, 266_030, 205_148, 387_109, 387_109, 387_263, 1_245_664, 1_245_633,
482 387_108, 1_244_860, 1_244_788, 80240, 387_157, 196_099, 445_474, 442_726, 196_447,
483 1_288_970, 462_599, 433_891, 433_885, 428_514, 431_944, 432_815, 432_816, 428_524,
484 432_794, 432_795, 1_269_643, 1_268_709, 1_268_713, 1_268_716, 1_269_879, 457_578,
485 1_245_089, 1_265_770, 1_265_772, 1_265_774, 1_265_939, 264_364, 266_087, 417_282,
486 445_731, 442_726, 445_474, 434_424, 432_794, 428_524, 432_795, 1_269_643, 432_815,
487 431_944, 432_816, 433_891, 1_269_879, 433_885,
488];
489static TALENTS: &[(&str, u32)] = &[
490 ("AVATAR_OF_DESTRUCTION", TALENT::AVATAR_OF_DESTRUCTION),
491 ("BACKDRAFT", TALENT::BACKDRAFT),
492 ("CATACLYSM", TALENT::CATACLYSM),
493 ("CHANNEL_DEMONFIRE", TALENT::CHANNEL_DEMONFIRE),
494 ("CHAOS_INCARNATE", TALENT::CHAOS_INCARNATE),
495 ("CHAOTIC_INFERNO", TALENT::CHAOTIC_INFERNO),
496 ("CONFLAGRATE", TALENT::CONFLAGRATE),
497 ("CONFLAGRATION_OF_CHAOS", TALENT::CONFLAGRATION_OF_CHAOS),
498 ("CRASHING_CHAOS", TALENT::CRASHING_CHAOS),
499 ("DEMONFIRE_INFUSION", TALENT::DEMONFIRE_INFUSION),
500 ("DIABOLIC_EMBERS", TALENT::DIABOLIC_EMBERS),
501 ("DIABOLIC_OCULI", TALENT::DIABOLIC_OCULI),
502 ("DIABOLIC_RITUAL", TALENT::DIABOLIC_RITUAL),
503 ("EMBERSTORM", TALENT::EMBERSTORM),
504 ("EMBERS_OF_NIHILAM_1", TALENT::EMBERS_OF_NIHILAM_1),
505 ("EMBERS_OF_NIHILAM_2", TALENT::EMBERS_OF_NIHILAM_2),
506 ("EMBERS_OF_NIHILAM_3", TALENT::EMBERS_OF_NIHILAM_3),
507 ("FIENDISH_CRUELTY", TALENT::FIENDISH_CRUELTY),
508 ("FIRE_AND_BRIMSTONE", TALENT::FIRE_AND_BRIMSTONE),
509 ("FLASHPOINT", TALENT::FLASHPOINT),
510 ("GRIMOIRE_OF_SACRIFICE", TALENT::GRIMOIRE_OF_SACRIFICE),
511 ("HAVOC", TALENT::HAVOC),
512 ("IMPROVED_CONFLAGRATE", TALENT::IMPROVED_CONFLAGRATE),
513 ("INFERNO", TALENT::INFERNO),
514 ("INTERNAL_COMBUSTION", TALENT::INTERNAL_COMBUSTION),
515 ("LOOKS_THAT_KILL", TALENT::LOOKS_THAT_KILL),
516 ("MALEVOLENCE", TALENT::MALEVOLENCE),
517 ("MAYHEM", TALENT::MAYHEM),
518 ("MINDS_EYES", TALENT::MINDS_EYES),
519 ("RAGING_DEMONFIRE", TALENT::RAGING_DEMONFIRE),
520 ("RAIN_OF_CHAOS", TALENT::RAIN_OF_CHAOS),
521 ("RAIN_OF_FIRE", TALENT::RAIN_OF_FIRE),
522 ("REVERSE_ENTROPY", TALENT::REVERSE_ENTROPY),
523 ("ROARING_BLAZE", TALENT::ROARING_BLAZE),
524 ("SHADOWBURN", TALENT::SHADOWBURN),
525 ("SOUL_FIRE", TALENT::SOUL_FIRE),
526 ("SUMMON_INFERNAL", TALENT::SUMMON_INFERNAL),
527];
528pub(crate) mod DESTRUCTION_WARLOCK {
529 pub(crate) const INCINERATE_CASTS: u32 = 0;
530 pub(crate) const CHAOS_BOLT_CASTS: u32 = 1;
531 pub(crate) const CONFLAGRATE_CASTS: u32 = 2;
532 pub(crate) const SUMMON_INFERNAL_CASTS: u32 = 3;
533 pub(crate) const RAIN_OF_FIRE_CASTS: u32 = 4;
534 pub(crate) const SHADOWBURN_CASTS: u32 = 5;
535 pub(crate) const SOUL_FIRE_CASTS: u32 = 6;
536 pub(crate) const IMMOLATE_UPTIME_MS: u32 = 7;
537 pub(crate) const BACKDRAFT_UPTIME_MS: u32 = 8;
538}
539fn aura_immolate(
540 a: AuraDefinitionDraft,
541 data: &ResolvedGameData,
542) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
543 a.on_target()
544 .apply_base_from_data(data, 157_736)?
545 .max_stacks(
546 data.require_aura_max_stacks(wowlab_types::sim::SpellIdx::from_raw(157_736))?,
547 )
548 .periodic_damage_sp_from_data(
549 data,
550 wowlab_engine_combat::PeriodicDamageDataInput {
551 tick_ms: wowlab_engine_combat::validated_milliseconds(
552 data.period(wowlab_types::sim::SpellIdx::from_raw(157_736), 1),
553 157_736,
554 "periodic_damage.tick_ms",
555 )?,
556 spell_id: 157_736,
557 effect_index: 1,
558 multiplier: 1.0,
559 offset: 0.0,
560 round_decimals: Some(5),
561 },
562 )?
563 .periodic_damage_resource_gain(0.1)
564 .periodic_damage_crit_resource_gain(0.5, 0.1)
565 .apply_periodic_behavior_from_data(data, 157_736)
566}
567fn aura_backdraft(
568 a: AuraDefinitionDraft,
569 data: &ResolvedGameData,
570) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
571 Ok(
572 a
573 .on_player()
574 .apply_base_from_data(data, 117_828)?
575 .max_stacks(
576 data
577 .require_aura_max_stacks(
578 wowlab_types::sim::SpellIdx::from_raw(117_828),
579 )?,
580 ),
581 )
582}
583fn aura_reverse_entropy(
584 a: AuraDefinitionDraft,
585 data: &ResolvedGameData,
586) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
587 Ok(
588 a
589 .on_player()
590 .apply_base_from_data(data, 266_030)?
591 .max_stacks(
592 data
593 .require_aura_max_stacks(
594 wowlab_types::sim::SpellIdx::from_raw(266_030),
595 )?,
596 ),
597 )
598}
599fn aura_reverse_entropy_talent(
600 a: AuraDefinitionDraft,
601 data: &ResolvedGameData,
602) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
603 Ok(
604 a
605 .on_player()
606 .apply_base_from_data(data, 205_148)?
607 .max_stacks(
608 data
609 .require_aura_max_stacks(
610 wowlab_types::sim::SpellIdx::from_raw(205_148),
611 )?,
612 ),
613 )
614}
615fn aura_conflagration_of_chaos_conflag(
616 a: AuraDefinitionDraft,
617 data: &ResolvedGameData,
618) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
619 Ok(
620 a
621 .on_player()
622 .apply_base_from_data(data, 387_109)?
623 .max_stacks(
624 data
625 .require_aura_max_stacks(
626 wowlab_types::sim::SpellIdx::from_raw(387_109),
627 )?,
628 ),
629 )
630}
631fn aura_conflagration_of_chaos_shadowburn(
632 a: AuraDefinitionDraft,
633 data: &ResolvedGameData,
634) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
635 Ok(
636 a
637 .on_player()
638 .apply_base_from_data(data, 387_109)?
639 .max_stacks(
640 data
641 .require_aura_max_stacks(
642 wowlab_types::sim::SpellIdx::from_raw(387_109),
643 )?,
644 ),
645 )
646}
647fn aura_flashpoint(
648 a: AuraDefinitionDraft,
649 data: &ResolvedGameData,
650) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
651 Ok(
652 a
653 .on_player()
654 .apply_base_from_data(data, 387_263)?
655 .max_stacks(
656 data
657 .require_aura_max_stacks(
658 wowlab_types::sim::SpellIdx::from_raw(387_263),
659 )?,
660 ),
661 )
662}
663fn aura_fiendish_cruelty(
664 a: AuraDefinitionDraft,
665 data: &ResolvedGameData,
666) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
667 Ok(
668 a
669 .on_player()
670 .apply_base_from_data(data, 1_245_664)?
671 .max_stacks(
672 data
673 .require_aura_max_stacks(
674 wowlab_types::sim::SpellIdx::from_raw(1_245_664),
675 )?,
676 ),
677 )
678}
679fn aura_fiendish_cruelty_talent(
680 a: AuraDefinitionDraft,
681 data: &ResolvedGameData,
682) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
683 Ok(
684 a
685 .on_player()
686 .apply_base_from_data(data, 1_245_633)?
687 .max_stacks(
688 data
689 .require_aura_max_stacks(
690 wowlab_types::sim::SpellIdx::from_raw(1_245_633),
691 )?,
692 ),
693 )
694}
695fn aura_conflagration_of_chaos_talent(
696 a: AuraDefinitionDraft,
697 data: &ResolvedGameData,
698) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
699 Ok(
700 a
701 .on_player()
702 .apply_base_from_data(data, 387_108)?
703 .max_stacks(
704 data
705 .require_aura_max_stacks(
706 wowlab_types::sim::SpellIdx::from_raw(387_108),
707 )?,
708 ),
709 )
710}
711fn aura_chaotic_inferno(
712 a: AuraDefinitionDraft,
713 data: &ResolvedGameData,
714) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
715 Ok(
716 a
717 .on_player()
718 .apply_base_from_data(data, 1_244_860)?
719 .max_stacks(
720 data
721 .require_aura_max_stacks(
722 wowlab_types::sim::SpellIdx::from_raw(1_244_860),
723 )?,
724 ),
725 )
726}
727fn aura_chaotic_inferno_talent(
728 a: AuraDefinitionDraft,
729 data: &ResolvedGameData,
730) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
731 Ok(
732 a
733 .on_player()
734 .apply_base_from_data(data, 1_244_788)?
735 .max_stacks(
736 data
737 .require_aura_max_stacks(
738 wowlab_types::sim::SpellIdx::from_raw(1_244_788),
739 )?,
740 ),
741 )
742}
743fn aura_havoc(
744 a: AuraDefinitionDraft,
745 data: &ResolvedGameData,
746) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
747 Ok(
748 a
749 .on_target()
750 .apply_base_from_data(data, 80240)?
751 .max_stacks(
752 data
753 .require_aura_max_stacks(
754 wowlab_types::sim::SpellIdx::from_raw(80240),
755 )?,
756 ),
757 )
758}
759fn aura_ritual_of_ruin(
760 a: AuraDefinitionDraft,
761 data: &ResolvedGameData,
762) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
763 Ok(
764 a
765 .on_player()
766 .apply_base_from_data(data, 387_157)?
767 .max_stacks(
768 data
769 .require_aura_max_stacks(
770 wowlab_types::sim::SpellIdx::from_raw(387_157),
771 )?,
772 ),
773 )
774}
775fn aura_grimoire_of_sacrifice(
776 a: AuraDefinitionDraft,
777 data: &ResolvedGameData,
778) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
779 Ok(
780 a
781 .on_player()
782 .apply_base_from_data(data, 196_099)?
783 .max_stacks(
784 data
785 .require_aura_max_stacks(
786 wowlab_types::sim::SpellIdx::from_raw(196_099),
787 )?,
788 ),
789 )
790}
791fn aura_wither(
792 a: AuraDefinitionDraft,
793 data: &ResolvedGameData,
794) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
795 a.on_target()
796 .apply_base_from_data(data, 445_474)?
797 .max_stacks(
798 data.require_aura_max_stacks(wowlab_types::sim::SpellIdx::from_raw(445_474))?,
799 )
800 .periodic_damage_sp(
801 wowlab_engine_combat::validated_milliseconds(
802 3000.0,
803 445_474,
804 "periodic_damage.tick_ms",
805 )?,
806 0.16,
807 wowlab_engine_combat::DamageFlags::empty(),
808 )
809 .apply_periodic_behavior_from_data(data, 445_474)
810}
811fn aura_malevolence(
812 a: AuraDefinitionDraft,
813 data: &ResolvedGameData,
814) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
815 Ok(
816 a
817 .on_player()
818 .apply_base_from_data(data, 442_726)?
819 .max_stacks(
820 data
821 .require_aura_max_stacks(
822 wowlab_types::sim::SpellIdx::from_raw(442_726),
823 )?,
824 ),
825 )
826}
827fn aura_channel_demonfire(
828 a: AuraDefinitionDraft,
829 data: &ResolvedGameData,
830) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
831 Ok(
832 a
833 .on_player()
834 .apply_base_from_data(data, 196_447)?
835 .max_stacks(
836 data
837 .require_aura_max_stacks(
838 wowlab_types::sim::SpellIdx::from_raw(196_447),
839 )?,
840 ),
841 )
842}
843fn aura_recently_demon_has_been_summoned_dnt(
844 a: AuraDefinitionDraft,
845 data: &ResolvedGameData,
846) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
847 Ok(
848 a
849 .on_player()
850 .apply_base_from_data(data, 1_288_970)?
851 .max_stacks(
852 data
853 .require_aura_max_stacks(
854 wowlab_types::sim::SpellIdx::from_raw(1_288_970),
855 )?,
856 ),
857 )
858}
859fn aura_track_pets(
860 a: AuraDefinitionDraft,
861 data: &ResolvedGameData,
862) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
863 Ok(
864 a
865 .on_player()
866 .apply_base_from_data(data, 462_599)?
867 .max_stacks(
868 data
869 .require_aura_max_stacks(
870 wowlab_types::sim::SpellIdx::from_raw(462_599),
871 )?,
872 ),
873 )
874}
875fn aura_infernal_bolt(
876 a: AuraDefinitionDraft,
877 data: &ResolvedGameData,
878) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
879 Ok(
880 a
881 .on_player()
882 .apply_base_from_data(data, 433_891)?
883 .max_stacks(
884 data
885 .require_aura_max_stacks(
886 wowlab_types::sim::SpellIdx::from_raw(433_891),
887 )?,
888 ),
889 )
890}
891fn aura_ruination(
892 a: AuraDefinitionDraft,
893 data: &ResolvedGameData,
894) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
895 Ok(
896 a
897 .on_player()
898 .apply_base_from_data(data, 433_885)?
899 .max_stacks(
900 data
901 .require_aura_max_stacks(
902 wowlab_types::sim::SpellIdx::from_raw(433_885),
903 )?,
904 ),
905 )
906}
907fn aura_diabolic_ritual_talent(
908 a: AuraDefinitionDraft,
909 data: &ResolvedGameData,
910) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
911 Ok(
912 a
913 .on_player()
914 .apply_base_from_data(data, 428_514)?
915 .max_stacks(
916 data
917 .require_aura_max_stacks(
918 wowlab_types::sim::SpellIdx::from_raw(428_514),
919 )?,
920 ),
921 )
922}
923fn aura_diabolic_ritual_overlord(
924 a: AuraDefinitionDraft,
925 data: &ResolvedGameData,
926) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
927 Ok(
928 a
929 .on_player()
930 .apply_base_from_data(data, 431_944)?
931 .max_stacks(
932 data
933 .require_aura_max_stacks(
934 wowlab_types::sim::SpellIdx::from_raw(431_944),
935 )?,
936 )
937 .on_expire(
938 crate::hooks::destruction_warlock::destruction_diabolic_ritual_overlord_expire_hook,
939 ),
940 )
941}
942fn aura_diabolic_ritual_mother(
943 a: AuraDefinitionDraft,
944 data: &ResolvedGameData,
945) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
946 Ok(
947 a
948 .on_player()
949 .apply_base_from_data(data, 432_815)?
950 .max_stacks(
951 data
952 .require_aura_max_stacks(
953 wowlab_types::sim::SpellIdx::from_raw(432_815),
954 )?,
955 )
956 .on_expire(
957 crate::hooks::destruction_warlock::destruction_diabolic_ritual_mother_expire_hook,
958 ),
959 )
960}
961fn aura_diabolic_ritual_pit_lord(
962 a: AuraDefinitionDraft,
963 data: &ResolvedGameData,
964) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
965 Ok(
966 a
967 .on_player()
968 .apply_base_from_data(data, 432_816)?
969 .max_stacks(
970 data
971 .require_aura_max_stacks(
972 wowlab_types::sim::SpellIdx::from_raw(432_816),
973 )?,
974 )
975 .on_expire(
976 crate::hooks::destruction_warlock::destruction_diabolic_ritual_pit_lord_expire_hook,
977 ),
978 )
979}
980fn aura_demonic_art_overlord(
981 a: AuraDefinitionDraft,
982 data: &ResolvedGameData,
983) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
984 Ok(
985 a
986 .on_player()
987 .apply_base_from_data(data, 428_524)?
988 .max_stacks(
989 data
990 .require_aura_max_stacks(
991 wowlab_types::sim::SpellIdx::from_raw(428_524),
992 )?,
993 )
994 .on_expire(
995 crate::hooks::destruction_warlock::destruction_demonic_art_overlord_expire_hook,
996 ),
997 )
998}
999fn aura_demonic_art_mother(
1000 a: AuraDefinitionDraft,
1001 data: &ResolvedGameData,
1002) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
1003 Ok(
1004 a
1005 .on_player()
1006 .apply_base_from_data(data, 432_794)?
1007 .max_stacks(
1008 data
1009 .require_aura_max_stacks(
1010 wowlab_types::sim::SpellIdx::from_raw(432_794),
1011 )?,
1012 )
1013 .on_expire(
1014 crate::hooks::destruction_warlock::destruction_demonic_art_mother_expire_hook,
1015 ),
1016 )
1017}
1018fn aura_demonic_art_pit_lord(
1019 a: AuraDefinitionDraft,
1020 data: &ResolvedGameData,
1021) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
1022 Ok(
1023 a
1024 .on_player()
1025 .apply_base_from_data(data, 432_795)?
1026 .max_stacks(
1027 data
1028 .require_aura_max_stacks(
1029 wowlab_types::sim::SpellIdx::from_raw(432_795),
1030 )?,
1031 )
1032 .on_expire(
1033 crate::hooks::destruction_warlock::destruction_demonic_art_pit_lord_expire_hook,
1034 ),
1035 )
1036}
1037fn aura_demonic_oculi(
1038 a: AuraDefinitionDraft,
1039 data: &ResolvedGameData,
1040) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
1041 Ok(
1042 a
1043 .on_player()
1044 .apply_base_from_data(data, 1_269_643)?
1045 .max_stacks(
1046 data
1047 .require_aura_max_stacks(
1048 wowlab_types::sim::SpellIdx::from_raw(1_269_643),
1049 )?,
1050 ),
1051 )
1052}
1053fn aura_diabolic_oculi_talent(
1054 a: AuraDefinitionDraft,
1055 data: &ResolvedGameData,
1056) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
1057 Ok(
1058 a
1059 .on_player()
1060 .apply_base_from_data(data, 1_268_709)?
1061 .max_stacks(
1062 data
1063 .require_aura_max_stacks(
1064 wowlab_types::sim::SpellIdx::from_raw(1_268_709),
1065 )?,
1066 ),
1067 )
1068}
1069fn aura_looks_that_kill_talent(
1070 a: AuraDefinitionDraft,
1071 data: &ResolvedGameData,
1072) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
1073 Ok(
1074 a
1075 .on_player()
1076 .apply_base_from_data(data, 1_268_713)?
1077 .max_stacks(
1078 data
1079 .require_aura_max_stacks(
1080 wowlab_types::sim::SpellIdx::from_raw(1_268_713),
1081 )?,
1082 ),
1083 )
1084}
1085fn aura_minds_eyes_talent(
1086 a: AuraDefinitionDraft,
1087 data: &ResolvedGameData,
1088) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
1089 Ok(
1090 a
1091 .on_player()
1092 .apply_base_from_data(data, 1_268_716)?
1093 .max_stacks(
1094 data
1095 .require_aura_max_stacks(
1096 wowlab_types::sim::SpellIdx::from_raw(1_268_716),
1097 )?,
1098 ),
1099 )
1100}
1101fn aura_minds_eyes(
1102 a: AuraDefinitionDraft,
1103 data: &ResolvedGameData,
1104) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
1105 a.on_player()
1106 .apply_base_from_data(data, 1_269_879)?
1107 .max_stacks(
1108 data
1109 .require_aura_max_stacks(
1110 wowlab_types::sim::SpellIdx::from_raw(1_269_879),
1111 )?,
1112 )
1113 .primary_pct_per_stack(
1114 data.base_points(wowlab_types::sim::SpellIdx::from_raw(1_269_879), 1),
1115 )
1116}
1117fn aura_overfiend(
1118 a: AuraDefinitionDraft,
1119 data: &ResolvedGameData,
1120) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
1121 Ok(
1122 a
1123 .on_player()
1124 .apply_base_from_data(data, 457_578)?
1125 .max_stacks(
1126 data
1127 .require_aura_max_stacks(
1128 wowlab_types::sim::SpellIdx::from_raw(457_578),
1129 )?,
1130 ),
1131 )
1132}
1133fn aura_avatar_of_destruction_talent(
1134 a: AuraDefinitionDraft,
1135 data: &ResolvedGameData,
1136) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
1137 Ok(
1138 a
1139 .on_player()
1140 .apply_base_from_data(data, 1_245_089)?
1141 .max_stacks(
1142 data
1143 .require_aura_max_stacks(
1144 wowlab_types::sim::SpellIdx::from_raw(1_245_089),
1145 )?,
1146 ),
1147 )
1148}
1149fn aura_embers_of_nihilam_1_talent(
1150 a: AuraDefinitionDraft,
1151 data: &ResolvedGameData,
1152) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
1153 Ok(
1154 a
1155 .on_player()
1156 .apply_base_from_data(data, 1_265_770)?
1157 .max_stacks(
1158 data
1159 .require_aura_max_stacks(
1160 wowlab_types::sim::SpellIdx::from_raw(1_265_770),
1161 )?,
1162 ),
1163 )
1164}
1165fn aura_embers_of_nihilam_2_talent(
1166 a: AuraDefinitionDraft,
1167 data: &ResolvedGameData,
1168) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
1169 Ok(
1170 a
1171 .on_player()
1172 .apply_base_from_data(data, 1_265_772)?
1173 .max_stacks(
1174 data
1175 .require_aura_max_stacks(
1176 wowlab_types::sim::SpellIdx::from_raw(1_265_772),
1177 )?,
1178 ),
1179 )
1180}
1181fn aura_embers_of_nihilam_3_talent(
1182 a: AuraDefinitionDraft,
1183 data: &ResolvedGameData,
1184) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
1185 Ok(
1186 a
1187 .on_player()
1188 .apply_base_from_data(data, 1_265_774)?
1189 .max_stacks(
1190 data
1191 .require_aura_max_stacks(
1192 wowlab_types::sim::SpellIdx::from_raw(1_265_774),
1193 )?,
1194 ),
1195 )
1196}
1197fn aura_vision_of_nihilam(
1198 a: AuraDefinitionDraft,
1199 data: &ResolvedGameData,
1200) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
1201 a.on_player()
1202 .apply_base_from_data(data, 1_265_939)?
1203 .max_stacks(
1204 data
1205 .require_aura_max_stacks(
1206 wowlab_types::sim::SpellIdx::from_raw(1_265_939),
1207 )?,
1208 )
1209 .haste_per_stack(
1210 (data.base_points(wowlab_types::sim::SpellIdx::from_raw(1_265_772), 1)) * 2.0,
1211 )?
1212 .crit_per_stack(
1213 (data.base_points(wowlab_types::sim::SpellIdx::from_raw(1_265_772), 1)) * 2.0,
1214 )
1215}
1216fn aura_infernal_embers(
1217 a: AuraDefinitionDraft,
1218 data: &ResolvedGameData,
1219) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
1220 Ok(
1221 a
1222 .on_player()
1223 .duration_ms(
1224 wowlab_engine_combat::validated_milliseconds(
1225 f64::from(
1226 data
1227 .require_aura_duration_ms(
1228 wowlab_types::sim::SpellIdx::from_raw(111_685),
1229 )?,
1230 ),
1231 264_364,
1232 "aura.duration_ms",
1233 )?,
1234 )
1235 .apply_periodic_effect_from_data(data, 264_364)?
1236 .apply_duration_behavior_from_data(data, 111_685)?
1237 .apply_timing_modifiers_from_data(data, 264_364)?
1238 .max_stacks(
1239 data
1240 .require_aura_max_stacks(
1241 wowlab_types::sim::SpellIdx::from_raw(264_364),
1242 )?,
1243 )
1244 .periodic_resource(
1245 wowlab_engine_combat::validated_milliseconds(
1246 data.period(wowlab_types::sim::SpellIdx::from_raw(264_364), 1),
1247 264_364,
1248 "periodic_resource.tick_ms",
1249 )?,
1250 (data.base_points(wowlab_types::sim::SpellIdx::from_raw(264_365), 1))
1251 * 0.1,
1252 )
1253 .apply_periodic_behavior_from_data(data, 264_364)?
1254 .unhasted_periodic(),
1255 )
1256}
1257fn aura_rain_of_chaos(
1258 a: AuraDefinitionDraft,
1259 data: &ResolvedGameData,
1260) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
1261 Ok(
1262 a
1263 .on_player()
1264 .apply_base_from_data(data, 266_087)?
1265 .max_stacks(
1266 data
1267 .require_aura_max_stacks(
1268 wowlab_types::sim::SpellIdx::from_raw(266_087),
1269 )?,
1270 ),
1271 )
1272}
1273fn aura_crashing_chaos(
1274 a: AuraDefinitionDraft,
1275 data: &ResolvedGameData,
1276) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
1277 Ok(
1278 a
1279 .on_player()
1280 .apply_base_from_data(data, 417_282)?
1281 .max_stacks(
1282 data
1283 .require_aura_max_stacks(
1284 wowlab_types::sim::SpellIdx::from_raw(417_282),
1285 )?,
1286 ),
1287 )
1288}
1289fn spell_summon_felhunter(
1290 s: SpellDefinitionDraft,
1291 data: &ResolvedGameData,
1292) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1293 Ok(s.apply_base_from_data(data, 691)?.apply_aoe_from_data(data))
1294}
1295fn spell_summon_imp(
1296 s: SpellDefinitionDraft,
1297 data: &ResolvedGameData,
1298) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1299 Ok(s.apply_base_from_data(data, 688)?.apply_aoe_from_data(data))
1300}
1301fn spell_grimoire_of_sacrifice(
1302 s: SpellDefinitionDraft,
1303 data: &ResolvedGameData,
1304) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1305 Ok(
1306 s
1307 .apply_base_from_data(data, 108_503)?
1308 .applies_aura(AURA_GRIMOIRE_OF_SACRIFICE)
1309 .apply_aoe_from_data(data),
1310 )
1311}
1312fn spell_immolate(
1313 s: SpellDefinitionDraft,
1314 data: &ResolvedGameData,
1315) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1316 Ok(
1317 s
1318 .apply_base_from_data(data, 348)?
1319 .applies_aura(AURA_IMMOLATE)
1320 .apply_aoe_from_data(data),
1321 )
1322}
1323fn spell_incinerate(
1324 s: SpellDefinitionDraft,
1325 data: &ResolvedGameData,
1326) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1327 Ok(
1328 s
1329 .apply_base_from_data(data, 29722)?
1330 .gain(0.5)
1331 .apply_aoe_from_data(data)
1332 .on_cast(crate::hooks::destruction_warlock::incinerate_hook),
1333 )
1334}
1335fn spell_conflagrate(
1336 s: SpellDefinitionDraft,
1337 data: &ResolvedGameData,
1338) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1339 Ok(
1340 s
1341 .apply_base_from_data(data, 17962)?
1342 .hasted_cooldown()
1343 .gain(0.7)
1344 .apply_aoe_from_data(data)
1345 .on_cast(crate::hooks::destruction_warlock::conflagrate_hook),
1346 )
1347}
1348fn spell_chaos_bolt(
1349 s: SpellDefinitionDraft,
1350 data: &ResolvedGameData,
1351) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1352 Ok(
1353 s
1354 .apply_base_from_data(data, 116_858)?
1355 .guaranteed_crit()
1356 .apply_aoe_from_data(data)
1357 .on_cast(crate::hooks::destruction_warlock::chaos_bolt_hook),
1358 )
1359}
1360fn spell_rain_of_fire(
1361 s: SpellDefinitionDraft,
1362 data: &ResolvedGameData,
1363) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1364 Ok(
1365 s
1366 .apply_base_from_data(data, 5740)?
1367 .apply_aoe_from_data(data)
1368 .on_cast(crate::hooks::destruction_warlock::rain_of_fire_hook),
1369 )
1370}
1371fn spell_shadowburn(
1372 s: SpellDefinitionDraft,
1373 data: &ResolvedGameData,
1374) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1375 Ok(
1376 s
1377 .apply_base_from_data(data, 17877)?
1378 .apply_aoe_from_data(data)
1379 .on_cast(crate::hooks::destruction_warlock::shadowburn_hook)
1380 .cost_free_when_aura(1_245_664)
1381 .execute_below_pct(20.0),
1382 )
1383}
1384fn spell_soul_fire(
1385 s: SpellDefinitionDraft,
1386 data: &ResolvedGameData,
1387) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1388 Ok(
1389 s
1390 .apply_base_from_data(data, 6353)?
1391 .gain(
1392 (data.base_points(wowlab_types::sim::SpellIdx::from_raw(281_490), 1))
1393 * 0.1,
1394 )
1395 .apply_aoe_from_data(data)
1396 .on_cast(crate::hooks::destruction_warlock::soul_fire_hook),
1397 )
1398}
1399fn spell_cataclysm(
1400 s: SpellDefinitionDraft,
1401 data: &ResolvedGameData,
1402) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1403 Ok(s.apply_base_from_data(data, 152_108)?.apply_aoe_from_data(data))
1404}
1405fn spell_channel_demonfire(
1406 s: SpellDefinitionDraft,
1407 data: &ResolvedGameData,
1408) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1409 s.apply_base_from_data(data, 196_447)?
1410 .applies_inferred_aura(AURA_CHANNEL_DEMONFIRE, 196_447)
1411 .apply_aoe_from_data(data)
1412 .channel(
1413 data
1414 .require_channel_tick_count(
1415 wowlab_types::sim::SpellIdx::from_raw(196_447),
1416 )?,
1417 )
1418 .channel_tick_damage_sp_from_data(
1419 wowlab_engine_domain::dbc::EffectLookup::new(
1420 data,
1421 wowlab_types::sim::EffectRef::new(
1422 wowlab_types::sim::SpellIdx::from_raw(196_448),
1423 1,
1424 ),
1425 ),
1426 )
1427}
1428fn spell_channel_demonfire_tick(
1429 s: SpellDefinitionDraft,
1430 data: &ResolvedGameData,
1431) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1432 Ok(s.apply_base_from_data(data, 196_448)?.apply_aoe_from_data(data))
1433}
1434fn spell_havoc(
1435 s: SpellDefinitionDraft,
1436 data: &ResolvedGameData,
1437) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1438 Ok(
1439 s
1440 .apply_base_from_data(data, 80240)?
1441 .applies_inferred_aura(AURA_HAVOC, 80240)
1442 .apply_aoe_from_data(data),
1443 )
1444}
1445fn spell_shadow_bolt(
1446 s: SpellDefinitionDraft,
1447 data: &ResolvedGameData,
1448) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1449 Ok(s.apply_base_from_data(data, 686)?.apply_aoe_from_data(data))
1450}
1451fn spell_corruption(
1452 s: SpellDefinitionDraft,
1453 data: &ResolvedGameData,
1454) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1455 Ok(s.apply_base_from_data(data, 172)?.apply_aoe_from_data(data))
1456}
1457fn spell_malevolence(
1458 s: SpellDefinitionDraft,
1459 data: &ResolvedGameData,
1460) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1461 Ok(
1462 s
1463 .apply_base_from_data(data, 430_014)?
1464 .applies_aura(AURA_MALEVOLENCE)
1465 .apply_aoe_from_data(data),
1466 )
1467}
1468fn spell_drain_life(
1469 s: SpellDefinitionDraft,
1470 data: &ResolvedGameData,
1471) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1472 Ok(s.apply_base_from_data(data, 234_153)?.apply_aoe_from_data(data))
1473}
1474fn spell_infernal_bolt(
1475 s: SpellDefinitionDraft,
1476 data: &ResolvedGameData,
1477) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1478 Ok(
1479 s
1480 .apply_base_from_data(data, 434_506)?
1481 .gain(
1482 (data.base_points(wowlab_types::sim::SpellIdx::from_raw(434_506), 2))
1483 * 0.1,
1484 )
1485 .apply_aoe_from_data(data)
1486 .on_cast(crate::hooks::destruction_warlock::infernal_bolt_hook)
1487 .requires_aura_at_min_stacks(433_891, 0)
1488 .consume_aura_on_cast(433_891),
1489 )
1490}
1491fn spell_ruination(
1492 s: SpellDefinitionDraft,
1493 data: &ResolvedGameData,
1494) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1495 Ok(
1496 s
1497 .apply_base_from_data(data, 434_635)?
1498 .travel_time(
1499 wowlab_engine_combat::validated_milliseconds(
1500 1000.0,
1501 434_635,
1502 "spell.travel_time_ms",
1503 )?,
1504 )
1505 .apply_aoe_from_data(data)
1506 .on_cast(crate::hooks::destruction_warlock::ruination_hook)
1507 .requires_aura_at_min_stacks(433_885, 0)
1508 .consume_aura_on_cast(433_885),
1509 )
1510}
1511fn spell_summon_infernal(
1512 s: SpellDefinitionDraft,
1513 data: &ResolvedGameData,
1514) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1515 Ok(
1516 s
1517 .apply_base_from_data(data, 1122)?
1518 .apply_aoe_from_data(data)
1519 .on_cast(crate::hooks::destruction_warlock::summon_infernal_hook),
1520 )
1521}
1522pub(crate) fn build_combat_system(
1523 params: &wowlab_engine_ports::HandlerParams<'_>,
1524) -> Result<BuiltCombatSystem, wowlab_engine_ports::EngineError> {
1525 let builder = BuiltCombatSystem::builder(params.stats.clone())
1526 .spec_id(SpecId::Destruction)
1527 .hero_talent_trees(DECLARED_METADATA.hero_talent_trees)
1528 .mastery_spell(77220)
1529 .mastery_hook(crate::hooks::destruction_warlock::mastery)
1530 .resource(
1531 "soul_shards",
1532 5.0,
1533 params
1534 .game_data
1535 .power_regen_for_max(7, 5.0)
1536 .ok_or_else(|| {
1537 wowlab_engine_ports::EngineError::spec_construction(
1538 "missing power-type power_regen_for_max for type_id 7",
1539 )
1540 })?,
1541 )
1542 .resource_type_id(7)
1543 .resource_start(3.0)
1544 .has_pet(true)
1545 .aura("immolate", AURA::IMMOLATE, |a| aura_immolate(a, ¶ms.game_data))
1546 .aura("backdraft", AURA::BACKDRAFT, |a| aura_backdraft(a, ¶ms.game_data))
1547 .aura(
1548 "reverse_entropy",
1549 AURA::REVERSE_ENTROPY,
1550 |a| aura_reverse_entropy(a, ¶ms.game_data),
1551 )
1552 .aura(
1553 "reverse_entropy_talent",
1554 AURA::REVERSE_ENTROPY_TALENT,
1555 |a| aura_reverse_entropy_talent(a, ¶ms.game_data),
1556 )
1557 .aura(
1558 "conflagration_of_chaos_conflag",
1559 AURA::CONFLAGRATION_OF_CHAOS_CONFLAG,
1560 |a| aura_conflagration_of_chaos_conflag(a, ¶ms.game_data),
1561 )
1562 .aura(
1563 "conflagration_of_chaos_shadowburn",
1564 AURA::CONFLAGRATION_OF_CHAOS_SHADOWBURN,
1565 |a| aura_conflagration_of_chaos_shadowburn(a, ¶ms.game_data),
1566 )
1567 .aura("flashpoint", AURA::FLASHPOINT, |a| aura_flashpoint(a, ¶ms.game_data))
1568 .aura(
1569 "fiendish_cruelty",
1570 AURA::FIENDISH_CRUELTY,
1571 |a| aura_fiendish_cruelty(a, ¶ms.game_data),
1572 )
1573 .aura(
1574 "fiendish_cruelty_talent",
1575 AURA::FIENDISH_CRUELTY_TALENT,
1576 |a| aura_fiendish_cruelty_talent(a, ¶ms.game_data),
1577 )
1578 .aura(
1579 "conflagration_of_chaos_talent",
1580 AURA::CONFLAGRATION_OF_CHAOS_TALENT,
1581 |a| aura_conflagration_of_chaos_talent(a, ¶ms.game_data),
1582 )
1583 .aura(
1584 "chaotic_inferno",
1585 AURA::CHAOTIC_INFERNO,
1586 |a| aura_chaotic_inferno(a, ¶ms.game_data),
1587 )
1588 .aura(
1589 "chaotic_inferno_talent",
1590 AURA::CHAOTIC_INFERNO_TALENT,
1591 |a| aura_chaotic_inferno_talent(a, ¶ms.game_data),
1592 )
1593 .aura("havoc", AURA::HAVOC, |a| aura_havoc(a, ¶ms.game_data))
1594 .aura(
1595 "ritual_of_ruin",
1596 AURA::RITUAL_OF_RUIN,
1597 |a| aura_ritual_of_ruin(a, ¶ms.game_data),
1598 )
1599 .aura(
1600 "grimoire_of_sacrifice",
1601 AURA::GRIMOIRE_OF_SACRIFICE,
1602 |a| aura_grimoire_of_sacrifice(a, ¶ms.game_data),
1603 )
1604 .aura("wither", AURA::WITHER, |a| aura_wither(a, ¶ms.game_data))
1605 .aura(
1606 "malevolence",
1607 AURA::MALEVOLENCE,
1608 |a| aura_malevolence(a, ¶ms.game_data),
1609 )
1610 .aura(
1611 "channel_demonfire",
1612 AURA::CHANNEL_DEMONFIRE,
1613 |a| aura_channel_demonfire(a, ¶ms.game_data),
1614 )
1615 .aura(
1616 "recently_demon_has_been_summoned_dnt",
1617 AURA::RECENTLY_DEMON_HAS_BEEN_SUMMONED_DNT,
1618 |a| aura_recently_demon_has_been_summoned_dnt(a, ¶ms.game_data),
1619 )
1620 .aura("track_pets", AURA::TRACK_PETS, |a| aura_track_pets(a, ¶ms.game_data))
1621 .aura(
1622 "infernal_bolt",
1623 AURA::INFERNAL_BOLT,
1624 |a| aura_infernal_bolt(a, ¶ms.game_data),
1625 )
1626 .aura("ruination", AURA::RUINATION, |a| aura_ruination(a, ¶ms.game_data))
1627 .aura(
1628 "diabolic_ritual_talent",
1629 AURA::DIABOLIC_RITUAL_TALENT,
1630 |a| aura_diabolic_ritual_talent(a, ¶ms.game_data),
1631 )
1632 .aura(
1633 "diabolic_ritual_overlord",
1634 AURA::DIABOLIC_RITUAL_OVERLORD,
1635 |a| aura_diabolic_ritual_overlord(a, ¶ms.game_data),
1636 )
1637 .aura(
1638 "diabolic_ritual_mother",
1639 AURA::DIABOLIC_RITUAL_MOTHER,
1640 |a| aura_diabolic_ritual_mother(a, ¶ms.game_data),
1641 )
1642 .aura(
1643 "diabolic_ritual_pit_lord",
1644 AURA::DIABOLIC_RITUAL_PIT_LORD,
1645 |a| aura_diabolic_ritual_pit_lord(a, ¶ms.game_data),
1646 )
1647 .aura(
1648 "demonic_art_overlord",
1649 AURA::DEMONIC_ART_OVERLORD,
1650 |a| aura_demonic_art_overlord(a, ¶ms.game_data),
1651 )
1652 .aura(
1653 "demonic_art_mother",
1654 AURA::DEMONIC_ART_MOTHER,
1655 |a| aura_demonic_art_mother(a, ¶ms.game_data),
1656 )
1657 .aura(
1658 "demonic_art_pit_lord",
1659 AURA::DEMONIC_ART_PIT_LORD,
1660 |a| aura_demonic_art_pit_lord(a, ¶ms.game_data),
1661 )
1662 .aura(
1663 "demonic_oculi",
1664 AURA::DEMONIC_OCULI,
1665 |a| aura_demonic_oculi(a, ¶ms.game_data),
1666 )
1667 .aura(
1668 "diabolic_oculi_talent",
1669 AURA::DIABOLIC_OCULI_TALENT,
1670 |a| aura_diabolic_oculi_talent(a, ¶ms.game_data),
1671 )
1672 .aura(
1673 "looks_that_kill_talent",
1674 AURA::LOOKS_THAT_KILL_TALENT,
1675 |a| aura_looks_that_kill_talent(a, ¶ms.game_data),
1676 )
1677 .aura(
1678 "minds_eyes_talent",
1679 AURA::MINDS_EYES_TALENT,
1680 |a| aura_minds_eyes_talent(a, ¶ms.game_data),
1681 )
1682 .aura("minds_eyes", AURA::MINDS_EYES, |a| aura_minds_eyes(a, ¶ms.game_data))
1683 .aura("overfiend", AURA::OVERFIEND, |a| aura_overfiend(a, ¶ms.game_data))
1684 .aura(
1685 "avatar_of_destruction_talent",
1686 AURA::AVATAR_OF_DESTRUCTION_TALENT,
1687 |a| aura_avatar_of_destruction_talent(a, ¶ms.game_data),
1688 )
1689 .aura(
1690 "embers_of_nihilam_1_talent",
1691 AURA::EMBERS_OF_NIHILAM_1_TALENT,
1692 |a| aura_embers_of_nihilam_1_talent(a, ¶ms.game_data),
1693 )
1694 .aura(
1695 "embers_of_nihilam_2_talent",
1696 AURA::EMBERS_OF_NIHILAM_2_TALENT,
1697 |a| aura_embers_of_nihilam_2_talent(a, ¶ms.game_data),
1698 )
1699 .aura(
1700 "embers_of_nihilam_3_talent",
1701 AURA::EMBERS_OF_NIHILAM_3_TALENT,
1702 |a| aura_embers_of_nihilam_3_talent(a, ¶ms.game_data),
1703 )
1704 .aura(
1705 "vision_of_nihilam",
1706 AURA::VISION_OF_NIHILAM,
1707 |a| aura_vision_of_nihilam(a, ¶ms.game_data),
1708 )
1709 .aura(
1710 "infernal_embers",
1711 AURA::INFERNAL_EMBERS,
1712 |a| aura_infernal_embers(a, ¶ms.game_data),
1713 )
1714 .aura(
1715 "rain_of_chaos",
1716 AURA::RAIN_OF_CHAOS,
1717 |a| aura_rain_of_chaos(a, ¶ms.game_data),
1718 )
1719 .aura(
1720 "crashing_chaos",
1721 AURA::CRASHING_CHAOS,
1722 |a| aura_crashing_chaos(a, ¶ms.game_data),
1723 )
1724 .spell(
1725 "summon_felhunter",
1726 SPELL::SUMMON_FELHUNTER,
1727 |s| spell_summon_felhunter(s, ¶ms.game_data),
1728 )
1729 .spell(
1730 "summon_imp",
1731 SPELL::SUMMON_IMP,
1732 |s| spell_summon_imp(s, ¶ms.game_data),
1733 )
1734 .spell(
1735 "grimoire_of_sacrifice",
1736 SPELL::GRIMOIRE_OF_SACRIFICE,
1737 |s| spell_grimoire_of_sacrifice(s, ¶ms.game_data),
1738 )
1739 .spell("immolate", SPELL::IMMOLATE, |s| spell_immolate(s, ¶ms.game_data))
1740 .spell(
1741 "incinerate",
1742 SPELL::INCINERATE,
1743 |s| spell_incinerate(s, ¶ms.game_data),
1744 )
1745 .spell(
1746 "conflagrate",
1747 SPELL::CONFLAGRATE,
1748 |s| spell_conflagrate(s, ¶ms.game_data),
1749 )
1750 .spell(
1751 "chaos_bolt",
1752 SPELL::CHAOS_BOLT,
1753 |s| spell_chaos_bolt(s, ¶ms.game_data),
1754 )
1755 .spell(
1756 "rain_of_fire",
1757 SPELL::RAIN_OF_FIRE,
1758 |s| spell_rain_of_fire(s, ¶ms.game_data),
1759 )
1760 .spell(
1761 "shadowburn",
1762 SPELL::SHADOWBURN,
1763 |s| spell_shadowburn(s, ¶ms.game_data),
1764 )
1765 .spell("soul_fire", SPELL::SOUL_FIRE, |s| spell_soul_fire(s, ¶ms.game_data))
1766 .spell("cataclysm", SPELL::CATACLYSM, |s| spell_cataclysm(s, ¶ms.game_data))
1767 .spell(
1768 "channel_demonfire",
1769 SPELL::CHANNEL_DEMONFIRE,
1770 |s| spell_channel_demonfire(s, ¶ms.game_data),
1771 )
1772 .spell(
1773 "channel_demonfire_tick",
1774 SPELL::CHANNEL_DEMONFIRE_TICK,
1775 |s| spell_channel_demonfire_tick(s, ¶ms.game_data),
1776 )
1777 .spell("havoc", SPELL::HAVOC, |s| spell_havoc(s, ¶ms.game_data))
1778 .spell(
1779 "shadow_bolt",
1780 SPELL::SHADOW_BOLT,
1781 |s| spell_shadow_bolt(s, ¶ms.game_data),
1782 )
1783 .spell(
1784 "corruption",
1785 SPELL::CORRUPTION,
1786 |s| spell_corruption(s, ¶ms.game_data),
1787 )
1788 .spell(
1789 "malevolence",
1790 SPELL::MALEVOLENCE,
1791 |s| spell_malevolence(s, ¶ms.game_data),
1792 )
1793 .spell(
1794 "drain_life",
1795 SPELL::DRAIN_LIFE,
1796 |s| spell_drain_life(s, ¶ms.game_data),
1797 )
1798 .spell(
1799 "infernal_bolt",
1800 SPELL::INFERNAL_BOLT,
1801 |s| spell_infernal_bolt(s, ¶ms.game_data),
1802 )
1803 .spell("ruination", SPELL::RUINATION, |s| spell_ruination(s, ¶ms.game_data))
1804 .spell(
1805 "summon_infernal",
1806 SPELL::SUMMON_INFERNAL,
1807 |s| spell_summon_infernal(s, ¶ms.game_data),
1808 )
1809 .auto_attack(|a| {
1810 a
1811 .spell_id(1)
1812 .swing_ms(3000)
1813 .apply_base_from_data(¶ms.game_data)
1814 .ap_coef(
1815 wowlab_engine_domain::damage::pet_swing_power_coefficient(
1816 0.575,
1817 3000,
1818 1.0,
1819 ),
1820 )
1821 .is_pet()
1822 .uses_spell_power()
1823 })
1824 .game_data(params.game_data.clone())
1825 .talent_spell_ids(TALENTS)
1826 .talent_selections(params.talent_selections)
1827 .talent_companion_aura(
1828 TALENT::AVATAR_OF_DESTRUCTION,
1829 AURA_AVATAR_OF_DESTRUCTION_TALENT,
1830 )
1831 .talent_companion_aura(TALENT::CHAOTIC_INFERNO, AURA_CHAOTIC_INFERNO_TALENT)
1832 .talent_companion_aura(
1833 TALENT::CONFLAGRATION_OF_CHAOS,
1834 AURA_CONFLAGRATION_OF_CHAOS_TALENT,
1835 )
1836 .talent_companion_aura(TALENT::DIABOLIC_OCULI, AURA_DIABOLIC_OCULI_TALENT)
1837 .talent_companion_aura(TALENT::DIABOLIC_RITUAL, AURA_DIABOLIC_RITUAL_TALENT)
1838 .talent_companion_aura(
1839 TALENT::EMBERS_OF_NIHILAM_1,
1840 AURA_EMBERS_OF_NIHILAM_1_TALENT,
1841 )
1842 .talent_companion_aura(
1843 TALENT::EMBERS_OF_NIHILAM_2,
1844 AURA_EMBERS_OF_NIHILAM_2_TALENT,
1845 )
1846 .talent_companion_aura(
1847 TALENT::EMBERS_OF_NIHILAM_3,
1848 AURA_EMBERS_OF_NIHILAM_3_TALENT,
1849 )
1850 .talent_companion_aura(TALENT::FIENDISH_CRUELTY, AURA_FIENDISH_CRUELTY_TALENT)
1851 .talent_companion_aura(TALENT::LOOKS_THAT_KILL, AURA_LOOKS_THAT_KILL_TALENT)
1852 .talent_companion_aura(TALENT::MINDS_EYES, AURA_MINDS_EYES_TALENT)
1853 .talent_companion_aura(TALENT::REVERSE_ENTROPY, AURA_REVERSE_ENTROPY_TALENT)
1854 .set_bonus_auras(params.set_bonus_auras)
1855 .encounter(params.encounter.clone());
1856 let builder = crate::generated::items::register_equipped(
1857 builder,
1858 ¶ms.game_data,
1859 params.equipped_items,
1860 )?;
1861
1862 builder
1863 .build(params.rotation)
1864 .map_err(wowlab_engine_ports::EngineError::rotation_compile)
1865}
1866fn new_handler(
1867 params: wowlab_engine_ports::HandlerParams<'_>,
1868) -> Result<Box<dyn SpecHandler>, wowlab_engine_ports::EngineError> {
1869 let handler = crate::composition::compose_handler(
1870 build_combat_system,
1871 ¶ms,
1872 |parts, params| Ok(
1873 crate::hooks::destruction_warlock::DestructionHandler::new(parts, params),
1874 ),
1875 )?;
1876
1877 Ok(Box::new(handler))
1878}
1879static DECLARED_METADATA: DeclaredSpecMetadata = DeclaredSpecMetadata {
1880 primary_resource: ResourceType::SoulShards,
1881 secondary_resource: None,
1882 spell_ids: DECLARED_SPELL_IDS,
1883 aura_ids: DECLARED_AURA_IDS,
1884 server_proc_entries: &[
1885 DeclaredServerProcEntry {
1886 spell_id: 117_828,
1887 attributes: ProcAttributes::REQUIRE_SPELL_MODIFIER.bits()
1888 | ProcAttributes::USE_STACKS_FOR_CHARGES.bits(),
1889 },
1890 ],
1891 talents: TALENTS,
1892 rotation_field_schema: &[],
1893 metrics_plugin_id: None,
1894 hero_talent_trees: &[
1895 HeroTalentTreeDesc {
1896 name: "Hellcaller",
1897 spells: HERO_TREE_HELLCALLER_SPELLS,
1898 auras: HERO_TREE_HELLCALLER_AURAS,
1899 },
1900 HeroTalentTreeDesc {
1901 name: "Diabolist",
1902 spells: HERO_TREE_DIABOLIST_SPELLS,
1903 auras: HERO_TREE_DIABOLIST_AURAS,
1904 },
1905 ],
1906 reported_spells: REPORTED_SPELLS,
1907 masked_passive_effects: &[],
1908 passive_effect_overrides: &[],
1909};
1910pub(super) const SPEC_DESCRIPTOR: SpecDescriptor = SpecDescriptor {
1911 spec_id: SpecId::Destruction,
1912 display_name: "Destruction Warlock",
1913 metadata: DECLARED_METADATA,
1914 handler_factory: new_handler,
1915};
1916wowlab_engine_combat::smoke_test!(build_combat_system);