Skip to main content

wowlab_engine_content/generated/specs/
havoc_demon_hunter.rs

1//! @generated by codegen-cli from manifests/specs/demon_hunter/havoc/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/162794>
15    pub(crate) const CHAOS_STRIKE: u32 = 162_794;
16    ///<https://wowlab.gg/inspect/spell/201427>
17    pub(crate) const ANNIHILATION: u32 = 201_427;
18    ///<https://wowlab.gg/inspect/spell/188499>
19    pub(crate) const BLADE_DANCE: u32 = 188_499;
20    ///<https://wowlab.gg/inspect/spell/210152>
21    pub(crate) const DEATH_SWEEP: u32 = 210_152;
22    ///<https://wowlab.gg/inspect/spell/191427>
23    pub(crate) const METAMORPHOSIS: u32 = 191_427;
24    ///<https://wowlab.gg/inspect/spell/185123>
25    pub(crate) const THROW_GLAIVE: u32 = 185_123;
26    ///<https://wowlab.gg/inspect/spell/195072>
27    pub(crate) const FEL_RUSH: u32 = 195_072;
28    ///<https://wowlab.gg/inspect/spell/198793>
29    pub(crate) const VENGEFUL_RETREAT: u32 = 198_793;
30    ///<https://wowlab.gg/inspect/spell/258860>
31    pub(crate) const ESSENCE_BREAK: u32 = 258_860;
32    ///<https://wowlab.gg/inspect/spell/232893>
33    pub(crate) const FELBLADE: u32 = 232_893;
34    ///<https://wowlab.gg/inspect/spell/198013>
35    pub(crate) const EYE_BEAM: u32 = 198_013;
36    ///<https://wowlab.gg/inspect/spell/452497>
37    pub(crate) const ABYSSAL_GAZE: u32 = 452_497;
38    ///<https://wowlab.gg/inspect/spell/258920>
39    pub(crate) const IMMOLATION_AURA: u32 = 258_920;
40    ///<https://wowlab.gg/inspect/spell/370965>
41    pub(crate) const THE_HUNT: u32 = 370_965;
42}
43pub(crate) mod AURA {
44    ///<https://wowlab.gg/inspect/spell/162264>
45    pub(crate) const METAMORPHOSIS: u32 = 162_264;
46    ///<https://wowlab.gg/inspect/spell/320338>
47    pub(crate) const ESSENCE_BREAK: u32 = 320_338;
48    ///<https://wowlab.gg/inspect/spell/427640>
49    pub(crate) const INERTIA: u32 = 427_640;
50    ///<https://wowlab.gg/inspect/spell/1214887>
51    pub(crate) const CYCLE_OF_HATRED: u32 = 1_214_887;
52    ///<https://wowlab.gg/inspect/spell/343312>
53    pub(crate) const FURIOUS_GAZE: u32 = 343_312;
54    ///<https://wowlab.gg/inspect/spell/453239>
55    pub(crate) const STUDENT_OF_SUFFERING: u32 = 453_239;
56    ///<https://wowlab.gg/inspect/spell/452489>
57    pub(crate) const DEMONIC_INTENSITY: u32 = 452_489;
58    ///<https://wowlab.gg/inspect/spell/1271144>
59    pub(crate) const EMPOWERED_EYE_BEAM: u32 = 1_271_144;
60    ///<https://wowlab.gg/inspect/spell/442294>
61    pub(crate) const REAVERS_GLAIVE: u32 = 442_294;
62    ///<https://wowlab.gg/inspect/spell/442266>
63    pub(crate) const EXERGY: u32 = 442_266;
64    ///<https://wowlab.gg/inspect/spell/258920>
65    pub(crate) const IMMOLATION_AURA: u32 = 258_920;
66    ///<https://wowlab.gg/inspect/spell/370969>
67    pub(crate) const THE_HUNT_DOT: u32 = 370_969;
68    ///<https://wowlab.gg/inspect/spell/453177>
69    pub(crate) const BURNING_BLADES: u32 = 453_177;
70    ///<https://wowlab.gg/inspect/spell/390155>
71    pub(crate) const SERRATED_GLAIVE: u32 = 390_155;
72    ///<https://wowlab.gg/inspect/spell/390181>
73    pub(crate) const SOULSCAR: u32 = 390_181;
74}
75pub(crate) mod TALENT {
76    ///<https://wowlab.gg/inspect/spell/203550>
77    pub(crate) const BLIND_FURY: u32 = 203_550;
78    ///<https://wowlab.gg/inspect/spell/388112>
79    pub(crate) const CHAOTIC_TRANSFORMATION: u32 = 388_112;
80    ///<https://wowlab.gg/inspect/spell/258887>
81    pub(crate) const CYCLE_OF_HATRED: u32 = 258_887;
82    ///<https://wowlab.gg/inspect/spell/213410>
83    pub(crate) const DEMONIC: u32 = 213_410;
84    ///<https://wowlab.gg/inspect/spell/258860>
85    pub(crate) const ESSENCE_BREAK: u32 = 258_860;
86    ///<https://wowlab.gg/inspect/spell/1270898>
87    pub(crate) const ETERNAL_HUNT: u32 = 1_270_898;
88    ///<https://wowlab.gg/inspect/spell/1270900>
89    pub(crate) const ETERNAL_HUNT_RANK_2: u32 = 1_270_900;
90    ///<https://wowlab.gg/inspect/spell/198013>
91    pub(crate) const EYE_BEAM: u32 = 198_013;
92    ///<https://wowlab.gg/inspect/spell/232893>
93    pub(crate) const FELBLADE: u32 = 232_893;
94    ///<https://wowlab.gg/inspect/spell/206416>
95    pub(crate) const FIRST_BLOOD: u32 = 206_416;
96    ///<https://wowlab.gg/inspect/spell/343311>
97    pub(crate) const FURIOUS_GAZE: u32 = 343_311;
98    ///<https://wowlab.gg/inspect/spell/393029>
99    pub(crate) const FURIOUS_THROWS: u32 = 393_029;
100    ///<https://wowlab.gg/inspect/spell/1220506>
101    pub(crate) const SCREAMING_BRUTALITY: u32 = 1_220_506;
102    ///<https://wowlab.gg/inspect/spell/390154>
103    pub(crate) const SERRATED_GLAIVE: u32 = 390_154;
104    ///<https://wowlab.gg/inspect/spell/388106>
105    pub(crate) const SOULSCAR: u32 = 388_106;
106    ///<https://wowlab.gg/inspect/spell/370965>
107    pub(crate) const THE_HUNT: u32 = 370_965;
108}
109pub(crate) mod REPORTED_SPELL {
110    ///<https://wowlab.gg/inspect/spell/227518>
111    pub(crate) const ANNIHILATION_DAMAGE_1: u32 = 227_518;
112    ///<https://wowlab.gg/inspect/spell/201428>
113    pub(crate) const ANNIHILATION_DAMAGE_2: u32 = 201_428;
114    ///<https://wowlab.gg/inspect/spell/6603>
115    pub(crate) const AUTO_ATTACK: u32 = 6603;
116    ///<https://wowlab.gg/inspect/spell/199552>
117    pub(crate) const BLADE_DANCE_DAMAGE: u32 = 199_552;
118    ///<https://wowlab.gg/inspect/spell/200685>
119    pub(crate) const BLADE_DANCE_DAMAGE_4: u32 = 200_685;
120    ///<https://wowlab.gg/inspect/spell/391374>
121    pub(crate) const BLADE_DANCE_FIRST_BLOOD: u32 = 391_374;
122    ///<https://wowlab.gg/inspect/spell/391378>
123    pub(crate) const BLADE_DANCE_FIRST_BLOOD_4: u32 = 391_378;
124    ///<https://wowlab.gg/inspect/spell/453177>
125    pub(crate) const BURNING_BLADES: u32 = 453_177;
126    ///<https://wowlab.gg/inspect/spell/222031>
127    pub(crate) const CHAOS_STRIKE_DAMAGE_1: u32 = 222_031;
128    ///<https://wowlab.gg/inspect/spell/199547>
129    pub(crate) const CHAOS_STRIKE_DAMAGE_2: u32 = 199_547;
130    ///<https://wowlab.gg/inspect/spell/393055>
131    pub(crate) const DEATH_SWEEP_FIRST_BLOOD: u32 = 393_055;
132    ///<https://wowlab.gg/inspect/spell/393054>
133    pub(crate) const DEATH_SWEEP_FIRST_BLOOD_4: u32 = 393_054;
134    ///<https://wowlab.gg/inspect/spell/203796>
135    pub(crate) const DEMON_BLADES: u32 = 203_796;
136    ///<https://wowlab.gg/inspect/spell/198030>
137    pub(crate) const EYE_BEAM_TICK: u32 = 198_030;
138    ///<https://wowlab.gg/inspect/spell/192611>
139    pub(crate) const FEL_RUSH_DAMAGE: u32 = 192_611;
140    ///<https://wowlab.gg/inspect/spell/213243>
141    pub(crate) const FELBLADE_DAMAGE: u32 = 213_243;
142    ///<https://wowlab.gg/inspect/spell/258921>
143    pub(crate) const IMMOLATION_AURA_DAMAGE: u32 = 258_921;
144    ///<https://wowlab.gg/inspect/spell/390181>
145    pub(crate) const SOULSCAR: u32 = 390_181;
146    ///<https://wowlab.gg/inspect/spell/370966>
147    pub(crate) const THE_HUNT_DAMAGE: u32 = 370_966;
148    ///<https://wowlab.gg/inspect/spell/337819>
149    pub(crate) const THROW_GLAIVE_DAMAGE: u32 = 337_819;
150    ///<https://wowlab.gg/inspect/spell/393035>
151    pub(crate) const THROW_GLAIVE_FURIOUS_THROWS: u32 = 393_035;
152    ///<https://wowlab.gg/inspect/spell/198813>
153    pub(crate) const VENGEFUL_RETREAT_DAMAGE: u32 = 198_813;
154}
155pub(crate) mod HERO {
156    pub(crate) mod ALDRACHI_REAVER {
157        pub(crate) mod SPELL {
158            ///<https://wowlab.gg/inspect/spell/444810>
159            pub(crate) const ART_OF_THE_GLAIVE_DAMAGE: u32 = 444_810;
160            ///<https://wowlab.gg/inspect/spell/444806>
161            pub(crate) const FURY_OF_THE_ALDRACHI: u32 = 444_806;
162            ///<https://wowlab.gg/inspect/spell/442294>
163            pub(crate) const REAVERS_GLAIVE: u32 = 442_294;
164            ///<https://wowlab.gg/inspect/spell/444686>
165            pub(crate) const REAVERS_GLAIVE_HAVOC: u32 = 444_686;
166            ///<https://wowlab.gg/inspect/spell/442808>
167            pub(crate) const WOUNDED_QUARRY_DAMAGE: u32 = 442_808;
168        }
169        pub(crate) mod AURA {
170            ///<https://wowlab.gg/inspect/spell/444929>
171            pub(crate) const EVASIVE_ACTION: u32 = 444_929;
172            ///<https://wowlab.gg/inspect/spell/442435>
173            pub(crate) const GLAIVE_FLURRY: u32 = 442_435;
174            ///<https://wowlab.gg/inspect/spell/442294>
175            pub(crate) const REAVERS_GLAIVE_BUFF: u32 = 442_294;
176            ///<https://wowlab.gg/inspect/spell/442624>
177            pub(crate) const REAVERS_MARK: u32 = 442_624;
178            ///<https://wowlab.gg/inspect/spell/442442>
179            pub(crate) const RENDING_STRIKE: u32 = 442_442;
180            ///<https://wowlab.gg/inspect/spell/442695>
181            pub(crate) const THRILL_OF_THE_FIGHT: u32 = 442_695;
182        }
183    }
184    pub(crate) mod FEL_SCARRED {
185        pub(crate) mod SPELL {
186            ///<https://wowlab.gg/inspect/spell/452408>
187            pub(crate) const BURNING_BLADES: u32 = 452_408;
188            ///<https://wowlab.gg/inspect/spell/452415>
189            pub(crate) const DEMONIC_INTENSITY: u32 = 452_415;
190            ///<https://wowlab.gg/inspect/spell/452402>
191            pub(crate) const DEMONSURGE: u32 = 452_402;
192            ///<https://wowlab.gg/inspect/spell/452437>
193            pub(crate) const SPIRIT_BURST: u32 = 452_437;
194            ///<https://wowlab.gg/inspect/spell/452412>
195            pub(crate) const STUDENT_OF_SUFFERING: u32 = 452_412;
196            ///<https://wowlab.gg/inspect/spell/453236>
197            pub(crate) const STUDENT_OF_SUFFERING_FURY: u32 = 453_236;
198            ///<https://wowlab.gg/inspect/spell/1272453>
199            pub(crate) const VOLATILE_INSTINCT: u32 = 1_272_453;
200        }
201        pub(crate) mod AURA {
202            ///<https://wowlab.gg/inspect/spell/452416>
203            pub(crate) const DEMONSURGE: u32 = 452_416;
204            ///<https://wowlab.gg/inspect/spell/453239>
205            pub(crate) const STUDENT_OF_SUFFERING: u32 = 453_239;
206        }
207    }
208}
209static HERO_TREE_ALDRACHI_REAVER_SPELLS: &[(&str, u32)] = &[
210    ("ART_OF_THE_GLAIVE_DAMAGE", 444_810),
211    ("FURY_OF_THE_ALDRACHI", 444_806),
212    ("REAVERS_GLAIVE", 442_294),
213    ("REAVERS_GLAIVE_HAVOC", 444_686),
214    ("WOUNDED_QUARRY_DAMAGE", 442_808),
215];
216static HERO_TREE_ALDRACHI_REAVER_AURAS: &[(&str, u32)] = &[
217    ("EVASIVE_ACTION", 444_929),
218    ("GLAIVE_FLURRY", 442_435),
219    ("REAVERS_GLAIVE_BUFF", 442_294),
220    ("REAVERS_MARK", 442_624),
221    ("RENDING_STRIKE", 442_442),
222    ("THRILL_OF_THE_FIGHT", 442_695),
223];
224static HERO_TREE_FEL_SCARRED_SPELLS: &[(&str, u32)] = &[
225    ("BURNING_BLADES", 452_408),
226    ("DEMONIC_INTENSITY", 452_415),
227    ("DEMONSURGE", 452_402),
228    ("SPIRIT_BURST", 452_437),
229    ("STUDENT_OF_SUFFERING", 452_412),
230    ("STUDENT_OF_SUFFERING_FURY", 453_236),
231    ("VOLATILE_INSTINCT", 1_272_453),
232];
233static HERO_TREE_FEL_SCARRED_AURAS: &[(&str, u32)] = &[
234    ("DEMONSURGE", 452_416),
235    ("STUDENT_OF_SUFFERING", 453_239),
236];
237pub(crate) const AURA_METAMORPHOSIS: LocalAuraIdx = LocalAuraIdx::new(0);
238pub(crate) const AURA_ESSENCE_BREAK: LocalAuraIdx = LocalAuraIdx::new(1);
239pub(crate) const AURA_INERTIA: LocalAuraIdx = LocalAuraIdx::new(2);
240pub(crate) const AURA_CYCLE_OF_HATRED: LocalAuraIdx = LocalAuraIdx::new(3);
241pub(crate) const AURA_FURIOUS_GAZE: LocalAuraIdx = LocalAuraIdx::new(4);
242pub(crate) const AURA_STUDENT_OF_SUFFERING: LocalAuraIdx = LocalAuraIdx::new(5);
243pub(crate) const AURA_DEMONIC_INTENSITY: LocalAuraIdx = LocalAuraIdx::new(6);
244pub(crate) const AURA_EMPOWERED_EYE_BEAM: LocalAuraIdx = LocalAuraIdx::new(7);
245pub(crate) const AURA_REAVERS_GLAIVE: LocalAuraIdx = LocalAuraIdx::new(8);
246pub(crate) const AURA_EXERGY: LocalAuraIdx = LocalAuraIdx::new(9);
247pub(crate) const AURA_IMMOLATION_AURA: LocalAuraIdx = LocalAuraIdx::new(10);
248pub(crate) const AURA_THE_HUNT_DOT: LocalAuraIdx = LocalAuraIdx::new(11);
249pub(crate) const AURA_BURNING_BLADES: LocalAuraIdx = LocalAuraIdx::new(12);
250pub(crate) const AURA_SERRATED_GLAIVE: LocalAuraIdx = LocalAuraIdx::new(13);
251pub(crate) const AURA_SOULSCAR: LocalAuraIdx = LocalAuraIdx::new(14);
252pub(crate) const AURA_COUNT: usize = 15;
253const _: () = assert!(
254    AURA_COUNT == 15, "AURA index ABI: count changed -- update positional hook consumers"
255);
256pub(crate) const SPELL_CHAOS_STRIKE: LocalSpellIdx = LocalSpellIdx::new(0);
257pub(crate) const SPELL_ANNIHILATION: LocalSpellIdx = LocalSpellIdx::new(1);
258pub(crate) const SPELL_BLADE_DANCE: LocalSpellIdx = LocalSpellIdx::new(2);
259pub(crate) const SPELL_DEATH_SWEEP: LocalSpellIdx = LocalSpellIdx::new(3);
260pub(crate) const SPELL_METAMORPHOSIS: LocalSpellIdx = LocalSpellIdx::new(4);
261pub(crate) const SPELL_THROW_GLAIVE: LocalSpellIdx = LocalSpellIdx::new(5);
262pub(crate) const SPELL_FEL_RUSH: LocalSpellIdx = LocalSpellIdx::new(6);
263pub(crate) const SPELL_VENGEFUL_RETREAT: LocalSpellIdx = LocalSpellIdx::new(7);
264pub(crate) const SPELL_ESSENCE_BREAK: LocalSpellIdx = LocalSpellIdx::new(8);
265pub(crate) const SPELL_FELBLADE: LocalSpellIdx = LocalSpellIdx::new(9);
266pub(crate) const SPELL_EYE_BEAM: LocalSpellIdx = LocalSpellIdx::new(10);
267pub(crate) const SPELL_ABYSSAL_GAZE: LocalSpellIdx = LocalSpellIdx::new(11);
268pub(crate) const SPELL_IMMOLATION_AURA: LocalSpellIdx = LocalSpellIdx::new(12);
269pub(crate) const SPELL_THE_HUNT: LocalSpellIdx = LocalSpellIdx::new(13);
270pub(crate) const SPELL_COUNT: usize = 14;
271const _: () = assert!(
272    SPELL_COUNT == 14,
273    "SPELL index ABI: count changed -- update positional hook consumers"
274);
275pub(crate) mod EFFECT {
276    ///<https://wowlab.gg/inspect/spell/200685>
277    pub(crate) const BLADE_DANCE_FINAL: (u32, u8) = (200_685, 2);
278    ///<https://wowlab.gg/inspect/spell/199552>
279    pub(crate) const BLADE_DANCE_HIT: (u32, u8) = (199_552, 2);
280    ///<https://wowlab.gg/inspect/spell/203550>
281    pub(crate) const BLIND_FURY_FURY: (u32, u8) = (203_550, 3);
282    ///<https://wowlab.gg/inspect/spell/452408>
283    pub(crate) const BURNING_BLADES_FRACTION: (u32, u8) = (452_408, 1);
284    ///<https://wowlab.gg/inspect/spell/193840>
285    pub(crate) const CHAOS_STRIKE_FURY_REFUND: (u32, u8) = (193_840, 1);
286    ///<https://wowlab.gg/inspect/spell/197125>
287    pub(crate) const CHAOS_STRIKE_REFUND_PROC: (u32, u8) = (197_125, 1);
288    ///<https://wowlab.gg/inspect/spell/258887>
289    pub(crate) const CYCLE_OF_HATRED_CDR: (u32, u8) = (258_887, 1);
290    ///<https://wowlab.gg/inspect/spell/393054>
291    pub(crate) const DEATH_SWEEP_FIRST_BLOOD_FINAL: (u32, u8) = (393_054, 2);
292    ///<https://wowlab.gg/inspect/spell/393055>
293    pub(crate) const DEATH_SWEEP_FIRST_BLOOD_HIT: (u32, u8) = (393_055, 2);
294    ///<https://wowlab.gg/inspect/spell/213410>
295    pub(crate) const DEMONIC_EXTENSION: (u32, u8) = (213_410, 1);
296    ///<https://wowlab.gg/inspect/spell/452416>
297    pub(crate) const DEMONSURGE_DAMAGE: (u32, u8) = (452_416, 1);
298    ///<https://wowlab.gg/inspect/spell/452416>
299    pub(crate) const DEMONSURGE_STACK_PCT: (u32, u8) = (452_416, 2);
300    ///<https://wowlab.gg/inspect/spell/203796>
301    pub(crate) const DEMON_BLADES_DAMAGE: (u32, u8) = (203_796, 1);
302    ///<https://wowlab.gg/inspect/spell/203796>
303    pub(crate) const DEMON_BLADES_FURY: (u32, u8) = (203_796, 2);
304    ///<https://wowlab.gg/inspect/spell/1287949>
305    pub(crate) const EMPOWERED_EYE_BEAM_DAMAGE: (u32, u8) = (1_287_949, 1);
306    ///<https://wowlab.gg/inspect/spell/1270900>
307    pub(crate) const ETERNAL_HUNT_COOLDOWN_MS: (u32, u8) = (1_270_900, 2);
308    ///<https://wowlab.gg/inspect/spell/1270900>
309    pub(crate) const ETERNAL_HUNT_DAMAGE_PCT: (u32, u8) = (1_270_900, 1);
310    ///<https://wowlab.gg/inspect/spell/1270900>
311    pub(crate) const ETERNAL_HUNT_PERIODIC_PCT: (u32, u8) = (1_270_900, 4);
312    ///<https://wowlab.gg/inspect/spell/198030>
313    pub(crate) const EYE_BEAM_DAMAGE: (u32, u8) = (198_030, 1);
314    ///<https://wowlab.gg/inspect/spell/391378>
315    pub(crate) const FIRST_BLOOD_FINAL: (u32, u8) = (391_378, 2);
316    ///<https://wowlab.gg/inspect/spell/391374>
317    pub(crate) const FIRST_BLOOD_HIT: (u32, u8) = (391_374, 2);
318    ///<https://wowlab.gg/inspect/spell/206416>
319    pub(crate) const FIRST_BLOOD_MULT: (u32, u8) = (206_416, 1);
320    ///<https://wowlab.gg/inspect/spell/393035>
321    pub(crate) const FURIOUS_THROWS_DAMAGE: (u32, u8) = (393_035, 1);
322    ///<https://wowlab.gg/inspect/spell/212612>
323    pub(crate) const HAVOC_AURA_DIRECT: (u32, u8) = (212_612, 1);
324    ///<https://wowlab.gg/inspect/spell/185164>
325    pub(crate) const MASTERY_DIRECT_BONUS: (u32, u8) = (185_164, 1);
326    ///<https://wowlab.gg/inspect/spell/185164>
327    pub(crate) const MASTERY_PERIODIC_BONUS: (u32, u8) = (185_164, 2);
328    ///<https://wowlab.gg/inspect/spell/1220506>
329    pub(crate) const SB_FULL_PCT: (u32, u8) = (1_220_506, 3);
330    ///<https://wowlab.gg/inspect/spell/1220506>
331    pub(crate) const SB_SLASH_CHANCE: (u32, u8) = (1_220_506, 2);
332    ///<https://wowlab.gg/inspect/spell/1220506>
333    pub(crate) const SB_SLASH_PCT: (u32, u8) = (1_220_506, 1);
334    ///<https://wowlab.gg/inspect/spell/390154>
335    pub(crate) const SERRATED_GLAIVE_PCT: (u32, u8) = (390_154, 1);
336    ///<https://wowlab.gg/inspect/spell/388106>
337    pub(crate) const SOULSCAR_FRACTION: (u32, u8) = (388_106, 1);
338    ///<https://wowlab.gg/inspect/spell/337819>
339    pub(crate) const THROW_GLAIVE_DAMAGE: (u32, u8) = (337_819, 1);
340}
341static REPORTED_SPELLS: &[(&str, u32)] = &[
342    ("annihilation_damage_1", 227_518),
343    ("annihilation_damage_2", 201_428),
344    ("auto_attack", 6603),
345    ("blade_dance_damage", 199_552),
346    ("blade_dance_damage_4", 200_685),
347    ("blade_dance_first_blood", 391_374),
348    ("blade_dance_first_blood_4", 391_378),
349    ("burning_blades", 453_177),
350    ("chaos_strike_damage_1", 222_031),
351    ("chaos_strike_damage_2", 199_547),
352    ("death_sweep_first_blood", 393_055),
353    ("death_sweep_first_blood_4", 393_054),
354    ("demon_blades", 203_796),
355    ("eye_beam_tick", 198_030),
356    ("fel_rush_damage", 192_611),
357    ("felblade_damage", 213_243),
358    ("immolation_aura_damage", 258_921),
359    ("soulscar", 390_181),
360    ("the_hunt_damage", 370_966),
361    ("throw_glaive_damage", 337_819),
362    ("throw_glaive_furious_throws", 393_035),
363    ("vengeful_retreat_damage", 198_813),
364];
365static DECLARED_SPELL_IDS: &[u32] = &[
366    162_794, 201_427, 188_499, 210_152, 191_427, 185_123, 195_072, 198_793, 258_860,
367    232_893, 198_013, 452_497, 258_920, 370_965, 162_264, 320_338, 427_640, 1_214_887,
368    343_312, 453_239, 452_489, 1_271_144, 442_294, 442_266, 258_920, 370_969, 453_177,
369    390_155, 390_181, 6603, 6603, 6603, 185_164, 192_611, 193_840, 197_125, 198_030,
370    198_813, 199_547, 199_552, 200_685, 201_428, 203_550, 203_796, 206_416, 212_612,
371    213_243, 213_410, 222_031, 227_518, 258_887, 258_920, 258_921, 258_922, 337_819,
372    370_966, 388_106, 390_154, 390_181, 391_374, 391_378, 393_035, 393_054, 393_055,
373    452_408, 452_416, 453_177, 453_236, 453_239, 1_220_506, 1_270_900, 1_287_949,
374    227_518, 201_428, 6603, 199_552, 200_685, 391_374, 391_378, 453_177, 222_031,
375    199_547, 393_055, 393_054, 203_796, 198_030, 192_611, 213_243, 258_921, 390_181,
376    370_966, 337_819, 393_035, 198_813, 444_810, 444_806, 442_294, 444_686, 442_808,
377    444_929, 442_435, 442_294, 442_624, 442_442, 442_695, 452_408, 452_415, 452_402,
378    452_437, 452_412, 453_236, 1_272_453, 452_416, 453_239,
379];
380static DECLARED_AURA_IDS: &[u32] = &[
381    162_264, 320_338, 427_640, 1_214_887, 343_312, 453_239, 452_489, 1_271_144, 442_294,
382    442_266, 258_920, 370_969, 453_177, 390_155, 390_181, 444_929, 442_435, 442_294,
383    442_624, 442_442, 442_695, 452_416, 453_239,
384];
385static TALENTS: &[(&str, u32)] = &[
386    ("BLIND_FURY", TALENT::BLIND_FURY),
387    ("CHAOTIC_TRANSFORMATION", TALENT::CHAOTIC_TRANSFORMATION),
388    ("CYCLE_OF_HATRED", TALENT::CYCLE_OF_HATRED),
389    ("DEMONIC", TALENT::DEMONIC),
390    ("ESSENCE_BREAK", TALENT::ESSENCE_BREAK),
391    ("ETERNAL_HUNT", TALENT::ETERNAL_HUNT),
392    ("ETERNAL_HUNT_RANK_2", TALENT::ETERNAL_HUNT_RANK_2),
393    ("EYE_BEAM", TALENT::EYE_BEAM),
394    ("FELBLADE", TALENT::FELBLADE),
395    ("FIRST_BLOOD", TALENT::FIRST_BLOOD),
396    ("FURIOUS_GAZE", TALENT::FURIOUS_GAZE),
397    ("FURIOUS_THROWS", TALENT::FURIOUS_THROWS),
398    ("SCREAMING_BRUTALITY", TALENT::SCREAMING_BRUTALITY),
399    ("SERRATED_GLAIVE", TALENT::SERRATED_GLAIVE),
400    ("SOULSCAR", TALENT::SOULSCAR),
401    ("THE_HUNT", TALENT::THE_HUNT),
402];
403fn aura_metamorphosis(
404    a: AuraDefinitionDraft,
405    data: &ResolvedGameData,
406) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
407    Ok(
408        a
409            .on_player()
410            .apply_base_from_data(data, 162_264)?
411            .max_stacks(
412                data
413                    .require_aura_max_stacks(
414                        wowlab_types::sim::SpellIdx::from_raw(162_264),
415                    )?,
416            ),
417    )
418}
419fn aura_essence_break(
420    a: AuraDefinitionDraft,
421    data: &ResolvedGameData,
422) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
423    Ok(
424        a
425            .on_target()
426            .apply_base_from_data(data, 320_338)?
427            .max_stacks(
428                data
429                    .require_aura_max_stacks(
430                        wowlab_types::sim::SpellIdx::from_raw(320_338),
431                    )?,
432            ),
433    )
434}
435fn aura_inertia(
436    a: AuraDefinitionDraft,
437    data: &ResolvedGameData,
438) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
439    Ok(
440        a
441            .on_player()
442            .apply_base_from_data(data, 427_640)?
443            .max_stacks(
444                data
445                    .require_aura_max_stacks(
446                        wowlab_types::sim::SpellIdx::from_raw(427_640),
447                    )?,
448            ),
449    )
450}
451fn aura_cycle_of_hatred(
452    a: AuraDefinitionDraft,
453    data: &ResolvedGameData,
454) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
455    Ok(
456        a
457            .on_player()
458            .apply_base_from_data(data, 1_214_887)?
459            .max_stacks(
460                data
461                    .require_aura_max_stacks(
462                        wowlab_types::sim::SpellIdx::from_raw(1_214_887),
463                    )?,
464            ),
465    )
466}
467fn aura_furious_gaze(
468    a: AuraDefinitionDraft,
469    data: &ResolvedGameData,
470) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
471    Ok(
472        a
473            .on_player()
474            .apply_base_from_data(data, 343_312)?
475            .max_stacks(
476                data
477                    .require_aura_max_stacks(
478                        wowlab_types::sim::SpellIdx::from_raw(343_312),
479                    )?,
480            ),
481    )
482}
483fn aura_student_of_suffering(
484    a: AuraDefinitionDraft,
485    data: &ResolvedGameData,
486) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
487    a.on_player()
488        .apply_base_from_data(data, 453_239)?
489        .max_stacks(
490            data.require_aura_max_stacks(wowlab_types::sim::SpellIdx::from_raw(453_239))?,
491        )
492        .periodic_resource(
493            wowlab_engine_combat::validated_milliseconds(
494                data.period(wowlab_types::sim::SpellIdx::from_raw(453_239), 2),
495                453_239,
496                "periodic_resource.tick_ms",
497            )?,
498            data.base_points(wowlab_types::sim::SpellIdx::from_raw(453_236), 1),
499        )
500        .apply_periodic_behavior_from_data(data, 453_239)
501}
502fn aura_demonic_intensity(
503    a: AuraDefinitionDraft,
504    data: &ResolvedGameData,
505) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
506    Ok(
507        a
508            .on_player()
509            .apply_base_from_data(data, 452_489)?
510            .max_stacks(
511                data
512                    .require_aura_max_stacks(
513                        wowlab_types::sim::SpellIdx::from_raw(452_489),
514                    )?,
515            ),
516    )
517}
518fn aura_empowered_eye_beam(
519    a: AuraDefinitionDraft,
520    data: &ResolvedGameData,
521) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
522    Ok(
523        a
524            .on_player()
525            .apply_base_from_data(data, 1_271_144)?
526            .max_stacks(
527                data
528                    .require_aura_max_stacks(
529                        wowlab_types::sim::SpellIdx::from_raw(1_271_144),
530                    )?,
531            ),
532    )
533}
534fn aura_reavers_glaive(
535    a: AuraDefinitionDraft,
536    data: &ResolvedGameData,
537) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
538    Ok(
539        a
540            .on_player()
541            .apply_base_from_data(data, 442_294)?
542            .max_stacks(
543                data
544                    .require_aura_max_stacks(
545                        wowlab_types::sim::SpellIdx::from_raw(442_294),
546                    )?,
547            ),
548    )
549}
550fn aura_exergy(
551    a: AuraDefinitionDraft,
552    data: &ResolvedGameData,
553) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
554    Ok(
555        a
556            .on_player()
557            .apply_base_from_data(data, 442_266)?
558            .max_stacks(
559                data
560                    .require_aura_max_stacks(
561                        wowlab_types::sim::SpellIdx::from_raw(442_266),
562                    )?,
563            ),
564    )
565}
566fn aura_immolation_aura(
567    a: AuraDefinitionDraft,
568    data: &ResolvedGameData,
569) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
570    a.on_player()
571        .apply_base_from_data(data, 258_920)?
572        .max_stacks(
573            data.require_aura_max_stacks(wowlab_types::sim::SpellIdx::from_raw(258_920))?,
574        )
575        .periodic_damage_ap_from_data(
576            data,
577            wowlab_engine_combat::PeriodicDamageDataInput {
578                tick_ms: wowlab_engine_combat::validated_milliseconds(
579                    data.period(wowlab_types::sim::SpellIdx::from_raw(258_920), 1),
580                    258_920,
581                    "periodic_damage.tick_ms",
582                )?,
583                spell_id: 258_922,
584                effect_index: 1,
585                multiplier: 1.0,
586                offset: 0.0,
587                round_decimals: Some(4),
588            },
589            wowlab_engine_combat::PeriodicDamageMode::Standard,
590        )?
591        .periodic_resource(
592            wowlab_engine_combat::validated_milliseconds(
593                data.period(wowlab_types::sim::SpellIdx::from_raw(258_920), 1),
594                258_920,
595                "periodic_resource.tick_ms",
596            )?,
597            data.base_points(wowlab_types::sim::SpellIdx::from_raw(258_922), 2),
598        )
599        .apply_periodic_behavior_from_data(data, 258_920)
600}
601fn aura_the_hunt_dot(
602    a: AuraDefinitionDraft,
603    data: &ResolvedGameData,
604) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
605    Ok(
606        a
607            .on_target()
608            .apply_base_from_data(data, 370_969)?
609            .max_stacks(
610                data
611                    .require_aura_max_stacks(
612                        wowlab_types::sim::SpellIdx::from_raw(370_969),
613                    )?,
614            ),
615    )
616}
617fn aura_burning_blades(
618    a: AuraDefinitionDraft,
619    data: &ResolvedGameData,
620) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
621    a.on_target()
622        .apply_base_from_data(data, 453_177)?
623        .max_stacks(
624            data.require_aura_max_stacks(wowlab_types::sim::SpellIdx::from_raw(453_177))?,
625        )
626        .periodic_residual_damage(
627            wowlab_engine_combat::validated_milliseconds(
628                data.period(wowlab_types::sim::SpellIdx::from_raw(453_177), 1),
629                453_177,
630                "periodic_residual_damage.tick_ms",
631            )?,
632        )
633        .apply_periodic_behavior_from_data(data, 453_177)
634}
635fn aura_serrated_glaive(
636    a: AuraDefinitionDraft,
637    data: &ResolvedGameData,
638) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
639    a.on_target()
640        .apply_base_from_data(data, 390_155)?
641        .max_stacks(
642            data.require_aura_max_stacks(wowlab_types::sim::SpellIdx::from_raw(390_155))?,
643        )
644        .damage_taken_from_caster_spells(
645            data,
646            data.base_points(wowlab_types::sim::SpellIdx::from_raw(390_154), 1),
647        )
648}
649fn aura_soulscar(
650    a: AuraDefinitionDraft,
651    data: &ResolvedGameData,
652) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
653    a.on_target()
654        .apply_base_from_data(data, 390_181)?
655        .max_stacks(
656            data.require_aura_max_stacks(wowlab_types::sim::SpellIdx::from_raw(390_181))?,
657        )
658        .periodic_residual_damage(
659            wowlab_engine_combat::validated_milliseconds(
660                data.period(wowlab_types::sim::SpellIdx::from_raw(390_181), 1),
661                390_181,
662                "periodic_residual_damage.tick_ms",
663            )?,
664        )
665        .apply_periodic_behavior_from_data(data, 390_181)
666}
667fn spell_chaos_strike(
668    s: SpellDefinitionDraft,
669    data: &ResolvedGameData,
670) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
671    Ok(
672        s
673            .apply_base_from_data(data, 162_794)?
674            .apply_aoe_from_data(data)
675            .on_cast(crate::hooks::havoc_demon_hunter::chaos_strike_hook)
676            .overridden_by(SPELL::ANNIHILATION, AURA::METAMORPHOSIS)
677            .override_preserves_aura(),
678    )
679}
680fn spell_annihilation(
681    s: SpellDefinitionDraft,
682    data: &ResolvedGameData,
683) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
684    Ok(
685        s
686            .apply_base_from_data(data, 201_427)?
687            .apply_aoe_from_data(data)
688            .on_cast(crate::hooks::havoc_demon_hunter::annihilation_hook),
689    )
690}
691fn spell_blade_dance(
692    s: SpellDefinitionDraft,
693    data: &ResolvedGameData,
694) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
695    Ok(
696        s
697            .apply_base_from_data(data, 188_499)?
698            .without_data_damage()
699            .apply_aoe_from_data(data)
700            .on_cast(crate::hooks::havoc_demon_hunter::blade_dance_hook)
701            .overridden_by(SPELL::DEATH_SWEEP, AURA::METAMORPHOSIS)
702            .override_shares_base_cooldown()
703            .override_preserves_aura(),
704    )
705}
706fn spell_death_sweep(
707    s: SpellDefinitionDraft,
708    data: &ResolvedGameData,
709) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
710    Ok(
711        s
712            .apply_base_from_data(data, 210_152)?
713            .without_data_damage()
714            .apply_aoe_from_data(data)
715            .on_cast(crate::hooks::havoc_demon_hunter::death_sweep_hook),
716    )
717}
718fn spell_metamorphosis(
719    s: SpellDefinitionDraft,
720    data: &ResolvedGameData,
721) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
722    Ok(
723        s
724            .apply_base_from_data(data, 191_427)?
725            .applies_aura(AURA_METAMORPHOSIS)
726            .apply_aoe_from_data(data)
727            .on_cast(crate::hooks::havoc_demon_hunter::metamorphosis_hook),
728    )
729}
730fn spell_throw_glaive(
731    s: SpellDefinitionDraft,
732    data: &ResolvedGameData,
733) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
734    Ok(
735        s
736            .apply_base_from_data(data, 185_123)?
737            .apply_aoe_from_data(data)
738            .on_cast(crate::hooks::havoc_demon_hunter::throw_glaive_hook),
739    )
740}
741fn spell_fel_rush(
742    s: SpellDefinitionDraft,
743    data: &ResolvedGameData,
744) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
745    Ok(
746        s
747            .apply_base_from_data(data, 195_072)?
748            .damage_ap_from_data(
749                wowlab_engine_domain::dbc::EffectLookup::new(
750                    data,
751                    wowlab_types::sim::EffectRef::new(
752                        wowlab_types::sim::SpellIdx::from_raw(192_611),
753                        1,
754                    ),
755                ),
756            )?
757            .apply_aoe_from_data(data),
758    )
759}
760fn spell_vengeful_retreat(
761    s: SpellDefinitionDraft,
762    data: &ResolvedGameData,
763) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
764    Ok(s.apply_base_from_data(data, 198_793)?.apply_aoe_from_data(data))
765}
766fn spell_essence_break(
767    s: SpellDefinitionDraft,
768    data: &ResolvedGameData,
769) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
770    Ok(
771        s
772            .apply_base_from_data(data, 258_860)?
773            .applies_aura(AURA_ESSENCE_BREAK)
774            .apply_aoe_from_data(data),
775    )
776}
777fn spell_felblade(
778    s: SpellDefinitionDraft,
779    data: &ResolvedGameData,
780) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
781    Ok(
782        s
783            .apply_base_from_data(data, 232_893)?
784            .gain(data.base_points(wowlab_types::sim::SpellIdx::from_raw(213_243), 3))
785            .damage_ap_from_data(
786                wowlab_engine_domain::dbc::EffectLookup::new(
787                    data,
788                    wowlab_types::sim::EffectRef::new(
789                        wowlab_types::sim::SpellIdx::from_raw(213_243),
790                        2,
791                    ),
792                ),
793            )?
794            .apply_aoe_from_data(data),
795    )
796}
797fn spell_eye_beam(
798    s: SpellDefinitionDraft,
799    data: &ResolvedGameData,
800) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
801    Ok(
802        s
803            .apply_base_from_data(data, 198_013)?
804            .apply_aoe_from_data(data)
805            .channel(
806                wowlab_engine_combat::validated_channel_tick_count(
807                    10.0,
808                    198_013,
809                    "channel.tick_count",
810                )?,
811            )
812            .on_channel_tick(crate::hooks::havoc_demon_hunter::eye_beam_tick_hook)
813            .on_cast(crate::hooks::havoc_demon_hunter::eye_beam_hook)
814            .overridden_by(SPELL::ABYSSAL_GAZE, AURA::DEMONIC_INTENSITY)
815            .override_shares_base_cooldown(),
816    )
817}
818fn spell_abyssal_gaze(
819    s: SpellDefinitionDraft,
820    data: &ResolvedGameData,
821) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
822    Ok(
823        s
824            .apply_base_from_data(data, 452_497)?
825            .apply_aoe_from_data(data)
826            .channel(
827                wowlab_engine_combat::validated_channel_tick_count(
828                    10.0,
829                    452_497,
830                    "channel.tick_count",
831                )?,
832            )
833            .on_channel_tick(crate::hooks::havoc_demon_hunter::eye_beam_tick_hook)
834            .on_cast(crate::hooks::havoc_demon_hunter::abyssal_gaze_hook),
835    )
836}
837fn spell_immolation_aura(
838    s: SpellDefinitionDraft,
839    data: &ResolvedGameData,
840) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
841    Ok(
842        s
843            .apply_base_from_data(data, 258_920)?
844            .damage_ap_from_data(
845                wowlab_engine_domain::dbc::EffectLookup::new(
846                    data,
847                    wowlab_types::sim::EffectRef::new(
848                        wowlab_types::sim::SpellIdx::from_raw(258_921),
849                        1,
850                    ),
851                ),
852            )?
853            .applies_inferred_aura(AURA_IMMOLATION_AURA, 258_920)
854            .apply_aoe_from_data(data)
855            .on_cast(crate::hooks::havoc_demon_hunter::consuming_fire_hook),
856    )
857}
858fn spell_the_hunt(
859    s: SpellDefinitionDraft,
860    data: &ResolvedGameData,
861) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
862    Ok(
863        s
864            .apply_base_from_data(data, 370_965)?
865            .damage_ap_from_data(
866                wowlab_engine_domain::dbc::EffectLookup::new(
867                    data,
868                    wowlab_types::sim::EffectRef::new(
869                        wowlab_types::sim::SpellIdx::from_raw(370_966),
870                        1,
871                    ),
872                ),
873            )?
874            .applies_aura(AURA_THE_HUNT_DOT)
875            .apply_aoe_from_data(data)
876            .on_cast(crate::hooks::havoc_demon_hunter::the_hunt_hook),
877    )
878}
879pub(crate) fn build_combat_system(
880    params: &wowlab_engine_ports::HandlerParams<'_>,
881) -> Result<BuiltCombatSystem, wowlab_engine_ports::EngineError> {
882    let builder = BuiltCombatSystem::builder(params.stats.clone())
883        .spec_id(SpecId::Havoc)
884        .hero_talent_trees(DECLARED_METADATA.hero_talent_trees)
885        .mastery_spell(185_164)
886        .mastery_hook(crate::hooks::havoc_demon_hunter::mastery)
887        .resource(
888            "fury",
889            120.0,
890            params
891                .game_data
892                .power_regen_for_max(17, 120.0)
893                .ok_or_else(|| {
894                    wowlab_engine_ports::EngineError::spec_construction(
895                        "missing power-type power_regen_for_max for type_id 17",
896                    )
897                })?,
898        )
899        .resource_type_id(17)
900        .resource_start(
901            params
902                .game_data
903                .power_default(17)
904                .ok_or_else(|| {
905                    wowlab_engine_ports::EngineError::spec_construction(
906                        "missing power-type power_default for type_id 17",
907                    )
908                })?,
909        )
910        .aura(
911            "metamorphosis",
912            AURA::METAMORPHOSIS,
913            |a| aura_metamorphosis(a, &params.game_data),
914        )
915        .aura(
916            "essence_break",
917            AURA::ESSENCE_BREAK,
918            |a| aura_essence_break(a, &params.game_data),
919        )
920        .aura("inertia", AURA::INERTIA, |a| aura_inertia(a, &params.game_data))
921        .aura(
922            "cycle_of_hatred",
923            AURA::CYCLE_OF_HATRED,
924            |a| aura_cycle_of_hatred(a, &params.game_data),
925        )
926        .aura(
927            "furious_gaze",
928            AURA::FURIOUS_GAZE,
929            |a| aura_furious_gaze(a, &params.game_data),
930        )
931        .aura(
932            "student_of_suffering",
933            AURA::STUDENT_OF_SUFFERING,
934            |a| aura_student_of_suffering(a, &params.game_data),
935        )
936        .aura(
937            "demonic_intensity",
938            AURA::DEMONIC_INTENSITY,
939            |a| aura_demonic_intensity(a, &params.game_data),
940        )
941        .aura(
942            "empowered_eye_beam",
943            AURA::EMPOWERED_EYE_BEAM,
944            |a| aura_empowered_eye_beam(a, &params.game_data),
945        )
946        .aura(
947            "reavers_glaive",
948            AURA::REAVERS_GLAIVE,
949            |a| aura_reavers_glaive(a, &params.game_data),
950        )
951        .aura("exergy", AURA::EXERGY, |a| aura_exergy(a, &params.game_data))
952        .aura(
953            "immolation_aura",
954            AURA::IMMOLATION_AURA,
955            |a| aura_immolation_aura(a, &params.game_data),
956        )
957        .aura(
958            "the_hunt_dot",
959            AURA::THE_HUNT_DOT,
960            |a| aura_the_hunt_dot(a, &params.game_data),
961        )
962        .aura(
963            "burning_blades",
964            AURA::BURNING_BLADES,
965            |a| aura_burning_blades(a, &params.game_data),
966        )
967        .aura(
968            "serrated_glaive",
969            AURA::SERRATED_GLAIVE,
970            |a| aura_serrated_glaive(a, &params.game_data),
971        )
972        .aura("soulscar", AURA::SOULSCAR, |a| aura_soulscar(a, &params.game_data))
973        .spell(
974            "chaos_strike",
975            SPELL::CHAOS_STRIKE,
976            |s| spell_chaos_strike(s, &params.game_data),
977        )
978        .spell(
979            "annihilation",
980            SPELL::ANNIHILATION,
981            |s| spell_annihilation(s, &params.game_data),
982        )
983        .spell(
984            "blade_dance",
985            SPELL::BLADE_DANCE,
986            |s| spell_blade_dance(s, &params.game_data),
987        )
988        .spell(
989            "death_sweep",
990            SPELL::DEATH_SWEEP,
991            |s| spell_death_sweep(s, &params.game_data),
992        )
993        .spell(
994            "metamorphosis",
995            SPELL::METAMORPHOSIS,
996            |s| spell_metamorphosis(s, &params.game_data),
997        )
998        .spell(
999            "throw_glaive",
1000            SPELL::THROW_GLAIVE,
1001            |s| spell_throw_glaive(s, &params.game_data),
1002        )
1003        .spell("fel_rush", SPELL::FEL_RUSH, |s| spell_fel_rush(s, &params.game_data))
1004        .spell(
1005            "vengeful_retreat",
1006            SPELL::VENGEFUL_RETREAT,
1007            |s| spell_vengeful_retreat(s, &params.game_data),
1008        )
1009        .spell(
1010            "essence_break",
1011            SPELL::ESSENCE_BREAK,
1012            |s| spell_essence_break(s, &params.game_data),
1013        )
1014        .spell("felblade", SPELL::FELBLADE, |s| spell_felblade(s, &params.game_data))
1015        .spell("eye_beam", SPELL::EYE_BEAM, |s| spell_eye_beam(s, &params.game_data))
1016        .spell(
1017            "abyssal_gaze",
1018            SPELL::ABYSSAL_GAZE,
1019            |s| spell_abyssal_gaze(s, &params.game_data),
1020        )
1021        .spell(
1022            "immolation_aura",
1023            SPELL::IMMOLATION_AURA,
1024            |s| spell_immolation_aura(s, &params.game_data),
1025        )
1026        .spell("the_hunt", SPELL::THE_HUNT, |s| spell_the_hunt(s, &params.game_data))
1027        .auto_attack(|a| {
1028            a
1029                .spell_id(6603)
1030                .swing_ms(2600)
1031                .apply_base_from_data(&params.game_data)
1032                .on_swing(crate::hooks::havoc_demon_hunter::swing_hook)
1033        })
1034        .auto_attack(|a| {
1035            a
1036                .spell_id(6603)
1037                .swing_ms(2600)
1038                .apply_base_from_data(&params.game_data)
1039                .on_swing(crate::hooks::havoc_demon_hunter::swing_hook)
1040        })
1041        .game_data(params.game_data.clone())
1042        .talent_spell_ids(TALENTS)
1043        .talent_selections(params.talent_selections)
1044        .set_bonus_auras(params.set_bonus_auras)
1045        .encounter(params.encounter.clone());
1046    let builder = crate::generated::items::register_equipped(
1047        builder,
1048        &params.game_data,
1049        params.equipped_items,
1050    )?;
1051
1052    builder
1053        .build(params.rotation)
1054        .map_err(wowlab_engine_ports::EngineError::rotation_compile)
1055}
1056fn new_handler(
1057    params: wowlab_engine_ports::HandlerParams<'_>,
1058) -> Result<Box<dyn SpecHandler>, wowlab_engine_ports::EngineError> {
1059    let handler = crate::composition::compose_handler(
1060        build_combat_system,
1061        &params,
1062        |parts, params| Ok(
1063            crate::hooks::havoc_demon_hunter::HavocHandler::new(parts, params),
1064        ),
1065    )?;
1066
1067    Ok(Box::new(handler))
1068}
1069static DECLARED_METADATA: DeclaredSpecMetadata = DeclaredSpecMetadata {
1070    primary_resource: ResourceType::Fury,
1071    secondary_resource: None,
1072    spell_ids: DECLARED_SPELL_IDS,
1073    aura_ids: DECLARED_AURA_IDS,
1074    server_proc_entries: &[],
1075    talents: TALENTS,
1076    rotation_field_schema: &[],
1077    metrics_plugin_id: None,
1078    hero_talent_trees: &[
1079        HeroTalentTreeDesc {
1080            name: "Aldrachi Reaver",
1081            spells: HERO_TREE_ALDRACHI_REAVER_SPELLS,
1082            auras: HERO_TREE_ALDRACHI_REAVER_AURAS,
1083        },
1084        HeroTalentTreeDesc {
1085            name: "Fel Scarred",
1086            spells: HERO_TREE_FEL_SCARRED_SPELLS,
1087            auras: HERO_TREE_FEL_SCARRED_AURAS,
1088        },
1089    ],
1090    reported_spells: REPORTED_SPELLS,
1091    masked_passive_effects: &[],
1092    passive_effect_overrides: &[
1093        wowlab_engine_ports::DeclaredPassiveEffectOverride {
1094            spell_id: 388_118,
1095            effect: 2,
1096            source: Some((388_118, 2)),
1097            value: 0.0,
1098            multiplier: 0.5,
1099        },
1100    ],
1101};
1102pub(super) const SPEC_DESCRIPTOR: SpecDescriptor = SpecDescriptor {
1103    spec_id: SpecId::Havoc,
1104    display_name: "Havoc Demon Hunter",
1105    metadata: DECLARED_METADATA,
1106    handler_factory: new_handler,
1107};
1108wowlab_engine_combat::smoke_test!(build_combat_system);