Skip to main content

wowlab_engine_content/generated/specs/
unholy_death_knight.rs

1//! @generated by codegen-cli from manifests/specs/death_knight/unholy/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/85948>
15    pub(crate) const FESTERING_STRIKE: u32 = 85948;
16    ///<https://wowlab.gg/inspect/spell/55090>
17    pub(crate) const SCOURGE_STRIKE: u32 = 55090;
18    ///<https://wowlab.gg/inspect/spell/47541>
19    pub(crate) const DEATH_COIL: u32 = 47541;
20    ///<https://wowlab.gg/inspect/spell/212739>
21    pub(crate) const EPIDEMIC: u32 = 212_739;
22    ///<https://wowlab.gg/inspect/spell/343294>
23    pub(crate) const SOUL_REAPER: u32 = 343_294;
24    ///<https://wowlab.gg/inspect/spell/77575>
25    pub(crate) const OUTBREAK: u32 = 77575;
26    ///<https://wowlab.gg/inspect/spell/51963>
27    pub(crate) const GARGOYLE_STRIKE: u32 = 51963;
28    ///<https://wowlab.gg/inspect/spell/46584>
29    pub(crate) const RAISE_DEAD: u32 = 46584;
30    ///<https://wowlab.gg/inspect/spell/1233448>
31    pub(crate) const DARK_TRANSFORMATION: u32 = 1_233_448;
32    ///<https://wowlab.gg/inspect/spell/42650>
33    pub(crate) const ARMY_OF_THE_DEAD: u32 = 42650;
34    ///<https://wowlab.gg/inspect/spell/1247378>
35    pub(crate) const PUTREFY: u32 = 1_247_378;
36}
37pub(crate) mod AURA {
38    ///<https://wowlab.gg/inspect/spell/81340>
39    pub(crate) const SUDDEN_DOOM: u32 = 81340;
40    ///<https://wowlab.gg/inspect/spell/51460>
41    pub(crate) const RUNIC_CORRUPTION: u32 = 51460;
42    ///<https://wowlab.gg/inspect/spell/458123>
43    pub(crate) const FESTERING_SCYTHE: u32 = 458_123;
44    ///<https://wowlab.gg/inspect/spell/1241077>
45    pub(crate) const FESTERING_SCYTHE_TT: u32 = 1_241_077;
46    ///<https://wowlab.gg/inspect/spell/390271>
47    pub(crate) const COIL_OF_DEVASTATION: u32 = 390_271;
48    ///<https://wowlab.gg/inspect/spell/327095>
49    pub(crate) const APOCALYPSE_DEATH: u32 = 327_095;
50    ///<https://wowlab.gg/inspect/spell/327092>
51    pub(crate) const APOCALYPSE_FAMINE: u32 = 327_092;
52    ///<https://wowlab.gg/inspect/spell/327093>
53    pub(crate) const APOCALYPSE_PESTILENCE: u32 = 327_093;
54    ///<https://wowlab.gg/inspect/spell/327096>
55    pub(crate) const APOCALYPSE_WAR: u32 = 327_096;
56    ///<https://wowlab.gg/inspect/spell/1241521>
57    pub(crate) const SOUL_REAPER: u32 = 1_241_521;
58    ///<https://wowlab.gg/inspect/spell/444505>
59    pub(crate) const MOGRAINES_MIGHT: u32 = 444_505;
60    ///<https://wowlab.gg/inspect/spell/444763>
61    pub(crate) const APOCALYPTIC_CONQUEST: u32 = 444_763;
62    ///<https://wowlab.gg/inspect/spell/444828>
63    pub(crate) const TROLLBANE_CHAINS: u32 = 444_828;
64    ///<https://wowlab.gg/inspect/spell/444633>
65    pub(crate) const UNDEATH: u32 = 444_633;
66    ///<https://wowlab.gg/inspect/spell/1242654>
67    pub(crate) const REAPING: u32 = 1_242_654;
68    ///<https://wowlab.gg/inspect/spell/1242223>
69    pub(crate) const FORBIDDEN_KNOWLEDGE: u32 = 1_242_223;
70    ///<https://wowlab.gg/inspect/spell/1271975>
71    pub(crate) const BLIGHTFALL: u32 = 1_271_975;
72    ///<https://wowlab.gg/inspect/spell/194879>
73    pub(crate) const ICY_TALONS: u32 = 194_879;
74    ///<https://wowlab.gg/inspect/spell/374585>
75    pub(crate) const RUNE_MASTERY: u32 = 374_585;
76    ///<https://wowlab.gg/inspect/spell/374557>
77    pub(crate) const BRITTLE: u32 = 374_557;
78    ///<https://wowlab.gg/inspect/spell/191587>
79    pub(crate) const VIRULENT_PLAGUE: u32 = 191_587;
80    ///<https://wowlab.gg/inspect/spell/1240996>
81    pub(crate) const DREAD_PLAGUE: u32 = 1_240_996;
82    ///<https://wowlab.gg/inspect/spell/1241786>
83    pub(crate) const INFECTED_CLAWS: u32 = 1_241_786;
84    ///<https://wowlab.gg/inspect/spell/1254252>
85    pub(crate) const LESSER_GHOUL: u32 = 1_254_252;
86    ///<https://wowlab.gg/inspect/spell/1242998>
87    pub(crate) const LESSER_GHOUL_COUNTER: u32 = 1_242_998;
88    ///<https://wowlab.gg/inspect/spell/1270491>
89    pub(crate) const UNHOLY_DEVOTION: u32 = 1_270_491;
90    ///<https://wowlab.gg/inspect/spell/49206>
91    pub(crate) const GARGOYLE_ACTIVE: u32 = 49206;
92    ///<https://wowlab.gg/inspect/spell/211947>
93    pub(crate) const GARGOYLE_EMPOWERMENT: u32 = 211_947;
94    ///<https://wowlab.gg/inspect/spell/1235391>
95    pub(crate) const DARK_TRANSFORMATION: u32 = 1_235_391;
96    ///<https://wowlab.gg/inspect/spell/390260>
97    pub(crate) const COMMANDER_OF_THE_DEAD: u32 = 390_260;
98}
99pub(crate) mod TALENT {
100    ///<https://wowlab.gg/inspect/spell/444040>
101    pub(crate) const APOCALYPSE_NOW: u32 = 444_040;
102    ///<https://wowlab.gg/inspect/spell/42650>
103    pub(crate) const ARMY_OF_THE_DEAD: u32 = 42650;
104    ///<https://wowlab.gg/inspect/spell/1254552>
105    pub(crate) const BLIGHTBURST: u32 = 1_254_552;
106    ///<https://wowlab.gg/inspect/spell/374504>
107    pub(crate) const BRITTLE: u32 = 374_504;
108    ///<https://wowlab.gg/inspect/spell/1233448>
109    pub(crate) const DARK_TRANSFORMATION: u32 = 1_233_448;
110    ///<https://wowlab.gg/inspect/spell/1256565>
111    pub(crate) const FORBIDDEN_KNOWLEDGE_2: u32 = 1_256_565;
112    ///<https://wowlab.gg/inspect/spell/1256566>
113    pub(crate) const FORBIDDEN_KNOWLEDGE_3: u32 = 1_256_566;
114    ///<https://wowlab.gg/inspect/spell/444069>
115    pub(crate) const FURY_OF_THE_HORSEMEN: u32 = 444_069;
116    ///<https://wowlab.gg/inspect/spell/1238900>
117    pub(crate) const GRAVE_MASTERY: u32 = 1_238_900;
118    ///<https://wowlab.gg/inspect/spell/1265949>
119    pub(crate) const LET_TERROR_REIGN: u32 = 1_265_949;
120    ///<https://wowlab.gg/inspect/spell/444052>
121    pub(crate) const NAZGRIMS_CONQUEST: u32 = 444_052;
122    ///<https://wowlab.gg/inspect/spell/77575>
123    pub(crate) const OUTBREAK: u32 = 77575;
124    ///<https://wowlab.gg/inspect/spell/1247378>
125    pub(crate) const PUTREFY: u32 = 1_247_378;
126    ///<https://wowlab.gg/inspect/spell/444005>
127    pub(crate) const RIDERS_CHAMPION: u32 = 444_005;
128    ///<https://wowlab.gg/inspect/spell/55090>
129    pub(crate) const SCOURGE_STRIKE: u32 = 55090;
130    ///<https://wowlab.gg/inspect/spell/343294>
131    pub(crate) const SOUL_REAPER: u32 = 343_294;
132    ///<https://wowlab.gg/inspect/spell/1242147>
133    pub(crate) const SUMMON_GARGOYLE: u32 = 1_242_147;
134    ///<https://wowlab.gg/inspect/spell/444097>
135    pub(crate) const TROLLBANES_ICY_FURY: u32 = 444_097;
136    ///<https://wowlab.gg/inspect/spell/1241858>
137    pub(crate) const UNHOLY_DEVOTION: u32 = 1_241_858;
138    ///<https://wowlab.gg/inspect/spell/444033>
139    pub(crate) const WHITEMANES_FAMINE: u32 = 444_033;
140}
141pub(crate) mod REPORTED_SPELL {
142    ///<https://wowlab.gg/inspect/spell/6603>
143    pub(crate) const AUTO_ATTACK: u32 = 6603;
144    ///<https://wowlab.gg/inspect/spell/199373>
145    pub(crate) const CLAW: u32 = 199_373;
146    ///<https://wowlab.gg/inspect/spell/1251951>
147    pub(crate) const DEATH_AND_DECAY: u32 = 1_251_951;
148    ///<https://wowlab.gg/inspect/spell/1265949>
149    pub(crate) const DEATH_COIL_LET_TERROR_REIGN: u32 = 1_265_949;
150    ///<https://wowlab.gg/inspect/spell/1241171>
151    pub(crate) const DREAD_PLAGUE_ERUPT: u32 = 1_241_171;
152    ///<https://wowlab.gg/inspect/spell/458128>
153    pub(crate) const FESTERING_SCYTHE: u32 = 458_128;
154    ///<https://wowlab.gg/inspect/spell/445504>
155    pub(crate) const HEART_STRIKE: u32 = 445_504;
156    ///<https://wowlab.gg/inspect/spell/1242178>
157    pub(crate) const NECROTIC_COIL_SHADOW: u32 = 1_242_178;
158    ///<https://wowlab.gg/inspect/spell/445507>
159    pub(crate) const OBLITERATE: u32 = 445_507;
160    ///<https://wowlab.gg/inspect/spell/327093>
161    pub(crate) const PESTILENCE_RUNEFORGE: u32 = 327_093;
162    ///<https://wowlab.gg/inspect/spell/445509>
163    pub(crate) const SCOURGE_STRIKE_SHADOW: u32 = 445_509;
164    ///<https://wowlab.gg/inspect/spell/1278150>
165    pub(crate) const SWEEPING_CLAWS: u32 = 1_278_150;
166    ///<https://wowlab.gg/inspect/spell/444834>
167    pub(crate) const TROLLBANES_ICY_FURY: u32 = 444_834;
168    ///<https://wowlab.gg/inspect/spell/444633>
169    pub(crate) const UNDEATH: u32 = 444_633;
170    ///<https://wowlab.gg/inspect/spell/1241167>
171    pub(crate) const VIRULENT_PLAGUE_ERUPT: u32 = 1_241_167;
172    ///<https://wowlab.gg/inspect/spell/445513>
173    pub(crate) const WHITEMANE_DEATH_COIL: u32 = 445_513;
174}
175pub(crate) mod HERO {
176    pub(crate) mod UNHOLY_PETS {
177        pub(crate) mod SPELL {
178            ///<https://wowlab.gg/inspect/spell/91776>
179            pub(crate) const CLAW: u32 = 91776;
180            ///<https://wowlab.gg/inspect/spell/390271>
181            pub(crate) const COIL_OF_DEVASTATION: u32 = 390_271;
182            ///<https://wowlab.gg/inspect/spell/458128>
183            pub(crate) const FESTERING_SCYTHE_STRIKE: u32 = 458_128;
184            ///<https://wowlab.gg/inspect/spell/317792>
185            pub(crate) const FROSTBOLT: u32 = 317_792;
186            ///<https://wowlab.gg/inspect/spell/51963>
187            pub(crate) const GARGOYLE_STRIKE: u32 = 51963;
188            ///<https://wowlab.gg/inspect/spell/199373>
189            pub(crate) const LESSER_CLAW: u32 = 199_373;
190            ///<https://wowlab.gg/inspect/spell/1278150>
191            pub(crate) const LESSER_SWEEPING_CLAWS: u32 = 1_278_150;
192            ///<https://wowlab.gg/inspect/spell/6603>
193            pub(crate) const MELEE: u32 = 6603;
194            ///<https://wowlab.gg/inspect/spell/1242178>
195            pub(crate) const NECROTIC_COIL: u32 = 1_242_178;
196            ///<https://wowlab.gg/inspect/spell/1242172>
197            pub(crate) const NECROTIC_COIL_SHADOWSTRIKE: u32 = 1_242_172;
198            ///<https://wowlab.gg/inspect/spell/390220>
199            pub(crate) const PUTREFY_AOE: u32 = 390_220;
200            ///<https://wowlab.gg/inspect/spell/1277016>
201            pub(crate) const PUTREFY_ST: u32 = 1_277_016;
202            ///<https://wowlab.gg/inspect/spell/1247379>
203            pub(crate) const RUPTURED_VISCERA: u32 = 1_247_379;
204            ///<https://wowlab.gg/inspect/spell/317791>
205            pub(crate) const SHADOW_BOLT: u32 = 317_791;
206            ///<https://wowlab.gg/inspect/spell/49206>
207            pub(crate) const SUMMON_GARGOYLE: u32 = 49206;
208            ///<https://wowlab.gg/inspect/spell/91778>
209            pub(crate) const SWEEPING_CLAWS: u32 = 91778;
210        }
211    }
212    pub(crate) mod RIDERS {
213        pub(crate) mod SPELL {
214            ///<https://wowlab.gg/inspect/spell/444248>
215            pub(crate) const MOGRAINE: u32 = 444_248;
216            ///<https://wowlab.gg/inspect/spell/444252>
217            pub(crate) const NAZGRIM: u32 = 444_252;
218            ///<https://wowlab.gg/inspect/spell/454389>
219            pub(crate) const RANDOM_SUMMON: u32 = 454_389;
220            ///<https://wowlab.gg/inspect/spell/444254>
221            pub(crate) const TROLLBANE: u32 = 444_254;
222            ///<https://wowlab.gg/inspect/spell/444251>
223            pub(crate) const WHITEMANE: u32 = 444_251;
224        }
225    }
226}
227static HERO_TREE_UNHOLY_PETS_SPELLS: &[(&str, u32)] = &[
228    ("CLAW", 91776),
229    ("COIL_OF_DEVASTATION", 390_271),
230    ("FESTERING_SCYTHE_STRIKE", 458_128),
231    ("FROSTBOLT", 317_792),
232    ("GARGOYLE_STRIKE", 51963),
233    ("LESSER_CLAW", 199_373),
234    ("LESSER_SWEEPING_CLAWS", 1_278_150),
235    ("MELEE", 6603),
236    ("NECROTIC_COIL", 1_242_178),
237    ("NECROTIC_COIL_SHADOWSTRIKE", 1_242_172),
238    ("PUTREFY_AOE", 390_220),
239    ("PUTREFY_ST", 1_277_016),
240    ("RUPTURED_VISCERA", 1_247_379),
241    ("SHADOW_BOLT", 317_791),
242    ("SUMMON_GARGOYLE", 49206),
243    ("SWEEPING_CLAWS", 91778),
244];
245static HERO_TREE_UNHOLY_PETS_AURAS: &[(&str, u32)] = &[];
246static HERO_TREE_RIDERS_SPELLS: &[(&str, u32)] = &[
247    ("MOGRAINE", 444_248),
248    ("NAZGRIM", 444_252),
249    ("RANDOM_SUMMON", 454_389),
250    ("TROLLBANE", 444_254),
251    ("WHITEMANE", 444_251),
252];
253static HERO_TREE_RIDERS_AURAS: &[(&str, u32)] = &[];
254pub(crate) const AURA_SUDDEN_DOOM: LocalAuraIdx = LocalAuraIdx::new(0);
255pub(crate) const AURA_RUNIC_CORRUPTION: LocalAuraIdx = LocalAuraIdx::new(1);
256pub(crate) const AURA_FESTERING_SCYTHE: LocalAuraIdx = LocalAuraIdx::new(2);
257pub(crate) const AURA_FESTERING_SCYTHE_TT: LocalAuraIdx = LocalAuraIdx::new(3);
258pub(crate) const AURA_COIL_OF_DEVASTATION: LocalAuraIdx = LocalAuraIdx::new(4);
259pub(crate) const AURA_APOCALYPSE_DEATH: LocalAuraIdx = LocalAuraIdx::new(5);
260pub(crate) const AURA_APOCALYPSE_FAMINE: LocalAuraIdx = LocalAuraIdx::new(6);
261pub(crate) const AURA_APOCALYPSE_PESTILENCE: LocalAuraIdx = LocalAuraIdx::new(7);
262pub(crate) const AURA_APOCALYPSE_WAR: LocalAuraIdx = LocalAuraIdx::new(8);
263pub(crate) const AURA_SOUL_REAPER: LocalAuraIdx = LocalAuraIdx::new(9);
264pub(crate) const AURA_MOGRAINES_MIGHT: LocalAuraIdx = LocalAuraIdx::new(10);
265pub(crate) const AURA_APOCALYPTIC_CONQUEST: LocalAuraIdx = LocalAuraIdx::new(11);
266pub(crate) const AURA_TROLLBANE_CHAINS: LocalAuraIdx = LocalAuraIdx::new(12);
267pub(crate) const AURA_UNDEATH: LocalAuraIdx = LocalAuraIdx::new(13);
268pub(crate) const AURA_REAPING: LocalAuraIdx = LocalAuraIdx::new(14);
269pub(crate) const AURA_FORBIDDEN_KNOWLEDGE: LocalAuraIdx = LocalAuraIdx::new(15);
270pub(crate) const AURA_BLIGHTFALL: LocalAuraIdx = LocalAuraIdx::new(16);
271pub(crate) const AURA_ICY_TALONS: LocalAuraIdx = LocalAuraIdx::new(17);
272pub(crate) const AURA_RUNE_MASTERY: LocalAuraIdx = LocalAuraIdx::new(18);
273pub(crate) const AURA_BRITTLE: LocalAuraIdx = LocalAuraIdx::new(19);
274pub(crate) const AURA_VIRULENT_PLAGUE: LocalAuraIdx = LocalAuraIdx::new(20);
275pub(crate) const AURA_DREAD_PLAGUE: LocalAuraIdx = LocalAuraIdx::new(21);
276pub(crate) const AURA_INFECTED_CLAWS: LocalAuraIdx = LocalAuraIdx::new(22);
277pub(crate) const AURA_LESSER_GHOUL: LocalAuraIdx = LocalAuraIdx::new(23);
278pub(crate) const AURA_LESSER_GHOUL_COUNTER: LocalAuraIdx = LocalAuraIdx::new(24);
279pub(crate) const AURA_UNHOLY_DEVOTION: LocalAuraIdx = LocalAuraIdx::new(25);
280pub(crate) const AURA_GARGOYLE_ACTIVE: LocalAuraIdx = LocalAuraIdx::new(26);
281pub(crate) const AURA_GARGOYLE_EMPOWERMENT: LocalAuraIdx = LocalAuraIdx::new(27);
282pub(crate) const AURA_DARK_TRANSFORMATION: LocalAuraIdx = LocalAuraIdx::new(28);
283pub(crate) const AURA_COMMANDER_OF_THE_DEAD: LocalAuraIdx = LocalAuraIdx::new(29);
284pub(crate) const AURA_COUNT: usize = 30;
285const _: () = assert!(
286    AURA_COUNT == 30, "AURA index ABI: count changed -- update positional hook consumers"
287);
288pub(crate) const SPELL_FESTERING_STRIKE: LocalSpellIdx = LocalSpellIdx::new(0);
289pub(crate) const SPELL_SCOURGE_STRIKE: LocalSpellIdx = LocalSpellIdx::new(1);
290pub(crate) const SPELL_DEATH_COIL: LocalSpellIdx = LocalSpellIdx::new(2);
291pub(crate) const SPELL_EPIDEMIC: LocalSpellIdx = LocalSpellIdx::new(3);
292pub(crate) const SPELL_SOUL_REAPER: LocalSpellIdx = LocalSpellIdx::new(4);
293pub(crate) const SPELL_OUTBREAK: LocalSpellIdx = LocalSpellIdx::new(5);
294pub(crate) const SPELL_GARGOYLE_STRIKE: LocalSpellIdx = LocalSpellIdx::new(6);
295pub(crate) const SPELL_RAISE_DEAD: LocalSpellIdx = LocalSpellIdx::new(7);
296pub(crate) const SPELL_DARK_TRANSFORMATION: LocalSpellIdx = LocalSpellIdx::new(8);
297pub(crate) const SPELL_ARMY_OF_THE_DEAD: LocalSpellIdx = LocalSpellIdx::new(9);
298pub(crate) const SPELL_PUTREFY: LocalSpellIdx = LocalSpellIdx::new(10);
299pub(crate) const SPELL_COUNT: usize = 11;
300const _: () = assert!(
301    SPELL_COUNT == 11,
302    "SPELL index ABI: count changed -- update positional hook consumers"
303);
304pub(crate) mod EFFECT {
305    ///<https://wowlab.gg/inspect/spell/444040>
306    pub(crate) const APOCALYPSE_NOW_DURATION: (u32, u8) = (444_040, 2);
307    ///<https://wowlab.gg/inspect/spell/42650>
308    pub(crate) const ARMY_GHOUL_COUNT: (u32, u8) = (42650, 1);
309    ///<https://wowlab.gg/inspect/spell/1254552>
310    pub(crate) const BLIGHTBURST_DAMAGE: (u32, u8) = (1_254_552, 2);
311    ///<https://wowlab.gg/inspect/spell/1254552>
312    pub(crate) const BLIGHTBURST_DURATION: (u32, u8) = (1_254_552, 1);
313    ///<https://wowlab.gg/inspect/spell/91776>
314    pub(crate) const CLAW: (u32, u8) = (91776, 1);
315    ///<https://wowlab.gg/inspect/spell/390270>
316    pub(crate) const COIL_OF_DEVASTATION_PCT: (u32, u8) = (390_270, 1);
317    ///<https://wowlab.gg/inspect/spell/390260>
318    pub(crate) const COMMANDER_PCT: (u32, u8) = (390_260, 3);
319    ///<https://wowlab.gg/inspect/spell/47632>
320    pub(crate) const DC_DAMAGE: (u32, u8) = (47632, 1);
321    ///<https://wowlab.gg/inspect/spell/1240996>
322    pub(crate) const DP_TICK: (u32, u8) = (1_240_996, 1);
323    ///<https://wowlab.gg/inspect/spell/77515>
324    pub(crate) const DREADBLADE_PET_CRIT: (u32, u8) = (77515, 6);
325    ///<https://wowlab.gg/inspect/spell/1233448>
326    pub(crate) const DT_ENERGY_PCT: (u32, u8) = (1_233_448, 4);
327    ///<https://wowlab.gg/inspect/spell/1233448>
328    pub(crate) const DT_PET_PCT: (u32, u8) = (1_233_448, 1);
329    ///<https://wowlab.gg/inspect/spell/390268>
330    pub(crate) const ETERNAL_AGONY_EXTENSION_MS: (u32, u8) = (390_268, 1);
331    ///<https://wowlab.gg/inspect/spell/207269>
332    pub(crate) const EBON_FEVER_PCT: (u32, u8) = (207_269, 1);
333    ///<https://wowlab.gg/inspect/spell/85948>
334    pub(crate) const FS_GHOULS_MAX: (u32, u8) = (85948, 4);
335    ///<https://wowlab.gg/inspect/spell/85948>
336    pub(crate) const FS_GHOULS_MIN: (u32, u8) = (85948, 3);
337    ///<https://wowlab.gg/inspect/spell/1256565>
338    pub(crate) const FORBIDDEN_KNOWLEDGE_READY_STACKS: (u32, u8) = (1_256_565, 2);
339    ///<https://wowlab.gg/inspect/spell/1256566>
340    pub(crate) const FORBIDDEN_KNOWLEDGE_PUTREFY_PCT: (u32, u8) = (1_256_566, 2);
341    ///<https://wowlab.gg/inspect/spell/1256566>
342    pub(crate) const FORBIDDEN_KNOWLEDGE_PROC_PCT: (u32, u8) = (1_256_566, 3);
343    ///<https://wowlab.gg/inspect/spell/444069>
344    pub(crate) const FURY_EXTENSION_SECONDS: (u32, u8) = (444_069, 3);
345    ///<https://wowlab.gg/inspect/spell/444069>
346    pub(crate) const FURY_MAX_SECONDS: (u32, u8) = (444_069, 2);
347    ///<https://wowlab.gg/inspect/spell/444069>
348    pub(crate) const FURY_RP_THRESHOLD: (u32, u8) = (444_069, 1);
349    ///<https://wowlab.gg/inspect/spell/51963>
350    pub(crate) const GARGOYLE_STRIKE: (u32, u8) = (51963, 1);
351    ///<https://wowlab.gg/inspect/spell/1238902>
352    pub(crate) const GRAVE_MASTERY_PCT: (u32, u8) = (1_238_902, 1);
353    ///<https://wowlab.gg/inspect/spell/276023>
354    pub(crate) const HARBINGER_SD_PCT: (u32, u8) = (276_023, 2);
355    ///<https://wowlab.gg/inspect/spell/444834>
356    pub(crate) const ICY_FURY_DAMAGE: (u32, u8) = (444_834, 2);
357    ///<https://wowlab.gg/inspect/spell/199373>
358    pub(crate) const LESSER_CLAW: (u32, u8) = (199_373, 1);
359    ///<https://wowlab.gg/inspect/spell/1278150>
360    pub(crate) const LESSER_SWEEPING: (u32, u8) = (1_278_150, 2);
361    ///<https://wowlab.gg/inspect/spell/317792>
362    pub(crate) const MAGUS_FROSTBOLT: (u32, u8) = (317_792, 1);
363    ///<https://wowlab.gg/inspect/spell/317791>
364    pub(crate) const MAGUS_SHADOW_BOLT: (u32, u8) = (317_791, 1);
365    ///<https://wowlab.gg/inspect/spell/1265949>
366    pub(crate) const LET_TERROR_REIGN_UNHOLY_PCT: (u32, u8) = (1_265_949, 2);
367    ///<https://wowlab.gg/inspect/spell/1251951>
368    pub(crate) const MOGRAINE_DND: (u32, u8) = (1_251_951, 1);
369    ///<https://wowlab.gg/inspect/spell/444474>
370    pub(crate) const MOGRAINE_DND_PERIOD: (u32, u8) = (444_474, 3);
371    ///<https://wowlab.gg/inspect/spell/445504>
372    pub(crate) const MOGRAINE_HEART_STRIKE: (u32, u8) = (445_504, 1);
373    ///<https://wowlab.gg/inspect/spell/444763>
374    pub(crate) const NAZGRIM_CONQUEST_BASE_PCT: (u32, u8) = (444_763, 1);
375    ///<https://wowlab.gg/inspect/spell/445508>
376    pub(crate) const NAZGRIM_SCOURGE_STRIKE: (u32, u8) = (445_508, 1);
377    ///<https://wowlab.gg/inspect/spell/445509>
378    pub(crate) const NAZGRIM_SCOURGE_STRIKE_SHADOW: (u32, u8) = (445_509, 1);
379    ///<https://wowlab.gg/inspect/spell/1242178>
380    pub(crate) const NECROTIC_SHADOW: (u32, u8) = (1_242_178, 1);
381    ///<https://wowlab.gg/inspect/spell/1242172>
382    pub(crate) const NECROTIC_STRIKE: (u32, u8) = (1_242_172, 1);
383    ///<https://wowlab.gg/inspect/spell/390220>
384    pub(crate) const PUTREFY_AOE: (u32, u8) = (390_220, 1);
385    ///<https://wowlab.gg/inspect/spell/1277016>
386    pub(crate) const PUTREFY_ST: (u32, u8) = (1_277_016, 1);
387    ///<https://wowlab.gg/inspect/spell/51462>
388    pub(crate) const RC_CHANCE_PCT: (u32, u8) = (51462, 1);
389    ///<https://wowlab.gg/inspect/spell/1247379>
390    pub(crate) const RUPTURED_VISCERA: (u32, u8) = (1_247_379, 1);
391    ///<https://wowlab.gg/inspect/spell/458128>
392    pub(crate) const SCYTHE_DAMAGE: (u32, u8) = (458_128, 1);
393    ///<https://wowlab.gg/inspect/spell/81340>
394    pub(crate) const SD_DC_PCT: (u32, u8) = (81340, 4);
395    ///<https://wowlab.gg/inspect/spell/343294>
396    pub(crate) const SR_GHOULS: (u32, u8) = (343_294, 3);
397    ///<https://wowlab.gg/inspect/spell/55090>
398    pub(crate) const SS_ERUPT_PCT: (u32, u8) = (55090, 2);
399    ///<https://wowlab.gg/inspect/spell/49530>
400    pub(crate) const SUDDEN_DOOM_PCT: (u32, u8) = (49530, 2);
401    ///<https://wowlab.gg/inspect/spell/91778>
402    pub(crate) const SWEEPING_MAIN: (u32, u8) = (91778, 2);
403    ///<https://wowlab.gg/inspect/spell/445507>
404    pub(crate) const TROLLBANE_OBLITERATE: (u32, u8) = (445_507, 1);
405    ///<https://wowlab.gg/inspect/spell/191587>
406    pub(crate) const VP_TICK: (u32, u8) = (191_587, 1);
407    ///<https://wowlab.gg/inspect/spell/445513>
408    pub(crate) const WHITEMANE_DEATH_COIL: (u32, u8) = (445_513, 1);
409}
410static REPORTED_SPELLS: &[(&str, u32)] = &[
411    ("auto_attack", 6603),
412    ("claw", 199_373),
413    ("death_and_decay", 1_251_951),
414    ("death_coil_let_terror_reign", 1_265_949),
415    ("dread_plague_erupt", 1_241_171),
416    ("festering_scythe", 458_128),
417    ("heart_strike", 445_504),
418    ("necrotic_coil_shadow", 1_242_178),
419    ("obliterate", 445_507),
420    ("pestilence_runeforge", 327_093),
421    ("scourge_strike_shadow", 445_509),
422    ("sweeping_claws", 1_278_150),
423    ("trollbanes_icy_fury", 444_834),
424    ("undeath", 444_633),
425    ("virulent_plague_erupt", 1_241_167),
426    ("whitemane_death_coil", 445_513),
427];
428static DECLARED_SPELL_IDS: &[u32] = &[
429    85948, 55090, 47541, 212_739, 343_294, 77575, 51963, 46584, 1_233_448, 42650,
430    1_247_378, 81340, 51460, 458_123, 1_241_077, 390_271, 327_095, 327_092, 327_093,
431    327_096, 1_241_521, 444_505, 444_763, 444_828, 444_633, 1_242_654, 1_242_223,
432    1_271_975, 194_879, 374_585, 374_557, 191_587, 1_240_996, 1_241_786, 1_254_252,
433    1_242_998, 1_270_491, 49206, 211_947, 1_235_391, 390_260, 6603, 6603, 6603, 42650,
434    47632, 49530, 51462, 51963, 55090, 77515, 81340, 85948, 91776, 91778, 191_587,
435    199_373, 207_269, 211_947, 276_023, 317_791, 317_792, 327_093, 343_294, 374_585,
436    390_220, 390_260, 390_268, 390_270, 390_271, 444_040, 444_052, 444_069, 444_474,
437    444_633, 444_763, 444_834, 445_504, 445_507, 445_508, 445_509, 445_513, 458_128,
438    1_233_448, 1_238_902, 1_240_996, 1_241_167, 1_241_171, 1_242_172, 1_242_178,
439    1_247_379, 1_251_951, 1_254_552, 1_256_565, 1_256_566, 1_265_949, 1_277_016,
440    1_278_150, 6603, 199_373, 1_251_951, 1_265_949, 1_241_171, 458_128, 445_504,
441    1_242_178, 445_507, 327_093, 445_509, 1_278_150, 444_834, 444_633, 1_241_167,
442    445_513, 91776, 390_271, 458_128, 317_792, 51963, 199_373, 1_278_150, 6603,
443    1_242_178, 1_242_172, 390_220, 1_277_016, 1_247_379, 317_791, 49206, 91778, 444_248,
444    444_252, 454_389, 444_254, 444_251,
445];
446static DECLARED_AURA_IDS: &[u32] = &[
447    81340, 51460, 458_123, 1_241_077, 390_271, 327_095, 327_092, 327_093, 327_096,
448    1_241_521, 444_505, 444_763, 444_828, 444_633, 1_242_654, 1_242_223, 1_271_975,
449    194_879, 374_585, 374_557, 191_587, 1_240_996, 1_241_786, 1_254_252, 1_242_998,
450    1_270_491, 49206, 211_947, 1_235_391, 390_260,
451];
452static TALENTS: &[(&str, u32)] = &[
453    ("APOCALYPSE_NOW", TALENT::APOCALYPSE_NOW),
454    ("ARMY_OF_THE_DEAD", TALENT::ARMY_OF_THE_DEAD),
455    ("BLIGHTBURST", TALENT::BLIGHTBURST),
456    ("BRITTLE", TALENT::BRITTLE),
457    ("DARK_TRANSFORMATION", TALENT::DARK_TRANSFORMATION),
458    ("FORBIDDEN_KNOWLEDGE_2", TALENT::FORBIDDEN_KNOWLEDGE_2),
459    ("FORBIDDEN_KNOWLEDGE_3", TALENT::FORBIDDEN_KNOWLEDGE_3),
460    ("FURY_OF_THE_HORSEMEN", TALENT::FURY_OF_THE_HORSEMEN),
461    ("GRAVE_MASTERY", TALENT::GRAVE_MASTERY),
462    ("LET_TERROR_REIGN", TALENT::LET_TERROR_REIGN),
463    ("NAZGRIMS_CONQUEST", TALENT::NAZGRIMS_CONQUEST),
464    ("OUTBREAK", TALENT::OUTBREAK),
465    ("PUTREFY", TALENT::PUTREFY),
466    ("RIDERS_CHAMPION", TALENT::RIDERS_CHAMPION),
467    ("SCOURGE_STRIKE", TALENT::SCOURGE_STRIKE),
468    ("SOUL_REAPER", TALENT::SOUL_REAPER),
469    ("SUMMON_GARGOYLE", TALENT::SUMMON_GARGOYLE),
470    ("TROLLBANES_ICY_FURY", TALENT::TROLLBANES_ICY_FURY),
471    ("UNHOLY_DEVOTION", TALENT::UNHOLY_DEVOTION),
472    ("WHITEMANES_FAMINE", TALENT::WHITEMANES_FAMINE),
473];
474pub(crate) mod UNHOLY_DK {
475    pub(crate) const FESTERING_STRIKE_CASTS: u32 = 0;
476    pub(crate) const SCOURGE_STRIKE_CASTS: u32 = 1;
477    pub(crate) const DEATH_COIL_CASTS: u32 = 2;
478    pub(crate) const DARK_TRANSFORMATION_CASTS: u32 = 3;
479    pub(crate) const ARMY_OF_THE_DEAD_CASTS: u32 = 4;
480    pub(crate) const SOUL_REAPER_CASTS: u32 = 5;
481    pub(crate) const PUTREFY_CASTS: u32 = 6;
482    pub(crate) const DARK_TRANSFORMATION_UPTIME_MS: u32 = 7;
483    pub(crate) const VIRULENT_PLAGUE_UPTIME_MS: u32 = 8;
484}
485fn aura_sudden_doom(
486    a: AuraDefinitionDraft,
487    data: &ResolvedGameData,
488) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
489    Ok(
490        a
491            .on_player()
492            .apply_base_from_data(data, 81340)?
493            .max_stacks(
494                data
495                    .require_aura_max_stacks(
496                        wowlab_types::sim::SpellIdx::from_raw(81340),
497                    )?,
498            ),
499    )
500}
501fn aura_runic_corruption(
502    a: AuraDefinitionDraft,
503    data: &ResolvedGameData,
504) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
505    Ok(
506        a
507            .on_player()
508            .apply_base_from_data(data, 51460)?
509            .max_stacks(
510                data
511                    .require_aura_max_stacks(
512                        wowlab_types::sim::SpellIdx::from_raw(51460),
513                    )?,
514            ),
515    )
516}
517fn aura_festering_scythe(
518    a: AuraDefinitionDraft,
519    data: &ResolvedGameData,
520) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
521    Ok(
522        a
523            .on_player()
524            .apply_base_from_data(data, 458_123)?
525            .max_stacks(
526                data
527                    .require_aura_max_stacks(
528                        wowlab_types::sim::SpellIdx::from_raw(458_123),
529                    )?,
530            ),
531    )
532}
533fn aura_festering_scythe_tt(
534    a: AuraDefinitionDraft,
535    data: &ResolvedGameData,
536) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
537    Ok(
538        a
539            .on_player()
540            .apply_base_from_data(data, 1_241_077)?
541            .max_stacks(
542                data
543                    .require_aura_max_stacks(
544                        wowlab_types::sim::SpellIdx::from_raw(1_241_077),
545                    )?,
546            ),
547    )
548}
549fn aura_coil_of_devastation(
550    a: AuraDefinitionDraft,
551    data: &ResolvedGameData,
552) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
553    a.on_target()
554        .apply_base_from_data(data, 390_271)?
555        .max_stacks(
556            data.require_aura_max_stacks(wowlab_types::sim::SpellIdx::from_raw(390_271))?,
557        )
558        .periodic_residual_damage(
559            wowlab_engine_combat::validated_milliseconds(
560                data.period(wowlab_types::sim::SpellIdx::from_raw(390_271), 1),
561                390_271,
562                "periodic_residual_damage.tick_ms",
563            )?,
564        )
565        .apply_periodic_behavior_from_data(data, 390_271)
566}
567fn aura_apocalypse_death(
568    a: AuraDefinitionDraft,
569    data: &ResolvedGameData,
570) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
571    Ok(
572        a
573            .on_target()
574            .apply_base_from_data(data, 327_095)?
575            .max_stacks(
576                data
577                    .require_aura_max_stacks(
578                        wowlab_types::sim::SpellIdx::from_raw(327_095),
579                    )?,
580            ),
581    )
582}
583fn aura_apocalypse_famine(
584    a: AuraDefinitionDraft,
585    data: &ResolvedGameData,
586) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
587    Ok(
588        a
589            .on_target()
590            .apply_base_from_data(data, 327_092)?
591            .max_stacks(
592                data
593                    .require_aura_max_stacks(
594                        wowlab_types::sim::SpellIdx::from_raw(327_092),
595                    )?,
596            ),
597    )
598}
599fn aura_apocalypse_pestilence(
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, 327_093)?
607            .max_stacks(
608                data
609                    .require_aura_max_stacks(
610                        wowlab_types::sim::SpellIdx::from_raw(327_093),
611                    )?,
612            )
613            .async_stacks(),
614    )
615}
616fn aura_apocalypse_war(
617    a: AuraDefinitionDraft,
618    data: &ResolvedGameData,
619) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
620    Ok(
621        a
622            .on_target()
623            .apply_base_from_data(data, 327_096)?
624            .max_stacks(
625                data
626                    .require_aura_max_stacks(
627                        wowlab_types::sim::SpellIdx::from_raw(327_096),
628                    )?,
629            ),
630    )
631}
632fn aura_soul_reaper(
633    a: AuraDefinitionDraft,
634    data: &ResolvedGameData,
635) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
636    Ok(
637        a
638            .on_target()
639            .apply_base_from_data(data, 1_241_521)?
640            .max_stacks(
641                data
642                    .require_aura_max_stacks(
643                        wowlab_types::sim::SpellIdx::from_raw(1_241_521),
644                    )?,
645            ),
646    )
647}
648fn aura_mograines_might(
649    a: AuraDefinitionDraft,
650    data: &ResolvedGameData,
651) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
652    Ok(
653        a
654            .on_player()
655            .apply_base_from_data(data, 444_505)?
656            .max_stacks(
657                data
658                    .require_aura_max_stacks(
659                        wowlab_types::sim::SpellIdx::from_raw(444_505),
660                    )?,
661            ),
662    )
663}
664fn aura_apocalyptic_conquest(
665    a: AuraDefinitionDraft,
666    data: &ResolvedGameData,
667) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
668    a.on_player()
669        .apply_base_from_data(data, 444_763)?
670        .max_stacks(
671            wowlab_engine_combat::validated_max_stacks(
672                255.0,
673                444_763,
674                "aura.max_stacks",
675            )?,
676        )
677        .primary_pct_per_stack(
678            data.base_points(wowlab_types::sim::SpellIdx::from_raw(444_052), 2),
679        )
680}
681fn aura_trollbane_chains(
682    a: AuraDefinitionDraft,
683    data: &ResolvedGameData,
684) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
685    Ok(
686        a
687            .on_target()
688            .apply_base_from_data(data, 444_828)?
689            .max_stacks(
690                data
691                    .require_aura_max_stacks(
692                        wowlab_types::sim::SpellIdx::from_raw(444_828),
693                    )?,
694            ),
695    )
696}
697fn aura_undeath(
698    a: AuraDefinitionDraft,
699    data: &ResolvedGameData,
700) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
701    Ok(
702        a
703            .on_target()
704            .apply_base_from_data(data, 444_633)?
705            .max_stacks(
706                wowlab_engine_combat::validated_max_stacks(
707                    255.0,
708                    444_633,
709                    "aura.max_stacks",
710                )?,
711            )
712            .periodic_damage_scales_with_stacks()
713            .periodic_hook(
714                wowlab_engine_combat::validated_milliseconds(
715                    data.period(wowlab_types::sim::SpellIdx::from_raw(444_633), 1),
716                    444_633,
717                    "periodic_hook.tick_ms",
718                )?,
719            )
720            .apply_periodic_behavior_from_data(data, 444_633)?
721            .tick_hook(crate::hooks::unholy_death_knight::undeath_tick_hook),
722    )
723}
724fn aura_reaping(
725    a: AuraDefinitionDraft,
726    data: &ResolvedGameData,
727) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
728    Ok(
729        a
730            .on_player()
731            .apply_base_from_data(data, 1_242_654)?
732            .max_stacks(
733                data
734                    .require_aura_max_stacks(
735                        wowlab_types::sim::SpellIdx::from_raw(1_242_654),
736                    )?,
737            ),
738    )
739}
740fn aura_forbidden_knowledge(
741    a: AuraDefinitionDraft,
742    data: &ResolvedGameData,
743) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
744    Ok(
745        a
746            .on_player()
747            .apply_base_from_data(data, 1_242_223)?
748            .max_stacks(
749                data
750                    .require_aura_max_stacks(
751                        wowlab_types::sim::SpellIdx::from_raw(1_242_223),
752                    )?,
753            ),
754    )
755}
756fn aura_blightfall(
757    a: AuraDefinitionDraft,
758    data: &ResolvedGameData,
759) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
760    Ok(
761        a
762            .on_player()
763            .apply_base_from_data(data, 1_271_975)?
764            .max_stacks(
765                data
766                    .require_aura_max_stacks(
767                        wowlab_types::sim::SpellIdx::from_raw(1_271_975),
768                    )?,
769            ),
770    )
771}
772fn aura_icy_talons(
773    a: AuraDefinitionDraft,
774    data: &ResolvedGameData,
775) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
776    Ok(
777        a
778            .on_player()
779            .apply_base_from_data(data, 194_879)?
780            .max_stacks(
781                data
782                    .require_aura_max_stacks(
783                        wowlab_types::sim::SpellIdx::from_raw(194_879),
784                    )?,
785            ),
786    )
787}
788fn aura_rune_mastery(
789    a: AuraDefinitionDraft,
790    data: &ResolvedGameData,
791) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
792    a.on_player()
793        .apply_base_from_data(data, 374_585)?
794        .max_stacks(
795            data.require_aura_max_stacks(wowlab_types::sim::SpellIdx::from_raw(374_585))?,
796        )
797        .primary_pct_per_stack(
798            data.base_points(wowlab_types::sim::SpellIdx::from_raw(374_585), 1),
799        )
800}
801fn aura_brittle(
802    a: AuraDefinitionDraft,
803    data: &ResolvedGameData,
804) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
805    Ok(
806        a
807            .on_target()
808            .apply_base_from_data(data, 374_557)?
809            .max_stacks(
810                data
811                    .require_aura_max_stacks(
812                        wowlab_types::sim::SpellIdx::from_raw(374_557),
813                    )?,
814            ),
815    )
816}
817fn aura_virulent_plague(
818    a: AuraDefinitionDraft,
819    data: &ResolvedGameData,
820) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
821    Ok(
822        a
823            .on_target()
824            .apply_base_from_data(data, 191_587)?
825            .max_stacks(
826                data
827                    .require_aura_max_stacks(
828                        wowlab_types::sim::SpellIdx::from_raw(191_587),
829                    )?,
830            )
831            .periodic_hook(
832                wowlab_engine_combat::validated_milliseconds(
833                    data.period(wowlab_types::sim::SpellIdx::from_raw(191_587), 1),
834                    191_587,
835                    "periodic_hook.tick_ms",
836                )?,
837            )
838            .apply_periodic_behavior_from_data(data, 191_587)?
839            .tick_hook(crate::hooks::unholy_death_knight::disease_tick_hook),
840    )
841}
842fn aura_dread_plague(
843    a: AuraDefinitionDraft,
844    data: &ResolvedGameData,
845) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
846    Ok(
847        a
848            .on_target()
849            .apply_base_from_data(data, 1_240_996)?
850            .max_stacks(
851                data
852                    .require_aura_max_stacks(
853                        wowlab_types::sim::SpellIdx::from_raw(1_240_996),
854                    )?,
855            )
856            .periodic_hook(
857                wowlab_engine_combat::validated_milliseconds(
858                    data.period(wowlab_types::sim::SpellIdx::from_raw(1_240_996), 1),
859                    1_240_996,
860                    "periodic_hook.tick_ms",
861                )?,
862            )
863            .apply_periodic_behavior_from_data(data, 1_240_996)?
864            .tick_hook(crate::hooks::unholy_death_knight::disease_tick_hook),
865    )
866}
867fn aura_infected_claws(
868    a: AuraDefinitionDraft,
869    data: &ResolvedGameData,
870) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
871    Ok(
872        a
873            .on_target()
874            .apply_base_from_data(data, 1_241_786)?
875            .max_stacks(
876                data
877                    .require_aura_max_stacks(
878                        wowlab_types::sim::SpellIdx::from_raw(1_241_786),
879                    )?,
880            ),
881    )
882}
883fn aura_lesser_ghoul(
884    a: AuraDefinitionDraft,
885    data: &ResolvedGameData,
886) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
887    Ok(
888        a
889            .on_player()
890            .apply_base_from_data(data, 1_254_252)?
891            .max_stacks(
892                wowlab_engine_combat::validated_max_stacks(
893                    8.0,
894                    1_254_252,
895                    "aura.max_stacks",
896                )?,
897            ),
898    )
899}
900fn aura_lesser_ghoul_counter(
901    a: AuraDefinitionDraft,
902    data: &ResolvedGameData,
903) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
904    Ok(
905        a
906            .on_player()
907            .apply_base_from_data(data, 1_242_998)?
908            .max_stacks(
909                wowlab_engine_combat::validated_max_stacks(
910                    20.0,
911                    1_242_998,
912                    "aura.max_stacks",
913                )?,
914            ),
915    )
916}
917fn aura_unholy_devotion(
918    a: AuraDefinitionDraft,
919    data: &ResolvedGameData,
920) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
921    Ok(
922        a
923            .on_pet()
924            .apply_base_from_data(data, 1_270_491)?
925            .max_stacks(
926                data
927                    .require_aura_max_stacks(
928                        wowlab_types::sim::SpellIdx::from_raw(1_270_491),
929                    )?,
930            )
931            .async_stacks(),
932    )
933}
934fn aura_gargoyle_active(
935    a: AuraDefinitionDraft,
936    data: &ResolvedGameData,
937) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
938    a.on_player()
939        .apply_base_from_data(data, 49206)?
940        .no_pandemic()
941        .max_stacks(
942            wowlab_engine_combat::validated_max_stacks(1.0, 49206, "aura.max_stacks")?,
943        )
944        .crit_chance_spells(100.0, &[51963])
945}
946fn aura_gargoyle_empowerment(
947    a: AuraDefinitionDraft,
948    data: &ResolvedGameData,
949) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
950    a.on_player()
951        .apply_base_from_data(data, 211_947)?
952        .max_stacks(
953            wowlab_engine_combat::validated_max_stacks(
954                255.0,
955                211_947,
956                "aura.max_stacks",
957            )?,
958        )
959        .damage_percent_spells_linear(
960            data.base_points(wowlab_types::sim::SpellIdx::from_raw(211_947), 1),
961            &[51963],
962        )
963}
964fn aura_dark_transformation(
965    a: AuraDefinitionDraft,
966    data: &ResolvedGameData,
967) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
968    Ok(
969        a
970            .on_player()
971            .apply_base_from_data(data, 1_235_391)?
972            .max_stacks(
973                data
974                    .require_aura_max_stacks(
975                        wowlab_types::sim::SpellIdx::from_raw(1_235_391),
976                    )?,
977            ),
978    )
979}
980fn aura_commander_of_the_dead(
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, 390_260)?
988            .max_stacks(
989                data
990                    .require_aura_max_stacks(
991                        wowlab_types::sim::SpellIdx::from_raw(390_260),
992                    )?,
993            ),
994    )
995}
996fn spell_festering_strike(
997    s: SpellDefinitionDraft,
998    data: &ResolvedGameData,
999) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1000    Ok(
1001        s
1002            .apply_base_from_data(data, 85948)?
1003            .apply_aoe_from_data(data)
1004            .on_cast(crate::hooks::unholy_death_knight::festering_strike_hook),
1005    )
1006}
1007fn spell_scourge_strike(
1008    s: SpellDefinitionDraft,
1009    data: &ResolvedGameData,
1010) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1011    Ok(
1012        s
1013            .apply_base_from_data(data, 55090)?
1014            .apply_aoe_from_data(data)
1015            .on_cast(crate::hooks::unholy_death_knight::scourge_strike_hook),
1016    )
1017}
1018fn spell_death_coil(
1019    s: SpellDefinitionDraft,
1020    data: &ResolvedGameData,
1021) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1022    Ok(
1023        s
1024            .apply_base_from_data(data, 47541)?
1025            .extends_aura(AURA_VIRULENT_PLAGUE, 1500)
1026            .extends_aura(AURA_DREAD_PLAGUE, 1500)
1027            .apply_aoe_from_data(data)
1028            .on_cast(crate::hooks::unholy_death_knight::death_coil_hook)
1029            .cost_free_when_aura(81340),
1030    )
1031}
1032fn spell_epidemic(
1033    s: SpellDefinitionDraft,
1034    data: &ResolvedGameData,
1035) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1036    Ok(s.apply_base_from_data(data, 212_739)?.apply_aoe_from_data(data))
1037}
1038fn spell_soul_reaper(
1039    s: SpellDefinitionDraft,
1040    data: &ResolvedGameData,
1041) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1042    Ok(
1043        s
1044            .apply_base_from_data(data, 343_294)?
1045            .applies_inferred_aura(AURA_SOUL_REAPER, 1_241_521)
1046            .apply_aoe_from_data(data)
1047            .on_cast(crate::hooks::unholy_death_knight::soul_reaper_hook),
1048    )
1049}
1050fn spell_outbreak(
1051    s: SpellDefinitionDraft,
1052    data: &ResolvedGameData,
1053) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1054    Ok(
1055        s
1056            .apply_base_from_data(data, 77575)?
1057            .apply_aoe_from_data(data)
1058            .on_cast(crate::hooks::unholy_death_knight::outbreak_hook),
1059    )
1060}
1061fn spell_gargoyle_strike(
1062    s: SpellDefinitionDraft,
1063    data: &ResolvedGameData,
1064) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1065    Ok(s.apply_base_from_data(data, 51963)?.apply_aoe_from_data(data))
1066}
1067fn spell_raise_dead(
1068    s: SpellDefinitionDraft,
1069    data: &ResolvedGameData,
1070) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1071    Ok(s.apply_base_from_data(data, 46584)?.apply_aoe_from_data(data))
1072}
1073fn spell_dark_transformation(
1074    s: SpellDefinitionDraft,
1075    data: &ResolvedGameData,
1076) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1077    Ok(
1078        s
1079            .apply_base_from_data(data, 1_233_448)?
1080            .applies_aura(AURA_DARK_TRANSFORMATION)
1081            .apply_aoe_from_data(data)
1082            .on_cast(crate::hooks::unholy_death_knight::dark_transformation_hook),
1083    )
1084}
1085fn spell_army_of_the_dead(
1086    s: SpellDefinitionDraft,
1087    data: &ResolvedGameData,
1088) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1089    Ok(
1090        s
1091            .apply_base_from_data(data, 42650)?
1092            .apply_aoe_from_data(data)
1093            .on_cast(crate::hooks::unholy_death_knight::army_of_the_dead_hook),
1094    )
1095}
1096fn spell_putrefy(
1097    s: SpellDefinitionDraft,
1098    data: &ResolvedGameData,
1099) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1100    Ok(
1101        s
1102            .apply_base_from_data(data, 1_247_378)?
1103            .apply_aoe_from_data(data)
1104            .on_cast(crate::hooks::unholy_death_knight::putrefy_hook),
1105    )
1106}
1107pub(crate) fn build_combat_system(
1108    params: &wowlab_engine_ports::HandlerParams<'_>,
1109) -> Result<BuiltCombatSystem, wowlab_engine_ports::EngineError> {
1110    let builder = BuiltCombatSystem::builder(params.stats.clone())
1111        .spec_id(SpecId::Unholy)
1112        .hero_talent_trees(DECLARED_METADATA.hero_talent_trees)
1113        .mastery_spell(77515)
1114        .mastery_hook(crate::hooks::unholy_death_knight::mastery)
1115        .resource("runes", 6.0, 0.0)
1116        .resource_type_id(5)
1117        .resource_start(6.0)
1118        .mastery_crit_damage_hook(crate::hooks::unholy_death_knight::crit_damage)
1119        .has_pet(true)
1120        .secondary_resource("runic_power", 100.0)
1121        .secondary_resource_type_id(6)
1122        .aura(
1123            "sudden_doom",
1124            AURA::SUDDEN_DOOM,
1125            |a| aura_sudden_doom(a, &params.game_data),
1126        )
1127        .aura(
1128            "runic_corruption",
1129            AURA::RUNIC_CORRUPTION,
1130            |a| aura_runic_corruption(a, &params.game_data),
1131        )
1132        .aura(
1133            "festering_scythe",
1134            AURA::FESTERING_SCYTHE,
1135            |a| aura_festering_scythe(a, &params.game_data),
1136        )
1137        .aura(
1138            "festering_scythe_tt",
1139            AURA::FESTERING_SCYTHE_TT,
1140            |a| aura_festering_scythe_tt(a, &params.game_data),
1141        )
1142        .aura(
1143            "coil_of_devastation",
1144            AURA::COIL_OF_DEVASTATION,
1145            |a| aura_coil_of_devastation(a, &params.game_data),
1146        )
1147        .aura(
1148            "apocalypse_death",
1149            AURA::APOCALYPSE_DEATH,
1150            |a| aura_apocalypse_death(a, &params.game_data),
1151        )
1152        .aura(
1153            "apocalypse_famine",
1154            AURA::APOCALYPSE_FAMINE,
1155            |a| aura_apocalypse_famine(a, &params.game_data),
1156        )
1157        .aura(
1158            "apocalypse_pestilence",
1159            AURA::APOCALYPSE_PESTILENCE,
1160            |a| aura_apocalypse_pestilence(a, &params.game_data),
1161        )
1162        .aura(
1163            "apocalypse_war",
1164            AURA::APOCALYPSE_WAR,
1165            |a| aura_apocalypse_war(a, &params.game_data),
1166        )
1167        .aura(
1168            "soul_reaper",
1169            AURA::SOUL_REAPER,
1170            |a| aura_soul_reaper(a, &params.game_data),
1171        )
1172        .aura(
1173            "mograines_might",
1174            AURA::MOGRAINES_MIGHT,
1175            |a| aura_mograines_might(a, &params.game_data),
1176        )
1177        .aura(
1178            "apocalyptic_conquest",
1179            AURA::APOCALYPTIC_CONQUEST,
1180            |a| aura_apocalyptic_conquest(a, &params.game_data),
1181        )
1182        .aura(
1183            "trollbane_chains",
1184            AURA::TROLLBANE_CHAINS,
1185            |a| aura_trollbane_chains(a, &params.game_data),
1186        )
1187        .aura("undeath", AURA::UNDEATH, |a| aura_undeath(a, &params.game_data))
1188        .aura("reaping", AURA::REAPING, |a| aura_reaping(a, &params.game_data))
1189        .aura(
1190            "forbidden_knowledge",
1191            AURA::FORBIDDEN_KNOWLEDGE,
1192            |a| aura_forbidden_knowledge(a, &params.game_data),
1193        )
1194        .aura("blightfall", AURA::BLIGHTFALL, |a| aura_blightfall(a, &params.game_data))
1195        .aura("icy_talons", AURA::ICY_TALONS, |a| aura_icy_talons(a, &params.game_data))
1196        .aura(
1197            "rune_mastery",
1198            AURA::RUNE_MASTERY,
1199            |a| aura_rune_mastery(a, &params.game_data),
1200        )
1201        .aura("brittle", AURA::BRITTLE, |a| aura_brittle(a, &params.game_data))
1202        .aura(
1203            "virulent_plague",
1204            AURA::VIRULENT_PLAGUE,
1205            |a| aura_virulent_plague(a, &params.game_data),
1206        )
1207        .aura(
1208            "dread_plague",
1209            AURA::DREAD_PLAGUE,
1210            |a| aura_dread_plague(a, &params.game_data),
1211        )
1212        .aura(
1213            "infected_claws",
1214            AURA::INFECTED_CLAWS,
1215            |a| aura_infected_claws(a, &params.game_data),
1216        )
1217        .aura(
1218            "lesser_ghoul",
1219            AURA::LESSER_GHOUL,
1220            |a| aura_lesser_ghoul(a, &params.game_data),
1221        )
1222        .aura(
1223            "lesser_ghoul_counter",
1224            AURA::LESSER_GHOUL_COUNTER,
1225            |a| aura_lesser_ghoul_counter(a, &params.game_data),
1226        )
1227        .aura(
1228            "unholy_devotion",
1229            AURA::UNHOLY_DEVOTION,
1230            |a| aura_unholy_devotion(a, &params.game_data),
1231        )
1232        .aura(
1233            "gargoyle_active",
1234            AURA::GARGOYLE_ACTIVE,
1235            |a| aura_gargoyle_active(a, &params.game_data),
1236        )
1237        .aura(
1238            "gargoyle_empowerment",
1239            AURA::GARGOYLE_EMPOWERMENT,
1240            |a| aura_gargoyle_empowerment(a, &params.game_data),
1241        )
1242        .aura(
1243            "dark_transformation",
1244            AURA::DARK_TRANSFORMATION,
1245            |a| aura_dark_transformation(a, &params.game_data),
1246        )
1247        .aura(
1248            "commander_of_the_dead",
1249            AURA::COMMANDER_OF_THE_DEAD,
1250            |a| aura_commander_of_the_dead(a, &params.game_data),
1251        )
1252        .spell(
1253            "festering_strike",
1254            SPELL::FESTERING_STRIKE,
1255            |s| spell_festering_strike(s, &params.game_data),
1256        )
1257        .spell(
1258            "scourge_strike",
1259            SPELL::SCOURGE_STRIKE,
1260            |s| spell_scourge_strike(s, &params.game_data),
1261        )
1262        .spell(
1263            "death_coil",
1264            SPELL::DEATH_COIL,
1265            |s| spell_death_coil(s, &params.game_data),
1266        )
1267        .spell("epidemic", SPELL::EPIDEMIC, |s| spell_epidemic(s, &params.game_data))
1268        .spell(
1269            "soul_reaper",
1270            SPELL::SOUL_REAPER,
1271            |s| spell_soul_reaper(s, &params.game_data),
1272        )
1273        .spell("outbreak", SPELL::OUTBREAK, |s| spell_outbreak(s, &params.game_data))
1274        .spell(
1275            "gargoyle_strike",
1276            SPELL::GARGOYLE_STRIKE,
1277            |s| spell_gargoyle_strike(s, &params.game_data),
1278        )
1279        .spell(
1280            "raise_dead",
1281            SPELL::RAISE_DEAD,
1282            |s| spell_raise_dead(s, &params.game_data),
1283        )
1284        .spell(
1285            "dark_transformation",
1286            SPELL::DARK_TRANSFORMATION,
1287            |s| spell_dark_transformation(s, &params.game_data),
1288        )
1289        .spell(
1290            "army_of_the_dead",
1291            SPELL::ARMY_OF_THE_DEAD,
1292            |s| spell_army_of_the_dead(s, &params.game_data),
1293        )
1294        .spell("putrefy", SPELL::PUTREFY, |s| spell_putrefy(s, &params.game_data))
1295        .auto_attack(|a| {
1296            a.spell_id(6603).swing_ms(3600).apply_base_from_data(&params.game_data)
1297        })
1298        .auto_attack(|a| {
1299            a
1300                .spell_id(6603)
1301                .swing_ms(2000)
1302                .apply_base_from_data(&params.game_data)
1303                .ap_coef(
1304                    wowlab_engine_domain::damage::pet_swing_power_coefficient(
1305                        0.474,
1306                        2000,
1307                        1.0,
1308                    ),
1309                )
1310                .is_pet()
1311                .npc_id(26125)
1312                .on_swing(crate::hooks::unholy_death_knight::pet_swing)
1313        })
1314        .game_data(params.game_data.clone())
1315        .talent_spell_ids(TALENTS)
1316        .talent_selections(params.talent_selections)
1317        .set_bonus_auras(params.set_bonus_auras)
1318        .encounter(params.encounter.clone());
1319    let builder = crate::generated::items::register_equipped(
1320        builder,
1321        &params.game_data,
1322        params.equipped_items,
1323    )?;
1324
1325    builder
1326        .build(params.rotation)
1327        .map_err(wowlab_engine_ports::EngineError::rotation_compile)
1328}
1329fn new_handler(
1330    params: wowlab_engine_ports::HandlerParams<'_>,
1331) -> Result<Box<dyn SpecHandler>, wowlab_engine_ports::EngineError> {
1332    let handler = crate::composition::compose_handler(
1333        build_combat_system,
1334        &params,
1335        crate::hooks::unholy_death_knight::UnholyDkHandler::try_new,
1336    )?;
1337
1338    Ok(Box::new(handler))
1339}
1340static DECLARED_METADATA: DeclaredSpecMetadata = DeclaredSpecMetadata {
1341    primary_resource: ResourceType::Runes,
1342    secondary_resource: Some(ResourceType::RunicPower),
1343    spell_ids: DECLARED_SPELL_IDS,
1344    aura_ids: DECLARED_AURA_IDS,
1345    server_proc_entries: &[],
1346    talents: TALENTS,
1347    rotation_field_schema: &[],
1348    metrics_plugin_id: None,
1349    hero_talent_trees: &[
1350        HeroTalentTreeDesc {
1351            name: "Unholy Pets",
1352            spells: HERO_TREE_UNHOLY_PETS_SPELLS,
1353            auras: HERO_TREE_UNHOLY_PETS_AURAS,
1354        },
1355        HeroTalentTreeDesc {
1356            name: "Riders",
1357            spells: HERO_TREE_RIDERS_SPELLS,
1358            auras: HERO_TREE_RIDERS_AURAS,
1359        },
1360    ],
1361    reported_spells: REPORTED_SPELLS,
1362    masked_passive_effects: &[],
1363    passive_effect_overrides: &[],
1364};
1365pub(super) const SPEC_DESCRIPTOR: SpecDescriptor = SpecDescriptor {
1366    spec_id: SpecId::Unholy,
1367    display_name: "Unholy Death Knight",
1368    metadata: DECLARED_METADATA,
1369    handler_factory: new_handler,
1370};
1371wowlab_engine_combat::smoke_test!(build_combat_system);