Skip to main content

wowlab_engine_content/generated/specs/
vengeance_demon_hunter.rs

1//! @generated by codegen-cli from manifests/specs/demon_hunter/vengeance/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/228477>
15    pub(crate) const SOUL_CLEAVE: u32 = 228_477;
16    ///<https://wowlab.gg/inspect/spell/258920>
17    pub(crate) const IMMOLATION_AURA: u32 = 258_920;
18    ///<https://wowlab.gg/inspect/spell/212084>
19    pub(crate) const FEL_DEVASTATION: u32 = 212_084;
20    ///<https://wowlab.gg/inspect/spell/204596>
21    pub(crate) const SIGIL_OF_FLAME: u32 = 204_596;
22    ///<https://wowlab.gg/inspect/spell/203782>
23    pub(crate) const SHEAR: u32 = 203_782;
24    ///<https://wowlab.gg/inspect/spell/187827>
25    pub(crate) const METAMORPHOSIS: u32 = 187_827;
26    ///<https://wowlab.gg/inspect/spell/204157>
27    pub(crate) const THROW_GLAIVE: u32 = 204_157;
28    ///<https://wowlab.gg/inspect/spell/207407>
29    pub(crate) const SOUL_CARVER: u32 = 207_407;
30    ///<https://wowlab.gg/inspect/spell/247454>
31    pub(crate) const SPIRIT_BOMB: u32 = 247_454;
32    ///<https://wowlab.gg/inspect/spell/390163>
33    pub(crate) const SIGIL_OF_SPITE: u32 = 390_163;
34    ///<https://wowlab.gg/inspect/spell/263642>
35    pub(crate) const FRACTURE: u32 = 263_642;
36}
37pub(crate) mod AURA {
38    ///<https://wowlab.gg/inspect/spell/204598>
39    pub(crate) const SIGIL_OF_FLAME: u32 = 204_598;
40    ///<https://wowlab.gg/inspect/spell/203981>
41    pub(crate) const SOUL_FRAGMENTS: u32 = 203_981;
42    ///<https://wowlab.gg/inspect/spell/442294>
43    pub(crate) const REAVERS_GLAIVE: u32 = 442_294;
44    ///<https://wowlab.gg/inspect/spell/442442>
45    pub(crate) const RENDING_STRIKE: u32 = 442_442;
46    ///<https://wowlab.gg/inspect/spell/442435>
47    pub(crate) const GLAIVE_FLURRY: u32 = 442_435;
48    ///<https://wowlab.gg/inspect/spell/1256301>
49    pub(crate) const VOIDFALL_BUILDING: u32 = 1_256_301;
50    ///<https://wowlab.gg/inspect/spell/1256302>
51    pub(crate) const VOIDFALL_SPENDING: u32 = 1_256_302;
52    ///<https://wowlab.gg/inspect/spell/1256322>
53    pub(crate) const VOIDFALL_FINAL_HOUR: u32 = 1_256_322;
54    ///<https://wowlab.gg/inspect/spell/1256667>
55    pub(crate) const CATASTROPHE: u32 = 1_256_667;
56    ///<https://wowlab.gg/inspect/spell/1256308>
57    pub(crate) const DARK_MATTER: u32 = 1_256_308;
58    ///<https://wowlab.gg/inspect/spell/1270476>
59    pub(crate) const UNTETHERED_RAGE: u32 = 1_270_476;
60    ///<https://wowlab.gg/inspect/spell/1270547>
61    pub(crate) const SEETHING_ANGER: u32 = 1_270_547;
62}
63pub(crate) mod TALENT {
64    ///<https://wowlab.gg/inspect/spell/390163>
65    pub(crate) const SIGIL_OF_SPITE: u32 = 390_163;
66    ///<https://wowlab.gg/inspect/spell/207407>
67    pub(crate) const SOUL_CARVER: u32 = 207_407;
68    ///<https://wowlab.gg/inspect/spell/247454>
69    pub(crate) const SPIRIT_BOMB: u32 = 247_454;
70    ///<https://wowlab.gg/inspect/spell/1270444>
71    pub(crate) const UNTETHERED_RAGE_1: u32 = 1_270_444;
72    ///<https://wowlab.gg/inspect/spell/1270448>
73    pub(crate) const UNTETHERED_RAGE_2: u32 = 1_270_448;
74    ///<https://wowlab.gg/inspect/spell/1270449>
75    pub(crate) const UNTETHERED_RAGE_3: u32 = 1_270_449;
76}
77pub(crate) mod REPORTED_SPELL {
78    ///<https://wowlab.gg/inspect/spell/225919>
79    pub(crate) const FRACTURE_MH: u32 = 225_919;
80    ///<https://wowlab.gg/inspect/spell/225921>
81    pub(crate) const FRACTURE_OH: u32 = 225_921;
82    ///<https://wowlab.gg/inspect/spell/228478>
83    pub(crate) const SOUL_CLEAVE_DAMAGE: u32 = 228_478;
84}
85pub(crate) mod HERO {
86    pub(crate) mod ALDRACHI_REAVER {
87        pub(crate) mod SPELL {
88            ///<https://wowlab.gg/inspect/spell/444810>
89            pub(crate) const ART_OF_THE_GLAIVE_DAMAGE: u32 = 444_810;
90            ///<https://wowlab.gg/inspect/spell/444806>
91            pub(crate) const FURY_OF_THE_ALDRACHI: u32 = 444_806;
92            ///<https://wowlab.gg/inspect/spell/442294>
93            pub(crate) const REAVERS_GLAIVE: u32 = 442_294;
94            ///<https://wowlab.gg/inspect/spell/444764>
95            pub(crate) const REAVERS_GLAIVE_VENGEANCE: u32 = 444_764;
96            ///<https://wowlab.gg/inspect/spell/442808>
97            pub(crate) const WOUNDED_QUARRY_DAMAGE: u32 = 442_808;
98        }
99        pub(crate) mod AURA {
100            ///<https://wowlab.gg/inspect/spell/444929>
101            pub(crate) const EVASIVE_ACTION: u32 = 444_929;
102            ///<https://wowlab.gg/inspect/spell/442435>
103            pub(crate) const GLAIVE_FLURRY: u32 = 442_435;
104            ///<https://wowlab.gg/inspect/spell/442294>
105            pub(crate) const REAVERS_GLAIVE_BUFF: u32 = 442_294;
106            ///<https://wowlab.gg/inspect/spell/442624>
107            pub(crate) const REAVERS_MARK: u32 = 442_624;
108            ///<https://wowlab.gg/inspect/spell/442442>
109            pub(crate) const RENDING_STRIKE: u32 = 442_442;
110            ///<https://wowlab.gg/inspect/spell/442695>
111            pub(crate) const THRILL_OF_THE_FIGHT: u32 = 442_695;
112        }
113    }
114    pub(crate) mod ANNIHILATOR {
115        pub(crate) mod SPELL {
116            ///<https://wowlab.gg/inspect/spell/1253769>
117            pub(crate) const CATASTROPHE: u32 = 1_253_769;
118            ///<https://wowlab.gg/inspect/spell/1256667>
119            pub(crate) const CATASTROPHE_DOT: u32 = 1_256_667;
120            ///<https://wowlab.gg/inspect/spell/1256307>
121            pub(crate) const DARK_MATTER: u32 = 1_256_307;
122            ///<https://wowlab.gg/inspect/spell/1253805>
123            pub(crate) const FINAL_HOUR: u32 = 1_253_805;
124            ///<https://wowlab.gg/inspect/spell/1279247>
125            pub(crate) const HARNESS_THE_COSMOS: u32 = 1_279_247;
126            ///<https://wowlab.gg/inspect/spell/1256295>
127            pub(crate) const MASS_ACCELERATION: u32 = 1_256_295;
128            ///<https://wowlab.gg/inspect/spell/1253391>
129            pub(crate) const METEORIC_FALL: u32 = 1_253_391;
130            ///<https://wowlab.gg/inspect/spell/1253377>
131            pub(crate) const METEORIC_RISE: u32 = 1_253_377;
132            ///<https://wowlab.gg/inspect/spell/1264130>
133            pub(crate) const METEOR_SHOWER_DAMAGE: u32 = 1_264_130;
134            ///<https://wowlab.gg/inspect/spell/1253817>
135            pub(crate) const OTHERWORLDLY_FOCUS: u32 = 1_253_817;
136            ///<https://wowlab.gg/inspect/spell/1253668>
137            pub(crate) const SWIFT_ERASURE: u32 = 1_253_668;
138            ///<https://wowlab.gg/inspect/spell/1253304>
139            pub(crate) const VOIDFALL: u32 = 1_253_304;
140            ///<https://wowlab.gg/inspect/spell/1256306>
141            pub(crate) const VOIDFALL_METEOR_DAMAGE: u32 = 1_256_306;
142            ///<https://wowlab.gg/inspect/spell/1256353>
143            pub(crate) const WORLD_KILLER: u32 = 1_256_353;
144            ///<https://wowlab.gg/inspect/spell/1256617>
145            pub(crate) const WORLD_KILLER_DAMAGE: u32 = 1_256_617;
146        }
147        pub(crate) mod AURA {
148            ///<https://wowlab.gg/inspect/spell/1256308>
149            pub(crate) const DARK_MATTER: u32 = 1_256_308;
150            ///<https://wowlab.gg/inspect/spell/1256301>
151            pub(crate) const VOIDFALL_BUILDING: u32 = 1_256_301;
152            ///<https://wowlab.gg/inspect/spell/1256322>
153            pub(crate) const VOIDFALL_FINAL_HOUR: u32 = 1_256_322;
154            ///<https://wowlab.gg/inspect/spell/1256302>
155            pub(crate) const VOIDFALL_SPENDING: u32 = 1_256_302;
156        }
157    }
158    pub(crate) mod FEL_SCARRED {
159        pub(crate) mod SPELL {
160            ///<https://wowlab.gg/inspect/spell/451263>
161            pub(crate) const DEMONSURGE_DAMAGE: u32 = 451_263;
162            ///<https://wowlab.gg/inspect/spell/452437>
163            pub(crate) const SPIRIT_BURST: u32 = 452_437;
164            ///<https://wowlab.gg/inspect/spell/453236>
165            pub(crate) const STUDENT_OF_SUFFERING_FURY: u32 = 453_236;
166        }
167        pub(crate) mod AURA {
168            ///<https://wowlab.gg/inspect/spell/452408>
169            pub(crate) const BURNING_BLADES: u32 = 452_408;
170            ///<https://wowlab.gg/inspect/spell/452415>
171            pub(crate) const DEMONIC_INTENSITY: u32 = 452_415;
172            ///<https://wowlab.gg/inspect/spell/452416>
173            pub(crate) const DEMONSURGE: u32 = 452_416;
174            ///<https://wowlab.gg/inspect/spell/453239>
175            pub(crate) const STUDENT_OF_SUFFERING: u32 = 453_239;
176        }
177    }
178}
179static HERO_TREE_ALDRACHI_REAVER_SPELLS: &[(&str, u32)] = &[
180    ("ART_OF_THE_GLAIVE_DAMAGE", 444_810),
181    ("FURY_OF_THE_ALDRACHI", 444_806),
182    ("REAVERS_GLAIVE", 442_294),
183    ("REAVERS_GLAIVE_VENGEANCE", 444_764),
184    ("WOUNDED_QUARRY_DAMAGE", 442_808),
185];
186static HERO_TREE_ALDRACHI_REAVER_AURAS: &[(&str, u32)] = &[
187    ("EVASIVE_ACTION", 444_929),
188    ("GLAIVE_FLURRY", 442_435),
189    ("REAVERS_GLAIVE_BUFF", 442_294),
190    ("REAVERS_MARK", 442_624),
191    ("RENDING_STRIKE", 442_442),
192    ("THRILL_OF_THE_FIGHT", 442_695),
193];
194static HERO_TREE_ANNIHILATOR_SPELLS: &[(&str, u32)] = &[
195    ("CATASTROPHE", 1_253_769),
196    ("CATASTROPHE_DOT", 1_256_667),
197    ("DARK_MATTER", 1_256_307),
198    ("FINAL_HOUR", 1_253_805),
199    ("HARNESS_THE_COSMOS", 1_279_247),
200    ("MASS_ACCELERATION", 1_256_295),
201    ("METEORIC_FALL", 1_253_391),
202    ("METEORIC_RISE", 1_253_377),
203    ("METEOR_SHOWER_DAMAGE", 1_264_130),
204    ("OTHERWORLDLY_FOCUS", 1_253_817),
205    ("SWIFT_ERASURE", 1_253_668),
206    ("VOIDFALL", 1_253_304),
207    ("VOIDFALL_METEOR_DAMAGE", 1_256_306),
208    ("WORLD_KILLER", 1_256_353),
209    ("WORLD_KILLER_DAMAGE", 1_256_617),
210];
211static HERO_TREE_ANNIHILATOR_AURAS: &[(&str, u32)] = &[
212    ("DARK_MATTER", 1_256_308),
213    ("VOIDFALL_BUILDING", 1_256_301),
214    ("VOIDFALL_FINAL_HOUR", 1_256_322),
215    ("VOIDFALL_SPENDING", 1_256_302),
216];
217static HERO_TREE_FEL_SCARRED_SPELLS: &[(&str, u32)] = &[
218    ("DEMONSURGE_DAMAGE", 451_263),
219    ("SPIRIT_BURST", 452_437),
220    ("STUDENT_OF_SUFFERING_FURY", 453_236),
221];
222static HERO_TREE_FEL_SCARRED_AURAS: &[(&str, u32)] = &[
223    ("BURNING_BLADES", 452_408),
224    ("DEMONIC_INTENSITY", 452_415),
225    ("DEMONSURGE", 452_416),
226    ("STUDENT_OF_SUFFERING", 453_239),
227];
228pub(crate) const AURA_SIGIL_OF_FLAME: LocalAuraIdx = LocalAuraIdx::new(0);
229pub(crate) const AURA_SOUL_FRAGMENTS: LocalAuraIdx = LocalAuraIdx::new(1);
230pub(crate) const AURA_REAVERS_GLAIVE: LocalAuraIdx = LocalAuraIdx::new(2);
231pub(crate) const AURA_RENDING_STRIKE: LocalAuraIdx = LocalAuraIdx::new(3);
232pub(crate) const AURA_GLAIVE_FLURRY: LocalAuraIdx = LocalAuraIdx::new(4);
233pub(crate) const AURA_VOIDFALL_BUILDING: LocalAuraIdx = LocalAuraIdx::new(5);
234pub(crate) const AURA_VOIDFALL_SPENDING: LocalAuraIdx = LocalAuraIdx::new(6);
235pub(crate) const AURA_VOIDFALL_FINAL_HOUR: LocalAuraIdx = LocalAuraIdx::new(7);
236pub(crate) const AURA_CATASTROPHE: LocalAuraIdx = LocalAuraIdx::new(8);
237pub(crate) const AURA_DARK_MATTER: LocalAuraIdx = LocalAuraIdx::new(9);
238pub(crate) const AURA_UNTETHERED_RAGE: LocalAuraIdx = LocalAuraIdx::new(10);
239pub(crate) const AURA_SEETHING_ANGER: LocalAuraIdx = LocalAuraIdx::new(11);
240pub(crate) const AURA_COUNT: usize = 12;
241const _: () = assert!(
242    AURA_COUNT == 12, "AURA index ABI: count changed -- update positional hook consumers"
243);
244pub(crate) const SPELL_SOUL_CLEAVE: LocalSpellIdx = LocalSpellIdx::new(0);
245pub(crate) const SPELL_IMMOLATION_AURA: LocalSpellIdx = LocalSpellIdx::new(1);
246pub(crate) const SPELL_FEL_DEVASTATION: LocalSpellIdx = LocalSpellIdx::new(2);
247pub(crate) const SPELL_SIGIL_OF_FLAME: LocalSpellIdx = LocalSpellIdx::new(3);
248pub(crate) const SPELL_SHEAR: LocalSpellIdx = LocalSpellIdx::new(4);
249pub(crate) const SPELL_METAMORPHOSIS: LocalSpellIdx = LocalSpellIdx::new(5);
250pub(crate) const SPELL_THROW_GLAIVE: LocalSpellIdx = LocalSpellIdx::new(6);
251pub(crate) const SPELL_SOUL_CARVER: LocalSpellIdx = LocalSpellIdx::new(7);
252pub(crate) const SPELL_SPIRIT_BOMB: LocalSpellIdx = LocalSpellIdx::new(8);
253pub(crate) const SPELL_SIGIL_OF_SPITE: LocalSpellIdx = LocalSpellIdx::new(9);
254pub(crate) const SPELL_FRACTURE: LocalSpellIdx = LocalSpellIdx::new(10);
255pub(crate) const SPELL_COUNT: usize = 11;
256const _: () = assert!(
257    SPELL_COUNT == 11,
258    "SPELL index ABI: count changed -- update positional hook consumers"
259);
260pub(crate) mod EFFECT {
261    ///<https://wowlab.gg/inspect/spell/321299>
262    pub(crate) const FEL_BLOOD: (u32, u8) = (321_299, 1);
263    ///<https://wowlab.gg/inspect/spell/263642>
264    pub(crate) const FRACTURE_FRAGMENTS: (u32, u8) = (263_642, 1);
265    ///<https://wowlab.gg/inspect/spell/247455>
266    pub(crate) const SPIRIT_BOMB_DAMAGE: (u32, u8) = (247_455, 1);
267    ///<https://wowlab.gg/inspect/spell/1253304>
268    pub(crate) const VOIDFALL_CHANCE: (u32, u8) = (1_253_304, 3);
269    ///<https://wowlab.gg/inspect/spell/1253304>
270    pub(crate) const VOIDFALL_STACKS: (u32, u8) = (1_253_304, 1);
271    ///<https://wowlab.gg/inspect/spell/1256306>
272    pub(crate) const VOIDFALL_METEOR_COEF: (u32, u8) = (1_256_306, 1);
273    ///<https://wowlab.gg/inspect/spell/1256617>
274    pub(crate) const WORLD_KILLER_COEF: (u32, u8) = (1_256_617, 1);
275    ///<https://wowlab.gg/inspect/spell/1256353>
276    pub(crate) const WORLD_KILLER_META_CDR: (u32, u8) = (1_256_353, 3);
277    ///<https://wowlab.gg/inspect/spell/1253769>
278    pub(crate) const CATASTROPHE_PCT: (u32, u8) = (1_253_769, 1);
279    ///<https://wowlab.gg/inspect/spell/1256307>
280    pub(crate) const METEOR_SHOWER_TICKS: (u32, u8) = (1_256_307, 1);
281    ///<https://wowlab.gg/inspect/spell/1264130>
282    pub(crate) const METEOR_SHOWER_COEF: (u32, u8) = (1_264_130, 1);
283    ///<https://wowlab.gg/inspect/spell/1256295>
284    pub(crate) const MASS_ACCELERATION_STACKS: (u32, u8) = (1_256_295, 1);
285    ///<https://wowlab.gg/inspect/spell/1253817>
286    pub(crate) const OTHERWORLDLY_FOCUS_PCT: (u32, u8) = (1_253_817, 1);
287    ///<https://wowlab.gg/inspect/spell/1279247>
288    pub(crate) const HARNESS_THE_COSMOS_PCT: (u32, u8) = (1_279_247, 1);
289}
290static REPORTED_SPELLS: &[(&str, u32)] = &[
291    ("fracture_mh", 225_919),
292    ("fracture_oh", 225_921),
293    ("soul_cleave_damage", 228_478),
294];
295static DECLARED_SPELL_IDS: &[u32] = &[
296    228_477, 258_920, 212_084, 204_596, 203_782, 187_827, 204_157, 207_407, 247_454,
297    390_163, 263_642, 204_598, 203_981, 442_294, 442_442, 442_435, 1_256_301, 1_256_302,
298    1_256_322, 1_256_667, 1_256_308, 1_270_476, 1_270_547, 6603, 6603, 203_747, 204_255,
299    204_598, 225_919, 225_921, 228_478, 247_455, 263_642, 321_299, 1_253_304, 1_253_769,
300    1_253_817, 1_256_295, 1_256_306, 1_256_307, 1_256_353, 1_256_617, 1_256_667,
301    1_264_130, 1_279_247, 225_919, 225_921, 228_478, 444_810, 444_806, 442_294, 444_764,
302    442_808, 444_929, 442_435, 442_294, 442_624, 442_442, 442_695, 1_253_769, 1_256_667,
303    1_256_307, 1_253_805, 1_279_247, 1_256_295, 1_253_391, 1_253_377, 1_264_130,
304    1_253_817, 1_253_668, 1_253_304, 1_256_306, 1_256_353, 1_256_617, 1_256_308,
305    1_256_301, 1_256_322, 1_256_302, 451_263, 452_437, 453_236, 452_408, 452_415,
306    452_416, 453_239,
307];
308static DECLARED_AURA_IDS: &[u32] = &[
309    204_598, 203_981, 442_294, 442_442, 442_435, 1_256_301, 1_256_302, 1_256_322,
310    1_256_667, 1_256_308, 1_270_476, 1_270_547, 444_929, 442_435, 442_294, 442_624,
311    442_442, 442_695, 1_256_308, 1_256_301, 1_256_322, 1_256_302, 452_408, 452_415,
312    452_416, 453_239,
313];
314static TALENTS: &[(&str, u32)] = &[
315    ("SIGIL_OF_SPITE", TALENT::SIGIL_OF_SPITE),
316    ("SOUL_CARVER", TALENT::SOUL_CARVER),
317    ("SPIRIT_BOMB", TALENT::SPIRIT_BOMB),
318    ("UNTETHERED_RAGE_1", TALENT::UNTETHERED_RAGE_1),
319    ("UNTETHERED_RAGE_2", TALENT::UNTETHERED_RAGE_2),
320    ("UNTETHERED_RAGE_3", TALENT::UNTETHERED_RAGE_3),
321];
322fn aura_sigil_of_flame(
323    a: AuraDefinitionDraft,
324    data: &ResolvedGameData,
325) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
326    Ok(
327        a
328            .on_target()
329            .apply_base_from_data(data, 204_598)?
330            .max_stacks(
331                data
332                    .require_aura_max_stacks(
333                        wowlab_types::sim::SpellIdx::from_raw(204_598),
334                    )?,
335            ),
336    )
337}
338fn aura_soul_fragments(
339    a: AuraDefinitionDraft,
340    data: &ResolvedGameData,
341) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
342    a.on_player()
343        .duration_ms(
344            wowlab_engine_combat::validated_milliseconds(
345                f64::from(
346                    data
347                        .require_aura_duration_ms(
348                            wowlab_types::sim::SpellIdx::from_raw(204_255),
349                        )?,
350                ),
351                203_981,
352                "aura.duration_ms",
353            )?,
354        )
355        .apply_periodic_effect_from_data(data, 203_981)?
356        .apply_duration_behavior_from_data(data, 204_255)?
357        .apply_timing_modifiers_from_data(data, 203_981)?
358        .max_stacks(
359            wowlab_engine_combat::validated_max_stacks(5.0, 203_981, "aura.max_stacks")?,
360        )
361        .apply_periodic_behavior_from_data(data, 204_255)
362}
363fn aura_reavers_glaive(
364    a: AuraDefinitionDraft,
365    data: &ResolvedGameData,
366) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
367    Ok(
368        a
369            .on_player()
370            .apply_base_from_data(data, 442_294)?
371            .max_stacks(
372                data
373                    .require_aura_max_stacks(
374                        wowlab_types::sim::SpellIdx::from_raw(442_294),
375                    )?,
376            ),
377    )
378}
379fn aura_rending_strike(
380    a: AuraDefinitionDraft,
381    data: &ResolvedGameData,
382) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
383    Ok(
384        a
385            .on_player()
386            .apply_base_from_data(data, 442_442)?
387            .max_stacks(
388                data
389                    .require_aura_max_stacks(
390                        wowlab_types::sim::SpellIdx::from_raw(442_442),
391                    )?,
392            ),
393    )
394}
395fn aura_glaive_flurry(
396    a: AuraDefinitionDraft,
397    data: &ResolvedGameData,
398) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
399    Ok(
400        a
401            .on_player()
402            .apply_base_from_data(data, 442_435)?
403            .max_stacks(
404                data
405                    .require_aura_max_stacks(
406                        wowlab_types::sim::SpellIdx::from_raw(442_435),
407                    )?,
408            ),
409    )
410}
411fn aura_voidfall_building(
412    a: AuraDefinitionDraft,
413    data: &ResolvedGameData,
414) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
415    Ok(
416        a
417            .on_player()
418            .apply_base_from_data(data, 1_256_301)?
419            .max_stacks(
420                data
421                    .require_aura_max_stacks(
422                        wowlab_types::sim::SpellIdx::from_raw(1_256_301),
423                    )?,
424            ),
425    )
426}
427fn aura_voidfall_spending(
428    a: AuraDefinitionDraft,
429    data: &ResolvedGameData,
430) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
431    Ok(
432        a
433            .on_player()
434            .apply_base_from_data(data, 1_256_302)?
435            .max_stacks(
436                data
437                    .require_aura_max_stacks(
438                        wowlab_types::sim::SpellIdx::from_raw(1_256_302),
439                    )?,
440            ),
441    )
442}
443fn aura_voidfall_final_hour(
444    a: AuraDefinitionDraft,
445    data: &ResolvedGameData,
446) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
447    Ok(
448        a
449            .on_player()
450            .apply_base_from_data(data, 1_256_322)?
451            .max_stacks(
452                data
453                    .require_aura_max_stacks(
454                        wowlab_types::sim::SpellIdx::from_raw(1_256_322),
455                    )?,
456            ),
457    )
458}
459fn aura_catastrophe(
460    a: AuraDefinitionDraft,
461    data: &ResolvedGameData,
462) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
463    a.on_target()
464        .apply_base_from_data(data, 1_256_667)?
465        .max_stacks(
466            data
467                .require_aura_max_stacks(
468                    wowlab_types::sim::SpellIdx::from_raw(1_256_667),
469                )?,
470        )
471        .periodic_residual_damage(
472            wowlab_engine_combat::validated_milliseconds(
473                data.period(wowlab_types::sim::SpellIdx::from_raw(1_256_667), 1),
474                1_256_667,
475                "periodic_residual_damage.tick_ms",
476            )?,
477        )
478        .apply_periodic_behavior_from_data(data, 1_256_667)
479}
480fn aura_dark_matter(
481    a: AuraDefinitionDraft,
482    data: &ResolvedGameData,
483) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
484    Ok(
485        a
486            .on_player()
487            .apply_base_from_data(data, 1_256_308)?
488            .max_stacks(
489                data
490                    .require_aura_max_stacks(
491                        wowlab_types::sim::SpellIdx::from_raw(1_256_308),
492                    )?,
493            ),
494    )
495}
496fn aura_untethered_rage(
497    a: AuraDefinitionDraft,
498    data: &ResolvedGameData,
499) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
500    Ok(
501        a
502            .on_player()
503            .apply_base_from_data(data, 1_270_476)?
504            .max_stacks(
505                data
506                    .require_aura_max_stacks(
507                        wowlab_types::sim::SpellIdx::from_raw(1_270_476),
508                    )?,
509            ),
510    )
511}
512fn aura_seething_anger(
513    a: AuraDefinitionDraft,
514    data: &ResolvedGameData,
515) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
516    Ok(
517        a
518            .on_player()
519            .apply_base_from_data(data, 1_270_547)?
520            .max_stacks(
521                data
522                    .require_aura_max_stacks(
523                        wowlab_types::sim::SpellIdx::from_raw(1_270_547),
524                    )?,
525            ),
526    )
527}
528fn spell_soul_cleave(
529    s: SpellDefinitionDraft,
530    data: &ResolvedGameData,
531) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
532    Ok(
533        s
534            .apply_base_from_data(data, 228_477)?
535            .without_primary_data_damage()
536            .apply_aoe_from_data(data)
537            .on_cast(crate::hooks::vengeance_demon_hunter::soul_cleave_hook),
538    )
539}
540fn spell_immolation_aura(
541    s: SpellDefinitionDraft,
542    data: &ResolvedGameData,
543) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
544    Ok(s.apply_base_from_data(data, 258_920)?.apply_aoe_from_data(data))
545}
546fn spell_fel_devastation(
547    s: SpellDefinitionDraft,
548    data: &ResolvedGameData,
549) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
550    Ok(s.apply_base_from_data(data, 212_084)?.apply_aoe_from_data(data))
551}
552fn spell_sigil_of_flame(
553    s: SpellDefinitionDraft,
554    data: &ResolvedGameData,
555) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
556    Ok(
557        s
558            .apply_base_from_data(data, 204_596)?
559            .damage_ap_from_data(
560                wowlab_engine_domain::dbc::EffectLookup::new(
561                    data,
562                    wowlab_types::sim::EffectRef::new(
563                        wowlab_types::sim::SpellIdx::from_raw(204_598),
564                        1,
565                    ),
566                ),
567            )?
568            .applies_aura(AURA_SIGIL_OF_FLAME)
569            .apply_aoe_from_data(data),
570    )
571}
572fn spell_shear(
573    s: SpellDefinitionDraft,
574    data: &ResolvedGameData,
575) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
576    Ok(s.apply_base_from_data(data, 203_782)?.apply_aoe_from_data(data))
577}
578fn spell_metamorphosis(
579    s: SpellDefinitionDraft,
580    data: &ResolvedGameData,
581) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
582    Ok(
583        s
584            .apply_base_from_data(data, 187_827)?
585            .apply_aoe_from_data(data)
586            .on_cast(crate::hooks::vengeance_demon_hunter::metamorphosis_hook),
587    )
588}
589fn spell_throw_glaive(
590    s: SpellDefinitionDraft,
591    data: &ResolvedGameData,
592) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
593    Ok(s.apply_base_from_data(data, 204_157)?.apply_aoe_from_data(data))
594}
595fn spell_soul_carver(
596    s: SpellDefinitionDraft,
597    data: &ResolvedGameData,
598) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
599    Ok(s.apply_base_from_data(data, 207_407)?.apply_aoe_from_data(data))
600}
601fn spell_spirit_bomb(
602    s: SpellDefinitionDraft,
603    data: &ResolvedGameData,
604) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
605    Ok(
606        s
607            .apply_base_from_data(data, 247_454)?
608            .apply_aoe_from_data(data)
609            .on_cast(crate::hooks::vengeance_demon_hunter::spirit_bomb_hook),
610    )
611}
612fn spell_sigil_of_spite(
613    s: SpellDefinitionDraft,
614    data: &ResolvedGameData,
615) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
616    Ok(s.apply_base_from_data(data, 390_163)?.apply_aoe_from_data(data))
617}
618fn spell_fracture(
619    s: SpellDefinitionDraft,
620    data: &ResolvedGameData,
621) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
622    Ok(
623        s
624            .apply_base_from_data(data, 263_642)?
625            .without_primary_data_damage()
626            .apply_aoe_from_data(data)
627            .on_cast(crate::hooks::vengeance_demon_hunter::fracture_hook),
628    )
629}
630pub(crate) fn build_combat_system(
631    params: &wowlab_engine_ports::HandlerParams<'_>,
632) -> Result<BuiltCombatSystem, wowlab_engine_ports::EngineError> {
633    let builder = BuiltCombatSystem::builder(params.stats.clone())
634        .spec_id(SpecId::Vengeance)
635        .hero_talent_trees(DECLARED_METADATA.hero_talent_trees)
636        .mastery_spell(203_747)
637        .mastery_hook(crate::hooks::vengeance_demon_hunter::mastery)
638        .resource(
639            "fury",
640            params
641                .game_data
642                .power_max(17)
643                .ok_or_else(|| {
644                    wowlab_engine_ports::EngineError::spec_construction(
645                        "missing power-type power_max for type_id 17",
646                    )
647                })?,
648            params
649                .game_data
650                .power_regen_for_max(
651                    17,
652                    params
653                        .game_data
654                        .power_max(17)
655                        .ok_or_else(|| {
656                            wowlab_engine_ports::EngineError::spec_construction(
657                                "missing power-type power_max for type_id 17",
658                            )
659                        })?,
660                )
661                .ok_or_else(|| {
662                    wowlab_engine_ports::EngineError::spec_construction(
663                        "missing power-type power_regen_for_max for type_id 17",
664                    )
665                })?,
666        )
667        .resource_type_id(17)
668        .resource_start(
669            params
670                .game_data
671                .power_default(17)
672                .ok_or_else(|| {
673                    wowlab_engine_ports::EngineError::spec_construction(
674                        "missing power-type power_default for type_id 17",
675                    )
676                })?,
677        )
678        .aura(
679            "sigil_of_flame",
680            AURA::SIGIL_OF_FLAME,
681            |a| aura_sigil_of_flame(a, &params.game_data),
682        )
683        .aura(
684            "soul_fragments",
685            AURA::SOUL_FRAGMENTS,
686            |a| aura_soul_fragments(a, &params.game_data),
687        )
688        .aura(
689            "reavers_glaive",
690            AURA::REAVERS_GLAIVE,
691            |a| aura_reavers_glaive(a, &params.game_data),
692        )
693        .aura(
694            "rending_strike",
695            AURA::RENDING_STRIKE,
696            |a| aura_rending_strike(a, &params.game_data),
697        )
698        .aura(
699            "glaive_flurry",
700            AURA::GLAIVE_FLURRY,
701            |a| aura_glaive_flurry(a, &params.game_data),
702        )
703        .aura(
704            "voidfall_building",
705            AURA::VOIDFALL_BUILDING,
706            |a| aura_voidfall_building(a, &params.game_data),
707        )
708        .aura(
709            "voidfall_spending",
710            AURA::VOIDFALL_SPENDING,
711            |a| aura_voidfall_spending(a, &params.game_data),
712        )
713        .aura(
714            "voidfall_final_hour",
715            AURA::VOIDFALL_FINAL_HOUR,
716            |a| aura_voidfall_final_hour(a, &params.game_data),
717        )
718        .aura(
719            "catastrophe",
720            AURA::CATASTROPHE,
721            |a| aura_catastrophe(a, &params.game_data),
722        )
723        .aura(
724            "dark_matter",
725            AURA::DARK_MATTER,
726            |a| aura_dark_matter(a, &params.game_data),
727        )
728        .aura(
729            "untethered_rage",
730            AURA::UNTETHERED_RAGE,
731            |a| aura_untethered_rage(a, &params.game_data),
732        )
733        .aura(
734            "seething_anger",
735            AURA::SEETHING_ANGER,
736            |a| aura_seething_anger(a, &params.game_data),
737        )
738        .spell(
739            "soul_cleave",
740            SPELL::SOUL_CLEAVE,
741            |s| spell_soul_cleave(s, &params.game_data),
742        )
743        .spell(
744            "immolation_aura",
745            SPELL::IMMOLATION_AURA,
746            |s| spell_immolation_aura(s, &params.game_data),
747        )
748        .spell(
749            "fel_devastation",
750            SPELL::FEL_DEVASTATION,
751            |s| spell_fel_devastation(s, &params.game_data),
752        )
753        .spell(
754            "sigil_of_flame",
755            SPELL::SIGIL_OF_FLAME,
756            |s| spell_sigil_of_flame(s, &params.game_data),
757        )
758        .spell("shear", SPELL::SHEAR, |s| spell_shear(s, &params.game_data))
759        .spell(
760            "metamorphosis",
761            SPELL::METAMORPHOSIS,
762            |s| spell_metamorphosis(s, &params.game_data),
763        )
764        .spell(
765            "throw_glaive",
766            SPELL::THROW_GLAIVE,
767            |s| spell_throw_glaive(s, &params.game_data),
768        )
769        .spell(
770            "soul_carver",
771            SPELL::SOUL_CARVER,
772            |s| spell_soul_carver(s, &params.game_data),
773        )
774        .spell(
775            "spirit_bomb",
776            SPELL::SPIRIT_BOMB,
777            |s| spell_spirit_bomb(s, &params.game_data),
778        )
779        .spell(
780            "sigil_of_spite",
781            SPELL::SIGIL_OF_SPITE,
782            |s| spell_sigil_of_spite(s, &params.game_data),
783        )
784        .spell("fracture", SPELL::FRACTURE, |s| spell_fracture(s, &params.game_data))
785        .auto_attack(|a| {
786            a.spell_id(6603).swing_ms(2600).apply_base_from_data(&params.game_data)
787        })
788        .auto_attack(|a| {
789            a.spell_id(6603).swing_ms(2600).apply_base_from_data(&params.game_data)
790        })
791        .game_data(params.game_data.clone())
792        .talent_spell_ids(TALENTS)
793        .talent_selections(params.talent_selections)
794        .set_bonus_auras(params.set_bonus_auras)
795        .encounter(params.encounter.clone());
796    let builder = crate::generated::items::register_equipped(
797        builder,
798        &params.game_data,
799        params.equipped_items,
800    )?;
801
802    builder
803        .build(params.rotation)
804        .map_err(wowlab_engine_ports::EngineError::rotation_compile)
805}
806fn new_handler(
807    params: wowlab_engine_ports::HandlerParams<'_>,
808) -> Result<Box<dyn SpecHandler>, wowlab_engine_ports::EngineError> {
809    let handler = crate::composition::compose_handler(
810        build_combat_system,
811        &params,
812        crate::hooks::vengeance_demon_hunter::VengeanceHandler::try_new,
813    )?;
814
815    Ok(Box::new(handler))
816}
817static DECLARED_METADATA: DeclaredSpecMetadata = DeclaredSpecMetadata {
818    primary_resource: ResourceType::Fury,
819    secondary_resource: None,
820    spell_ids: DECLARED_SPELL_IDS,
821    aura_ids: DECLARED_AURA_IDS,
822    server_proc_entries: &[],
823    talents: TALENTS,
824    rotation_field_schema: &[],
825    metrics_plugin_id: None,
826    hero_talent_trees: &[
827        HeroTalentTreeDesc {
828            name: "Aldrachi Reaver",
829            spells: HERO_TREE_ALDRACHI_REAVER_SPELLS,
830            auras: HERO_TREE_ALDRACHI_REAVER_AURAS,
831        },
832        HeroTalentTreeDesc {
833            name: "Annihilator",
834            spells: HERO_TREE_ANNIHILATOR_SPELLS,
835            auras: HERO_TREE_ANNIHILATOR_AURAS,
836        },
837        HeroTalentTreeDesc {
838            name: "Fel Scarred",
839            spells: HERO_TREE_FEL_SCARRED_SPELLS,
840            auras: HERO_TREE_FEL_SCARRED_AURAS,
841        },
842    ],
843    reported_spells: REPORTED_SPELLS,
844    masked_passive_effects: &[],
845    passive_effect_overrides: &[],
846};
847pub(super) const SPEC_DESCRIPTOR: SpecDescriptor = SpecDescriptor {
848    spec_id: SpecId::Vengeance,
849    display_name: "Vengeance Demon Hunter",
850    metadata: DECLARED_METADATA,
851    handler_factory: new_handler,
852};
853wowlab_engine_combat::smoke_test!(build_combat_system);