Skip to main content

wowlab_engine_content/generated/specs/
demonology_warlock.rs

1//! @generated by codegen-cli from manifests/specs/warlock/demonology/manifest.toml -- do not edit by hand.
2// Generated code: naming follows game data conventions
3#![allow(non_snake_case, dead_code)]
4use wowlab_types::{combat::ResourceType, game::SpecId};
5use wowlab_engine_combat::{
6    BuiltCombatSystem, AuraDefinitionDraft, LocalAuraIdx, LocalSpellIdx,
7    SpellDefinitionDraft,
8};
9use wowlab_engine_ports::{
10    DeclaredSpecMetadata, SpecDescriptor, SpecHandler, HeroTalentTreeDesc,
11};
12use wowlab_engine_gamedata::ResolvedGameData;
13pub(crate) mod SPELL {
14    ///<https://wowlab.gg/inspect/spell/686>
15    pub(crate) const SHADOW_BOLT: u32 = 686;
16    ///<https://wowlab.gg/inspect/spell/264178>
17    pub(crate) const DEMONBOLT: u32 = 264_178;
18    ///<https://wowlab.gg/inspect/spell/105174>
19    pub(crate) const HAND_OF_GULDAN: u32 = 105_174;
20    ///<https://wowlab.gg/inspect/spell/264130>
21    pub(crate) const POWER_SIPHON: u32 = 264_130;
22    ///<https://wowlab.gg/inspect/spell/234153>
23    pub(crate) const DRAIN_LIFE: u32 = 234_153;
24    ///<https://wowlab.gg/inspect/spell/30146>
25    pub(crate) const SUMMON_FELGUARD: u32 = 30146;
26    ///<https://wowlab.gg/inspect/spell/691>
27    pub(crate) const SUMMON_FELHUNTER: u32 = 691;
28    ///<https://wowlab.gg/inspect/spell/688>
29    pub(crate) const SUMMON_IMP: u32 = 688;
30    ///<https://wowlab.gg/inspect/spell/104316>
31    pub(crate) const CALL_DREADSTALKERS: u32 = 104_316;
32    ///<https://wowlab.gg/inspect/spell/265187>
33    pub(crate) const SUMMON_DEMONIC_TYRANT: u32 = 265_187;
34    ///<https://wowlab.gg/inspect/spell/264119>
35    pub(crate) const SUMMON_VILEFIEND: u32 = 264_119;
36    ///<https://wowlab.gg/inspect/spell/196277>
37    pub(crate) const IMPLOSION: u32 = 196_277;
38    ///<https://wowlab.gg/inspect/spell/1276452>
39    pub(crate) const GRIMOIRE_IMP_LORD: u32 = 1_276_452;
40    ///<https://wowlab.gg/inspect/spell/1276467>
41    pub(crate) const GRIMOIRE_FEL_RAVAGER: u32 = 1_276_467;
42    ///<https://wowlab.gg/inspect/spell/1276672>
43    pub(crate) const SUMMON_DOOMGUARD: u32 = 1_276_672;
44    ///<https://wowlab.gg/inspect/spell/434506>
45    pub(crate) const INFERNAL_BOLT: u32 = 434_506;
46    ///<https://wowlab.gg/inspect/spell/434635>
47    pub(crate) const RUINATION: u32 = 434_635;
48}
49pub(crate) mod AURA {
50    ///<https://wowlab.gg/inspect/spell/264173>
51    pub(crate) const DEMONIC_CORE: u32 = 264_173;
52    ///<https://wowlab.gg/inspect/spell/386194>
53    pub(crate) const CARNIVOROUS_STALKERS_TALENT: u32 = 386_194;
54    ///<https://wowlab.gg/inspect/spell/334581>
55    pub(crate) const POWER_SIPHON: u32 = 334_581;
56    ///<https://wowlab.gg/inspect/spell/460553>
57    pub(crate) const DOOM: u32 = 460_553;
58    ///<https://wowlab.gg/inspect/spell/1276767>
59    pub(crate) const TYRANTS_OBLATION: u32 = 1_276_767;
60    ///<https://wowlab.gg/inspect/spell/1281559>
61    pub(crate) const HELLBENT_COMMANDER: u32 = 1_281_559;
62    ///<https://wowlab.gg/inspect/spell/267216>
63    pub(crate) const INNER_DEMONS: u32 = 267_216;
64    ///<https://wowlab.gg/inspect/spell/1276166>
65    pub(crate) const DOMINION_OF_ARGUS: u32 = 1_276_166;
66    ///<https://wowlab.gg/inspect/spell/449793>
67    pub(crate) const SUCCULENT_SOUL: u32 = 449_793;
68    ///<https://wowlab.gg/inspect/spell/1269042>
69    pub(crate) const MANIFESTED_DEMONIC_SOUL: u32 = 1_269_042;
70    ///<https://wowlab.gg/inspect/spell/196099>
71    pub(crate) const GRIMOIRE_OF_SACRIFICE: u32 = 196_099;
72    ///<https://wowlab.gg/inspect/spell/104317>
73    pub(crate) const WILD_IMPS: u32 = 104_317;
74    ///<https://wowlab.gg/inspect/spell/193332>
75    pub(crate) const DREADSTALKERS: u32 = 193_332;
76    ///<https://wowlab.gg/inspect/spell/462599>
77    pub(crate) const TRACK_PETS: u32 = 462_599;
78    ///<https://wowlab.gg/inspect/spell/453699>
79    pub(crate) const FLAMETOUCHED_TALENT: u32 = 453_699;
80    ///<https://wowlab.gg/inspect/spell/433891>
81    pub(crate) const INFERNAL_BOLT: u32 = 433_891;
82    ///<https://wowlab.gg/inspect/spell/433885>
83    pub(crate) const RUINATION: u32 = 433_885;
84    ///<https://wowlab.gg/inspect/spell/428514>
85    pub(crate) const DIABOLIC_RITUAL_TALENT: u32 = 428_514;
86    ///<https://wowlab.gg/inspect/spell/431944>
87    pub(crate) const DIABOLIC_RITUAL_OVERLORD: u32 = 431_944;
88    ///<https://wowlab.gg/inspect/spell/432815>
89    pub(crate) const DIABOLIC_RITUAL_MOTHER: u32 = 432_815;
90    ///<https://wowlab.gg/inspect/spell/432816>
91    pub(crate) const DIABOLIC_RITUAL_PIT_LORD: u32 = 432_816;
92    ///<https://wowlab.gg/inspect/spell/428524>
93    pub(crate) const DEMONIC_ART_OVERLORD: u32 = 428_524;
94    ///<https://wowlab.gg/inspect/spell/432794>
95    pub(crate) const DEMONIC_ART_MOTHER: u32 = 432_794;
96    ///<https://wowlab.gg/inspect/spell/432795>
97    pub(crate) const DEMONIC_ART_PIT_LORD: u32 = 432_795;
98    ///<https://wowlab.gg/inspect/spell/1269643>
99    pub(crate) const DEMONIC_OCULI: u32 = 1_269_643;
100    ///<https://wowlab.gg/inspect/spell/1268709>
101    pub(crate) const DIABOLIC_OCULI_TALENT: u32 = 1_268_709;
102    ///<https://wowlab.gg/inspect/spell/1268713>
103    pub(crate) const LOOKS_THAT_KILL_TALENT: u32 = 1_268_713;
104    ///<https://wowlab.gg/inspect/spell/1268716>
105    pub(crate) const MINDS_EYES_TALENT: u32 = 1_268_716;
106    ///<https://wowlab.gg/inspect/spell/1269879>
107    pub(crate) const MINDS_EYES: u32 = 1_269_879;
108    ///<https://wowlab.gg/inspect/spell/456323>
109    pub(crate) const ABYSSAL_DOMINION: u32 = 456_323;
110    ///<https://wowlab.gg/inspect/spell/429581>
111    pub(crate) const ABYSSAL_DOMINION_TALENT: u32 = 429_581;
112    ///<https://wowlab.gg/inspect/spell/434424>
113    pub(crate) const CLOVEN_SOUL: u32 = 434_424;
114}
115pub(crate) mod TALENT {
116    ///<https://wowlab.gg/inspect/spell/429581>
117    pub(crate) const ABYSSAL_DOMINION_TALENT: u32 = 429_581;
118    ///<https://wowlab.gg/inspect/spell/1250921>
119    pub(crate) const ANTORAN_ARMAMENTS: u32 = 1_250_921;
120    ///<https://wowlab.gg/inspect/spell/1276956>
121    pub(crate) const BLIGHTED_MAW: u32 = 1_276_956;
122    ///<https://wowlab.gg/inspect/spell/104316>
123    pub(crate) const CALL_DREADSTALKERS: u32 = 104_316;
124    ///<https://wowlab.gg/inspect/spell/386194>
125    pub(crate) const CARNIVOROUS_STALKERS: u32 = 386_194;
126    ///<https://wowlab.gg/inspect/spell/426115>
127    pub(crate) const DEMONIAC: u32 = 426_115;
128    ///<https://wowlab.gg/inspect/spell/453908>
129    pub(crate) const DEMONIC_BRUTALITY: u32 = 453_908;
130    ///<https://wowlab.gg/inspect/spell/1276947>
131    pub(crate) const DEMONIC_CALLING: u32 = 1_276_947;
132    ///<https://wowlab.gg/inspect/spell/386185>
133    pub(crate) const DEMONIC_KNOWLEDGE: u32 = 386_185;
134    ///<https://wowlab.gg/inspect/spell/1268709>
135    pub(crate) const DIABOLIC_OCULI: u32 = 1_268_709;
136    ///<https://wowlab.gg/inspect/spell/428514>
137    pub(crate) const DIABOLIC_RITUAL: u32 = 428_514;
138    ///<https://wowlab.gg/inspect/spell/1276163>
139    pub(crate) const DOMINION_OF_ARGUS: u32 = 1_276_163;
140    ///<https://wowlab.gg/inspect/spell/1276190>
141    pub(crate) const DOMINION_OF_ARGUS_2: u32 = 1_276_190;
142    ///<https://wowlab.gg/inspect/spell/1276222>
143    pub(crate) const DOMINION_OF_ARGUS_3: u32 = 1_276_222;
144    ///<https://wowlab.gg/inspect/spell/460551>
145    pub(crate) const DOOM: u32 = 460_551;
146    ///<https://wowlab.gg/inspect/spell/264078>
147    pub(crate) const DREADLASH: u32 = 264_078;
148    ///<https://wowlab.gg/inspect/spell/453699>
149    pub(crate) const FLAMETOUCHED: u32 = 453_699;
150    ///<https://wowlab.gg/inspect/spell/429899>
151    pub(crate) const GLOOM_OF_NATHREZA: u32 = 429_899;
152    ///<https://wowlab.gg/inspect/spell/1276467>
153    pub(crate) const GRIMOIRE_FEL_RAVAGER: u32 = 1_276_467;
154    ///<https://wowlab.gg/inspect/spell/1276452>
155    pub(crate) const GRIMOIRE_IMP_LORD: u32 = 1_276_452;
156    ///<https://wowlab.gg/inspect/spell/1250273>
157    pub(crate) const HAND_OF_GULDAN: u32 = 1_250_273;
158    ///<https://wowlab.gg/inspect/spell/1250897>
159    pub(crate) const HELLBENT_COMMANDER: u32 = 1_250_897;
160    ///<https://wowlab.gg/inspect/spell/196277>
161    pub(crate) const IMPLOSION: u32 = 196_277;
162    ///<https://wowlab.gg/inspect/spell/1250768>
163    pub(crate) const IMP_GANG_BOSS: u32 = 1_250_768;
164    ///<https://wowlab.gg/inspect/spell/1263941>
165    pub(crate) const INFERNAL_RAPIDITY: u32 = 1_263_941;
166    ///<https://wowlab.gg/inspect/spell/267216>
167    pub(crate) const INNER_DEMONS: u32 = 267_216;
168    ///<https://wowlab.gg/inspect/spell/1268713>
169    pub(crate) const LOOKS_THAT_KILL: u32 = 1_268_713;
170    ///<https://wowlab.gg/inspect/spell/455449>
171    pub(crate) const MARK_OF_SHATUG: u32 = 455_449;
172    ///<https://wowlab.gg/inspect/spell/1268716>
173    pub(crate) const MINDS_EYES: u32 = 1_268_716;
174    ///<https://wowlab.gg/inspect/spell/264130>
175    pub(crate) const POWER_SIPHON: u32 = 264_130;
176    ///<https://wowlab.gg/inspect/spell/1276748>
177    pub(crate) const REIGN_OF_TYRANNY: u32 = 1_276_748;
178    ///<https://wowlab.gg/inspect/spell/267214>
179    pub(crate) const SACRIFICED_SOULS: u32 = 267_214;
180    ///<https://wowlab.gg/inspect/spell/428394>
181    pub(crate) const SPITEFUL_RECONSTITUTION: u32 = 428_394;
182    ///<https://wowlab.gg/inspect/spell/265187>
183    pub(crate) const SUMMON_DEMONIC_TYRANT: u32 = 265_187;
184    ///<https://wowlab.gg/inspect/spell/1276672>
185    pub(crate) const SUMMON_DOOMGUARD: u32 = 1_276_672;
186    ///<https://wowlab.gg/inspect/spell/1251778>
187    pub(crate) const SUMMON_VILEFIEND: u32 = 1_251_778;
188    ///<https://wowlab.gg/inspect/spell/264119>
189    pub(crate) const SUMMON_VILEFIEND_CASTABLE: u32 = 264_119;
190    ///<https://wowlab.gg/inspect/spell/1281511>
191    pub(crate) const TO_HELL_AND_BACK: u32 = 1_281_511;
192    ///<https://wowlab.gg/inspect/spell/1276746>
193    pub(crate) const TYRANTS_OBLATION: u32 = 1_276_746;
194}
195pub(crate) mod SET_BONUS {
196    ///<https://wowlab.gg/inspect/spell/1264872>
197    pub(crate) const MID1_DEMONOLOGY_4PC: u32 = 1_264_872;
198}
199pub(crate) mod REPORTED_SPELL {
200    ///<https://wowlab.gg/inspect/spell/1276283>
201    pub(crate) const ANTORAN_INQUISITOR: u32 = 1_276_283;
202    ///<https://wowlab.gg/inspect/spell/1276182>
203    pub(crate) const ANTORAN_JAILER: u32 = 1_276_182;
204    ///<https://wowlab.gg/inspect/spell/267997>
205    pub(crate) const BILE_SPIT: u32 = 267_997;
206    ///<https://wowlab.gg/inspect/spell/1282534>
207    pub(crate) const BLAZE_MISSILE: u32 = 1_282_534;
208    ///<https://wowlab.gg/inspect/spell/1276960>
209    pub(crate) const BLIGHTED_MAW: u32 = 1_276_960;
210    ///<https://wowlab.gg/inspect/spell/1264093>
211    pub(crate) const BURNING_CLEAVE: u32 = 1_264_093;
212    ///<https://wowlab.gg/inspect/spell/432596>
213    pub(crate) const CHAOS_SALVO: u32 = 432_596;
214    ///<https://wowlab.gg/inspect/spell/1269892>
215    pub(crate) const DIABOLIC_GAZE_1: u32 = 1_269_892;
216    ///<https://wowlab.gg/inspect/spell/1269886>
217    pub(crate) const DIABOLIC_GAZE_2: u32 = 1_269_886;
218    ///<https://wowlab.gg/inspect/spell/1269885>
219    pub(crate) const DIABOLIC_GAZE_3: u32 = 1_269_885;
220    ///<https://wowlab.gg/inspect/spell/271971>
221    pub(crate) const DREADBITE: u32 = 271_971;
222    ///<https://wowlab.gg/inspect/spell/193332>
223    pub(crate) const DREADSTALKER_MELEE: u32 = 193_332;
224    ///<https://wowlab.gg/inspect/spell/1269800>
225    pub(crate) const EYE_EXPLOSION: u32 = 1_269_800;
226    ///<https://wowlab.gg/inspect/spell/434404>
227    pub(crate) const FELSEEKER: u32 = 434_404;
228    ///<https://wowlab.gg/inspect/spell/89753>
229    pub(crate) const FELSTORM: u32 = 89753;
230    ///<https://wowlab.gg/inspect/spell/104318>
231    pub(crate) const FEL_FIREBOLT: u32 = 104_318;
232    ///<https://wowlab.gg/inspect/spell/455491>
233    pub(crate) const GLOOM_SLASH: u32 = 455_491;
234    ///<https://wowlab.gg/inspect/spell/1282502>
235    pub(crate) const GRAND_WARLOCK_ALYTHESS: u32 = 1_282_502;
236    ///<https://wowlab.gg/inspect/spell/86040>
237    pub(crate) const HAND_OF_GULDAN_IMPACT: u32 = 86040;
238    ///<https://wowlab.gg/inspect/spell/267999>
239    pub(crate) const HEADBUTT: u32 = 267_999;
240    ///<https://wowlab.gg/inspect/spell/1282501>
241    pub(crate) const LADY_SACROLASH: u32 = 1_282_501;
242    ///<https://wowlab.gg/inspect/spell/30213>
243    pub(crate) const LEGION_STRIKE: u32 = 30213;
244    ///<https://wowlab.gg/inspect/spell/1280460>
245    pub(crate) const MIND_SEAR_CHANNEL: u32 = 1_280_460;
246    ///<https://wowlab.gg/inspect/spell/1282507>
247    pub(crate) const SHADOW_NOVA: u32 = 1_282_507;
248    ///<https://wowlab.gg/inspect/spell/1292391>
249    pub(crate) const SOUL_BARRAGE_CAST: u32 = 1_292_391;
250    ///<https://wowlab.gg/inspect/spell/1281512>
251    pub(crate) const UNSTABLE_GANG_BOSS: u32 = 1_281_512;
252    ///<https://wowlab.gg/inspect/spell/1251781>
253    pub(crate) const VILEFIEND: u32 = 1_251_781;
254    ///<https://wowlab.gg/inspect/spell/432120>
255    pub(crate) const WICKED_CLEAVE: u32 = 432_120;
256}
257pub(crate) mod HERO {
258    pub(crate) mod SOUL_HARVESTER {
259        pub(crate) mod SPELL {
260            ///<https://wowlab.gg/inspect/spell/449801>
261            pub(crate) const DEMONIC_SOUL_DAMAGE: u32 = 449_801;
262            ///<https://wowlab.gg/inspect/spell/449858>
263            pub(crate) const SHADOW_OF_DEATH_ENERGIZE: u32 = 449_858;
264            ///<https://wowlab.gg/inspect/spell/450591>
265            pub(crate) const SHARED_FATE: u32 = 450_591;
266            ///<https://wowlab.gg/inspect/spell/450538>
267            pub(crate) const SOUL_ANATHEMA: u32 = 450_538;
268            ///<https://wowlab.gg/inspect/spell/449826>
269            pub(crate) const WICKED_REAPING: u32 = 449_826;
270        }
271        pub(crate) mod AURA {
272            ///<https://wowlab.gg/inspect/spell/1269042>
273            pub(crate) const MANIFESTED_DEMONIC_SOUL: u32 = 1_269_042;
274            ///<https://wowlab.gg/inspect/spell/449793>
275            pub(crate) const SUCCULENT_SOUL: u32 = 449_793;
276        }
277    }
278    pub(crate) mod DIABOLIST {
279        pub(crate) mod SPELL {
280            ///<https://wowlab.gg/inspect/spell/434506>
281            pub(crate) const INFERNAL_BOLT: u32 = 434_506;
282            ///<https://wowlab.gg/inspect/spell/434635>
283            pub(crate) const RUINATION: u32 = 434_635;
284            ///<https://wowlab.gg/inspect/spell/434636>
285            pub(crate) const RUINATION_IMPACT: u32 = 434_636;
286        }
287        pub(crate) mod AURA {
288            ///<https://wowlab.gg/inspect/spell/456323>
289            pub(crate) const ABYSSAL_DOMINION: u32 = 456_323;
290            ///<https://wowlab.gg/inspect/spell/434424>
291            pub(crate) const CLOVEN_SOUL: u32 = 434_424;
292            ///<https://wowlab.gg/inspect/spell/432794>
293            pub(crate) const DEMONIC_ART_MOTHER: u32 = 432_794;
294            ///<https://wowlab.gg/inspect/spell/428524>
295            pub(crate) const DEMONIC_ART_OVERLORD: u32 = 428_524;
296            ///<https://wowlab.gg/inspect/spell/432795>
297            pub(crate) const DEMONIC_ART_PIT_LORD: u32 = 432_795;
298            ///<https://wowlab.gg/inspect/spell/1269643>
299            pub(crate) const DEMONIC_OCULI: u32 = 1_269_643;
300            ///<https://wowlab.gg/inspect/spell/432815>
301            pub(crate) const DIABOLIC_RITUAL_MOTHER: u32 = 432_815;
302            ///<https://wowlab.gg/inspect/spell/431944>
303            pub(crate) const DIABOLIC_RITUAL_OVERLORD: u32 = 431_944;
304            ///<https://wowlab.gg/inspect/spell/432816>
305            pub(crate) const DIABOLIC_RITUAL_PIT_LORD: u32 = 432_816;
306            ///<https://wowlab.gg/inspect/spell/433891>
307            pub(crate) const INFERNAL_BOLT_BUFF: u32 = 433_891;
308            ///<https://wowlab.gg/inspect/spell/1269879>
309            pub(crate) const MINDS_EYES: u32 = 1_269_879;
310            ///<https://wowlab.gg/inspect/spell/433885>
311            pub(crate) const RUINATION_BUFF: u32 = 433_885;
312        }
313    }
314}
315static HERO_TREE_SOUL_HARVESTER_SPELLS: &[(&str, u32)] = &[
316    ("DEMONIC_SOUL_DAMAGE", 449_801),
317    ("SHADOW_OF_DEATH_ENERGIZE", 449_858),
318    ("SHARED_FATE", 450_591),
319    ("SOUL_ANATHEMA", 450_538),
320    ("WICKED_REAPING", 449_826),
321];
322static HERO_TREE_SOUL_HARVESTER_AURAS: &[(&str, u32)] = &[
323    ("MANIFESTED_DEMONIC_SOUL", 1_269_042),
324    ("SUCCULENT_SOUL", 449_793),
325];
326static HERO_TREE_DIABOLIST_SPELLS: &[(&str, u32)] = &[
327    ("INFERNAL_BOLT", 434_506),
328    ("RUINATION", 434_635),
329    ("RUINATION_IMPACT", 434_636),
330];
331static HERO_TREE_DIABOLIST_AURAS: &[(&str, u32)] = &[
332    ("ABYSSAL_DOMINION", 456_323),
333    ("CLOVEN_SOUL", 434_424),
334    ("DEMONIC_ART_MOTHER", 432_794),
335    ("DEMONIC_ART_OVERLORD", 428_524),
336    ("DEMONIC_ART_PIT_LORD", 432_795),
337    ("DEMONIC_OCULI", 1_269_643),
338    ("DIABOLIC_RITUAL_MOTHER", 432_815),
339    ("DIABOLIC_RITUAL_OVERLORD", 431_944),
340    ("DIABOLIC_RITUAL_PIT_LORD", 432_816),
341    ("INFERNAL_BOLT_BUFF", 433_891),
342    ("MINDS_EYES", 1_269_879),
343    ("RUINATION_BUFF", 433_885),
344];
345pub(crate) const AURA_DEMONIC_CORE: LocalAuraIdx = LocalAuraIdx::new(0);
346pub(crate) const AURA_CARNIVOROUS_STALKERS_TALENT: LocalAuraIdx = LocalAuraIdx::new(1);
347pub(crate) const AURA_POWER_SIPHON: LocalAuraIdx = LocalAuraIdx::new(2);
348pub(crate) const AURA_DOOM: LocalAuraIdx = LocalAuraIdx::new(3);
349pub(crate) const AURA_TYRANTS_OBLATION: LocalAuraIdx = LocalAuraIdx::new(4);
350pub(crate) const AURA_HELLBENT_COMMANDER: LocalAuraIdx = LocalAuraIdx::new(5);
351pub(crate) const AURA_INNER_DEMONS: LocalAuraIdx = LocalAuraIdx::new(6);
352pub(crate) const AURA_DOMINION_OF_ARGUS: LocalAuraIdx = LocalAuraIdx::new(7);
353pub(crate) const AURA_SUCCULENT_SOUL: LocalAuraIdx = LocalAuraIdx::new(8);
354pub(crate) const AURA_MANIFESTED_DEMONIC_SOUL: LocalAuraIdx = LocalAuraIdx::new(9);
355pub(crate) const AURA_GRIMOIRE_OF_SACRIFICE: LocalAuraIdx = LocalAuraIdx::new(10);
356pub(crate) const AURA_WILD_IMPS: LocalAuraIdx = LocalAuraIdx::new(11);
357pub(crate) const AURA_DREADSTALKERS: LocalAuraIdx = LocalAuraIdx::new(12);
358pub(crate) const AURA_TRACK_PETS: LocalAuraIdx = LocalAuraIdx::new(13);
359pub(crate) const AURA_FLAMETOUCHED_TALENT: LocalAuraIdx = LocalAuraIdx::new(14);
360pub(crate) const AURA_INFERNAL_BOLT: LocalAuraIdx = LocalAuraIdx::new(15);
361pub(crate) const AURA_RUINATION: LocalAuraIdx = LocalAuraIdx::new(16);
362pub(crate) const AURA_DIABOLIC_RITUAL_TALENT: LocalAuraIdx = LocalAuraIdx::new(17);
363pub(crate) const AURA_DIABOLIC_RITUAL_OVERLORD: LocalAuraIdx = LocalAuraIdx::new(18);
364pub(crate) const AURA_DIABOLIC_RITUAL_MOTHER: LocalAuraIdx = LocalAuraIdx::new(19);
365pub(crate) const AURA_DIABOLIC_RITUAL_PIT_LORD: LocalAuraIdx = LocalAuraIdx::new(20);
366pub(crate) const AURA_DEMONIC_ART_OVERLORD: LocalAuraIdx = LocalAuraIdx::new(21);
367pub(crate) const AURA_DEMONIC_ART_MOTHER: LocalAuraIdx = LocalAuraIdx::new(22);
368pub(crate) const AURA_DEMONIC_ART_PIT_LORD: LocalAuraIdx = LocalAuraIdx::new(23);
369pub(crate) const AURA_DEMONIC_OCULI: LocalAuraIdx = LocalAuraIdx::new(24);
370pub(crate) const AURA_DIABOLIC_OCULI_TALENT: LocalAuraIdx = LocalAuraIdx::new(25);
371pub(crate) const AURA_LOOKS_THAT_KILL_TALENT: LocalAuraIdx = LocalAuraIdx::new(26);
372pub(crate) const AURA_MINDS_EYES_TALENT: LocalAuraIdx = LocalAuraIdx::new(27);
373pub(crate) const AURA_MINDS_EYES: LocalAuraIdx = LocalAuraIdx::new(28);
374pub(crate) const AURA_ABYSSAL_DOMINION: LocalAuraIdx = LocalAuraIdx::new(29);
375pub(crate) const AURA_ABYSSAL_DOMINION_TALENT: LocalAuraIdx = LocalAuraIdx::new(30);
376pub(crate) const AURA_CLOVEN_SOUL: LocalAuraIdx = LocalAuraIdx::new(31);
377pub(crate) const AURA_COUNT: usize = 32;
378const _: () = assert!(
379    AURA_COUNT == 32, "AURA index ABI: count changed -- update positional hook consumers"
380);
381pub(crate) const SPELL_SHADOW_BOLT: LocalSpellIdx = LocalSpellIdx::new(0);
382pub(crate) const SPELL_DEMONBOLT: LocalSpellIdx = LocalSpellIdx::new(1);
383pub(crate) const SPELL_HAND_OF_GULDAN: LocalSpellIdx = LocalSpellIdx::new(2);
384pub(crate) const SPELL_POWER_SIPHON: LocalSpellIdx = LocalSpellIdx::new(3);
385pub(crate) const SPELL_DRAIN_LIFE: LocalSpellIdx = LocalSpellIdx::new(4);
386pub(crate) const SPELL_SUMMON_FELGUARD: LocalSpellIdx = LocalSpellIdx::new(5);
387pub(crate) const SPELL_SUMMON_FELHUNTER: LocalSpellIdx = LocalSpellIdx::new(6);
388pub(crate) const SPELL_SUMMON_IMP: LocalSpellIdx = LocalSpellIdx::new(7);
389pub(crate) const SPELL_CALL_DREADSTALKERS: LocalSpellIdx = LocalSpellIdx::new(8);
390pub(crate) const SPELL_SUMMON_DEMONIC_TYRANT: LocalSpellIdx = LocalSpellIdx::new(9);
391pub(crate) const SPELL_SUMMON_VILEFIEND: LocalSpellIdx = LocalSpellIdx::new(10);
392pub(crate) const SPELL_IMPLOSION: LocalSpellIdx = LocalSpellIdx::new(11);
393pub(crate) const SPELL_GRIMOIRE_IMP_LORD: LocalSpellIdx = LocalSpellIdx::new(12);
394pub(crate) const SPELL_GRIMOIRE_FEL_RAVAGER: LocalSpellIdx = LocalSpellIdx::new(13);
395pub(crate) const SPELL_SUMMON_DOOMGUARD: LocalSpellIdx = LocalSpellIdx::new(14);
396pub(crate) const SPELL_INFERNAL_BOLT: LocalSpellIdx = LocalSpellIdx::new(15);
397pub(crate) const SPELL_RUINATION: LocalSpellIdx = LocalSpellIdx::new(16);
398pub(crate) const SPELL_COUNT: usize = 17;
399const _: () = assert!(
400    SPELL_COUNT == 17,
401    "SPELL index ABI: count changed -- update positional hook consumers"
402);
403pub(crate) mod EFFECT {
404    ///<https://wowlab.gg/inspect/spell/1264093>
405    pub(crate) const BURNING_CLEAVE: (u32, u8) = (1_264_093, 1);
406    ///<https://wowlab.gg/inspect/spell/104318>
407    pub(crate) const FEL_FIREBOLT_DAMAGE: (u32, u8) = (104_318, 1);
408    ///<https://wowlab.gg/inspect/spell/1282507>
409    pub(crate) const SHADOW_NOVA_DAMAGE: (u32, u8) = (1_282_507, 1);
410    ///<https://wowlab.gg/inspect/spell/1282534>
411    pub(crate) const BLAZE_MISSILE_DAMAGE: (u32, u8) = (1_282_534, 1);
412    ///<https://wowlab.gg/inspect/spell/1280460>
413    pub(crate) const MIND_SEAR_DAMAGE: (u32, u8) = (1_280_460, 2);
414    ///<https://wowlab.gg/inspect/spell/1292391>
415    pub(crate) const SOUL_BARRAGE_DAMAGE: (u32, u8) = (1_292_391, 1);
416    ///<https://wowlab.gg/inspect/spell/86040>
417    pub(crate) const HAND_OF_GULDAN_IMPACT_DAMAGE: (u32, u8) = (86040, 1);
418    ///<https://wowlab.gg/inspect/spell/267997>
419    pub(crate) const BILE_SPIT_DIRECT_DAMAGE: (u32, u8) = (267_997, 1);
420    ///<https://wowlab.gg/inspect/spell/267997>
421    pub(crate) const BILE_SPIT_TICK_DAMAGE: (u32, u8) = (267_997, 2);
422    ///<https://wowlab.gg/inspect/spell/267999>
423    pub(crate) const HEADBUTT_DAMAGE: (u32, u8) = (267_999, 1);
424    ///<https://wowlab.gg/inspect/spell/455491>
425    pub(crate) const GLOOM_SLASH_DAMAGE: (u32, u8) = (455_491, 1);
426    ///<https://wowlab.gg/inspect/spell/30213>
427    pub(crate) const LEGION_STRIKE_DAMAGE: (u32, u8) = (30213, 1);
428    ///<https://wowlab.gg/inspect/spell/89753>
429    pub(crate) const FELSTORM_DAMAGE: (u32, u8) = (89753, 1);
430    ///<https://wowlab.gg/inspect/spell/271971>
431    pub(crate) const DREADBITE_DAMAGE: (u32, u8) = (271_971, 1);
432    ///<https://wowlab.gg/inspect/spell/267102>
433    pub(crate) const DEMONIC_CORE_IMP_CHANCE: (u32, u8) = (267_102, 1);
434    ///<https://wowlab.gg/inspect/spell/432120>
435    pub(crate) const WICKED_CLEAVE_DAMAGE: (u32, u8) = (432_120, 1);
436    ///<https://wowlab.gg/inspect/spell/432596>
437    pub(crate) const CHAOS_SALVO_DAMAGE: (u32, u8) = (432_596, 1);
438    ///<https://wowlab.gg/inspect/spell/434404>
439    pub(crate) const FELSEEKER_DAMAGE: (u32, u8) = (434_404, 1);
440    ///<https://wowlab.gg/inspect/spell/1269800>
441    pub(crate) const EYE_EXPLOSION_DAMAGE: (u32, u8) = (1_269_800, 1);
442    ///<https://wowlab.gg/inspect/spell/1269892>
443    pub(crate) const DIABOLIC_GAZE_1_DAMAGE: (u32, u8) = (1_269_892, 1);
444    ///<https://wowlab.gg/inspect/spell/1269886>
445    pub(crate) const DIABOLIC_GAZE_2_DAMAGE: (u32, u8) = (1_269_886, 1);
446    ///<https://wowlab.gg/inspect/spell/1269885>
447    pub(crate) const DIABOLIC_GAZE_3_DAMAGE: (u32, u8) = (1_269_885, 1);
448}
449static REPORTED_SPELLS: &[(&str, u32)] = &[
450    ("antoran_inquisitor", 1_276_283),
451    ("antoran_jailer", 1_276_182),
452    ("bile_spit", 267_997),
453    ("blaze_missile", 1_282_534),
454    ("blighted_maw", 1_276_960),
455    ("burning_cleave", 1_264_093),
456    ("chaos_salvo", 432_596),
457    ("diabolic_gaze_1", 1_269_892),
458    ("diabolic_gaze_2", 1_269_886),
459    ("diabolic_gaze_3", 1_269_885),
460    ("dreadbite", 271_971),
461    ("dreadstalker_melee", 193_332),
462    ("eye_explosion", 1_269_800),
463    ("felseeker", 434_404),
464    ("felstorm", 89753),
465    ("fel_firebolt", 104_318),
466    ("gloom_slash", 455_491),
467    ("grand_warlock_alythess", 1_282_502),
468    ("hand_of_guldan_impact", 86040),
469    ("headbutt", 267_999),
470    ("lady_sacrolash", 1_282_501),
471    ("legion_strike", 30213),
472    ("mind_sear_channel", 1_280_460),
473    ("shadow_nova", 1_282_507),
474    ("soul_barrage_cast", 1_292_391),
475    ("unstable_gang_boss", 1_281_512),
476    ("vilefiend", 1_251_781),
477    ("wicked_cleave", 432_120),
478];
479static DECLARED_SPELL_IDS: &[u32] = &[
480    686, 264_178, 105_174, 264_130, 234_153, 30146, 691, 688, 104_316, 265_187, 264_119,
481    196_277, 1_276_452, 1_276_467, 1_276_672, 434_506, 434_635, 264_173, 386_194,
482    334_581, 460_553, 1_276_767, 1_281_559, 267_216, 1_276_166, 449_793, 1_269_042,
483    196_099, 104_317, 193_332, 462_599, 453_699, 433_891, 433_885, 428_514, 431_944,
484    432_815, 432_816, 428_524, 432_794, 432_795, 1_269_643, 1_268_709, 1_268_713,
485    1_268_716, 1_269_879, 456_323, 429_581, 434_424, 1, 30213, 77219, 86040, 89753,
486    104_318, 193_332, 267_102, 267_997, 267_999, 271_971, 432_120, 432_596, 434_404,
487    434_506, 455_491, 456_323, 1_251_781, 1_264_093, 1_269_800, 1_269_879, 1_269_885,
488    1_269_886, 1_269_892, 1_276_182, 1_276_283, 1_276_960, 1_280_460, 1_281_512,
489    1_282_501, 1_282_502, 1_282_507, 1_282_534, 1_292_391, 1_276_283, 1_276_182, 267_997,
490    1_282_534, 1_276_960, 1_264_093, 432_596, 1_269_892, 1_269_886, 1_269_885, 271_971,
491    193_332, 1_269_800, 434_404, 89753, 104_318, 455_491, 1_282_502, 86040, 267_999,
492    1_282_501, 30213, 1_280_460, 1_282_507, 1_292_391, 1_281_512, 1_251_781, 432_120,
493    449_801, 449_858, 450_591, 450_538, 449_826, 1_269_042, 449_793, 434_506, 434_635,
494    434_636, 456_323, 434_424, 432_794, 428_524, 432_795, 1_269_643, 432_815, 431_944,
495    432_816, 433_891, 1_269_879, 433_885,
496];
497static DECLARED_AURA_IDS: &[u32] = &[
498    264_173, 386_194, 334_581, 460_553, 1_276_767, 1_281_559, 267_216, 1_276_166,
499    449_793, 1_269_042, 196_099, 104_317, 193_332, 462_599, 453_699, 433_891, 433_885,
500    428_514, 431_944, 432_815, 432_816, 428_524, 432_794, 432_795, 1_269_643, 1_268_709,
501    1_268_713, 1_268_716, 1_269_879, 456_323, 429_581, 434_424, 1_269_042, 449_793,
502    456_323, 434_424, 432_794, 428_524, 432_795, 1_269_643, 432_815, 431_944, 432_816,
503    433_891, 1_269_879, 433_885,
504];
505static TALENTS: &[(&str, u32)] = &[
506    ("ABYSSAL_DOMINION_TALENT", TALENT::ABYSSAL_DOMINION_TALENT),
507    ("ANTORAN_ARMAMENTS", TALENT::ANTORAN_ARMAMENTS),
508    ("BLIGHTED_MAW", TALENT::BLIGHTED_MAW),
509    ("CALL_DREADSTALKERS", TALENT::CALL_DREADSTALKERS),
510    ("CARNIVOROUS_STALKERS", TALENT::CARNIVOROUS_STALKERS),
511    ("DEMONIAC", TALENT::DEMONIAC),
512    ("DEMONIC_BRUTALITY", TALENT::DEMONIC_BRUTALITY),
513    ("DEMONIC_CALLING", TALENT::DEMONIC_CALLING),
514    ("DEMONIC_KNOWLEDGE", TALENT::DEMONIC_KNOWLEDGE),
515    ("DIABOLIC_OCULI", TALENT::DIABOLIC_OCULI),
516    ("DIABOLIC_RITUAL", TALENT::DIABOLIC_RITUAL),
517    ("DOMINION_OF_ARGUS", TALENT::DOMINION_OF_ARGUS),
518    ("DOMINION_OF_ARGUS_2", TALENT::DOMINION_OF_ARGUS_2),
519    ("DOMINION_OF_ARGUS_3", TALENT::DOMINION_OF_ARGUS_3),
520    ("DOOM", TALENT::DOOM),
521    ("DREADLASH", TALENT::DREADLASH),
522    ("FLAMETOUCHED", TALENT::FLAMETOUCHED),
523    ("GLOOM_OF_NATHREZA", TALENT::GLOOM_OF_NATHREZA),
524    ("GRIMOIRE_FEL_RAVAGER", TALENT::GRIMOIRE_FEL_RAVAGER),
525    ("GRIMOIRE_IMP_LORD", TALENT::GRIMOIRE_IMP_LORD),
526    ("HAND_OF_GULDAN", TALENT::HAND_OF_GULDAN),
527    ("HELLBENT_COMMANDER", TALENT::HELLBENT_COMMANDER),
528    ("IMPLOSION", TALENT::IMPLOSION),
529    ("IMP_GANG_BOSS", TALENT::IMP_GANG_BOSS),
530    ("INFERNAL_RAPIDITY", TALENT::INFERNAL_RAPIDITY),
531    ("INNER_DEMONS", TALENT::INNER_DEMONS),
532    ("LOOKS_THAT_KILL", TALENT::LOOKS_THAT_KILL),
533    ("MARK_OF_SHATUG", TALENT::MARK_OF_SHATUG),
534    ("MINDS_EYES", TALENT::MINDS_EYES),
535    ("POWER_SIPHON", TALENT::POWER_SIPHON),
536    ("REIGN_OF_TYRANNY", TALENT::REIGN_OF_TYRANNY),
537    ("SACRIFICED_SOULS", TALENT::SACRIFICED_SOULS),
538    ("SPITEFUL_RECONSTITUTION", TALENT::SPITEFUL_RECONSTITUTION),
539    ("SUMMON_DEMONIC_TYRANT", TALENT::SUMMON_DEMONIC_TYRANT),
540    ("SUMMON_DOOMGUARD", TALENT::SUMMON_DOOMGUARD),
541    ("SUMMON_VILEFIEND", TALENT::SUMMON_VILEFIEND),
542    ("SUMMON_VILEFIEND_CASTABLE", TALENT::SUMMON_VILEFIEND_CASTABLE),
543    ("TO_HELL_AND_BACK", TALENT::TO_HELL_AND_BACK),
544    ("TYRANTS_OBLATION", TALENT::TYRANTS_OBLATION),
545];
546pub(crate) mod DEMONOLOGY_WARLOCK {
547    pub(crate) const SHADOW_BOLT_CASTS: u32 = 0;
548    pub(crate) const DEMONBOLT_CASTS: u32 = 1;
549    pub(crate) const HAND_OF_GULDAN_CASTS: u32 = 2;
550    pub(crate) const CALL_DREADSTALKERS_CASTS: u32 = 3;
551    pub(crate) const SUMMON_DEMONIC_TYRANT_CASTS: u32 = 4;
552    pub(crate) const POWER_SIPHON_CASTS: u32 = 5;
553    pub(crate) const DEMONIC_CORE_UPTIME_MS: u32 = 6;
554    pub(crate) const TYRANT_UPTIME_MS: u32 = 7;
555}
556fn aura_demonic_core(
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, 264_173)?
564            .max_stacks(
565                data
566                    .require_aura_max_stacks(
567                        wowlab_types::sim::SpellIdx::from_raw(264_173),
568                    )?,
569            ),
570    )
571}
572fn aura_carnivorous_stalkers_talent(
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, 386_194)?
580            .max_stacks(
581                data
582                    .require_aura_max_stacks(
583                        wowlab_types::sim::SpellIdx::from_raw(386_194),
584                    )?,
585            ),
586    )
587}
588fn aura_power_siphon(
589    a: AuraDefinitionDraft,
590    data: &ResolvedGameData,
591) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
592    a.on_player()
593        .apply_base_from_data(data, 334_581)?
594        .max_stacks(
595            data.require_aura_max_stacks(wowlab_types::sim::SpellIdx::from_raw(334_581))?,
596        )
597        .damage_percent_spells_linear(30.0, &[264_178])
598}
599fn aura_doom(
600    a: AuraDefinitionDraft,
601    data: &ResolvedGameData,
602) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
603    Ok(
604        a
605            .on_target()
606            .apply_base_from_data(data, 460_553)?
607            .max_stacks(
608                data
609                    .require_aura_max_stacks(
610                        wowlab_types::sim::SpellIdx::from_raw(460_553),
611                    )?,
612            ),
613    )
614}
615fn aura_tyrants_oblation(
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, 1_276_767)?
623            .max_stacks(
624                data
625                    .require_aura_max_stacks(
626                        wowlab_types::sim::SpellIdx::from_raw(1_276_767),
627                    )?,
628            ),
629    )
630}
631fn aura_hellbent_commander(
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, 1_281_559)?
639            .max_stacks(
640                data
641                    .require_aura_max_stacks(
642                        wowlab_types::sim::SpellIdx::from_raw(1_281_559),
643                    )?,
644            ),
645    )
646}
647fn aura_inner_demons(
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, 267_216)?
655            .max_stacks(
656                data
657                    .require_aura_max_stacks(
658                        wowlab_types::sim::SpellIdx::from_raw(267_216),
659                    )?,
660            ),
661    )
662}
663fn aura_dominion_of_argus(
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_276_166)?
671            .max_stacks(
672                data
673                    .require_aura_max_stacks(
674                        wowlab_types::sim::SpellIdx::from_raw(1_276_166),
675                    )?,
676            ),
677    )
678}
679fn aura_succulent_soul(
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, 449_793)?
687            .max_stacks(
688                data
689                    .require_aura_max_stacks(
690                        wowlab_types::sim::SpellIdx::from_raw(449_793),
691                    )?,
692            ),
693    )
694}
695fn aura_manifested_demonic_soul(
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, 1_269_042)?
703            .max_stacks(
704                data
705                    .require_aura_max_stacks(
706                        wowlab_types::sim::SpellIdx::from_raw(1_269_042),
707                    )?,
708            ),
709    )
710}
711fn aura_grimoire_of_sacrifice(
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, 196_099)?
719            .max_stacks(
720                data
721                    .require_aura_max_stacks(
722                        wowlab_types::sim::SpellIdx::from_raw(196_099),
723                    )?,
724            ),
725    )
726}
727fn aura_wild_imps(
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, 104_317)?
735            .max_stacks(
736                data
737                    .require_aura_max_stacks(
738                        wowlab_types::sim::SpellIdx::from_raw(104_317),
739                    )?,
740            ),
741    )
742}
743fn aura_dreadstalkers(
744    a: AuraDefinitionDraft,
745    data: &ResolvedGameData,
746) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
747    Ok(
748        a
749            .on_player()
750            .apply_base_from_data(data, 193_332)?
751            .max_stacks(
752                data
753                    .require_aura_max_stacks(
754                        wowlab_types::sim::SpellIdx::from_raw(193_332),
755                    )?,
756            ),
757    )
758}
759fn aura_track_pets(
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, 462_599)?
767            .max_stacks(
768                data
769                    .require_aura_max_stacks(
770                        wowlab_types::sim::SpellIdx::from_raw(462_599),
771                    )?,
772            ),
773    )
774}
775fn aura_flametouched_talent(
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, 453_699)?
783            .max_stacks(
784                data
785                    .require_aura_max_stacks(
786                        wowlab_types::sim::SpellIdx::from_raw(453_699),
787                    )?,
788            ),
789    )
790}
791fn aura_infernal_bolt(
792    a: AuraDefinitionDraft,
793    data: &ResolvedGameData,
794) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
795    Ok(
796        a
797            .on_player()
798            .apply_base_from_data(data, 433_891)?
799            .max_stacks(
800                data
801                    .require_aura_max_stacks(
802                        wowlab_types::sim::SpellIdx::from_raw(433_891),
803                    )?,
804            ),
805    )
806}
807fn aura_ruination(
808    a: AuraDefinitionDraft,
809    data: &ResolvedGameData,
810) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
811    Ok(
812        a
813            .on_player()
814            .apply_base_from_data(data, 433_885)?
815            .max_stacks(
816                data
817                    .require_aura_max_stacks(
818                        wowlab_types::sim::SpellIdx::from_raw(433_885),
819                    )?,
820            ),
821    )
822}
823fn aura_diabolic_ritual_talent(
824    a: AuraDefinitionDraft,
825    data: &ResolvedGameData,
826) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
827    Ok(
828        a
829            .on_player()
830            .apply_base_from_data(data, 428_514)?
831            .max_stacks(
832                data
833                    .require_aura_max_stacks(
834                        wowlab_types::sim::SpellIdx::from_raw(428_514),
835                    )?,
836            ),
837    )
838}
839fn aura_diabolic_ritual_overlord(
840    a: AuraDefinitionDraft,
841    data: &ResolvedGameData,
842) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
843    Ok(
844        a
845            .on_player()
846            .apply_base_from_data(data, 431_944)?
847            .max_stacks(
848                data
849                    .require_aura_max_stacks(
850                        wowlab_types::sim::SpellIdx::from_raw(431_944),
851                    )?,
852            )
853            .on_expire(
854                crate::hooks::demonology_warlock::demonology_diabolic_ritual_overlord_expire_hook,
855            ),
856    )
857}
858fn aura_diabolic_ritual_mother(
859    a: AuraDefinitionDraft,
860    data: &ResolvedGameData,
861) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
862    Ok(
863        a
864            .on_player()
865            .apply_base_from_data(data, 432_815)?
866            .max_stacks(
867                data
868                    .require_aura_max_stacks(
869                        wowlab_types::sim::SpellIdx::from_raw(432_815),
870                    )?,
871            )
872            .on_expire(
873                crate::hooks::demonology_warlock::demonology_diabolic_ritual_mother_expire_hook,
874            ),
875    )
876}
877fn aura_diabolic_ritual_pit_lord(
878    a: AuraDefinitionDraft,
879    data: &ResolvedGameData,
880) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
881    Ok(
882        a
883            .on_player()
884            .apply_base_from_data(data, 432_816)?
885            .max_stacks(
886                data
887                    .require_aura_max_stacks(
888                        wowlab_types::sim::SpellIdx::from_raw(432_816),
889                    )?,
890            )
891            .on_expire(
892                crate::hooks::demonology_warlock::demonology_diabolic_ritual_pit_lord_expire_hook,
893            ),
894    )
895}
896fn aura_demonic_art_overlord(
897    a: AuraDefinitionDraft,
898    data: &ResolvedGameData,
899) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
900    Ok(
901        a
902            .on_player()
903            .apply_base_from_data(data, 428_524)?
904            .max_stacks(
905                data
906                    .require_aura_max_stacks(
907                        wowlab_types::sim::SpellIdx::from_raw(428_524),
908                    )?,
909            )
910            .on_expire(
911                crate::hooks::demonology_warlock::demonology_demonic_art_overlord_expire_hook,
912            ),
913    )
914}
915fn aura_demonic_art_mother(
916    a: AuraDefinitionDraft,
917    data: &ResolvedGameData,
918) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
919    Ok(
920        a
921            .on_player()
922            .apply_base_from_data(data, 432_794)?
923            .max_stacks(
924                data
925                    .require_aura_max_stacks(
926                        wowlab_types::sim::SpellIdx::from_raw(432_794),
927                    )?,
928            )
929            .on_expire(
930                crate::hooks::demonology_warlock::demonology_demonic_art_mother_expire_hook,
931            ),
932    )
933}
934fn aura_demonic_art_pit_lord(
935    a: AuraDefinitionDraft,
936    data: &ResolvedGameData,
937) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
938    Ok(
939        a
940            .on_player()
941            .apply_base_from_data(data, 432_795)?
942            .max_stacks(
943                data
944                    .require_aura_max_stacks(
945                        wowlab_types::sim::SpellIdx::from_raw(432_795),
946                    )?,
947            )
948            .on_expire(
949                crate::hooks::demonology_warlock::demonology_demonic_art_pit_lord_expire_hook,
950            ),
951    )
952}
953fn aura_demonic_oculi(
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, 1_269_643)?
961            .max_stacks(
962                data
963                    .require_aura_max_stacks(
964                        wowlab_types::sim::SpellIdx::from_raw(1_269_643),
965                    )?,
966            ),
967    )
968}
969fn aura_diabolic_oculi_talent(
970    a: AuraDefinitionDraft,
971    data: &ResolvedGameData,
972) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
973    Ok(
974        a
975            .on_player()
976            .apply_base_from_data(data, 1_268_709)?
977            .max_stacks(
978                data
979                    .require_aura_max_stacks(
980                        wowlab_types::sim::SpellIdx::from_raw(1_268_709),
981                    )?,
982            ),
983    )
984}
985fn aura_looks_that_kill_talent(
986    a: AuraDefinitionDraft,
987    data: &ResolvedGameData,
988) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
989    Ok(
990        a
991            .on_player()
992            .apply_base_from_data(data, 1_268_713)?
993            .max_stacks(
994                data
995                    .require_aura_max_stacks(
996                        wowlab_types::sim::SpellIdx::from_raw(1_268_713),
997                    )?,
998            ),
999    )
1000}
1001fn aura_minds_eyes_talent(
1002    a: AuraDefinitionDraft,
1003    data: &ResolvedGameData,
1004) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
1005    Ok(
1006        a
1007            .on_player()
1008            .apply_base_from_data(data, 1_268_716)?
1009            .max_stacks(
1010                data
1011                    .require_aura_max_stacks(
1012                        wowlab_types::sim::SpellIdx::from_raw(1_268_716),
1013                    )?,
1014            ),
1015    )
1016}
1017fn aura_minds_eyes(
1018    a: AuraDefinitionDraft,
1019    data: &ResolvedGameData,
1020) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
1021    a.on_player()
1022        .apply_base_from_data(data, 1_269_879)?
1023        .max_stacks(
1024            data
1025                .require_aura_max_stacks(
1026                    wowlab_types::sim::SpellIdx::from_raw(1_269_879),
1027                )?,
1028        )
1029        .primary_pct_per_stack(
1030            data.base_points(wowlab_types::sim::SpellIdx::from_raw(1_269_879), 1),
1031        )
1032}
1033fn aura_abyssal_dominion(
1034    a: AuraDefinitionDraft,
1035    data: &ResolvedGameData,
1036) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
1037    a.on_player()
1038        .apply_base_from_data(data, 456_323)?
1039        .max_stacks(
1040            data.require_aura_max_stacks(wowlab_types::sim::SpellIdx::from_raw(456_323))?,
1041        )
1042        .pet_damage_multiplier(
1043            ((data.base_points(wowlab_types::sim::SpellIdx::from_raw(456_323), 1))
1044                * 0.01) + 1.0,
1045        )
1046}
1047fn aura_abyssal_dominion_talent(
1048    a: AuraDefinitionDraft,
1049    data: &ResolvedGameData,
1050) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
1051    Ok(
1052        a
1053            .on_player()
1054            .apply_base_from_data(data, 429_581)?
1055            .max_stacks(
1056                data
1057                    .require_aura_max_stacks(
1058                        wowlab_types::sim::SpellIdx::from_raw(429_581),
1059                    )?,
1060            ),
1061    )
1062}
1063fn aura_cloven_soul(
1064    a: AuraDefinitionDraft,
1065    data: &ResolvedGameData,
1066) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
1067    Ok(
1068        a
1069            .on_target()
1070            .apply_base_from_data(data, 434_424)?
1071            .max_stacks(
1072                data
1073                    .require_aura_max_stacks(
1074                        wowlab_types::sim::SpellIdx::from_raw(434_424),
1075                    )?,
1076            ),
1077    )
1078}
1079fn spell_shadow_bolt(
1080    s: SpellDefinitionDraft,
1081    data: &ResolvedGameData,
1082) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1083    Ok(s.apply_base_from_data(data, 686)?.gain(1.0).apply_aoe_from_data(data))
1084}
1085fn spell_demonbolt(
1086    s: SpellDefinitionDraft,
1087    data: &ResolvedGameData,
1088) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1089    Ok(
1090        s
1091            .apply_base_from_data(data, 264_178)?
1092            .gain(2.0)
1093            .apply_aoe_from_data(data)
1094            .on_cast(crate::hooks::demonology_warlock::demonbolt_hook)
1095            .instant_when_aura(AURA::DEMONIC_CORE),
1096    )
1097}
1098fn spell_hand_of_guldan(
1099    s: SpellDefinitionDraft,
1100    data: &ResolvedGameData,
1101) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1102    Ok(
1103        s
1104            .apply_base_from_data(data, 105_174)?
1105            .apply_aoe_from_data(data)
1106            .on_cast(crate::hooks::demonology_warlock::hand_of_guldan_hook),
1107    )
1108}
1109fn spell_power_siphon(
1110    s: SpellDefinitionDraft,
1111    data: &ResolvedGameData,
1112) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1113    Ok(
1114        s
1115            .apply_base_from_data(data, 264_130)?
1116            .applies_inferred_aura(AURA_POWER_SIPHON, 334_581)
1117            .apply_aoe_from_data(data)
1118            .on_cast(crate::hooks::demonology_warlock::power_siphon_hook),
1119    )
1120}
1121fn spell_drain_life(
1122    s: SpellDefinitionDraft,
1123    data: &ResolvedGameData,
1124) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1125    Ok(s.apply_base_from_data(data, 234_153)?.apply_aoe_from_data(data))
1126}
1127fn spell_summon_felguard(
1128    s: SpellDefinitionDraft,
1129    data: &ResolvedGameData,
1130) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1131    Ok(s.apply_base_from_data(data, 30146)?.apply_aoe_from_data(data))
1132}
1133fn spell_summon_felhunter(
1134    s: SpellDefinitionDraft,
1135    data: &ResolvedGameData,
1136) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1137    Ok(s.apply_base_from_data(data, 691)?.apply_aoe_from_data(data))
1138}
1139fn spell_summon_imp(
1140    s: SpellDefinitionDraft,
1141    data: &ResolvedGameData,
1142) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1143    Ok(s.apply_base_from_data(data, 688)?.apply_aoe_from_data(data))
1144}
1145fn spell_call_dreadstalkers(
1146    s: SpellDefinitionDraft,
1147    data: &ResolvedGameData,
1148) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1149    Ok(
1150        s
1151            .apply_base_from_data(data, 104_316)?
1152            .apply_aoe_from_data(data)
1153            .on_cast(crate::hooks::demonology_warlock::call_dreadstalkers_hook),
1154    )
1155}
1156fn spell_summon_demonic_tyrant(
1157    s: SpellDefinitionDraft,
1158    data: &ResolvedGameData,
1159) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1160    Ok(
1161        s
1162            .apply_base_from_data(data, 265_187)?
1163            .apply_aoe_from_data(data)
1164            .on_cast(crate::hooks::demonology_warlock::summon_demonic_tyrant_hook),
1165    )
1166}
1167fn spell_summon_vilefiend(
1168    s: SpellDefinitionDraft,
1169    data: &ResolvedGameData,
1170) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1171    Ok(s.apply_base_from_data(data, 264_119)?.apply_aoe_from_data(data))
1172}
1173fn spell_implosion(
1174    s: SpellDefinitionDraft,
1175    data: &ResolvedGameData,
1176) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1177    Ok(s.apply_base_from_data(data, 196_277)?.apply_aoe_from_data(data))
1178}
1179fn spell_grimoire_imp_lord(
1180    s: SpellDefinitionDraft,
1181    data: &ResolvedGameData,
1182) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1183    Ok(s.apply_base_from_data(data, 1_276_452)?.apply_aoe_from_data(data))
1184}
1185fn spell_grimoire_fel_ravager(
1186    s: SpellDefinitionDraft,
1187    data: &ResolvedGameData,
1188) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1189    Ok(s.apply_base_from_data(data, 1_276_467)?.apply_aoe_from_data(data))
1190}
1191fn spell_summon_doomguard(
1192    s: SpellDefinitionDraft,
1193    data: &ResolvedGameData,
1194) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1195    Ok(s.apply_base_from_data(data, 1_276_672)?.apply_aoe_from_data(data))
1196}
1197fn spell_infernal_bolt(
1198    s: SpellDefinitionDraft,
1199    data: &ResolvedGameData,
1200) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1201    Ok(
1202        s
1203            .apply_base_from_data(data, 434_506)?
1204            .gain(
1205                (data.base_points(wowlab_types::sim::SpellIdx::from_raw(434_506), 2))
1206                    * 0.1,
1207            )
1208            .apply_aoe_from_data(data)
1209            .requires_aura_at_min_stacks(433_891, 0)
1210            .consume_aura_on_cast(433_891),
1211    )
1212}
1213fn spell_ruination(
1214    s: SpellDefinitionDraft,
1215    data: &ResolvedGameData,
1216) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1217    Ok(
1218        s
1219            .apply_base_from_data(data, 434_635)?
1220            .travel_time(
1221                wowlab_engine_combat::validated_milliseconds(
1222                    1000.0,
1223                    434_635,
1224                    "spell.travel_time_ms",
1225                )?,
1226            )
1227            .apply_aoe_from_data(data)
1228            .on_cast(crate::hooks::demonology_warlock::ruination_hook)
1229            .requires_aura_at_min_stacks(433_885, 0)
1230            .consume_aura_on_cast(433_885),
1231    )
1232}
1233pub(crate) fn build_combat_system(
1234    params: &wowlab_engine_ports::HandlerParams<'_>,
1235) -> Result<BuiltCombatSystem, wowlab_engine_ports::EngineError> {
1236    let builder = BuiltCombatSystem::builder(params.stats.clone())
1237        .spec_id(SpecId::Demonology)
1238        .hero_talent_trees(DECLARED_METADATA.hero_talent_trees)
1239        .mastery_spell(77219)
1240        .mastery_hook(crate::hooks::demonology_warlock::mastery)
1241        .resource(
1242            "soul_shards",
1243            5.0,
1244            params
1245                .game_data
1246                .power_regen_for_max(7, 5.0)
1247                .ok_or_else(|| {
1248                    wowlab_engine_ports::EngineError::spec_construction(
1249                        "missing power-type power_regen_for_max for type_id 7",
1250                    )
1251                })?,
1252        )
1253        .resource_type_id(7)
1254        .resource_start(3.0)
1255        .mastery_crit_damage_hook(crate::hooks::demonology_warlock::crit_damage)
1256        .has_pet(true)
1257        .aura(
1258            "demonic_core",
1259            AURA::DEMONIC_CORE,
1260            |a| aura_demonic_core(a, &params.game_data),
1261        )
1262        .aura(
1263            "carnivorous_stalkers_talent",
1264            AURA::CARNIVOROUS_STALKERS_TALENT,
1265            |a| aura_carnivorous_stalkers_talent(a, &params.game_data),
1266        )
1267        .aura(
1268            "power_siphon",
1269            AURA::POWER_SIPHON,
1270            |a| aura_power_siphon(a, &params.game_data),
1271        )
1272        .aura("doom", AURA::DOOM, |a| aura_doom(a, &params.game_data))
1273        .aura(
1274            "tyrants_oblation",
1275            AURA::TYRANTS_OBLATION,
1276            |a| aura_tyrants_oblation(a, &params.game_data),
1277        )
1278        .aura(
1279            "hellbent_commander",
1280            AURA::HELLBENT_COMMANDER,
1281            |a| aura_hellbent_commander(a, &params.game_data),
1282        )
1283        .aura(
1284            "inner_demons",
1285            AURA::INNER_DEMONS,
1286            |a| aura_inner_demons(a, &params.game_data),
1287        )
1288        .aura(
1289            "dominion_of_argus",
1290            AURA::DOMINION_OF_ARGUS,
1291            |a| aura_dominion_of_argus(a, &params.game_data),
1292        )
1293        .aura(
1294            "succulent_soul",
1295            AURA::SUCCULENT_SOUL,
1296            |a| aura_succulent_soul(a, &params.game_data),
1297        )
1298        .aura(
1299            "manifested_demonic_soul",
1300            AURA::MANIFESTED_DEMONIC_SOUL,
1301            |a| aura_manifested_demonic_soul(a, &params.game_data),
1302        )
1303        .aura(
1304            "grimoire_of_sacrifice",
1305            AURA::GRIMOIRE_OF_SACRIFICE,
1306            |a| aura_grimoire_of_sacrifice(a, &params.game_data),
1307        )
1308        .aura("wild_imps", AURA::WILD_IMPS, |a| aura_wild_imps(a, &params.game_data))
1309        .aura(
1310            "dreadstalkers",
1311            AURA::DREADSTALKERS,
1312            |a| aura_dreadstalkers(a, &params.game_data),
1313        )
1314        .aura("track_pets", AURA::TRACK_PETS, |a| aura_track_pets(a, &params.game_data))
1315        .aura(
1316            "flametouched_talent",
1317            AURA::FLAMETOUCHED_TALENT,
1318            |a| aura_flametouched_talent(a, &params.game_data),
1319        )
1320        .aura(
1321            "infernal_bolt",
1322            AURA::INFERNAL_BOLT,
1323            |a| aura_infernal_bolt(a, &params.game_data),
1324        )
1325        .aura("ruination", AURA::RUINATION, |a| aura_ruination(a, &params.game_data))
1326        .aura(
1327            "diabolic_ritual_talent",
1328            AURA::DIABOLIC_RITUAL_TALENT,
1329            |a| aura_diabolic_ritual_talent(a, &params.game_data),
1330        )
1331        .aura(
1332            "diabolic_ritual_overlord",
1333            AURA::DIABOLIC_RITUAL_OVERLORD,
1334            |a| aura_diabolic_ritual_overlord(a, &params.game_data),
1335        )
1336        .aura(
1337            "diabolic_ritual_mother",
1338            AURA::DIABOLIC_RITUAL_MOTHER,
1339            |a| aura_diabolic_ritual_mother(a, &params.game_data),
1340        )
1341        .aura(
1342            "diabolic_ritual_pit_lord",
1343            AURA::DIABOLIC_RITUAL_PIT_LORD,
1344            |a| aura_diabolic_ritual_pit_lord(a, &params.game_data),
1345        )
1346        .aura(
1347            "demonic_art_overlord",
1348            AURA::DEMONIC_ART_OVERLORD,
1349            |a| aura_demonic_art_overlord(a, &params.game_data),
1350        )
1351        .aura(
1352            "demonic_art_mother",
1353            AURA::DEMONIC_ART_MOTHER,
1354            |a| aura_demonic_art_mother(a, &params.game_data),
1355        )
1356        .aura(
1357            "demonic_art_pit_lord",
1358            AURA::DEMONIC_ART_PIT_LORD,
1359            |a| aura_demonic_art_pit_lord(a, &params.game_data),
1360        )
1361        .aura(
1362            "demonic_oculi",
1363            AURA::DEMONIC_OCULI,
1364            |a| aura_demonic_oculi(a, &params.game_data),
1365        )
1366        .aura(
1367            "diabolic_oculi_talent",
1368            AURA::DIABOLIC_OCULI_TALENT,
1369            |a| aura_diabolic_oculi_talent(a, &params.game_data),
1370        )
1371        .aura(
1372            "looks_that_kill_talent",
1373            AURA::LOOKS_THAT_KILL_TALENT,
1374            |a| aura_looks_that_kill_talent(a, &params.game_data),
1375        )
1376        .aura(
1377            "minds_eyes_talent",
1378            AURA::MINDS_EYES_TALENT,
1379            |a| aura_minds_eyes_talent(a, &params.game_data),
1380        )
1381        .aura("minds_eyes", AURA::MINDS_EYES, |a| aura_minds_eyes(a, &params.game_data))
1382        .aura(
1383            "abyssal_dominion",
1384            AURA::ABYSSAL_DOMINION,
1385            |a| aura_abyssal_dominion(a, &params.game_data),
1386        )
1387        .aura(
1388            "abyssal_dominion_talent",
1389            AURA::ABYSSAL_DOMINION_TALENT,
1390            |a| aura_abyssal_dominion_talent(a, &params.game_data),
1391        )
1392        .aura(
1393            "cloven_soul",
1394            AURA::CLOVEN_SOUL,
1395            |a| aura_cloven_soul(a, &params.game_data),
1396        )
1397        .spell(
1398            "shadow_bolt",
1399            SPELL::SHADOW_BOLT,
1400            |s| spell_shadow_bolt(s, &params.game_data),
1401        )
1402        .spell("demonbolt", SPELL::DEMONBOLT, |s| spell_demonbolt(s, &params.game_data))
1403        .spell(
1404            "hand_of_guldan",
1405            SPELL::HAND_OF_GULDAN,
1406            |s| spell_hand_of_guldan(s, &params.game_data),
1407        )
1408        .spell(
1409            "power_siphon",
1410            SPELL::POWER_SIPHON,
1411            |s| spell_power_siphon(s, &params.game_data),
1412        )
1413        .spell(
1414            "drain_life",
1415            SPELL::DRAIN_LIFE,
1416            |s| spell_drain_life(s, &params.game_data),
1417        )
1418        .spell(
1419            "summon_felguard",
1420            SPELL::SUMMON_FELGUARD,
1421            |s| spell_summon_felguard(s, &params.game_data),
1422        )
1423        .spell(
1424            "summon_felhunter",
1425            SPELL::SUMMON_FELHUNTER,
1426            |s| spell_summon_felhunter(s, &params.game_data),
1427        )
1428        .spell(
1429            "summon_imp",
1430            SPELL::SUMMON_IMP,
1431            |s| spell_summon_imp(s, &params.game_data),
1432        )
1433        .spell(
1434            "call_dreadstalkers",
1435            SPELL::CALL_DREADSTALKERS,
1436            |s| spell_call_dreadstalkers(s, &params.game_data),
1437        )
1438        .spell(
1439            "summon_demonic_tyrant",
1440            SPELL::SUMMON_DEMONIC_TYRANT,
1441            |s| spell_summon_demonic_tyrant(s, &params.game_data),
1442        )
1443        .spell(
1444            "summon_vilefiend",
1445            SPELL::SUMMON_VILEFIEND,
1446            |s| spell_summon_vilefiend(s, &params.game_data),
1447        )
1448        .spell("implosion", SPELL::IMPLOSION, |s| spell_implosion(s, &params.game_data))
1449        .spell(
1450            "grimoire_imp_lord",
1451            SPELL::GRIMOIRE_IMP_LORD,
1452            |s| spell_grimoire_imp_lord(s, &params.game_data),
1453        )
1454        .spell(
1455            "grimoire_fel_ravager",
1456            SPELL::GRIMOIRE_FEL_RAVAGER,
1457            |s| spell_grimoire_fel_ravager(s, &params.game_data),
1458        )
1459        .spell(
1460            "summon_doomguard",
1461            SPELL::SUMMON_DOOMGUARD,
1462            |s| spell_summon_doomguard(s, &params.game_data),
1463        )
1464        .spell(
1465            "infernal_bolt",
1466            SPELL::INFERNAL_BOLT,
1467            |s| spell_infernal_bolt(s, &params.game_data),
1468        )
1469        .spell("ruination", SPELL::RUINATION, |s| spell_ruination(s, &params.game_data))
1470        .auto_attack(|a| {
1471            a
1472                .spell_id(1)
1473                .swing_ms(2000)
1474                .apply_base_from_data(&params.game_data)
1475                .ap_coef(0.7297)
1476                .is_pet()
1477                .uses_spell_power()
1478        })
1479        .game_data(params.game_data.clone())
1480        .talent_spell_ids(TALENTS)
1481        .talent_selections(params.talent_selections)
1482        .talent_companion_aura(
1483            TALENT::ABYSSAL_DOMINION_TALENT,
1484            AURA_ABYSSAL_DOMINION_TALENT,
1485        )
1486        .talent_companion_aura(
1487            TALENT::CARNIVOROUS_STALKERS,
1488            AURA_CARNIVOROUS_STALKERS_TALENT,
1489        )
1490        .talent_companion_aura(TALENT::DIABOLIC_OCULI, AURA_DIABOLIC_OCULI_TALENT)
1491        .talent_companion_aura(TALENT::DIABOLIC_RITUAL, AURA_DIABOLIC_RITUAL_TALENT)
1492        .talent_companion_aura(TALENT::FLAMETOUCHED, AURA_FLAMETOUCHED_TALENT)
1493        .talent_companion_aura(TALENT::LOOKS_THAT_KILL, AURA_LOOKS_THAT_KILL_TALENT)
1494        .talent_companion_aura(TALENT::MINDS_EYES, AURA_MINDS_EYES_TALENT)
1495        .set_bonus_auras(params.set_bonus_auras)
1496        .encounter(params.encounter.clone());
1497    let builder = crate::generated::items::register_equipped(
1498        builder,
1499        &params.game_data,
1500        params.equipped_items,
1501    )?;
1502
1503    builder
1504        .build(params.rotation)
1505        .map_err(wowlab_engine_ports::EngineError::rotation_compile)
1506}
1507fn new_handler(
1508    params: wowlab_engine_ports::HandlerParams<'_>,
1509) -> Result<Box<dyn SpecHandler>, wowlab_engine_ports::EngineError> {
1510    let handler = crate::composition::compose_handler(
1511        build_combat_system,
1512        &params,
1513        |parts, params| Ok(
1514            crate::hooks::demonology_warlock::DemonologyHandler::new(parts, params),
1515        ),
1516    )?;
1517
1518    Ok(Box::new(handler))
1519}
1520static DECLARED_METADATA: DeclaredSpecMetadata = DeclaredSpecMetadata {
1521    primary_resource: ResourceType::SoulShards,
1522    secondary_resource: None,
1523    spell_ids: DECLARED_SPELL_IDS,
1524    aura_ids: DECLARED_AURA_IDS,
1525    server_proc_entries: &[],
1526    talents: TALENTS,
1527    rotation_field_schema: &[],
1528    metrics_plugin_id: None,
1529    hero_talent_trees: &[
1530        HeroTalentTreeDesc {
1531            name: "Soul Harvester",
1532            spells: HERO_TREE_SOUL_HARVESTER_SPELLS,
1533            auras: HERO_TREE_SOUL_HARVESTER_AURAS,
1534        },
1535        HeroTalentTreeDesc {
1536            name: "Diabolist",
1537            spells: HERO_TREE_DIABOLIST_SPELLS,
1538            auras: HERO_TREE_DIABOLIST_AURAS,
1539        },
1540    ],
1541    reported_spells: REPORTED_SPELLS,
1542    masked_passive_effects: &[],
1543    passive_effect_overrides: &[],
1544};
1545pub(super) const SPEC_DESCRIPTOR: SpecDescriptor = SpecDescriptor {
1546    spec_id: SpecId::Demonology,
1547    display_name: "Demonology Warlock",
1548    metadata: DECLARED_METADATA,
1549    handler_factory: new_handler,
1550};
1551wowlab_engine_combat::smoke_test!(build_combat_system);