Skip to main content

wowlab_engine_content/generated/specs/
affliction_warlock.rs

1//! @generated by codegen-cli from manifests/specs/warlock/affliction/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/691>
15    pub(crate) const SUMMON_FELHUNTER: u32 = 691;
16    ///<https://wowlab.gg/inspect/spell/688>
17    pub(crate) const SUMMON_IMP: u32 = 688;
18    ///<https://wowlab.gg/inspect/spell/108503>
19    pub(crate) const GRIMOIRE_OF_SACRIFICE: u32 = 108_503;
20    ///<https://wowlab.gg/inspect/spell/980>
21    pub(crate) const AGONY: u32 = 980;
22    ///<https://wowlab.gg/inspect/spell/172>
23    pub(crate) const CORRUPTION: u32 = 172;
24    ///<https://wowlab.gg/inspect/spell/1259790>
25    pub(crate) const UNSTABLE_AFFLICTION: u32 = 1_259_790;
26    ///<https://wowlab.gg/inspect/spell/27243>
27    pub(crate) const SEED_OF_CORRUPTION: u32 = 27243;
28    ///<https://wowlab.gg/inspect/spell/48181>
29    pub(crate) const HAUNT: u32 = 48181;
30    ///<https://wowlab.gg/inspect/spell/205180>
31    pub(crate) const SUMMON_DARKGLARE: u32 = 205_180;
32    ///<https://wowlab.gg/inspect/spell/1257052>
33    pub(crate) const DARK_HARVEST: u32 = 1_257_052;
34    ///<https://wowlab.gg/inspect/spell/686>
35    pub(crate) const SHADOW_BOLT: u32 = 686;
36    ///<https://wowlab.gg/inspect/spell/198590>
37    pub(crate) const DRAIN_SOUL: u32 = 198_590;
38    ///<https://wowlab.gg/inspect/spell/1261153>
39    pub(crate) const MALEFIC_GRASP: u32 = 1_261_153;
40    ///<https://wowlab.gg/inspect/spell/234153>
41    pub(crate) const DRAIN_LIFE: u32 = 234_153;
42    ///<https://wowlab.gg/inspect/spell/430014>
43    pub(crate) const MALEVOLENCE: u32 = 430_014;
44}
45pub(crate) mod AURA {
46    ///<https://wowlab.gg/inspect/spell/980>
47    pub(crate) const AGONY: u32 = 980;
48    ///<https://wowlab.gg/inspect/spell/146739>
49    pub(crate) const CORRUPTION: u32 = 146_739;
50    ///<https://wowlab.gg/inspect/spell/1259790>
51    pub(crate) const UNSTABLE_AFFLICTION: u32 = 1_259_790;
52    ///<https://wowlab.gg/inspect/spell/27243>
53    pub(crate) const SEED_OF_CORRUPTION: u32 = 27243;
54    ///<https://wowlab.gg/inspect/spell/1279998>
55    pub(crate) const SEED_OF_CORRUPTION_IS_OUT_DNT: u32 = 1_279_998;
56    ///<https://wowlab.gg/inspect/spell/1288970>
57    pub(crate) const RECENTLY_DEMON_HAS_BEEN_SUMMONED_DNT: u32 = 1_288_970;
58    ///<https://wowlab.gg/inspect/spell/264571>
59    pub(crate) const NIGHTFALL: u32 = 264_571;
60    ///<https://wowlab.gg/inspect/spell/48181>
61    pub(crate) const HAUNT: u32 = 48181;
62    ///<https://wowlab.gg/inspect/spell/1280663>
63    pub(crate) const DARKGLARE_PRESENCE: u32 = 1_280_663;
64    ///<https://wowlab.gg/inspect/spell/1260269>
65    pub(crate) const SHARD_INSTABILITY: u32 = 1_260_269;
66    ///<https://wowlab.gg/inspect/spell/1261125>
67    pub(crate) const CASCADING_CALAMITY: u32 = 1_261_125;
68    ///<https://wowlab.gg/inspect/spell/196099>
69    pub(crate) const GRIMOIRE_OF_SACRIFICE: u32 = 196_099;
70    ///<https://wowlab.gg/inspect/spell/445474>
71    pub(crate) const WITHER: u32 = 445_474;
72    ///<https://wowlab.gg/inspect/spell/442726>
73    pub(crate) const MALEVOLENCE: u32 = 442_726;
74    ///<https://wowlab.gg/inspect/spell/449793>
75    pub(crate) const SUCCULENT_SOUL: u32 = 449_793;
76    ///<https://wowlab.gg/inspect/spell/1269042>
77    pub(crate) const MANIFESTED_DEMONIC_SOUL: u32 = 1_269_042;
78    ///<https://wowlab.gg/inspect/spell/450538>
79    pub(crate) const SOUL_ANATHEMA: u32 = 450_538;
80    ///<https://wowlab.gg/inspect/spell/462599>
81    pub(crate) const TRACK_PETS: u32 = 462_599;
82}
83pub(crate) mod TALENT {
84    ///<https://wowlab.gg/inspect/spell/196103>
85    pub(crate) const ABSOLUTE_CORRUPTION: u32 = 196_103;
86    ///<https://wowlab.gg/inspect/spell/1261124>
87    pub(crate) const CASCADING_CALAMITY: u32 = 1_261_124;
88    ///<https://wowlab.gg/inspect/spell/264000>
89    pub(crate) const CREEPING_DEATH: u32 = 264_000;
90    ///<https://wowlab.gg/inspect/spell/453172>
91    pub(crate) const CUNNING_CRUELTY: u32 = 453_172;
92    ///<https://wowlab.gg/inspect/spell/1257052>
93    pub(crate) const DARK_HARVEST: u32 = 1_257_052;
94    ///<https://wowlab.gg/inspect/spell/234876>
95    pub(crate) const DEATHS_EMBRACE: u32 = 234_876;
96    ///<https://wowlab.gg/inspect/spell/449629>
97    pub(crate) const DEMONIACS_FERVOR: u32 = 449_629;
98    ///<https://wowlab.gg/inspect/spell/449614>
99    pub(crate) const DEMONIC_SOUL: u32 = 449_614;
100    ///<https://wowlab.gg/inspect/spell/388667>
101    pub(crate) const DRAIN_SOUL: u32 = 388_667;
102    ///<https://wowlab.gg/inspect/spell/1260229>
103    pub(crate) const FATAL_ECHOES: u32 = 1_260_229;
104    ///<https://wowlab.gg/inspect/spell/108503>
105    pub(crate) const GRIMOIRE_OF_SACRIFICE: u32 = 108_503;
106    ///<https://wowlab.gg/inspect/spell/48181>
107    pub(crate) const HAUNT: u32 = 48181;
108    ///<https://wowlab.gg/inspect/spell/453080>
109    pub(crate) const IMPROVED_SHADOW_BOLT: u32 = 453_080;
110    ///<https://wowlab.gg/inspect/spell/1261149>
111    pub(crate) const MALEFIC_GRASP: u32 = 1_261_149;
112    ///<https://wowlab.gg/inspect/spell/430014>
113    pub(crate) const MALEVOLENCE: u32 = 430_014;
114    ///<https://wowlab.gg/inspect/spell/1268884>
115    pub(crate) const MANIFESTED_AVARICE: u32 = 1_268_884;
116    ///<https://wowlab.gg/inspect/spell/108558>
117    pub(crate) const NIGHTFALL: u32 = 108_558;
118    ///<https://wowlab.gg/inspect/spell/1260271>
119    pub(crate) const NOCTURNAL_YIELD: u32 = 1_260_271;
120    ///<https://wowlab.gg/inspect/spell/459440>
121    pub(crate) const RAVENOUS_AFFLICTIONS: u32 = 459_440;
122    ///<https://wowlab.gg/inspect/spell/449638>
123    pub(crate) const SHADOW_OF_DEATH: u32 = 449_638;
124    ///<https://wowlab.gg/inspect/spell/1261984>
125    pub(crate) const SHADOW_OF_NATHREZA: u32 = 1_261_984;
126    ///<https://wowlab.gg/inspect/spell/1261990>
127    pub(crate) const SHADOW_OF_NATHREZA_2: u32 = 1_261_990;
128    ///<https://wowlab.gg/inspect/spell/1261992>
129    pub(crate) const SHADOW_OF_NATHREZA_3: u32 = 1_261_992;
130    ///<https://wowlab.gg/inspect/spell/1260264>
131    pub(crate) const SHARD_INSTABILITY: u32 = 1_260_264;
132    ///<https://wowlab.gg/inspect/spell/449624>
133    pub(crate) const SOUL_ANATHEMA: u32 = 449_624;
134    ///<https://wowlab.gg/inspect/spell/205180>
135    pub(crate) const SUMMON_DARKGLARE: u32 = 205_180;
136    ///<https://wowlab.gg/inspect/spell/386976>
137    pub(crate) const WITHERING_BOLT: u32 = 386_976;
138}
139pub(crate) mod REPORTED_SPELL {
140    ///<https://wowlab.gg/inspect/spell/1257065>
141    pub(crate) const DARK_HARVEST_TICK: u32 = 1_257_065;
142    ///<https://wowlab.gg/inspect/spell/449801>
143    pub(crate) const DEMONIC_SOUL: u32 = 449_801;
144    ///<https://wowlab.gg/inspect/spell/205231>
145    pub(crate) const EYE_BEAM: u32 = 205_231;
146    ///<https://wowlab.gg/inspect/spell/1262710>
147    pub(crate) const SHADOW_OF_NATHREZA: u32 = 1_262_710;
148    ///<https://wowlab.gg/inspect/spell/1269049>
149    pub(crate) const SOUL_SWIPE: u32 = 1_269_049;
150    ///<https://wowlab.gg/inspect/spell/1278047>
151    pub(crate) const WRATH_OF_NATHREZA: u32 = 1_278_047;
152}
153pub(crate) mod HERO {
154    pub(crate) mod HELLCALLER {
155        pub(crate) mod SPELL {
156            ///<https://wowlab.gg/inspect/spell/445736>
157            pub(crate) const BLACKENED_SOUL_DAMAGE: u32 = 445_736;
158            ///<https://wowlab.gg/inspect/spell/445731>
159            pub(crate) const BLACKENED_SOUL_TRIGGER: u32 = 445_731;
160            ///<https://wowlab.gg/inspect/spell/430014>
161            pub(crate) const MALEVOLENCE: u32 = 430_014;
162            ///<https://wowlab.gg/inspect/spell/446285>
163            pub(crate) const MALEVOLENCE_DAMAGE: u32 = 446_285;
164            ///<https://wowlab.gg/inspect/spell/445465>
165            pub(crate) const WITHER: u32 = 445_465;
166            ///<https://wowlab.gg/inspect/spell/445468>
167            pub(crate) const WITHER_DIRECT: u32 = 445_468;
168        }
169        pub(crate) mod AURA {
170            ///<https://wowlab.gg/inspect/spell/445731>
171            pub(crate) const BLACKENED_SOUL: u32 = 445_731;
172            ///<https://wowlab.gg/inspect/spell/442726>
173            pub(crate) const MALEVOLENCE_BUFF: u32 = 442_726;
174            ///<https://wowlab.gg/inspect/spell/445474>
175            pub(crate) const WITHER_DOT: u32 = 445_474;
176        }
177    }
178    pub(crate) mod SOUL_HARVESTER {
179        pub(crate) mod SPELL {
180            ///<https://wowlab.gg/inspect/spell/449858>
181            pub(crate) const DARK_HARVEST_ENERGIZE: u32 = 449_858;
182            ///<https://wowlab.gg/inspect/spell/449801>
183            pub(crate) const DEMONIC_SOUL_DAMAGE: u32 = 449_801;
184            ///<https://wowlab.gg/inspect/spell/450591>
185            pub(crate) const SHARED_FATE: u32 = 450_591;
186            ///<https://wowlab.gg/inspect/spell/450538>
187            pub(crate) const SOUL_ANATHEMA: u32 = 450_538;
188            ///<https://wowlab.gg/inspect/spell/449826>
189            pub(crate) const WICKED_REAPING: u32 = 449_826;
190        }
191        pub(crate) mod AURA {
192            ///<https://wowlab.gg/inspect/spell/1269042>
193            pub(crate) const MANIFESTED_DEMONIC_SOUL: u32 = 1_269_042;
194            ///<https://wowlab.gg/inspect/spell/449793>
195            pub(crate) const SUCCULENT_SOUL: u32 = 449_793;
196        }
197    }
198}
199static HERO_TREE_HELLCALLER_SPELLS: &[(&str, u32)] = &[
200    ("BLACKENED_SOUL_DAMAGE", 445_736),
201    ("BLACKENED_SOUL_TRIGGER", 445_731),
202    ("MALEVOLENCE", 430_014),
203    ("MALEVOLENCE_DAMAGE", 446_285),
204    ("WITHER", 445_465),
205    ("WITHER_DIRECT", 445_468),
206];
207static HERO_TREE_HELLCALLER_AURAS: &[(&str, u32)] = &[
208    ("BLACKENED_SOUL", 445_731),
209    ("MALEVOLENCE_BUFF", 442_726),
210    ("WITHER_DOT", 445_474),
211];
212static HERO_TREE_SOUL_HARVESTER_SPELLS: &[(&str, u32)] = &[
213    ("DARK_HARVEST_ENERGIZE", 449_858),
214    ("DEMONIC_SOUL_DAMAGE", 449_801),
215    ("SHARED_FATE", 450_591),
216    ("SOUL_ANATHEMA", 450_538),
217    ("WICKED_REAPING", 449_826),
218];
219static HERO_TREE_SOUL_HARVESTER_AURAS: &[(&str, u32)] = &[
220    ("MANIFESTED_DEMONIC_SOUL", 1_269_042),
221    ("SUCCULENT_SOUL", 449_793),
222];
223pub(crate) const AURA_AGONY: LocalAuraIdx = LocalAuraIdx::new(0);
224pub(crate) const AURA_CORRUPTION: LocalAuraIdx = LocalAuraIdx::new(1);
225pub(crate) const AURA_UNSTABLE_AFFLICTION: LocalAuraIdx = LocalAuraIdx::new(2);
226pub(crate) const AURA_SEED_OF_CORRUPTION: LocalAuraIdx = LocalAuraIdx::new(3);
227pub(crate) const AURA_SEED_OF_CORRUPTION_IS_OUT_DNT: LocalAuraIdx = LocalAuraIdx::new(4);
228pub(crate) const AURA_RECENTLY_DEMON_HAS_BEEN_SUMMONED_DNT: LocalAuraIdx = LocalAuraIdx::new(
229    5,
230);
231pub(crate) const AURA_NIGHTFALL: LocalAuraIdx = LocalAuraIdx::new(6);
232pub(crate) const AURA_HAUNT: LocalAuraIdx = LocalAuraIdx::new(7);
233pub(crate) const AURA_DARKGLARE_PRESENCE: LocalAuraIdx = LocalAuraIdx::new(8);
234pub(crate) const AURA_SHARD_INSTABILITY: LocalAuraIdx = LocalAuraIdx::new(9);
235pub(crate) const AURA_CASCADING_CALAMITY: LocalAuraIdx = LocalAuraIdx::new(10);
236pub(crate) const AURA_GRIMOIRE_OF_SACRIFICE: LocalAuraIdx = LocalAuraIdx::new(11);
237pub(crate) const AURA_WITHER: LocalAuraIdx = LocalAuraIdx::new(12);
238pub(crate) const AURA_MALEVOLENCE: LocalAuraIdx = LocalAuraIdx::new(13);
239pub(crate) const AURA_SUCCULENT_SOUL: LocalAuraIdx = LocalAuraIdx::new(14);
240pub(crate) const AURA_MANIFESTED_DEMONIC_SOUL: LocalAuraIdx = LocalAuraIdx::new(15);
241pub(crate) const AURA_SOUL_ANATHEMA: LocalAuraIdx = LocalAuraIdx::new(16);
242pub(crate) const AURA_TRACK_PETS: LocalAuraIdx = LocalAuraIdx::new(17);
243pub(crate) const AURA_COUNT: usize = 18;
244const _: () = assert!(
245    AURA_COUNT == 18, "AURA index ABI: count changed -- update positional hook consumers"
246);
247pub(crate) const SPELL_SUMMON_FELHUNTER: LocalSpellIdx = LocalSpellIdx::new(0);
248pub(crate) const SPELL_SUMMON_IMP: LocalSpellIdx = LocalSpellIdx::new(1);
249pub(crate) const SPELL_GRIMOIRE_OF_SACRIFICE: LocalSpellIdx = LocalSpellIdx::new(2);
250pub(crate) const SPELL_AGONY: LocalSpellIdx = LocalSpellIdx::new(3);
251pub(crate) const SPELL_CORRUPTION: LocalSpellIdx = LocalSpellIdx::new(4);
252pub(crate) const SPELL_UNSTABLE_AFFLICTION: LocalSpellIdx = LocalSpellIdx::new(5);
253pub(crate) const SPELL_SEED_OF_CORRUPTION: LocalSpellIdx = LocalSpellIdx::new(6);
254pub(crate) const SPELL_HAUNT: LocalSpellIdx = LocalSpellIdx::new(7);
255pub(crate) const SPELL_SUMMON_DARKGLARE: LocalSpellIdx = LocalSpellIdx::new(8);
256pub(crate) const SPELL_DARK_HARVEST: LocalSpellIdx = LocalSpellIdx::new(9);
257pub(crate) const SPELL_SHADOW_BOLT: LocalSpellIdx = LocalSpellIdx::new(10);
258pub(crate) const SPELL_DRAIN_SOUL: LocalSpellIdx = LocalSpellIdx::new(11);
259pub(crate) const SPELL_MALEFIC_GRASP: LocalSpellIdx = LocalSpellIdx::new(12);
260pub(crate) const SPELL_DRAIN_LIFE: LocalSpellIdx = LocalSpellIdx::new(13);
261pub(crate) const SPELL_MALEVOLENCE: LocalSpellIdx = LocalSpellIdx::new(14);
262pub(crate) const SPELL_COUNT: usize = 15;
263const _: () = assert!(
264    SPELL_COUNT == 15,
265    "SPELL index ABI: count changed -- update positional hook consumers"
266);
267pub(crate) mod EFFECT {
268    ///<https://wowlab.gg/inspect/spell/77215>
269    pub(crate) const POTENT_AFFLICTIONS_DAMAGE: (u32, u8) = (77215, 1);
270    ///<https://wowlab.gg/inspect/spell/77215>
271    pub(crate) const POTENT_AFFLICTIONS_DIRECT: (u32, u8) = (77215, 2);
272    ///<https://wowlab.gg/inspect/spell/77215>
273    pub(crate) const POTENT_AFFLICTIONS_LABEL_DAMAGE: (u32, u8) = (77215, 3);
274    ///<https://wowlab.gg/inspect/spell/205231>
275    pub(crate) const EYE_BEAM_DAMAGE: (u32, u8) = (205_231, 1);
276    ///<https://wowlab.gg/inspect/spell/205180>
277    pub(crate) const EYE_BEAM_PER_DOT: (u32, u8) = (205_180, 3);
278    ///<https://wowlab.gg/inspect/spell/449801>
279    pub(crate) const DEMONIC_SOUL_DAMAGE: (u32, u8) = (449_801, 1);
280    ///<https://wowlab.gg/inspect/spell/449629>
281    pub(crate) const DEMONIACS_FERVOR_DAMAGE: (u32, u8) = (449_629, 1);
282    ///<https://wowlab.gg/inspect/spell/1269049>
283    pub(crate) const SOUL_SWIPE_DAMAGE: (u32, u8) = (1_269_049, 1);
284    ///<https://wowlab.gg/inspect/spell/1269049>
285    pub(crate) const SOUL_SWIPE_AOE_DAMAGE: (u32, u8) = (1_269_049, 2);
286    ///<https://wowlab.gg/inspect/spell/1262710>
287    pub(crate) const SHADOW_OF_NATHREZA_DAMAGE: (u32, u8) = (1_262_710, 1);
288    ///<https://wowlab.gg/inspect/spell/1278047>
289    pub(crate) const WRATH_OF_NATHREZA_DAMAGE: (u32, u8) = (1_278_047, 1);
290    ///<https://wowlab.gg/inspect/spell/449638>
291    pub(crate) const SHADOW_OF_DEATH_SHARDS: (u32, u8) = (449_638, 2);
292}
293static REPORTED_SPELLS: &[(&str, u32)] = &[
294    ("dark_harvest_tick", 1_257_065),
295    ("demonic_soul", 449_801),
296    ("eye_beam", 205_231),
297    ("shadow_of_nathreza", 1_262_710),
298    ("soul_swipe", 1_269_049),
299    ("wrath_of_nathreza", 1_278_047),
300];
301static DECLARED_SPELL_IDS: &[u32] = &[
302    691, 688, 108_503, 980, 172, 1_259_790, 27243, 48181, 205_180, 1_257_052, 686,
303    198_590, 1_261_153, 234_153, 430_014, 980, 146_739, 1_259_790, 27243, 1_279_998,
304    1_288_970, 264_571, 48181, 1_280_663, 1_260_269, 1_261_125, 196_099, 445_474,
305    442_726, 449_793, 1_269_042, 450_538, 462_599, 1, 980, 48181, 77215, 146_739,
306    196_103, 205_180, 205_231, 449_629, 449_638, 449_801, 1_257_065, 1_262_710,
307    1_269_049, 1_278_047, 1_257_065, 449_801, 205_231, 1_262_710, 1_269_049, 1_278_047,
308    445_736, 445_731, 430_014, 446_285, 445_465, 445_468, 445_731, 442_726, 445_474,
309    449_858, 449_801, 450_591, 450_538, 449_826, 1_269_042, 449_793,
310];
311static DECLARED_AURA_IDS: &[u32] = &[
312    980, 146_739, 1_259_790, 27243, 1_279_998, 1_288_970, 264_571, 48181, 1_280_663,
313    1_260_269, 1_261_125, 196_099, 445_474, 442_726, 449_793, 1_269_042, 450_538,
314    462_599, 445_731, 442_726, 445_474, 1_269_042, 449_793,
315];
316static TALENTS: &[(&str, u32)] = &[
317    ("ABSOLUTE_CORRUPTION", TALENT::ABSOLUTE_CORRUPTION),
318    ("CASCADING_CALAMITY", TALENT::CASCADING_CALAMITY),
319    ("CREEPING_DEATH", TALENT::CREEPING_DEATH),
320    ("CUNNING_CRUELTY", TALENT::CUNNING_CRUELTY),
321    ("DARK_HARVEST", TALENT::DARK_HARVEST),
322    ("DEATHS_EMBRACE", TALENT::DEATHS_EMBRACE),
323    ("DEMONIACS_FERVOR", TALENT::DEMONIACS_FERVOR),
324    ("DEMONIC_SOUL", TALENT::DEMONIC_SOUL),
325    ("DRAIN_SOUL", TALENT::DRAIN_SOUL),
326    ("FATAL_ECHOES", TALENT::FATAL_ECHOES),
327    ("GRIMOIRE_OF_SACRIFICE", TALENT::GRIMOIRE_OF_SACRIFICE),
328    ("HAUNT", TALENT::HAUNT),
329    ("IMPROVED_SHADOW_BOLT", TALENT::IMPROVED_SHADOW_BOLT),
330    ("MALEFIC_GRASP", TALENT::MALEFIC_GRASP),
331    ("MALEVOLENCE", TALENT::MALEVOLENCE),
332    ("MANIFESTED_AVARICE", TALENT::MANIFESTED_AVARICE),
333    ("NIGHTFALL", TALENT::NIGHTFALL),
334    ("NOCTURNAL_YIELD", TALENT::NOCTURNAL_YIELD),
335    ("RAVENOUS_AFFLICTIONS", TALENT::RAVENOUS_AFFLICTIONS),
336    ("SHADOW_OF_DEATH", TALENT::SHADOW_OF_DEATH),
337    ("SHADOW_OF_NATHREZA", TALENT::SHADOW_OF_NATHREZA),
338    ("SHADOW_OF_NATHREZA_2", TALENT::SHADOW_OF_NATHREZA_2),
339    ("SHADOW_OF_NATHREZA_3", TALENT::SHADOW_OF_NATHREZA_3),
340    ("SHARD_INSTABILITY", TALENT::SHARD_INSTABILITY),
341    ("SOUL_ANATHEMA", TALENT::SOUL_ANATHEMA),
342    ("SUMMON_DARKGLARE", TALENT::SUMMON_DARKGLARE),
343    ("WITHERING_BOLT", TALENT::WITHERING_BOLT),
344];
345pub(crate) mod AFFLICTION_WARLOCK {
346    pub(crate) const AGONY_CASTS: u32 = 0;
347    pub(crate) const CORRUPTION_CASTS: u32 = 1;
348    pub(crate) const UNSTABLE_AFFLICTION_CASTS: u32 = 2;
349    pub(crate) const SHADOW_BOLT_CASTS: u32 = 3;
350    pub(crate) const HAUNT_CASTS: u32 = 4;
351    pub(crate) const SUMMON_DARKGLARE_CASTS: u32 = 5;
352    pub(crate) const DARK_HARVEST_CASTS: u32 = 6;
353    pub(crate) const AGONY_UPTIME_MS: u32 = 7;
354    pub(crate) const CORRUPTION_UPTIME_MS: u32 = 8;
355    pub(crate) const UNSTABLE_AFFLICTION_UPTIME_MS: u32 = 9;
356}
357fn aura_agony(
358    a: AuraDefinitionDraft,
359    data: &ResolvedGameData,
360) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
361    a.on_target()
362        .apply_base_from_data(data, 980)?
363        .max_stacks(
364            data.require_aura_max_stacks(wowlab_types::sim::SpellIdx::from_raw(980))?,
365        )
366        .snapshot()
367        .periodic_damage_sp_from_data(
368            data,
369            wowlab_engine_combat::PeriodicDamageDataInput {
370                tick_ms: wowlab_engine_combat::validated_milliseconds(
371                    data.period(wowlab_types::sim::SpellIdx::from_raw(980), 1),
372                    980,
373                    "periodic_damage.tick_ms",
374                )?,
375                spell_id: 980,
376                effect_index: 1,
377                multiplier: 8.0,
378                offset: -0.000_000_808_56,
379                round_decimals: Some(6),
380            },
381        )?
382        .apply_periodic_behavior_from_data(data, 980)
383}
384fn aura_corruption(
385    a: AuraDefinitionDraft,
386    data: &ResolvedGameData,
387) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
388    a.on_target()
389        .duration_ms(
390            wowlab_engine_combat::validated_milliseconds(
391                f64::from(
392                    data
393                        .require_aura_duration_ms(
394                            wowlab_types::sim::SpellIdx::from_raw(196_103),
395                        )?,
396                ),
397                146_739,
398                "aura.duration_ms",
399            )?,
400        )
401        .apply_periodic_effect_from_data(data, 146_739)?
402        .apply_duration_behavior_from_data(data, 196_103)?
403        .apply_timing_modifiers_from_data(data, 146_739)?
404        .max_stacks(
405            data.require_aura_max_stacks(wowlab_types::sim::SpellIdx::from_raw(146_739))?,
406        )
407        .snapshot()
408        .periodic_damage_sp_from_data(
409            data,
410            wowlab_engine_combat::PeriodicDamageDataInput {
411                tick_ms: wowlab_engine_combat::validated_milliseconds(
412                    data.period(wowlab_types::sim::SpellIdx::from_raw(146_739), 1),
413                    146_739,
414                    "periodic_damage.tick_ms",
415                )?,
416                spell_id: 146_739,
417                effect_index: 1,
418                multiplier: 1.15,
419                offset: 0.0,
420                round_decimals: Some(6),
421            },
422        )?
423        .apply_periodic_behavior_from_data(data, 146_739)
424}
425fn aura_unstable_affliction(
426    a: AuraDefinitionDraft,
427    data: &ResolvedGameData,
428) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
429    Ok(
430        a
431            .on_target()
432            .apply_base_from_data(data, 1_259_790)?
433            .max_stacks(
434                data
435                    .require_aura_max_stacks(
436                        wowlab_types::sim::SpellIdx::from_raw(1_259_790),
437                    )?,
438            )
439            .snapshot(),
440    )
441}
442fn aura_seed_of_corruption(
443    a: AuraDefinitionDraft,
444    data: &ResolvedGameData,
445) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
446    Ok(
447        a
448            .on_target()
449            .apply_base_from_data(data, 27243)?
450            .max_stacks(
451                data
452                    .require_aura_max_stacks(
453                        wowlab_types::sim::SpellIdx::from_raw(27243),
454                    )?,
455            ),
456    )
457}
458fn aura_seed_of_corruption_is_out_dnt(
459    a: AuraDefinitionDraft,
460    data: &ResolvedGameData,
461) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
462    Ok(
463        a
464            .on_player()
465            .apply_base_from_data(data, 1_279_998)?
466            .max_stacks(
467                data
468                    .require_aura_max_stacks(
469                        wowlab_types::sim::SpellIdx::from_raw(1_279_998),
470                    )?,
471            ),
472    )
473}
474fn aura_recently_demon_has_been_summoned_dnt(
475    a: AuraDefinitionDraft,
476    data: &ResolvedGameData,
477) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
478    Ok(
479        a
480            .on_player()
481            .apply_base_from_data(data, 1_288_970)?
482            .max_stacks(
483                data
484                    .require_aura_max_stacks(
485                        wowlab_types::sim::SpellIdx::from_raw(1_288_970),
486                    )?,
487            ),
488    )
489}
490fn aura_nightfall(
491    a: AuraDefinitionDraft,
492    data: &ResolvedGameData,
493) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
494    Ok(
495        a
496            .on_player()
497            .apply_base_from_data(data, 264_571)?
498            .max_stacks(
499                data
500                    .require_aura_max_stacks(
501                        wowlab_types::sim::SpellIdx::from_raw(264_571),
502                    )?,
503            ),
504    )
505}
506fn aura_haunt(
507    a: AuraDefinitionDraft,
508    data: &ResolvedGameData,
509) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
510    Ok(
511        a
512            .on_target()
513            .apply_base_from_data(data, 48181)?
514            .max_stacks(
515                data
516                    .require_aura_max_stacks(
517                        wowlab_types::sim::SpellIdx::from_raw(48181),
518                    )?,
519            )
520            .periodic_hook(
521                wowlab_engine_combat::validated_milliseconds(
522                    data.period(wowlab_types::sim::SpellIdx::from_raw(48181), 5),
523                    48181,
524                    "periodic_hook.tick_ms",
525                )?,
526            )
527            .apply_periodic_behavior_from_data(data, 48181)?
528            .tick_hook(crate::hooks::affliction_warlock::haunt_tick_hook),
529    )
530}
531fn aura_darkglare_presence(
532    a: AuraDefinitionDraft,
533    data: &ResolvedGameData,
534) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
535    Ok(
536        a
537            .on_player()
538            .apply_base_from_data(data, 1_280_663)?
539            .max_stacks(
540                data
541                    .require_aura_max_stacks(
542                        wowlab_types::sim::SpellIdx::from_raw(1_280_663),
543                    )?,
544            ),
545    )
546}
547fn aura_shard_instability(
548    a: AuraDefinitionDraft,
549    data: &ResolvedGameData,
550) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
551    Ok(
552        a
553            .on_player()
554            .apply_base_from_data(data, 1_260_269)?
555            .max_stacks(
556                data
557                    .require_aura_max_stacks(
558                        wowlab_types::sim::SpellIdx::from_raw(1_260_269),
559                    )?,
560            ),
561    )
562}
563fn aura_cascading_calamity(
564    a: AuraDefinitionDraft,
565    data: &ResolvedGameData,
566) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
567    Ok(
568        a
569            .on_player()
570            .apply_base_from_data(data, 1_261_125)?
571            .max_stacks(
572                data
573                    .require_aura_max_stacks(
574                        wowlab_types::sim::SpellIdx::from_raw(1_261_125),
575                    )?,
576            ),
577    )
578}
579fn aura_grimoire_of_sacrifice(
580    a: AuraDefinitionDraft,
581    data: &ResolvedGameData,
582) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
583    Ok(
584        a
585            .on_player()
586            .apply_base_from_data(data, 196_099)?
587            .max_stacks(
588                data
589                    .require_aura_max_stacks(
590                        wowlab_types::sim::SpellIdx::from_raw(196_099),
591                    )?,
592            ),
593    )
594}
595fn aura_wither(
596    a: AuraDefinitionDraft,
597    data: &ResolvedGameData,
598) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
599    a.on_target()
600        .apply_base_from_data(data, 445_474)?
601        .max_stacks(
602            data.require_aura_max_stacks(wowlab_types::sim::SpellIdx::from_raw(445_474))?,
603        )
604        .snapshot()
605        .periodic_damage_sp(
606            wowlab_engine_combat::validated_milliseconds(
607                2000.0,
608                445_474,
609                "periodic_damage.tick_ms",
610            )?,
611            0.112,
612            wowlab_engine_combat::DamageFlags::empty(),
613        )
614        .apply_periodic_behavior_from_data(data, 445_474)
615}
616fn aura_malevolence(
617    a: AuraDefinitionDraft,
618    data: &ResolvedGameData,
619) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
620    Ok(
621        a
622            .on_player()
623            .apply_base_from_data(data, 442_726)?
624            .max_stacks(
625                data
626                    .require_aura_max_stacks(
627                        wowlab_types::sim::SpellIdx::from_raw(442_726),
628                    )?,
629            ),
630    )
631}
632fn aura_succulent_soul(
633    a: AuraDefinitionDraft,
634    data: &ResolvedGameData,
635) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
636    Ok(
637        a
638            .on_player()
639            .apply_base_from_data(data, 449_793)?
640            .max_stacks(
641                data
642                    .require_aura_max_stacks(
643                        wowlab_types::sim::SpellIdx::from_raw(449_793),
644                    )?,
645            ),
646    )
647}
648fn aura_manifested_demonic_soul(
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, 1_269_042)?
656            .max_stacks(
657                data
658                    .require_aura_max_stacks(
659                        wowlab_types::sim::SpellIdx::from_raw(1_269_042),
660                    )?,
661            ),
662    )
663}
664fn aura_soul_anathema(
665    a: AuraDefinitionDraft,
666    data: &ResolvedGameData,
667) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
668    Ok(
669        a
670            .on_target()
671            .apply_base_from_data(data, 450_538)?
672            .max_stacks(
673                data
674                    .require_aura_max_stacks(
675                        wowlab_types::sim::SpellIdx::from_raw(450_538),
676                    )?,
677            ),
678    )
679}
680fn aura_track_pets(
681    a: AuraDefinitionDraft,
682    data: &ResolvedGameData,
683) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
684    Ok(
685        a
686            .on_player()
687            .apply_base_from_data(data, 462_599)?
688            .max_stacks(
689                data
690                    .require_aura_max_stacks(
691                        wowlab_types::sim::SpellIdx::from_raw(462_599),
692                    )?,
693            ),
694    )
695}
696fn spell_summon_felhunter(
697    s: SpellDefinitionDraft,
698    data: &ResolvedGameData,
699) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
700    Ok(s.apply_base_from_data(data, 691)?.apply_aoe_from_data(data))
701}
702fn spell_summon_imp(
703    s: SpellDefinitionDraft,
704    data: &ResolvedGameData,
705) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
706    Ok(s.apply_base_from_data(data, 688)?.apply_aoe_from_data(data))
707}
708fn spell_grimoire_of_sacrifice(
709    s: SpellDefinitionDraft,
710    data: &ResolvedGameData,
711) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
712    Ok(
713        s
714            .apply_base_from_data(data, 108_503)?
715            .applies_aura(AURA_GRIMOIRE_OF_SACRIFICE)
716            .apply_aoe_from_data(data),
717    )
718}
719fn spell_agony(
720    s: SpellDefinitionDraft,
721    data: &ResolvedGameData,
722) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
723    Ok(
724        s
725            .apply_base_from_data(data, 980)?
726            .applies_inferred_aura(AURA_AGONY, 980)
727            .apply_aoe_from_data(data),
728    )
729}
730fn spell_corruption(
731    s: SpellDefinitionDraft,
732    data: &ResolvedGameData,
733) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
734    Ok(
735        s
736            .apply_base_from_data(data, 172)?
737            .applies_aura(AURA_CORRUPTION)
738            .apply_aoe_from_data(data),
739    )
740}
741fn spell_unstable_affliction(
742    s: SpellDefinitionDraft,
743    data: &ResolvedGameData,
744) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
745    Ok(
746        s
747            .apply_base_from_data(data, 1_259_790)?
748            .applies_inferred_aura(AURA_UNSTABLE_AFFLICTION, 1_259_790)
749            .apply_aoe_from_data(data)
750            .on_cast(crate::hooks::affliction_warlock::unstable_affliction_hook),
751    )
752}
753fn spell_seed_of_corruption(
754    s: SpellDefinitionDraft,
755    data: &ResolvedGameData,
756) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
757    Ok(
758        s
759            .apply_base_from_data(data, 27243)?
760            .applies_inferred_aura(AURA_SEED_OF_CORRUPTION, 27243)
761            .apply_aoe_from_data(data),
762    )
763}
764fn spell_haunt(
765    s: SpellDefinitionDraft,
766    data: &ResolvedGameData,
767) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
768    Ok(
769        s
770            .apply_base_from_data(data, 48181)?
771            .applies_inferred_aura(AURA_HAUNT, 48181)
772            .apply_aoe_from_data(data),
773    )
774}
775fn spell_summon_darkglare(
776    s: SpellDefinitionDraft,
777    data: &ResolvedGameData,
778) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
779    Ok(
780        s
781            .apply_base_from_data(data, 205_180)?
782            .apply_aoe_from_data(data)
783            .on_cast(crate::hooks::affliction_warlock::summon_darkglare_hook),
784    )
785}
786fn spell_dark_harvest(
787    s: SpellDefinitionDraft,
788    data: &ResolvedGameData,
789) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
790    Ok(
791        s
792            .apply_base_from_data(data, 1_257_052)?
793            .apply_aoe_from_data(data)
794            .channel(
795                wowlab_engine_combat::validated_channel_tick_count(
796                    4.0,
797                    1_257_052,
798                    "channel.tick_count",
799                )?,
800            )
801            .channel_tick_damage_sp_from_data(
802                wowlab_engine_domain::dbc::EffectLookup::new(
803                    data,
804                    wowlab_types::sim::EffectRef::new(
805                        wowlab_types::sim::SpellIdx::from_raw(1_257_065),
806                        1,
807                    ),
808                ),
809            )?
810            .on_channel_tick(crate::hooks::affliction_warlock::dark_harvest_tick_hook)
811            .on_cast(crate::hooks::affliction_warlock::dark_harvest_hook),
812    )
813}
814fn spell_shadow_bolt(
815    s: SpellDefinitionDraft,
816    data: &ResolvedGameData,
817) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
818    Ok(s.apply_base_from_data(data, 686)?.apply_aoe_from_data(data))
819}
820fn spell_drain_soul(
821    s: SpellDefinitionDraft,
822    data: &ResolvedGameData,
823) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
824    Ok(s.apply_base_from_data(data, 198_590)?.apply_aoe_from_data(data))
825}
826fn spell_malefic_grasp(
827    s: SpellDefinitionDraft,
828    data: &ResolvedGameData,
829) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
830    Ok(s.apply_base_from_data(data, 1_261_153)?.apply_aoe_from_data(data))
831}
832fn spell_drain_life(
833    s: SpellDefinitionDraft,
834    data: &ResolvedGameData,
835) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
836    Ok(s.apply_base_from_data(data, 234_153)?.apply_aoe_from_data(data))
837}
838fn spell_malevolence(
839    s: SpellDefinitionDraft,
840    data: &ResolvedGameData,
841) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
842    Ok(
843        s
844            .apply_base_from_data(data, 430_014)?
845            .applies_aura(AURA_MALEVOLENCE)
846            .apply_aoe_from_data(data),
847    )
848}
849pub(crate) fn build_combat_system(
850    params: &wowlab_engine_ports::HandlerParams<'_>,
851) -> Result<BuiltCombatSystem, wowlab_engine_ports::EngineError> {
852    let builder = BuiltCombatSystem::builder(params.stats.clone())
853        .spec_id(SpecId::Affliction)
854        .hero_talent_trees(DECLARED_METADATA.hero_talent_trees)
855        .mastery_spell(77215)
856        .mastery_hook(crate::hooks::affliction_warlock::mastery)
857        .resource(
858            "soul_shards",
859            5.0,
860            params
861                .game_data
862                .power_regen_for_max(7, 5.0)
863                .ok_or_else(|| {
864                    wowlab_engine_ports::EngineError::spec_construction(
865                        "missing power-type power_regen_for_max for type_id 7",
866                    )
867                })?,
868        )
869        .resource_type_id(7)
870        .resource_start(3.0)
871        .has_pet(true)
872        .aura("agony", AURA::AGONY, |a| aura_agony(a, &params.game_data))
873        .aura("corruption", AURA::CORRUPTION, |a| aura_corruption(a, &params.game_data))
874        .aura(
875            "unstable_affliction",
876            AURA::UNSTABLE_AFFLICTION,
877            |a| aura_unstable_affliction(a, &params.game_data),
878        )
879        .aura(
880            "seed_of_corruption",
881            AURA::SEED_OF_CORRUPTION,
882            |a| aura_seed_of_corruption(a, &params.game_data),
883        )
884        .aura(
885            "seed_of_corruption_is_out_dnt",
886            AURA::SEED_OF_CORRUPTION_IS_OUT_DNT,
887            |a| aura_seed_of_corruption_is_out_dnt(a, &params.game_data),
888        )
889        .aura(
890            "recently_demon_has_been_summoned_dnt",
891            AURA::RECENTLY_DEMON_HAS_BEEN_SUMMONED_DNT,
892            |a| aura_recently_demon_has_been_summoned_dnt(a, &params.game_data),
893        )
894        .aura("nightfall", AURA::NIGHTFALL, |a| aura_nightfall(a, &params.game_data))
895        .aura("haunt", AURA::HAUNT, |a| aura_haunt(a, &params.game_data))
896        .aura(
897            "darkglare_presence",
898            AURA::DARKGLARE_PRESENCE,
899            |a| aura_darkglare_presence(a, &params.game_data),
900        )
901        .aura(
902            "shard_instability",
903            AURA::SHARD_INSTABILITY,
904            |a| aura_shard_instability(a, &params.game_data),
905        )
906        .aura(
907            "cascading_calamity",
908            AURA::CASCADING_CALAMITY,
909            |a| aura_cascading_calamity(a, &params.game_data),
910        )
911        .aura(
912            "grimoire_of_sacrifice",
913            AURA::GRIMOIRE_OF_SACRIFICE,
914            |a| aura_grimoire_of_sacrifice(a, &params.game_data),
915        )
916        .aura("wither", AURA::WITHER, |a| aura_wither(a, &params.game_data))
917        .aura(
918            "malevolence",
919            AURA::MALEVOLENCE,
920            |a| aura_malevolence(a, &params.game_data),
921        )
922        .aura(
923            "succulent_soul",
924            AURA::SUCCULENT_SOUL,
925            |a| aura_succulent_soul(a, &params.game_data),
926        )
927        .aura(
928            "manifested_demonic_soul",
929            AURA::MANIFESTED_DEMONIC_SOUL,
930            |a| aura_manifested_demonic_soul(a, &params.game_data),
931        )
932        .aura(
933            "soul_anathema",
934            AURA::SOUL_ANATHEMA,
935            |a| aura_soul_anathema(a, &params.game_data),
936        )
937        .aura("track_pets", AURA::TRACK_PETS, |a| aura_track_pets(a, &params.game_data))
938        .spell(
939            "summon_felhunter",
940            SPELL::SUMMON_FELHUNTER,
941            |s| spell_summon_felhunter(s, &params.game_data),
942        )
943        .spell(
944            "summon_imp",
945            SPELL::SUMMON_IMP,
946            |s| spell_summon_imp(s, &params.game_data),
947        )
948        .spell(
949            "grimoire_of_sacrifice",
950            SPELL::GRIMOIRE_OF_SACRIFICE,
951            |s| spell_grimoire_of_sacrifice(s, &params.game_data),
952        )
953        .spell("agony", SPELL::AGONY, |s| spell_agony(s, &params.game_data))
954        .spell(
955            "corruption",
956            SPELL::CORRUPTION,
957            |s| spell_corruption(s, &params.game_data),
958        )
959        .spell(
960            "unstable_affliction",
961            SPELL::UNSTABLE_AFFLICTION,
962            |s| spell_unstable_affliction(s, &params.game_data),
963        )
964        .spell(
965            "seed_of_corruption",
966            SPELL::SEED_OF_CORRUPTION,
967            |s| spell_seed_of_corruption(s, &params.game_data),
968        )
969        .spell("haunt", SPELL::HAUNT, |s| spell_haunt(s, &params.game_data))
970        .spell(
971            "summon_darkglare",
972            SPELL::SUMMON_DARKGLARE,
973            |s| spell_summon_darkglare(s, &params.game_data),
974        )
975        .spell(
976            "dark_harvest",
977            SPELL::DARK_HARVEST,
978            |s| spell_dark_harvest(s, &params.game_data),
979        )
980        .spell(
981            "shadow_bolt",
982            SPELL::SHADOW_BOLT,
983            |s| spell_shadow_bolt(s, &params.game_data),
984        )
985        .spell(
986            "drain_soul",
987            SPELL::DRAIN_SOUL,
988            |s| spell_drain_soul(s, &params.game_data),
989        )
990        .spell(
991            "malefic_grasp",
992            SPELL::MALEFIC_GRASP,
993            |s| spell_malefic_grasp(s, &params.game_data),
994        )
995        .spell(
996            "drain_life",
997            SPELL::DRAIN_LIFE,
998            |s| spell_drain_life(s, &params.game_data),
999        )
1000        .spell(
1001            "malevolence",
1002            SPELL::MALEVOLENCE,
1003            |s| spell_malevolence(s, &params.game_data),
1004        )
1005        .auto_attack(|a| {
1006            a
1007                .spell_id(1)
1008                .swing_ms(2000)
1009                .apply_base_from_data(&params.game_data)
1010                .ap_coef(
1011                    wowlab_engine_domain::damage::pet_swing_power_coefficient(
1012                        0.575,
1013                        2000,
1014                        1.0,
1015                    ),
1016                )
1017                .is_pet()
1018                .uses_spell_power()
1019        })
1020        .game_data(params.game_data.clone())
1021        .talent_spell_ids(TALENTS)
1022        .talent_selections(params.talent_selections)
1023        .register_impact_effect_proc(
1024            wowlab_engine_combat::ImpactEffectProcDefinition::new(
1025                    wowlab_engine_combat::ImpactSource::Spell(SPELL::AGONY),
1026                )
1027                .chance(0.185)
1028                .periodic_only()
1029                .gain(1.0),
1030        )
1031        .set_bonus_auras(params.set_bonus_auras)
1032        .encounter(params.encounter.clone());
1033    let builder = crate::generated::items::register_equipped(
1034        builder,
1035        &params.game_data,
1036        params.equipped_items,
1037    )?;
1038
1039    builder
1040        .build(params.rotation)
1041        .map_err(wowlab_engine_ports::EngineError::rotation_compile)
1042}
1043fn new_handler(
1044    params: wowlab_engine_ports::HandlerParams<'_>,
1045) -> Result<Box<dyn SpecHandler>, wowlab_engine_ports::EngineError> {
1046    let handler = crate::composition::compose_handler(
1047        build_combat_system,
1048        &params,
1049        crate::hooks::affliction_warlock::AfflictionHandler::try_new,
1050    )?;
1051
1052    Ok(Box::new(handler))
1053}
1054static DECLARED_METADATA: DeclaredSpecMetadata = DeclaredSpecMetadata {
1055    primary_resource: ResourceType::SoulShards,
1056    secondary_resource: None,
1057    spell_ids: DECLARED_SPELL_IDS,
1058    aura_ids: DECLARED_AURA_IDS,
1059    server_proc_entries: &[],
1060    talents: TALENTS,
1061    rotation_field_schema: &[],
1062    metrics_plugin_id: None,
1063    hero_talent_trees: &[
1064        HeroTalentTreeDesc {
1065            name: "Hellcaller",
1066            spells: HERO_TREE_HELLCALLER_SPELLS,
1067            auras: HERO_TREE_HELLCALLER_AURAS,
1068        },
1069        HeroTalentTreeDesc {
1070            name: "Soul Harvester",
1071            spells: HERO_TREE_SOUL_HARVESTER_SPELLS,
1072            auras: HERO_TREE_SOUL_HARVESTER_AURAS,
1073        },
1074    ],
1075    reported_spells: REPORTED_SPELLS,
1076    masked_passive_effects: &[],
1077    passive_effect_overrides: &[],
1078};
1079pub(super) const SPEC_DESCRIPTOR: SpecDescriptor = SpecDescriptor {
1080    spec_id: SpecId::Affliction,
1081    display_name: "Affliction Warlock",
1082    metadata: DECLARED_METADATA,
1083    handler_factory: new_handler,
1084};
1085wowlab_engine_combat::smoke_test!(build_combat_system);