1#![allow(non_snake_case, dead_code)]
4use wowlab_types::{combat::ResourceType, game::SpecId};
5use wowlab_engine_domain::dbc::ProcAttributes;
6use wowlab_engine_combat::{
7 BuiltCombatSystem, AuraDefinitionDraft, LocalAuraIdx, LocalSpellIdx,
8 SpellDefinitionDraft,
9};
10use wowlab_engine_ports::{
11 DeclaredSpecMetadata, SpecDescriptor, SpecHandler, HeroTalentTreeDesc,
12 DeclaredServerProcEntry,
13};
14use wowlab_engine_gamedata::ResolvedGameData;
15pub(crate) mod SPELL {
16 pub(crate) const MORTAL_STRIKE: u32 = 12294;
18 pub(crate) const OVERPOWER: u32 = 7384;
20 pub(crate) const EXECUTE: u32 = 163_201;
22 pub(crate) const SLAM: u32 = 1464;
24 pub(crate) const COLOSSUS_SMASH: u32 = 167_105;
26 pub(crate) const AVATAR: u32 = 107_574;
28 pub(crate) const SWEEPING_STRIKES: u32 = 260_708;
30 pub(crate) const CLEAVE: u32 = 845;
32 pub(crate) const WHIRLWIND: u32 = 1680;
34 pub(crate) const REND: u32 = 772;
36 pub(crate) const THUNDER_CLAP: u32 = 6343;
38 pub(crate) const HEROIC_STRIKE: u32 = 1_269_383;
40 pub(crate) const CHAMPIONS_SPEAR: u32 = 376_079;
42 pub(crate) const BATTLE_SHOUT: u32 = 6673;
44 pub(crate) const HEROIC_THROW: u32 = 57755;
46 pub(crate) const EXECUTE_DAMAGE: u32 = 260_798;
48 pub(crate) const DREADNAUGHT: u32 = 315_961;
50 pub(crate) const FATALITY: u32 = 383_706;
52 pub(crate) const BLADESTORM: u32 = 227_847;
54 pub(crate) const RAVAGER: u32 = 228_920;
56 pub(crate) const DEMOLISH: u32 = 436_358;
58}
59pub(crate) mod AURA {
60 pub(crate) const COLOSSUS_SMASH: u32 = 208_086;
62 pub(crate) const DEEP_WOUNDS: u32 = 262_115;
64 pub(crate) const REND: u32 = 388_539;
66 pub(crate) const SWEEPING_STRIKES: u32 = 260_708;
68 pub(crate) const AVATAR: u32 = 107_574;
70 pub(crate) const SUDDEN_DEATH: u32 = 52437;
72 pub(crate) const MARTIAL_PROWESS: u32 = 316_440;
74 pub(crate) const BATTLELORD: u32 = 386_631;
76 pub(crate) const COLLATERAL_DAMAGE: u32 = 334_783;
78 pub(crate) const FATAL_MARK: u32 = 383_704;
80 pub(crate) const BATTLE_SHOUT: u32 = 6673;
82 pub(crate) const BATTLE_SHOUT_HIGHLIGHT: u32 = 6673;
84 pub(crate) const BATTLE_STANCE: u32 = 386_164;
86 pub(crate) const RAVAGER: u32 = 228_920;
88 pub(crate) const BLADESTORM: u32 = 227_847;
90 pub(crate) const EXECUTIONERS_PRECISION: u32 = 386_633;
92 pub(crate) const IMMINENT_DEMISE: u32 = 445_606;
94 pub(crate) const FIERCE_FOLLOWTHROUGH: u32 = 458_689;
96 pub(crate) const EXECUTIONER: u32 = 445_584;
98 pub(crate) const OVERWHELMED: u32 = 445_836;
100 pub(crate) const MASTER_OF_WARFARE: u32 = 1_269_391;
102 pub(crate) const MASTER_OF_WARFARE_DAMAGE: u32 = 1_269_394;
104}
105pub(crate) mod TALENT {
106 pub(crate) const ANGER_MANAGEMENT: u32 = 152_278;
108 pub(crate) const BATTLELORD: u32 = 386_630;
110 pub(crate) const BATTLE_STANCE: u32 = 386_164;
112 pub(crate) const CRITICAL_THINKING: u32 = 389_306;
114 pub(crate) const CRUSHING_FORCE: u32 = 382_764;
116 pub(crate) const DEEP_WOUNDS: u32 = 1_261_060;
118 pub(crate) const DREADNAUGHT: u32 = 262_150;
120 pub(crate) const EXECUTIONERS_PRECISION: u32 = 386_634;
122 pub(crate) const FATALITY: u32 = 383_703;
124 pub(crate) const FIERCE_FOLLOWTHROUGH: u32 = 444_773;
126 pub(crate) const FROTHING_BERSERKER: u32 = 392_792;
128 pub(crate) const IMMINENT_DEMISE: u32 = 444_769;
130 pub(crate) const IMPALE: u32 = 383_430;
132 pub(crate) const IMPROVED_EXECUTE: u32 = 316_405;
134 pub(crate) const IMPROVED_OVERPOWER: u32 = 385_571;
136 pub(crate) const MARTIAL_PROWESS: u32 = 1_273_062;
138 pub(crate) const MASSACRE: u32 = 281_001;
140 pub(crate) const MASTER_OF_WARFARE: u32 = 1_269_314;
142 pub(crate) const MORTAL_WOUNDS: u32 = 1_261_062;
144 pub(crate) const OVERPOWERING_FINISH: u32 = 400_205;
146 pub(crate) const OVERWHELMING_BLADES: u32 = 444_772;
148 pub(crate) const OVERWHELMING_RAGE: u32 = 382_767;
150 pub(crate) const RAVAGER: u32 = 228_920;
152 pub(crate) const REAP_THE_STORM: u32 = 444_775;
154 pub(crate) const SHARPENED_BLADES: u32 = 383_341;
156 pub(crate) const SLAYERS_DOMINANCE: u32 = 444_767;
158 pub(crate) const STRENGTH_OF_ARMS: u32 = 400_803;
160 pub(crate) const SUDDEN_DEATH: u32 = 29725;
162 pub(crate) const TACTICIAN: u32 = 184_783;
164 pub(crate) const UNHINGED: u32 = 386_628;
166 pub(crate) const UNRELENTING_ONSLAUGHT: u32 = 444_780;
168 pub(crate) const WAR_MACHINE: u32 = 262_231;
170}
171pub(crate) mod SET_BONUS {
172 pub(crate) const MID1_ARMS_4PC: u32 = 1_264_876;
174}
175pub(crate) mod HERO {
176 pub(crate) mod SLAYER {
177 pub(crate) mod SPELL {
178 pub(crate) const REAP_THE_STORM_EXECUTE: u32 = 446_005;
180 pub(crate) const SLAYERS_STRIKE: u32 = 445_579;
182 }
183 pub(crate) mod AURA {
184 pub(crate) const BRUTAL_FINISH: u32 = 446_918;
186 pub(crate) const OPPORTUNIST: u32 = 456_120;
188 pub(crate) const VIOLENT_EUPHORIA: u32 = 1_270_731;
190 }
191 }
192 pub(crate) mod COLOSSUS {
193 pub(crate) mod SPELL {
194 pub(crate) const DEMOLISH: u32 = 436_358;
196 pub(crate) const DEMOLISH_HIT_1: u32 = 440_884;
198 pub(crate) const DEMOLISH_HIT_2: u32 = 440_886;
200 pub(crate) const DEMOLISH_HIT_3: u32 = 440_888;
202 }
203 pub(crate) mod AURA {
204 pub(crate) const CELERITOUS_CONCLUSION_CRIT: u32 = 1_270_846;
206 pub(crate) const CELERITOUS_CONCLUSION_HASTE: u32 = 1_270_843;
208 pub(crate) const COLOSSAL_MIGHT: u32 = 440_989;
210 pub(crate) const CUT_TO_THE_BONE: u32 = 1_270_840;
212 pub(crate) const WRECKED: u32 = 447_513;
214 }
215 }
216}
217static HERO_TREE_SLAYER_SPELLS: &[(&str, u32)] = &[
218 ("REAP_THE_STORM_EXECUTE", 446_005),
219 ("SLAYERS_STRIKE", 445_579),
220];
221static HERO_TREE_SLAYER_AURAS: &[(&str, u32)] = &[
222 ("BRUTAL_FINISH", 446_918),
223 ("OPPORTUNIST", 456_120),
224 ("VIOLENT_EUPHORIA", 1_270_731),
225];
226static HERO_TREE_COLOSSUS_SPELLS: &[(&str, u32)] = &[
227 ("DEMOLISH", 436_358),
228 ("DEMOLISH_HIT_1", 440_884),
229 ("DEMOLISH_HIT_2", 440_886),
230 ("DEMOLISH_HIT_3", 440_888),
231];
232static HERO_TREE_COLOSSUS_AURAS: &[(&str, u32)] = &[
233 ("CELERITOUS_CONCLUSION_CRIT", 1_270_846),
234 ("CELERITOUS_CONCLUSION_HASTE", 1_270_843),
235 ("COLOSSAL_MIGHT", 440_989),
236 ("CUT_TO_THE_BONE", 1_270_840),
237 ("WRECKED", 447_513),
238];
239pub(crate) const AURA_COLOSSUS_SMASH: LocalAuraIdx = LocalAuraIdx::new(0);
240pub(crate) const AURA_DEEP_WOUNDS: LocalAuraIdx = LocalAuraIdx::new(1);
241pub(crate) const AURA_REND: LocalAuraIdx = LocalAuraIdx::new(2);
242pub(crate) const AURA_SWEEPING_STRIKES: LocalAuraIdx = LocalAuraIdx::new(3);
243pub(crate) const AURA_AVATAR: LocalAuraIdx = LocalAuraIdx::new(4);
244pub(crate) const AURA_SUDDEN_DEATH: LocalAuraIdx = LocalAuraIdx::new(5);
245pub(crate) const AURA_MARTIAL_PROWESS: LocalAuraIdx = LocalAuraIdx::new(6);
246pub(crate) const AURA_BATTLELORD: LocalAuraIdx = LocalAuraIdx::new(7);
247pub(crate) const AURA_COLLATERAL_DAMAGE: LocalAuraIdx = LocalAuraIdx::new(8);
248pub(crate) const AURA_FATAL_MARK: LocalAuraIdx = LocalAuraIdx::new(9);
249pub(crate) const AURA_BATTLE_SHOUT: LocalAuraIdx = LocalAuraIdx::new(10);
250pub(crate) const AURA_BATTLE_SHOUT_HIGHLIGHT: LocalAuraIdx = LocalAuraIdx::new(11);
251pub(crate) const AURA_BATTLE_STANCE: LocalAuraIdx = LocalAuraIdx::new(12);
252pub(crate) const AURA_RAVAGER: LocalAuraIdx = LocalAuraIdx::new(13);
253pub(crate) const AURA_BLADESTORM: LocalAuraIdx = LocalAuraIdx::new(14);
254pub(crate) const AURA_EXECUTIONERS_PRECISION: LocalAuraIdx = LocalAuraIdx::new(15);
255pub(crate) const AURA_IMMINENT_DEMISE: LocalAuraIdx = LocalAuraIdx::new(16);
256pub(crate) const AURA_FIERCE_FOLLOWTHROUGH: LocalAuraIdx = LocalAuraIdx::new(17);
257pub(crate) const AURA_EXECUTIONER: LocalAuraIdx = LocalAuraIdx::new(18);
258pub(crate) const AURA_OVERWHELMED: LocalAuraIdx = LocalAuraIdx::new(19);
259pub(crate) const AURA_MASTER_OF_WARFARE: LocalAuraIdx = LocalAuraIdx::new(20);
260pub(crate) const AURA_MASTER_OF_WARFARE_DAMAGE: LocalAuraIdx = LocalAuraIdx::new(21);
261pub(crate) const AURA_COUNT: usize = 22;
262const _: () = assert!(
263 AURA_COUNT == 22, "AURA index ABI: count changed -- update positional hook consumers"
264);
265pub(crate) const SPELL_MORTAL_STRIKE: LocalSpellIdx = LocalSpellIdx::new(0);
266pub(crate) const SPELL_OVERPOWER: LocalSpellIdx = LocalSpellIdx::new(1);
267pub(crate) const SPELL_EXECUTE: LocalSpellIdx = LocalSpellIdx::new(2);
268pub(crate) const SPELL_SLAM: LocalSpellIdx = LocalSpellIdx::new(3);
269pub(crate) const SPELL_COLOSSUS_SMASH: LocalSpellIdx = LocalSpellIdx::new(4);
270pub(crate) const SPELL_AVATAR: LocalSpellIdx = LocalSpellIdx::new(5);
271pub(crate) const SPELL_SWEEPING_STRIKES: LocalSpellIdx = LocalSpellIdx::new(6);
272pub(crate) const SPELL_CLEAVE: LocalSpellIdx = LocalSpellIdx::new(7);
273pub(crate) const SPELL_WHIRLWIND: LocalSpellIdx = LocalSpellIdx::new(8);
274pub(crate) const SPELL_REND: LocalSpellIdx = LocalSpellIdx::new(9);
275pub(crate) const SPELL_THUNDER_CLAP: LocalSpellIdx = LocalSpellIdx::new(10);
276pub(crate) const SPELL_HEROIC_STRIKE: LocalSpellIdx = LocalSpellIdx::new(11);
277pub(crate) const SPELL_CHAMPIONS_SPEAR: LocalSpellIdx = LocalSpellIdx::new(12);
278pub(crate) const SPELL_BATTLE_SHOUT: LocalSpellIdx = LocalSpellIdx::new(13);
279pub(crate) const SPELL_HEROIC_THROW: LocalSpellIdx = LocalSpellIdx::new(14);
280pub(crate) const SPELL_EXECUTE_DAMAGE: LocalSpellIdx = LocalSpellIdx::new(15);
281pub(crate) const SPELL_DREADNAUGHT: LocalSpellIdx = LocalSpellIdx::new(16);
282pub(crate) const SPELL_FATALITY: LocalSpellIdx = LocalSpellIdx::new(17);
283pub(crate) const SPELL_BLADESTORM: LocalSpellIdx = LocalSpellIdx::new(18);
284pub(crate) const SPELL_RAVAGER: LocalSpellIdx = LocalSpellIdx::new(19);
285pub(crate) const SPELL_DEMOLISH: LocalSpellIdx = LocalSpellIdx::new(20);
286pub(crate) const SPELL_COUNT: usize = 21;
287const _: () = assert!(
288 SPELL_COUNT == 21,
289 "SPELL index ABI: count changed -- update positional hook consumers"
290);
291pub(crate) mod EFFECT {
292 pub(crate) const SEASONED_SOLDIER_CRIT: (u32, u8) = (279_423, 1);
294 pub(crate) const EXECUTE_DMG: (u32, u8) = (260_798, 1);
296 pub(crate) const EXECUTE_REFUND: (u32, u8) = (163_201, 2);
298 pub(crate) const CRITICAL_THINKING_REFUND: (u32, u8) = (389_306, 2);
300 pub(crate) const MASSACRE_PCT: (u32, u8) = (281_001, 2);
302 pub(crate) const MORTAL_STRIKE_DMG: (u32, u8) = (12294, 1);
304 pub(crate) const BLADESTORM_PERIOD: (u32, u8) = (227_847, 1);
306 pub(crate) const OVERPOWER_DMG: (u32, u8) = (7384, 1);
308 pub(crate) const TACTICIAN_CHANCE: (u32, u8) = (184_783, 1);
310 pub(crate) const ANGER_MANAGEMENT_DIV: (u32, u8) = (152_278, 1);
312 pub(crate) const FATALITY_CHANCE: (u32, u8) = (383_703, 1);
314 pub(crate) const FATALITY_DMG: (u32, u8) = (383_706, 1);
316 pub(crate) const DREADNAUGHT_DMG: (u32, u8) = (315_961, 1);
318 pub(crate) const SLAYERS_STRIKE_DMG: (u32, u8) = (445_579, 1);
320 pub(crate) const IMMINENT_DEMISE_EVERY: (u32, u8) = (444_769, 1);
322 pub(crate) const REAP_DMG: (u32, u8) = (446_005, 1);
324 pub(crate) const OVERPOWERING_FINISH_BELOW: (u32, u8) = (400_205, 2);
326 pub(crate) const OVERPOWERING_FINISH_PCT: (u32, u8) = (400_205, 1);
328 pub(crate) const FROTHING_REFUND: (u32, u8) = (392_792, 1);
330 pub(crate) const UNRELENTING_CDR_S: (u32, u8) = (444_780, 1);
332 pub(crate) const UNRELENTING_OVERWHELMED: (u32, u8) = (444_780, 2);
334 pub(crate) const SET4PC_CS_EXTEND_MS: (u32, u8) = (1_264_876, 1);
336}
337static REPORTED_SPELLS: &[(&str, u32)] = &[];
338static DECLARED_SPELL_IDS: &[u32] = &[
339 12294, 7384, 163_201, 1464, 167_105, 107_574, 260_708, 845, 1680, 772, 6343,
340 1_269_383, 376_079, 6673, 57755, 260_798, 315_961, 383_706, 227_847, 228_920,
341 436_358, 208_086, 262_115, 388_539, 260_708, 107_574, 52437, 316_440, 386_631,
342 334_783, 383_704, 6673, 6673, 386_164, 228_920, 227_847, 386_633, 445_606, 458_689,
343 445_584, 445_836, 1_269_391, 1_269_394, 6603, 6673, 7384, 12294, 152_278, 163_201,
344 184_783, 227_847, 260_798, 279_423, 281_001, 315_961, 383_703, 383_706, 389_306,
345 392_792, 400_205, 444_769, 444_780, 445_579, 446_005, 1_258_398, 1_264_876, 446_005,
346 445_579, 446_918, 456_120, 1_270_731, 436_358, 440_884, 440_886, 440_888, 1_270_846,
347 1_270_843, 440_989, 1_270_840, 447_513,
348];
349static DECLARED_AURA_IDS: &[u32] = &[
350 208_086, 262_115, 388_539, 260_708, 107_574, 52437, 316_440, 386_631, 334_783,
351 383_704, 6673, 6673, 386_164, 228_920, 227_847, 386_633, 445_606, 458_689, 445_584,
352 445_836, 1_269_391, 1_269_394, 446_918, 456_120, 1_270_731, 1_270_846, 1_270_843,
353 440_989, 1_270_840, 447_513,
354];
355static TALENTS: &[(&str, u32)] = &[
356 ("ANGER_MANAGEMENT", TALENT::ANGER_MANAGEMENT),
357 ("BATTLELORD", TALENT::BATTLELORD),
358 ("BATTLE_STANCE", TALENT::BATTLE_STANCE),
359 ("CRITICAL_THINKING", TALENT::CRITICAL_THINKING),
360 ("CRUSHING_FORCE", TALENT::CRUSHING_FORCE),
361 ("DEEP_WOUNDS", TALENT::DEEP_WOUNDS),
362 ("DREADNAUGHT", TALENT::DREADNAUGHT),
363 ("EXECUTIONERS_PRECISION", TALENT::EXECUTIONERS_PRECISION),
364 ("FATALITY", TALENT::FATALITY),
365 ("FIERCE_FOLLOWTHROUGH", TALENT::FIERCE_FOLLOWTHROUGH),
366 ("FROTHING_BERSERKER", TALENT::FROTHING_BERSERKER),
367 ("IMMINENT_DEMISE", TALENT::IMMINENT_DEMISE),
368 ("IMPALE", TALENT::IMPALE),
369 ("IMPROVED_EXECUTE", TALENT::IMPROVED_EXECUTE),
370 ("IMPROVED_OVERPOWER", TALENT::IMPROVED_OVERPOWER),
371 ("MARTIAL_PROWESS", TALENT::MARTIAL_PROWESS),
372 ("MASSACRE", TALENT::MASSACRE),
373 ("MASTER_OF_WARFARE", TALENT::MASTER_OF_WARFARE),
374 ("MORTAL_WOUNDS", TALENT::MORTAL_WOUNDS),
375 ("OVERPOWERING_FINISH", TALENT::OVERPOWERING_FINISH),
376 ("OVERWHELMING_BLADES", TALENT::OVERWHELMING_BLADES),
377 ("OVERWHELMING_RAGE", TALENT::OVERWHELMING_RAGE),
378 ("RAVAGER", TALENT::RAVAGER),
379 ("REAP_THE_STORM", TALENT::REAP_THE_STORM),
380 ("SHARPENED_BLADES", TALENT::SHARPENED_BLADES),
381 ("SLAYERS_DOMINANCE", TALENT::SLAYERS_DOMINANCE),
382 ("STRENGTH_OF_ARMS", TALENT::STRENGTH_OF_ARMS),
383 ("SUDDEN_DEATH", TALENT::SUDDEN_DEATH),
384 ("TACTICIAN", TALENT::TACTICIAN),
385 ("UNHINGED", TALENT::UNHINGED),
386 ("UNRELENTING_ONSLAUGHT", TALENT::UNRELENTING_ONSLAUGHT),
387 ("WAR_MACHINE", TALENT::WAR_MACHINE),
388];
389pub(crate) mod ARMS_WARRIOR {
390 pub(crate) const MORTAL_STRIKE_CASTS: u32 = 0;
391 pub(crate) const OVERPOWER_CASTS: u32 = 1;
392 pub(crate) const EXECUTE_CASTS: u32 = 2;
393 pub(crate) const SLAM_CASTS: u32 = 3;
394 pub(crate) const COLOSSUS_SMASH_CASTS: u32 = 4;
395 pub(crate) const BLADESTORM_CASTS: u32 = 5;
396 pub(crate) const AVATAR_CASTS: u32 = 6;
397 pub(crate) const COLOSSUS_SMASH_UPTIME_MS: u32 = 7;
398 pub(crate) const AVATAR_UPTIME_MS: u32 = 8;
399}
400fn aura_colossus_smash(
401 a: AuraDefinitionDraft,
402 data: &ResolvedGameData,
403) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
404 Ok(
405 a
406 .on_target()
407 .apply_base_from_data(data, 208_086)?
408 .max_stacks(
409 data
410 .require_aura_max_stacks(
411 wowlab_types::sim::SpellIdx::from_raw(208_086),
412 )?,
413 ),
414 )
415}
416fn aura_deep_wounds(
417 a: AuraDefinitionDraft,
418 data: &ResolvedGameData,
419) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
420 Ok(
421 a
422 .on_target()
423 .apply_base_from_data(data, 262_115)?
424 .max_stacks(
425 data
426 .require_aura_max_stacks(
427 wowlab_types::sim::SpellIdx::from_raw(262_115),
428 )?,
429 ),
430 )
431}
432fn aura_rend(
433 a: AuraDefinitionDraft,
434 data: &ResolvedGameData,
435) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
436 Ok(
437 a
438 .on_target()
439 .apply_base_from_data(data, 388_539)?
440 .max_stacks(
441 data
442 .require_aura_max_stacks(
443 wowlab_types::sim::SpellIdx::from_raw(388_539),
444 )?,
445 ),
446 )
447}
448fn aura_sweeping_strikes(
449 a: AuraDefinitionDraft,
450 data: &ResolvedGameData,
451) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
452 Ok(
453 a
454 .on_player()
455 .apply_base_from_data(data, 260_708)?
456 .max_stacks(
457 data
458 .require_aura_max_stacks(
459 wowlab_types::sim::SpellIdx::from_raw(260_708),
460 )?,
461 ),
462 )
463}
464fn aura_avatar(
465 a: AuraDefinitionDraft,
466 data: &ResolvedGameData,
467) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
468 Ok(
469 a
470 .on_player()
471 .apply_base_from_data(data, 107_574)?
472 .max_stacks(
473 data
474 .require_aura_max_stacks(
475 wowlab_types::sim::SpellIdx::from_raw(107_574),
476 )?,
477 ),
478 )
479}
480fn aura_sudden_death(
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, 52437)?
488 .max_stacks(
489 data
490 .require_aura_max_stacks(
491 wowlab_types::sim::SpellIdx::from_raw(52437),
492 )?,
493 ),
494 )
495}
496fn aura_martial_prowess(
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, 316_440)?
504 .max_stacks(
505 data
506 .require_aura_max_stacks(
507 wowlab_types::sim::SpellIdx::from_raw(316_440),
508 )?,
509 ),
510 )
511}
512fn aura_battlelord(
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, 386_631)?
520 .max_stacks(
521 data
522 .require_aura_max_stacks(
523 wowlab_types::sim::SpellIdx::from_raw(386_631),
524 )?,
525 ),
526 )
527}
528fn aura_collateral_damage(
529 a: AuraDefinitionDraft,
530 data: &ResolvedGameData,
531) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
532 Ok(
533 a
534 .on_player()
535 .apply_base_from_data(data, 334_783)?
536 .max_stacks(
537 data
538 .require_aura_max_stacks(
539 wowlab_types::sim::SpellIdx::from_raw(334_783),
540 )?,
541 ),
542 )
543}
544fn aura_fatal_mark(
545 a: AuraDefinitionDraft,
546 data: &ResolvedGameData,
547) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
548 Ok(
549 a
550 .on_target()
551 .apply_base_from_data(data, 383_704)?
552 .max_stacks(
553 data
554 .require_aura_max_stacks(
555 wowlab_types::sim::SpellIdx::from_raw(383_704),
556 )?,
557 ),
558 )
559}
560fn aura_battle_shout(
561 a: AuraDefinitionDraft,
562 data: &ResolvedGameData,
563) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
564 a.on_player()
565 .apply_base_from_data(data, 6673)?
566 .max_stacks(
567 data.require_aura_max_stacks(wowlab_types::sim::SpellIdx::from_raw(6673))?,
568 )
569 .attack_power_pct_per_stack(
570 data.base_points(wowlab_types::sim::SpellIdx::from_raw(6673), 1),
571 )
572}
573fn aura_battle_shout_highlight(
574 a: AuraDefinitionDraft,
575 data: &ResolvedGameData,
576) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
577 Ok(
578 a
579 .on_player()
580 .apply_base_from_data(data, 6673)?
581 .max_stacks(
582 data
583 .require_aura_max_stacks(
584 wowlab_types::sim::SpellIdx::from_raw(6673),
585 )?,
586 ),
587 )
588}
589fn aura_battle_stance(
590 a: AuraDefinitionDraft,
591 data: &ResolvedGameData,
592) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
593 Ok(
594 a
595 .on_player()
596 .apply_base_from_data(data, 386_164)?
597 .max_stacks(
598 data
599 .require_aura_max_stacks(
600 wowlab_types::sim::SpellIdx::from_raw(386_164),
601 )?,
602 ),
603 )
604}
605fn aura_ravager(
606 a: AuraDefinitionDraft,
607 data: &ResolvedGameData,
608) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
609 Ok(
610 a
611 .on_player()
612 .apply_base_from_data(data, 228_920)?
613 .max_stacks(
614 data
615 .require_aura_max_stacks(
616 wowlab_types::sim::SpellIdx::from_raw(228_920),
617 )?,
618 ),
619 )
620}
621fn aura_bladestorm(
622 a: AuraDefinitionDraft,
623 data: &ResolvedGameData,
624) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
625 Ok(
626 a
627 .on_player()
628 .apply_base_from_data(data, 227_847)?
629 .max_stacks(
630 data
631 .require_aura_max_stacks(
632 wowlab_types::sim::SpellIdx::from_raw(227_847),
633 )?,
634 ),
635 )
636}
637fn aura_executioners_precision(
638 a: AuraDefinitionDraft,
639 data: &ResolvedGameData,
640) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
641 Ok(
642 a
643 .on_player()
644 .apply_base_from_data(data, 386_633)?
645 .max_stacks(
646 data
647 .require_aura_max_stacks(
648 wowlab_types::sim::SpellIdx::from_raw(386_633),
649 )?,
650 ),
651 )
652}
653fn aura_imminent_demise(
654 a: AuraDefinitionDraft,
655 data: &ResolvedGameData,
656) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
657 Ok(
658 a
659 .on_player()
660 .apply_base_from_data(data, 445_606)?
661 .max_stacks(
662 data
663 .require_aura_max_stacks(
664 wowlab_types::sim::SpellIdx::from_raw(445_606),
665 )?,
666 ),
667 )
668}
669fn aura_fierce_followthrough(
670 a: AuraDefinitionDraft,
671 data: &ResolvedGameData,
672) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
673 Ok(
674 a
675 .on_player()
676 .apply_base_from_data(data, 458_689)?
677 .max_stacks(
678 data
679 .require_aura_max_stacks(
680 wowlab_types::sim::SpellIdx::from_raw(458_689),
681 )?,
682 ),
683 )
684}
685fn aura_executioner(
686 a: AuraDefinitionDraft,
687 data: &ResolvedGameData,
688) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
689 Ok(
690 a
691 .on_player()
692 .apply_base_from_data(data, 445_584)?
693 .max_stacks(
694 data
695 .require_aura_max_stacks(
696 wowlab_types::sim::SpellIdx::from_raw(445_584),
697 )?,
698 ),
699 )
700}
701fn aura_overwhelmed(
702 a: AuraDefinitionDraft,
703 data: &ResolvedGameData,
704) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
705 Ok(
706 a
707 .on_target()
708 .apply_base_from_data(data, 445_836)?
709 .max_stacks(
710 data
711 .require_aura_max_stacks(
712 wowlab_types::sim::SpellIdx::from_raw(445_836),
713 )?,
714 ),
715 )
716}
717fn aura_master_of_warfare(
718 a: AuraDefinitionDraft,
719 data: &ResolvedGameData,
720) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
721 Ok(
722 a
723 .on_player()
724 .apply_base_from_data(data, 1_269_391)?
725 .max_stacks(
726 data
727 .require_aura_max_stacks(
728 wowlab_types::sim::SpellIdx::from_raw(1_269_391),
729 )?,
730 ),
731 )
732}
733fn aura_master_of_warfare_damage(
734 a: AuraDefinitionDraft,
735 data: &ResolvedGameData,
736) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
737 Ok(
738 a
739 .on_player()
740 .apply_base_from_data(data, 1_269_394)?
741 .max_stacks(
742 data
743 .require_aura_max_stacks(
744 wowlab_types::sim::SpellIdx::from_raw(1_269_394),
745 )?,
746 ),
747 )
748}
749fn spell_mortal_strike(
750 s: SpellDefinitionDraft,
751 data: &ResolvedGameData,
752) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
753 Ok(
754 s
755 .apply_base_from_data(data, 12294)?
756 .apply_aoe_from_data(data)
757 .on_cast(crate::hooks::arms_warrior::mortal_strike_hook),
758 )
759}
760fn spell_overpower(
761 s: SpellDefinitionDraft,
762 data: &ResolvedGameData,
763) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
764 Ok(
765 s
766 .apply_base_from_data(data, 7384)?
767 .apply_aoe_from_data(data)
768 .on_cast(crate::hooks::arms_warrior::overpower_hook),
769 )
770}
771fn spell_execute(
772 s: SpellDefinitionDraft,
773 data: &ResolvedGameData,
774) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
775 Ok(
776 s
777 .apply_base_from_data(data, 163_201)?
778 .apply_aoe_from_data(data)
779 .on_cast(crate::hooks::arms_warrior::execute_hook)
780 .cost_free_when_aura(52437),
781 )
782}
783fn spell_slam(
784 s: SpellDefinitionDraft,
785 data: &ResolvedGameData,
786) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
787 Ok(
788 s
789 .apply_base_from_data(data, 1464)?
790 .apply_aoe_from_data(data)
791 .on_cast(crate::hooks::arms_warrior::slam_hook),
792 )
793}
794fn spell_colossus_smash(
795 s: SpellDefinitionDraft,
796 data: &ResolvedGameData,
797) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
798 Ok(
799 s
800 .apply_base_from_data(data, 167_105)?
801 .applies_aura(AURA_COLOSSUS_SMASH)
802 .apply_aoe_from_data(data)
803 .on_cast(crate::hooks::arms_warrior::colossus_smash_hook),
804 )
805}
806fn spell_avatar(
807 s: SpellDefinitionDraft,
808 data: &ResolvedGameData,
809) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
810 Ok(
811 s
812 .apply_base_from_data(data, 107_574)?
813 .applies_inferred_aura(AURA_AVATAR, 107_574)
814 .apply_aoe_from_data(data),
815 )
816}
817fn spell_sweeping_strikes(
818 s: SpellDefinitionDraft,
819 data: &ResolvedGameData,
820) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
821 Ok(
822 s
823 .apply_base_from_data(data, 260_708)?
824 .applies_inferred_aura(AURA_SWEEPING_STRIKES, 260_708)
825 .apply_aoe_from_data(data),
826 )
827}
828fn spell_cleave(
829 s: SpellDefinitionDraft,
830 data: &ResolvedGameData,
831) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
832 Ok(s.apply_base_from_data(data, 845)?.apply_aoe_from_data(data))
833}
834fn spell_whirlwind(
835 s: SpellDefinitionDraft,
836 data: &ResolvedGameData,
837) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
838 Ok(s.apply_base_from_data(data, 1680)?.apply_aoe_from_data(data))
839}
840fn spell_rend(
841 s: SpellDefinitionDraft,
842 data: &ResolvedGameData,
843) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
844 Ok(
845 s
846 .apply_base_from_data(data, 772)?
847 .applies_aura(AURA_REND)
848 .apply_aoe_from_data(data)
849 .on_cast(crate::hooks::arms_warrior::rend_hook),
850 )
851}
852fn spell_thunder_clap(
853 s: SpellDefinitionDraft,
854 data: &ResolvedGameData,
855) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
856 Ok(
857 s
858 .apply_base_from_data(data, 6343)?
859 .gain(5.0)
860 .apply_aoe_from_data(data)
861 .on_cast(crate::hooks::arms_warrior::thunder_clap_hook),
862 )
863}
864fn spell_heroic_strike(
865 s: SpellDefinitionDraft,
866 data: &ResolvedGameData,
867) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
868 Ok(s.apply_base_from_data(data, 1_269_383)?.apply_aoe_from_data(data))
869}
870fn spell_champions_spear(
871 s: SpellDefinitionDraft,
872 data: &ResolvedGameData,
873) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
874 Ok(s.apply_base_from_data(data, 376_079)?.apply_aoe_from_data(data))
875}
876fn spell_battle_shout(
877 s: SpellDefinitionDraft,
878 data: &ResolvedGameData,
879) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
880 Ok(
881 s
882 .apply_base_from_data(data, 6673)?
883 .applies_inferred_aura(AURA_BATTLE_SHOUT, 6673)
884 .apply_aoe_from_data(data),
885 )
886}
887fn spell_heroic_throw(
888 s: SpellDefinitionDraft,
889 data: &ResolvedGameData,
890) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
891 Ok(s.apply_base_from_data(data, 57755)?.apply_aoe_from_data(data))
892}
893fn spell_execute_damage(
894 s: SpellDefinitionDraft,
895 data: &ResolvedGameData,
896) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
897 Ok(s.apply_base_from_data(data, 260_798)?.apply_aoe_from_data(data))
898}
899fn spell_dreadnaught(
900 s: SpellDefinitionDraft,
901 data: &ResolvedGameData,
902) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
903 Ok(s.apply_base_from_data(data, 315_961)?.apply_aoe_from_data(data))
904}
905fn spell_fatality(
906 s: SpellDefinitionDraft,
907 data: &ResolvedGameData,
908) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
909 Ok(s.apply_base_from_data(data, 383_706)?.apply_aoe_from_data(data))
910}
911fn spell_bladestorm(
912 s: SpellDefinitionDraft,
913 data: &ResolvedGameData,
914) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
915 Ok(
916 s
917 .apply_base_from_data(data, 227_847)?
918 .applies_inferred_aura(AURA_BLADESTORM, 227_847)
919 .apply_aoe_from_data(data)
920 .on_cast(crate::hooks::arms_warrior::bladestorm_hook),
921 )
922}
923fn spell_ravager(
924 s: SpellDefinitionDraft,
925 data: &ResolvedGameData,
926) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
927 Ok(
928 s
929 .apply_base_from_data(data, 228_920)?
930 .applies_inferred_aura(AURA_RAVAGER, 228_920)
931 .apply_aoe_from_data(data),
932 )
933}
934fn spell_demolish(
935 s: SpellDefinitionDraft,
936 data: &ResolvedGameData,
937) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
938 Ok(s.apply_base_from_data(data, 436_358)?.apply_aoe_from_data(data))
939}
940pub(crate) fn build_combat_system(
941 params: &wowlab_engine_ports::HandlerParams<'_>,
942) -> Result<BuiltCombatSystem, wowlab_engine_ports::EngineError> {
943 let builder = BuiltCombatSystem::builder(params.stats.clone())
944 .spec_id(SpecId::Arms)
945 .hero_talent_trees(DECLARED_METADATA.hero_talent_trees)
946 .mastery_spell(1_258_398)
947 .mastery_hook(crate::hooks::arms_warrior::mastery)
948 .resource(
949 "rage",
950 params
951 .game_data
952 .power_max(1)
953 .ok_or_else(|| {
954 wowlab_engine_ports::EngineError::spec_construction(
955 "missing power-type power_max for type_id 1",
956 )
957 })?,
958 params
959 .game_data
960 .power_regen_for_max(
961 1,
962 params
963 .game_data
964 .power_max(1)
965 .ok_or_else(|| {
966 wowlab_engine_ports::EngineError::spec_construction(
967 "missing power-type power_max for type_id 1",
968 )
969 })?,
970 )
971 .ok_or_else(|| {
972 wowlab_engine_ports::EngineError::spec_construction(
973 "missing power-type power_regen_for_max for type_id 1",
974 )
975 })?,
976 )
977 .resource_type_id(1)
978 .resource_start(
979 params
980 .game_data
981 .power_default(1)
982 .ok_or_else(|| {
983 wowlab_engine_ports::EngineError::spec_construction(
984 "missing power-type power_default for type_id 1",
985 )
986 })?,
987 )
988 .aura(
989 "colossus_smash",
990 AURA::COLOSSUS_SMASH,
991 |a| aura_colossus_smash(a, ¶ms.game_data),
992 )
993 .aura(
994 "deep_wounds",
995 AURA::DEEP_WOUNDS,
996 |a| aura_deep_wounds(a, ¶ms.game_data),
997 )
998 .aura("rend", AURA::REND, |a| aura_rend(a, ¶ms.game_data))
999 .aura(
1000 "sweeping_strikes",
1001 AURA::SWEEPING_STRIKES,
1002 |a| aura_sweeping_strikes(a, ¶ms.game_data),
1003 )
1004 .aura("avatar", AURA::AVATAR, |a| aura_avatar(a, ¶ms.game_data))
1005 .aura(
1006 "sudden_death",
1007 AURA::SUDDEN_DEATH,
1008 |a| aura_sudden_death(a, ¶ms.game_data),
1009 )
1010 .aura(
1011 "martial_prowess",
1012 AURA::MARTIAL_PROWESS,
1013 |a| aura_martial_prowess(a, ¶ms.game_data),
1014 )
1015 .aura("battlelord", AURA::BATTLELORD, |a| aura_battlelord(a, ¶ms.game_data))
1016 .aura(
1017 "collateral_damage",
1018 AURA::COLLATERAL_DAMAGE,
1019 |a| aura_collateral_damage(a, ¶ms.game_data),
1020 )
1021 .aura("fatal_mark", AURA::FATAL_MARK, |a| aura_fatal_mark(a, ¶ms.game_data))
1022 .aura(
1023 "battle_shout",
1024 AURA::BATTLE_SHOUT,
1025 |a| aura_battle_shout(a, ¶ms.game_data),
1026 )
1027 .aura(
1028 "battle_shout_highlight",
1029 AURA::BATTLE_SHOUT_HIGHLIGHT,
1030 |a| aura_battle_shout_highlight(a, ¶ms.game_data),
1031 )
1032 .aura(
1033 "battle_stance",
1034 AURA::BATTLE_STANCE,
1035 |a| aura_battle_stance(a, ¶ms.game_data),
1036 )
1037 .aura("ravager", AURA::RAVAGER, |a| aura_ravager(a, ¶ms.game_data))
1038 .aura("bladestorm", AURA::BLADESTORM, |a| aura_bladestorm(a, ¶ms.game_data))
1039 .aura(
1040 "executioners_precision",
1041 AURA::EXECUTIONERS_PRECISION,
1042 |a| aura_executioners_precision(a, ¶ms.game_data),
1043 )
1044 .aura(
1045 "imminent_demise",
1046 AURA::IMMINENT_DEMISE,
1047 |a| aura_imminent_demise(a, ¶ms.game_data),
1048 )
1049 .aura(
1050 "fierce_followthrough",
1051 AURA::FIERCE_FOLLOWTHROUGH,
1052 |a| aura_fierce_followthrough(a, ¶ms.game_data),
1053 )
1054 .aura(
1055 "executioner",
1056 AURA::EXECUTIONER,
1057 |a| aura_executioner(a, ¶ms.game_data),
1058 )
1059 .aura(
1060 "overwhelmed",
1061 AURA::OVERWHELMED,
1062 |a| aura_overwhelmed(a, ¶ms.game_data),
1063 )
1064 .aura(
1065 "master_of_warfare",
1066 AURA::MASTER_OF_WARFARE,
1067 |a| aura_master_of_warfare(a, ¶ms.game_data),
1068 )
1069 .aura(
1070 "master_of_warfare_damage",
1071 AURA::MASTER_OF_WARFARE_DAMAGE,
1072 |a| aura_master_of_warfare_damage(a, ¶ms.game_data),
1073 )
1074 .spell(
1075 "mortal_strike",
1076 SPELL::MORTAL_STRIKE,
1077 |s| spell_mortal_strike(s, ¶ms.game_data),
1078 )
1079 .spell("overpower", SPELL::OVERPOWER, |s| spell_overpower(s, ¶ms.game_data))
1080 .spell("execute", SPELL::EXECUTE, |s| spell_execute(s, ¶ms.game_data))
1081 .spell("slam", SPELL::SLAM, |s| spell_slam(s, ¶ms.game_data))
1082 .spell(
1083 "colossus_smash",
1084 SPELL::COLOSSUS_SMASH,
1085 |s| spell_colossus_smash(s, ¶ms.game_data),
1086 )
1087 .spell("avatar", SPELL::AVATAR, |s| spell_avatar(s, ¶ms.game_data))
1088 .spell(
1089 "sweeping_strikes",
1090 SPELL::SWEEPING_STRIKES,
1091 |s| spell_sweeping_strikes(s, ¶ms.game_data),
1092 )
1093 .spell("cleave", SPELL::CLEAVE, |s| spell_cleave(s, ¶ms.game_data))
1094 .spell("whirlwind", SPELL::WHIRLWIND, |s| spell_whirlwind(s, ¶ms.game_data))
1095 .spell("rend", SPELL::REND, |s| spell_rend(s, ¶ms.game_data))
1096 .spell(
1097 "thunder_clap",
1098 SPELL::THUNDER_CLAP,
1099 |s| spell_thunder_clap(s, ¶ms.game_data),
1100 )
1101 .spell(
1102 "heroic_strike",
1103 SPELL::HEROIC_STRIKE,
1104 |s| spell_heroic_strike(s, ¶ms.game_data),
1105 )
1106 .spell(
1107 "champions_spear",
1108 SPELL::CHAMPIONS_SPEAR,
1109 |s| spell_champions_spear(s, ¶ms.game_data),
1110 )
1111 .spell(
1112 "battle_shout",
1113 SPELL::BATTLE_SHOUT,
1114 |s| spell_battle_shout(s, ¶ms.game_data),
1115 )
1116 .spell(
1117 "heroic_throw",
1118 SPELL::HEROIC_THROW,
1119 |s| spell_heroic_throw(s, ¶ms.game_data),
1120 )
1121 .spell(
1122 "execute_damage",
1123 SPELL::EXECUTE_DAMAGE,
1124 |s| spell_execute_damage(s, ¶ms.game_data),
1125 )
1126 .spell(
1127 "dreadnaught",
1128 SPELL::DREADNAUGHT,
1129 |s| spell_dreadnaught(s, ¶ms.game_data),
1130 )
1131 .spell("fatality", SPELL::FATALITY, |s| spell_fatality(s, ¶ms.game_data))
1132 .spell(
1133 "bladestorm",
1134 SPELL::BLADESTORM,
1135 |s| spell_bladestorm(s, ¶ms.game_data),
1136 )
1137 .spell("ravager", SPELL::RAVAGER, |s| spell_ravager(s, ¶ms.game_data))
1138 .spell("demolish", SPELL::DEMOLISH, |s| spell_demolish(s, ¶ms.game_data))
1139 .auto_attack(|a| {
1140 a
1141 .spell_id(6603)
1142 .swing_ms(3600)
1143 .apply_base_from_data(¶ms.game_data)
1144 .on_swing(crate::hooks::arms_warrior::swing_hook)
1145 })
1146 .game_data(params.game_data.clone())
1147 .talent_spell_ids(TALENTS)
1148 .talent_selections(params.talent_selections)
1149 .set_bonus_auras(params.set_bonus_auras)
1150 .encounter(params.encounter.clone());
1151 let builder = crate::generated::items::register_equipped(
1152 builder,
1153 ¶ms.game_data,
1154 params.equipped_items,
1155 )?;
1156
1157 builder
1158 .build(params.rotation)
1159 .map_err(wowlab_engine_ports::EngineError::rotation_compile)
1160}
1161fn new_handler(
1162 params: wowlab_engine_ports::HandlerParams<'_>,
1163) -> Result<Box<dyn SpecHandler>, wowlab_engine_ports::EngineError> {
1164 let handler = crate::composition::compose_handler(
1165 build_combat_system,
1166 ¶ms,
1167 crate::hooks::arms_warrior::ArmsHandler::try_new,
1168 )?;
1169
1170 Ok(Box::new(handler))
1171}
1172static DECLARED_METADATA: DeclaredSpecMetadata = DeclaredSpecMetadata {
1173 primary_resource: ResourceType::Rage,
1174 secondary_resource: None,
1175 spell_ids: DECLARED_SPELL_IDS,
1176 aura_ids: DECLARED_AURA_IDS,
1177 server_proc_entries: &[
1178 DeclaredServerProcEntry {
1179 spell_id: 52437,
1180 attributes: ProcAttributes::REQUIRE_SPELL_MODIFIER.bits()
1181 | ProcAttributes::USE_STACKS_FOR_CHARGES.bits(),
1182 },
1183 ],
1184 talents: TALENTS,
1185 rotation_field_schema: &[],
1186 metrics_plugin_id: None,
1187 hero_talent_trees: &[
1188 HeroTalentTreeDesc {
1189 name: "Slayer",
1190 spells: HERO_TREE_SLAYER_SPELLS,
1191 auras: HERO_TREE_SLAYER_AURAS,
1192 },
1193 HeroTalentTreeDesc {
1194 name: "Colossus",
1195 spells: HERO_TREE_COLOSSUS_SPELLS,
1196 auras: HERO_TREE_COLOSSUS_AURAS,
1197 },
1198 ],
1199 reported_spells: REPORTED_SPELLS,
1200 masked_passive_effects: &[],
1201 passive_effect_overrides: &[],
1202};
1203pub(super) const SPEC_DESCRIPTOR: SpecDescriptor = SpecDescriptor {
1204 spec_id: SpecId::Arms,
1205 display_name: "Arms Warrior",
1206 metadata: DECLARED_METADATA,
1207 handler_factory: new_handler,
1208};
1209wowlab_engine_combat::smoke_test!(build_combat_system);