1#![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 pub(crate) const MUTILATE: u32 = 1329;
16 pub(crate) const AMBUSH: u32 = 8676;
18 pub(crate) const ENVENOM: u32 = 32645;
20 pub(crate) const SLICE_AND_DICE: u32 = 315_496;
22 pub(crate) const FAN_OF_KNIVES: u32 = 51723;
24 pub(crate) const CRIMSON_TEMPEST: u32 = 1_247_227;
26 pub(crate) const POISONED_KNIFE: u32 = 185_565;
28 pub(crate) const DEADLY_POISON: u32 = 2823;
30 pub(crate) const AMPLIFYING_POISON: u32 = 381_664;
32 pub(crate) const INSTANT_POISON: u32 = 315_584;
34 pub(crate) const WOUND_POISON: u32 = 8679;
36 pub(crate) const ATROPHIC_POISON: u32 = 381_637;
38 pub(crate) const NUMBING_POISON: u32 = 5761;
40 pub(crate) const CRIPPLING_POISON: u32 = 3408;
42 pub(crate) const MUTILATE_MH: u32 = 5374;
44 pub(crate) const MUTILATE_OH: u32 = 27576;
46 pub(crate) const DEADLY_POISON_INSTANT: u32 = 113_780;
48 pub(crate) const MUTILATED_FLESH: u32 = 394_021;
50 pub(crate) const GARROTE: u32 = 703;
52 pub(crate) const RUPTURE: u32 = 1943;
54 pub(crate) const INTERNAL_BLEEDING_DRIVER: u32 = 381_628;
56 pub(crate) const DEATHMARK: u32 = 360_194;
58 pub(crate) const KINGSBANE: u32 = 385_627;
60 pub(crate) const IMPLACABLE_STRIKES_NATURE: u32 = 1_265_794;
62 pub(crate) const IMPLACABLE_STRIKES_PHYSICAL: u32 = 1_265_795;
64 pub(crate) const THISTLE_TEA: u32 = 381_623;
66 pub(crate) const VANISH: u32 = 1856;
68}
69pub(crate) mod AURA {
70 pub(crate) const STEALTH: u32 = 1784;
72 pub(crate) const VANISH: u32 = 1856;
74 pub(crate) const DEADLY_POISON: u32 = 2823;
76 pub(crate) const AMPLIFYING_POISON: u32 = 381_664;
78 pub(crate) const INSTANT_POISON: u32 = 315_584;
80 pub(crate) const WOUND_POISON: u32 = 8679;
82 pub(crate) const ATROPHIC_POISON: u32 = 381_637;
84 pub(crate) const NUMBING_POISON: u32 = 5761;
86 pub(crate) const CRIPPLING_POISON: u32 = 3408;
88 pub(crate) const DEADLY_POISON_DOT: u32 = 2818;
90 pub(crate) const AMPLIFYING_POISON_DEBUFF: u32 = 383_414;
92 pub(crate) const ENVENOM: u32 = 32645;
94 pub(crate) const SLICE_AND_DICE: u32 = 315_496;
96 pub(crate) const BLINDSIDE: u32 = 121_153;
98 pub(crate) const ALACRITY: u32 = 193_538;
100 pub(crate) const DARKEST_NIGHT: u32 = 457_280;
102 pub(crate) const DEEPER_STRATAGEM: u32 = 193_531;
104 pub(crate) const SANGUINE_STRATAGEM: u32 = 457_512;
106 pub(crate) const DRAGON_TEMPERED_BLADES: u32 = 381_801;
108 pub(crate) const INSPIRING_STRIKE: u32 = 1_250_036;
110 pub(crate) const REGICIDES_REWARD: u32 = 1_250_331;
112 pub(crate) const GARROTE: u32 = 703;
114 pub(crate) const RUPTURE: u32 = 1943;
116 pub(crate) const INTERNAL_BLEEDING: u32 = 381_628;
118 pub(crate) const IMPROVED_GARROTE: u32 = 381_632;
120 pub(crate) const IMPROVED_GARROTE_WINDOW: u32 = 392_401;
122 pub(crate) const DEATHMARK: u32 = 360_194;
124 pub(crate) const KINGSBANE: u32 = 385_627;
126 pub(crate) const KINGSBANE_RAMP: u32 = 394_095;
128 pub(crate) const FINISH_THE_JOB: u32 = 1_249_810;
130 pub(crate) const IMPLACABLE_TRACKER: u32 = 1_265_389;
132 pub(crate) const IMPLACABLE_REGEN: u32 = 1_265_391;
134 pub(crate) const IMPLACABLE_BONUS: u32 = 1_265_385;
136 pub(crate) const IMPLACABLE: u32 = 1_265_385;
138 pub(crate) const PVP_RULES_ENABLED_HARDCODED: u32 = 134_735;
140 pub(crate) const FATEBOUND_COIN_HEADS: u32 = 452_923;
142 pub(crate) const FATEBOUND_COIN_TAILS: u32 = 452_917;
144 pub(crate) const FATEBOUND_LUCKY_COIN: u32 = 1_248_971;
146 pub(crate) const LUCKY_COIN_COUNTER: u32 = 1_249_093;
148}
149pub(crate) mod TALENT {
150 pub(crate) const ALACRITY: u32 = 193_539;
152 pub(crate) const AMPLIFYING_POISON: u32 = 381_664;
154 pub(crate) const BLINDSIDE: u32 = 328_085;
156 pub(crate) const CRIMSON_TEMPEST: u32 = 1_247_227;
158 pub(crate) const DASHING_SCOUNDREL: u32 = 381_797;
160 pub(crate) const DEADLY_POISON: u32 = 2823;
162 pub(crate) const DEATHMARK: u32 = 360_194;
164 pub(crate) const DEEPER_STRATAGEM: u32 = 193_531;
166 pub(crate) const DOOMBLADE: u32 = 381_673;
168 pub(crate) const DRAGON_TEMPERED_BLADES: u32 = 381_801;
170 pub(crate) const FINISH_THE_JOB: u32 = 1_249_809;
172 pub(crate) const IMPLACABLE_1: u32 = 1_265_385;
174 pub(crate) const IMPLACABLE_2: u32 = 1_265_386;
176 pub(crate) const IMPLACABLE_3: u32 = 1_265_387;
178 pub(crate) const IMPROVED_GARROTE: u32 = 381_632;
180 pub(crate) const IMPROVED_POISONS: u32 = 381_624;
182 pub(crate) const INSPIRING_STRIKE: u32 = 1_250_036;
184 pub(crate) const INTERNAL_BLEEDING: u32 = 381_627;
186 pub(crate) const KINGSBANE: u32 = 385_627;
188 pub(crate) const LETHALITY: u32 = 382_238;
190 pub(crate) const LETHAL_DOSE: u32 = 381_640;
192 pub(crate) const RAPID_INJECTION: u32 = 455_072;
194 pub(crate) const REGICIDES_REWARD: u32 = 1_250_325;
196 pub(crate) const SANGUINE_STRATAGEM: u32 = 457_512;
198 pub(crate) const SEAL_FATE: u32 = 14190;
200 pub(crate) const SYSTEMIC_FAILURE: u32 = 381_652;
202 pub(crate) const THISTLE_TEA: u32 = 469_779;
204 pub(crate) const VENOMOUS_WOUNDS: u32 = 79134;
206 pub(crate) const ZOLDYCK_RECIPE: u32 = 381_798;
208}
209pub(crate) mod SET_BONUS {
210 pub(crate) const MID1_ASSASSINATION_2PC: u32 = 1_264_856;
212 pub(crate) const MID1_ASSASSINATION_4PC: u32 = 1_264_857;
214}
215pub(crate) mod REPORTED_SPELL {
216 pub(crate) const AMPLIFYING_POISON: u32 = 383_414;
218 pub(crate) const DEADLY_POISON_DOT: u32 = 2818;
220}
221pub(crate) mod HERO {
222 pub(crate) mod FATEBOUND {
223 pub(crate) mod SPELL {
224 pub(crate) const CONTROLLED_CHAOS: u32 = 1_276_816;
226 pub(crate) const DEAL_FATE: u32 = 454_419;
228 pub(crate) const DELIVERED_DOOM_TALENT: u32 = 1_249_194;
230 pub(crate) const EDGE_CASE: u32 = 453_457;
232 pub(crate) const FATEBOUND_COIN_TAILS: u32 = 452_538;
234 pub(crate) const HAND_OF_FATE: u32 = 452_536;
236 pub(crate) const LUCKY_COIN: u32 = 1_248_970;
238 pub(crate) const MEAN_STREAK: u32 = 453_428;
240 pub(crate) const OVERFLOWING_PURSE: u32 = 1_249_190;
242 pub(crate) const RAVENHOLDT_MINT: u32 = 1_276_809;
244 pub(crate) const RUSH_TO_THE_INEVITABLE: u32 = 1_249_204;
246 }
247 pub(crate) mod AURA {
248 pub(crate) const FATEBOUND_COIN_HEADS: u32 = 452_923;
250 pub(crate) const FATEBOUND_COIN_TAILS: u32 = 452_917;
252 pub(crate) const FATEBOUND_LUCKY_COIN: u32 = 1_248_971;
254 }
255 }
256}
257static HERO_TREE_FATEBOUND_SPELLS: &[(&str, u32)] = &[
258 ("CONTROLLED_CHAOS", 1_276_816),
259 ("DEAL_FATE", 454_419),
260 ("DELIVERED_DOOM_TALENT", 1_249_194),
261 ("EDGE_CASE", 453_457),
262 ("FATEBOUND_COIN_TAILS", 452_538),
263 ("HAND_OF_FATE", 452_536),
264 ("LUCKY_COIN", 1_248_970),
265 ("MEAN_STREAK", 453_428),
266 ("OVERFLOWING_PURSE", 1_249_190),
267 ("RAVENHOLDT_MINT", 1_276_809),
268 ("RUSH_TO_THE_INEVITABLE", 1_249_204),
269];
270static HERO_TREE_FATEBOUND_AURAS: &[(&str, u32)] = &[
271 ("FATEBOUND_COIN_HEADS", 452_923),
272 ("FATEBOUND_COIN_TAILS", 452_917),
273 ("FATEBOUND_LUCKY_COIN", 1_248_971),
274];
275pub(crate) const AURA_STEALTH: LocalAuraIdx = LocalAuraIdx::new(0);
276pub(crate) const AURA_VANISH: LocalAuraIdx = LocalAuraIdx::new(1);
277pub(crate) const AURA_DEADLY_POISON: LocalAuraIdx = LocalAuraIdx::new(2);
278pub(crate) const AURA_AMPLIFYING_POISON: LocalAuraIdx = LocalAuraIdx::new(3);
279pub(crate) const AURA_INSTANT_POISON: LocalAuraIdx = LocalAuraIdx::new(4);
280pub(crate) const AURA_WOUND_POISON: LocalAuraIdx = LocalAuraIdx::new(5);
281pub(crate) const AURA_ATROPHIC_POISON: LocalAuraIdx = LocalAuraIdx::new(6);
282pub(crate) const AURA_NUMBING_POISON: LocalAuraIdx = LocalAuraIdx::new(7);
283pub(crate) const AURA_CRIPPLING_POISON: LocalAuraIdx = LocalAuraIdx::new(8);
284pub(crate) const AURA_DEADLY_POISON_DOT: LocalAuraIdx = LocalAuraIdx::new(9);
285pub(crate) const AURA_AMPLIFYING_POISON_DEBUFF: LocalAuraIdx = LocalAuraIdx::new(10);
286pub(crate) const AURA_ENVENOM: LocalAuraIdx = LocalAuraIdx::new(11);
287pub(crate) const AURA_SLICE_AND_DICE: LocalAuraIdx = LocalAuraIdx::new(12);
288pub(crate) const AURA_BLINDSIDE: LocalAuraIdx = LocalAuraIdx::new(13);
289pub(crate) const AURA_ALACRITY: LocalAuraIdx = LocalAuraIdx::new(14);
290pub(crate) const AURA_DARKEST_NIGHT: LocalAuraIdx = LocalAuraIdx::new(15);
291pub(crate) const AURA_DEEPER_STRATAGEM: LocalAuraIdx = LocalAuraIdx::new(16);
292pub(crate) const AURA_SANGUINE_STRATAGEM: LocalAuraIdx = LocalAuraIdx::new(17);
293pub(crate) const AURA_DRAGON_TEMPERED_BLADES: LocalAuraIdx = LocalAuraIdx::new(18);
294pub(crate) const AURA_INSPIRING_STRIKE: LocalAuraIdx = LocalAuraIdx::new(19);
295pub(crate) const AURA_REGICIDES_REWARD: LocalAuraIdx = LocalAuraIdx::new(20);
296pub(crate) const AURA_GARROTE: LocalAuraIdx = LocalAuraIdx::new(21);
297pub(crate) const AURA_RUPTURE: LocalAuraIdx = LocalAuraIdx::new(22);
298pub(crate) const AURA_INTERNAL_BLEEDING: LocalAuraIdx = LocalAuraIdx::new(23);
299pub(crate) const AURA_IMPROVED_GARROTE: LocalAuraIdx = LocalAuraIdx::new(24);
300pub(crate) const AURA_IMPROVED_GARROTE_WINDOW: LocalAuraIdx = LocalAuraIdx::new(25);
301pub(crate) const AURA_DEATHMARK: LocalAuraIdx = LocalAuraIdx::new(26);
302pub(crate) const AURA_KINGSBANE: LocalAuraIdx = LocalAuraIdx::new(27);
303pub(crate) const AURA_KINGSBANE_RAMP: LocalAuraIdx = LocalAuraIdx::new(28);
304pub(crate) const AURA_FINISH_THE_JOB: LocalAuraIdx = LocalAuraIdx::new(29);
305pub(crate) const AURA_IMPLACABLE_TRACKER: LocalAuraIdx = LocalAuraIdx::new(30);
306pub(crate) const AURA_IMPLACABLE_REGEN: LocalAuraIdx = LocalAuraIdx::new(31);
307pub(crate) const AURA_IMPLACABLE_BONUS: LocalAuraIdx = LocalAuraIdx::new(32);
308pub(crate) const AURA_IMPLACABLE: LocalAuraIdx = LocalAuraIdx::new(33);
309pub(crate) const AURA_PVP_RULES_ENABLED_HARDCODED: LocalAuraIdx = LocalAuraIdx::new(34);
310pub(crate) const AURA_FATEBOUND_COIN_HEADS: LocalAuraIdx = LocalAuraIdx::new(35);
311pub(crate) const AURA_FATEBOUND_COIN_TAILS: LocalAuraIdx = LocalAuraIdx::new(36);
312pub(crate) const AURA_FATEBOUND_LUCKY_COIN: LocalAuraIdx = LocalAuraIdx::new(37);
313pub(crate) const AURA_LUCKY_COIN_COUNTER: LocalAuraIdx = LocalAuraIdx::new(38);
314pub(crate) const AURA_COUNT: usize = 39;
315const _: () = assert!(
316 AURA_COUNT == 39, "AURA index ABI: count changed -- update positional hook consumers"
317);
318pub(crate) const SPELL_MUTILATE: LocalSpellIdx = LocalSpellIdx::new(0);
319pub(crate) const SPELL_AMBUSH: LocalSpellIdx = LocalSpellIdx::new(1);
320pub(crate) const SPELL_ENVENOM: LocalSpellIdx = LocalSpellIdx::new(2);
321pub(crate) const SPELL_SLICE_AND_DICE: LocalSpellIdx = LocalSpellIdx::new(3);
322pub(crate) const SPELL_FAN_OF_KNIVES: LocalSpellIdx = LocalSpellIdx::new(4);
323pub(crate) const SPELL_CRIMSON_TEMPEST: LocalSpellIdx = LocalSpellIdx::new(5);
324pub(crate) const SPELL_POISONED_KNIFE: LocalSpellIdx = LocalSpellIdx::new(6);
325pub(crate) const SPELL_DEADLY_POISON: LocalSpellIdx = LocalSpellIdx::new(7);
326pub(crate) const SPELL_AMPLIFYING_POISON: LocalSpellIdx = LocalSpellIdx::new(8);
327pub(crate) const SPELL_INSTANT_POISON: LocalSpellIdx = LocalSpellIdx::new(9);
328pub(crate) const SPELL_WOUND_POISON: LocalSpellIdx = LocalSpellIdx::new(10);
329pub(crate) const SPELL_ATROPHIC_POISON: LocalSpellIdx = LocalSpellIdx::new(11);
330pub(crate) const SPELL_NUMBING_POISON: LocalSpellIdx = LocalSpellIdx::new(12);
331pub(crate) const SPELL_CRIPPLING_POISON: LocalSpellIdx = LocalSpellIdx::new(13);
332pub(crate) const SPELL_MUTILATE_MH: LocalSpellIdx = LocalSpellIdx::new(14);
333pub(crate) const SPELL_MUTILATE_OH: LocalSpellIdx = LocalSpellIdx::new(15);
334pub(crate) const SPELL_DEADLY_POISON_INSTANT: LocalSpellIdx = LocalSpellIdx::new(16);
335pub(crate) const SPELL_MUTILATED_FLESH: LocalSpellIdx = LocalSpellIdx::new(17);
336pub(crate) const SPELL_GARROTE: LocalSpellIdx = LocalSpellIdx::new(18);
337pub(crate) const SPELL_RUPTURE: LocalSpellIdx = LocalSpellIdx::new(19);
338pub(crate) const SPELL_INTERNAL_BLEEDING_DRIVER: LocalSpellIdx = LocalSpellIdx::new(20);
339pub(crate) const SPELL_DEATHMARK: LocalSpellIdx = LocalSpellIdx::new(21);
340pub(crate) const SPELL_KINGSBANE: LocalSpellIdx = LocalSpellIdx::new(22);
341pub(crate) const SPELL_IMPLACABLE_STRIKES_NATURE: LocalSpellIdx = LocalSpellIdx::new(23);
342pub(crate) const SPELL_IMPLACABLE_STRIKES_PHYSICAL: LocalSpellIdx = LocalSpellIdx::new(
343 24,
344);
345pub(crate) const SPELL_THISTLE_TEA: LocalSpellIdx = LocalSpellIdx::new(25);
346pub(crate) const SPELL_VANISH: LocalSpellIdx = LocalSpellIdx::new(26);
347pub(crate) const SPELL_COUNT: usize = 27;
348const _: () = assert!(
349 SPELL_COUNT == 27,
350 "SPELL index ABI: count changed -- update positional hook consumers"
351);
352pub(crate) mod EFFECT {
353 pub(crate) const ALACRITY_CHANCE_PER_CP: (u32, u8) = (193_539, 2);
355 pub(crate) const AMBUSH_DMG: (u32, u8) = (8676, 1);
357 pub(crate) const AMPLIFYING_CONSUME_STACKS: (u32, u8) = (381_664, 2);
359 pub(crate) const AMPLIFYING_ENVENOM_BONUS: (u32, u8) = (381_664, 1);
361 pub(crate) const DEATHMARK_ENERGY: (u32, u8) = (360_194, 3);
363 pub(crate) const DEATHMARK_PERIOD: (u32, u8) = (360_194, 1);
365 pub(crate) const AMPLIFYING_POISON_DMG: (u32, u8) = (383_414, 1);
367 pub(crate) const BLINDSIDE_CHANCE: (u32, u8) = (328_085, 1);
369 pub(crate) const BLINDSIDE_EXECUTE_CHANCE: (u32, u8) = (328_085, 2);
371 pub(crate) const BLINDSIDE_EXECUTE_THRESHOLD: (u32, u8) = (328_085, 3);
373 pub(crate) const COIN_HEADS_INITIAL: (u32, u8) = (452_923, 4);
375 pub(crate) const COIN_HEADS_PER_STACK: (u32, u8) = (452_923, 1);
377 pub(crate) const COIN_HEADS_PER_STACK_PERIODIC: (u32, u8) = (452_923, 2);
379 pub(crate) const CONTROLLED_CHAOS_STREAK: (u32, u8) = (1_276_816, 1);
381 pub(crate) const DASHING_SCOUNDREL_ENERGY: (u32, u8) = (381_797, 2);
383 pub(crate) const DEADLY_POISON_INSTANT_DMG: (u32, u8) = (113_780, 1);
385 pub(crate) const DEAL_FATE_CP: (u32, u8) = (454_419, 1);
387 pub(crate) const DELIVERED_DOOM_CP: (u32, u8) = (1_249_194, 2);
389 pub(crate) const DELIVERED_DOOM_DMG: (u32, u8) = (1_249_194, 1);
391 pub(crate) const DOOMBLADE_PCT: (u32, u8) = (381_673, 1);
393 pub(crate) const ENVENOM_DMG: (u32, u8) = (32645, 1);
395 pub(crate) const ENVENOM_POISON_BONUS: (u32, u8) = (32645, 2);
397 pub(crate) const FATEBOUND_COIN_TAILS_DMG: (u32, u8) = (452_538, 1);
399 pub(crate) const HAND_OF_FATE_CP: (u32, u8) = (452_536, 1);
401 pub(crate) const IMPLACABLE_STRIKE_CP: (u32, u8) = (1_265_795, 2);
403 pub(crate) const IMPLACABLE_STRIKE_NATURE_DMG: (u32, u8) = (1_265_794, 1);
405 pub(crate) const IMPLACABLE_STRIKE_PHYSICAL_DMG: (u32, u8) = (1_265_795, 1);
407 pub(crate) const IMPROVED_GARROTE_DAMAGE: (u32, u8) = (392_401, 2);
409 pub(crate) const INSPIRING_STRIKE_DAMAGE: (u32, u8) = (1_250_036, 1);
411 pub(crate) const LETHAL_DOSE_PER_EFFECT: (u32, u8) = (381_640, 1);
413 pub(crate) const LUCKY_COIN_FLIPS: (u32, u8) = (1_248_970, 1);
415 pub(crate) const LUCKY_COIN_ODDS: (u32, u8) = (1_248_971, 5);
417 pub(crate) const MEAN_STREAK_ODDS: (u32, u8) = (453_428, 1);
419 pub(crate) const MID1_ASSASSINATION_4PC_DAMAGE: (u32, u8) = (1_264_857, 2);
421 pub(crate) const MUTILATE_MH_DMG: (u32, u8) = (5374, 2);
423 pub(crate) const MUTILATE_OH_DMG: (u32, u8) = (27576, 2);
425 pub(crate) const OVERFLOWING_PURSE_CHANCE: (u32, u8) = (1_249_190, 3);
427 pub(crate) const OVERFLOWING_PURSE_COINS: (u32, u8) = (1_249_190, 1);
429 pub(crate) const POTENT_ASSASSIN_DIRECT: (u32, u8) = (76803, 1);
431 pub(crate) const POTENT_ASSASSIN_DIRECT_LABEL: (u32, u8) = (76803, 3);
433 pub(crate) const POTENT_ASSASSIN_PERIODIC: (u32, u8) = (76803, 2);
435 pub(crate) const POTENT_ASSASSIN_SECONDARY_DIRECT_LABEL: (u32, u8) = (76803, 4);
437 pub(crate) const RAPID_INJECTION_PCT: (u32, u8) = (455_072, 1);
439 pub(crate) const RAVENHOLDT_MINT_HEADS: (u32, u8) = (1_276_809, 1);
441 pub(crate) const REGICIDES_REWARD_DIVISOR: (u32, u8) = (1_250_325, 1);
443 pub(crate) const RUSH_ENERGY: (u32, u8) = (1_249_204, 1);
445 pub(crate) const RUSH_ENERGY_EDGE: (u32, u8) = (1_249_204, 3);
447 pub(crate) const SEAL_FATE_CHANCE: (u32, u8) = (14190, 1);
449 pub(crate) const SEAL_FATE_CP: (u32, u8) = (14189, 1);
451 pub(crate) const SYSTEMIC_FAILURE_PCT: (u32, u8) = (381_652, 1);
453 pub(crate) const ZOLDYCK_DAMAGE: (u32, u8) = (381_798, 1);
455 pub(crate) const ZOLDYCK_THRESHOLD: (u32, u8) = (381_798, 2);
457}
458static REPORTED_SPELLS: &[(&str, u32)] = &[
459 ("amplifying_poison", 383_414),
460 ("deadly_poison_dot", 2818),
461];
462static DECLARED_SPELL_IDS: &[u32] = &[
463 1329, 8676, 32645, 315_496, 51723, 1_247_227, 185_565, 2823, 381_664, 315_584, 8679,
464 381_637, 5761, 3408, 5374, 27576, 113_780, 394_021, 703, 1943, 381_628, 360_194,
465 385_627, 1_265_794, 1_265_795, 381_623, 1856, 1784, 1856, 2823, 381_664, 315_584,
466 8679, 381_637, 5761, 3408, 2818, 383_414, 32645, 315_496, 121_153, 193_538, 457_280,
467 193_531, 457_512, 381_801, 1_250_036, 1_250_331, 703, 1943, 381_628, 381_632,
468 392_401, 360_194, 385_627, 394_095, 1_249_810, 1_265_389, 1_265_391, 1_265_385,
469 1_265_385, 134_735, 452_923, 452_917, 1_248_971, 1_249_093, 6603, 2818, 5374, 8676,
470 14189, 14190, 27576, 32645, 76803, 79134, 113_780, 193_538, 193_539, 328_085,
471 360_194, 381_640, 381_652, 381_664, 381_673, 381_797, 381_798, 383_414, 392_401,
472 394_095, 452_536, 452_538, 452_923, 453_428, 454_419, 455_072, 1_248_970, 1_248_971,
473 1_249_190, 1_249_194, 1_249_204, 1_250_036, 1_250_325, 1_250_331, 1_264_857,
474 1_265_385, 1_265_794, 1_265_795, 1_276_809, 1_276_816, 383_414, 2818, 1_276_816,
475 454_419, 1_249_194, 453_457, 452_538, 452_536, 1_248_970, 453_428, 1_249_190,
476 1_276_809, 1_249_204, 452_923, 452_917, 1_248_971,
477];
478static DECLARED_AURA_IDS: &[u32] = &[
479 1784, 1856, 2823, 381_664, 315_584, 8679, 381_637, 5761, 3408, 2818, 383_414, 32645,
480 315_496, 121_153, 193_538, 457_280, 193_531, 457_512, 381_801, 1_250_036, 1_250_331,
481 703, 1943, 381_628, 381_632, 392_401, 360_194, 385_627, 394_095, 1_249_810,
482 1_265_389, 1_265_391, 1_265_385, 1_265_385, 134_735, 452_923, 452_917, 1_248_971,
483 1_249_093, 452_923, 452_917, 1_248_971,
484];
485static TALENTS: &[(&str, u32)] = &[
486 ("ALACRITY", TALENT::ALACRITY),
487 ("AMPLIFYING_POISON", TALENT::AMPLIFYING_POISON),
488 ("BLINDSIDE", TALENT::BLINDSIDE),
489 ("CRIMSON_TEMPEST", TALENT::CRIMSON_TEMPEST),
490 ("DASHING_SCOUNDREL", TALENT::DASHING_SCOUNDREL),
491 ("DEADLY_POISON", TALENT::DEADLY_POISON),
492 ("DEATHMARK", TALENT::DEATHMARK),
493 ("DEEPER_STRATAGEM", TALENT::DEEPER_STRATAGEM),
494 ("DOOMBLADE", TALENT::DOOMBLADE),
495 ("DRAGON_TEMPERED_BLADES", TALENT::DRAGON_TEMPERED_BLADES),
496 ("FINISH_THE_JOB", TALENT::FINISH_THE_JOB),
497 ("IMPLACABLE_1", TALENT::IMPLACABLE_1),
498 ("IMPLACABLE_2", TALENT::IMPLACABLE_2),
499 ("IMPLACABLE_3", TALENT::IMPLACABLE_3),
500 ("IMPROVED_GARROTE", TALENT::IMPROVED_GARROTE),
501 ("IMPROVED_POISONS", TALENT::IMPROVED_POISONS),
502 ("INSPIRING_STRIKE", TALENT::INSPIRING_STRIKE),
503 ("INTERNAL_BLEEDING", TALENT::INTERNAL_BLEEDING),
504 ("KINGSBANE", TALENT::KINGSBANE),
505 ("LETHALITY", TALENT::LETHALITY),
506 ("LETHAL_DOSE", TALENT::LETHAL_DOSE),
507 ("RAPID_INJECTION", TALENT::RAPID_INJECTION),
508 ("REGICIDES_REWARD", TALENT::REGICIDES_REWARD),
509 ("SANGUINE_STRATAGEM", TALENT::SANGUINE_STRATAGEM),
510 ("SEAL_FATE", TALENT::SEAL_FATE),
511 ("SYSTEMIC_FAILURE", TALENT::SYSTEMIC_FAILURE),
512 ("THISTLE_TEA", TALENT::THISTLE_TEA),
513 ("VENOMOUS_WOUNDS", TALENT::VENOMOUS_WOUNDS),
514 ("ZOLDYCK_RECIPE", TALENT::ZOLDYCK_RECIPE),
515];
516pub(crate) mod ASSASSINATION_ROGUE {
517 pub(crate) const MUTILATE_CASTS: u32 = 0;
518 pub(crate) const AMBUSH_CASTS: u32 = 1;
519 pub(crate) const GARROTE_CASTS: u32 = 2;
520 pub(crate) const RUPTURE_CASTS: u32 = 3;
521 pub(crate) const ENVENOM_CASTS: u32 = 4;
522 pub(crate) const DEATHMARK_CASTS: u32 = 5;
523 pub(crate) const KINGSBANE_CASTS: u32 = 6;
524 pub(crate) const FAN_OF_KNIVES_CASTS: u32 = 7;
525 pub(crate) const GARROTE_UPTIME_MS: u32 = 8;
526 pub(crate) const RUPTURE_UPTIME_MS: u32 = 9;
527 pub(crate) const ENVENOM_UPTIME_MS: u32 = 10;
528 pub(crate) const DEATHMARK_UPTIME_MS: u32 = 11;
529}
530fn aura_stealth(
531 a: AuraDefinitionDraft,
532 data: &ResolvedGameData,
533) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
534 Ok(
535 a
536 .on_player()
537 .apply_base_from_data(data, 1784)?
538 .max_stacks(
539 data
540 .require_aura_max_stacks(
541 wowlab_types::sim::SpellIdx::from_raw(1784),
542 )?,
543 ),
544 )
545}
546fn aura_vanish(
547 a: AuraDefinitionDraft,
548 data: &ResolvedGameData,
549) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
550 Ok(
551 a
552 .on_player()
553 .apply_base_from_data(data, 1856)?
554 .max_stacks(
555 data
556 .require_aura_max_stacks(
557 wowlab_types::sim::SpellIdx::from_raw(1856),
558 )?,
559 ),
560 )
561}
562fn aura_deadly_poison(
563 a: AuraDefinitionDraft,
564 data: &ResolvedGameData,
565) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
566 Ok(
567 a
568 .on_player()
569 .apply_base_from_data(data, 2823)?
570 .max_stacks(
571 data
572 .require_aura_max_stacks(
573 wowlab_types::sim::SpellIdx::from_raw(2823),
574 )?,
575 ),
576 )
577}
578fn aura_amplifying_poison(
579 a: AuraDefinitionDraft,
580 data: &ResolvedGameData,
581) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
582 Ok(
583 a
584 .on_player()
585 .apply_base_from_data(data, 381_664)?
586 .max_stacks(
587 data
588 .require_aura_max_stacks(
589 wowlab_types::sim::SpellIdx::from_raw(381_664),
590 )?,
591 ),
592 )
593}
594fn aura_instant_poison(
595 a: AuraDefinitionDraft,
596 data: &ResolvedGameData,
597) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
598 Ok(
599 a
600 .on_player()
601 .apply_base_from_data(data, 315_584)?
602 .max_stacks(
603 data
604 .require_aura_max_stacks(
605 wowlab_types::sim::SpellIdx::from_raw(315_584),
606 )?,
607 ),
608 )
609}
610fn aura_wound_poison(
611 a: AuraDefinitionDraft,
612 data: &ResolvedGameData,
613) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
614 Ok(
615 a
616 .on_player()
617 .apply_base_from_data(data, 8679)?
618 .max_stacks(
619 data
620 .require_aura_max_stacks(
621 wowlab_types::sim::SpellIdx::from_raw(8679),
622 )?,
623 ),
624 )
625}
626fn aura_atrophic_poison(
627 a: AuraDefinitionDraft,
628 data: &ResolvedGameData,
629) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
630 Ok(
631 a
632 .on_player()
633 .apply_base_from_data(data, 381_637)?
634 .max_stacks(
635 data
636 .require_aura_max_stacks(
637 wowlab_types::sim::SpellIdx::from_raw(381_637),
638 )?,
639 )
640 .spell_group(0, wowlab_types::combat::SpellGroupRule::Exclusive),
641 )
642}
643fn aura_numbing_poison(
644 a: AuraDefinitionDraft,
645 data: &ResolvedGameData,
646) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
647 Ok(
648 a
649 .on_player()
650 .apply_base_from_data(data, 5761)?
651 .max_stacks(
652 data
653 .require_aura_max_stacks(
654 wowlab_types::sim::SpellIdx::from_raw(5761),
655 )?,
656 )
657 .spell_group(0, wowlab_types::combat::SpellGroupRule::Exclusive),
658 )
659}
660fn aura_crippling_poison(
661 a: AuraDefinitionDraft,
662 data: &ResolvedGameData,
663) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
664 Ok(
665 a
666 .on_player()
667 .apply_base_from_data(data, 3408)?
668 .max_stacks(
669 data
670 .require_aura_max_stacks(
671 wowlab_types::sim::SpellIdx::from_raw(3408),
672 )?,
673 ),
674 )
675}
676fn aura_deadly_poison_dot(
677 a: AuraDefinitionDraft,
678 data: &ResolvedGameData,
679) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
680 Ok(
681 a
682 .on_target()
683 .apply_base_from_data(data, 2818)?
684 .max_stacks(
685 data
686 .require_aura_max_stacks(
687 wowlab_types::sim::SpellIdx::from_raw(2818),
688 )?,
689 ),
690 )
691}
692fn aura_amplifying_poison_debuff(
693 a: AuraDefinitionDraft,
694 data: &ResolvedGameData,
695) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
696 Ok(
697 a
698 .on_target()
699 .apply_base_from_data(data, 383_414)?
700 .max_stacks(
701 data
702 .require_aura_max_stacks(
703 wowlab_types::sim::SpellIdx::from_raw(383_414),
704 )?,
705 ),
706 )
707}
708fn aura_envenom(
709 a: AuraDefinitionDraft,
710 data: &ResolvedGameData,
711) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
712 Ok(
713 a
714 .on_player()
715 .duration_ms(
716 wowlab_engine_combat::validated_milliseconds(
717 1000.0,
718 32645,
719 "aura.duration_ms",
720 )?,
721 )
722 .apply_periodic_effect_from_data(data, 32645)?
723 .max_stacks(
724 data
725 .require_aura_max_stacks(
726 wowlab_types::sim::SpellIdx::from_raw(32645),
727 )?,
728 )
729 .no_pandemic()
730 .on_expire(crate::hooks::assassination_rogue::envenom_expire_hook),
731 )
732}
733fn aura_slice_and_dice(
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, 315_496)?
741 .max_stacks(
742 data
743 .require_aura_max_stacks(
744 wowlab_types::sim::SpellIdx::from_raw(315_496),
745 )?,
746 ),
747 )
748}
749fn aura_blindside(
750 a: AuraDefinitionDraft,
751 data: &ResolvedGameData,
752) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
753 Ok(
754 a
755 .on_player()
756 .apply_base_from_data(data, 121_153)?
757 .max_stacks(
758 data
759 .require_aura_max_stacks(
760 wowlab_types::sim::SpellIdx::from_raw(121_153),
761 )?,
762 ),
763 )
764}
765fn aura_alacrity(
766 a: AuraDefinitionDraft,
767 data: &ResolvedGameData,
768) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
769 a.on_player()
770 .apply_base_from_data(data, 193_538)?
771 .max_stacks(
772 data.require_aura_max_stacks(wowlab_types::sim::SpellIdx::from_raw(193_538))?,
773 )
774 .haste_per_stack(
775 data.base_points(wowlab_types::sim::SpellIdx::from_raw(193_538), 1),
776 )
777}
778fn aura_darkest_night(
779 a: AuraDefinitionDraft,
780 data: &ResolvedGameData,
781) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
782 Ok(
783 a
784 .on_player()
785 .apply_base_from_data(data, 457_280)?
786 .max_stacks(
787 data
788 .require_aura_max_stacks(
789 wowlab_types::sim::SpellIdx::from_raw(457_280),
790 )?,
791 ),
792 )
793}
794fn aura_deeper_stratagem(
795 a: AuraDefinitionDraft,
796 data: &ResolvedGameData,
797) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
798 Ok(
799 a
800 .on_player()
801 .apply_base_from_data(data, 193_531)?
802 .max_stacks(
803 data
804 .require_aura_max_stacks(
805 wowlab_types::sim::SpellIdx::from_raw(193_531),
806 )?,
807 ),
808 )
809}
810fn aura_sanguine_stratagem(
811 a: AuraDefinitionDraft,
812 data: &ResolvedGameData,
813) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
814 Ok(
815 a
816 .on_player()
817 .apply_base_from_data(data, 457_512)?
818 .max_stacks(
819 data
820 .require_aura_max_stacks(
821 wowlab_types::sim::SpellIdx::from_raw(457_512),
822 )?,
823 ),
824 )
825}
826fn aura_dragon_tempered_blades(
827 a: AuraDefinitionDraft,
828 data: &ResolvedGameData,
829) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
830 Ok(
831 a
832 .on_player()
833 .apply_base_from_data(data, 381_801)?
834 .max_stacks(
835 data
836 .require_aura_max_stacks(
837 wowlab_types::sim::SpellIdx::from_raw(381_801),
838 )?,
839 ),
840 )
841}
842fn aura_inspiring_strike(
843 a: AuraDefinitionDraft,
844 data: &ResolvedGameData,
845) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
846 a.on_player()
847 .duration_ms(
848 wowlab_engine_combat::validated_milliseconds(
849 1000.0,
850 1_250_036,
851 "aura.duration_ms",
852 )?,
853 )
854 .apply_periodic_effect_from_data(data, 1_250_036)?
855 .max_stacks(
856 data
857 .require_aura_max_stacks(
858 wowlab_types::sim::SpellIdx::from_raw(1_250_036),
859 )?,
860 )
861 .damage_multiplier(
862 ((data.base_points(wowlab_types::sim::SpellIdx::from_raw(1_250_036), 1))
863 * 0.01) + 1.0,
864 )
865}
866fn aura_regicides_reward(
867 a: AuraDefinitionDraft,
868 data: &ResolvedGameData,
869) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
870 Ok(
871 a
872 .on_player()
873 .apply_base_from_data(data, 1_250_331)?
874 .max_stacks(
875 wowlab_engine_combat::validated_max_stacks(
876 10.0,
877 1_250_331,
878 "aura.max_stacks",
879 )?,
880 )
881 .periodic_remove_stack(
882 wowlab_engine_combat::validated_milliseconds(
883 data.period(wowlab_types::sim::SpellIdx::from_raw(1_250_331), 2),
884 1_250_331,
885 "periodic_remove_stack.tick_ms",
886 )?,
887 ),
888 )
889}
890fn aura_garrote(
891 a: AuraDefinitionDraft,
892 data: &ResolvedGameData,
893) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
894 Ok(
895 a
896 .on_target()
897 .apply_base_from_data(data, 703)?
898 .max_stacks(
899 data.require_aura_max_stacks(wowlab_types::sim::SpellIdx::from_raw(703))?,
900 ),
901 )
902}
903fn aura_rupture(
904 a: AuraDefinitionDraft,
905 data: &ResolvedGameData,
906) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
907 Ok(
908 a
909 .on_target()
910 .apply_base_from_data(data, 1943)?
911 .max_stacks(
912 data
913 .require_aura_max_stacks(
914 wowlab_types::sim::SpellIdx::from_raw(1943),
915 )?,
916 ),
917 )
918}
919fn aura_internal_bleeding(
920 a: AuraDefinitionDraft,
921 data: &ResolvedGameData,
922) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
923 Ok(
924 a
925 .on_target()
926 .apply_base_from_data(data, 381_628)?
927 .max_stacks(
928 data
929 .require_aura_max_stacks(
930 wowlab_types::sim::SpellIdx::from_raw(381_628),
931 )?,
932 ),
933 )
934}
935fn aura_improved_garrote(
936 a: AuraDefinitionDraft,
937 data: &ResolvedGameData,
938) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
939 Ok(
940 a
941 .on_player()
942 .apply_base_from_data(data, 381_632)?
943 .max_stacks(
944 data
945 .require_aura_max_stacks(
946 wowlab_types::sim::SpellIdx::from_raw(381_632),
947 )?,
948 ),
949 )
950}
951fn aura_improved_garrote_window(
952 a: AuraDefinitionDraft,
953 data: &ResolvedGameData,
954) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
955 Ok(
956 a
957 .on_player()
958 .apply_base_from_data(data, 392_401)?
959 .max_stacks(
960 data
961 .require_aura_max_stacks(
962 wowlab_types::sim::SpellIdx::from_raw(392_401),
963 )?,
964 ),
965 )
966}
967fn aura_deathmark(
968 a: AuraDefinitionDraft,
969 data: &ResolvedGameData,
970) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
971 Ok(
972 a
973 .on_target()
974 .apply_base_from_data(data, 360_194)?
975 .max_stacks(
976 data
977 .require_aura_max_stacks(
978 wowlab_types::sim::SpellIdx::from_raw(360_194),
979 )?,
980 ),
981 )
982}
983fn aura_kingsbane(
984 a: AuraDefinitionDraft,
985 data: &ResolvedGameData,
986) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
987 Ok(
988 a
989 .on_target()
990 .apply_base_from_data(data, 385_627)?
991 .max_stacks(
992 data
993 .require_aura_max_stacks(
994 wowlab_types::sim::SpellIdx::from_raw(385_627),
995 )?,
996 )
997 .on_expire(crate::hooks::assassination_rogue::kingsbane_expire_hook),
998 )
999}
1000fn aura_kingsbane_ramp(
1001 a: AuraDefinitionDraft,
1002 data: &ResolvedGameData,
1003) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
1004 a.on_player()
1005 .duration_ms(
1006 wowlab_engine_combat::validated_milliseconds(
1007 0.0,
1008 394_095,
1009 "aura.duration_ms",
1010 )?,
1011 )
1012 .apply_periodic_effect_from_data(data, 394_095)?
1013 .max_stacks(
1014 data.require_aura_max_stacks(wowlab_types::sim::SpellIdx::from_raw(394_095))?,
1015 )
1016 .damage_percent_spells_linear(
1017 data.base_points(wowlab_types::sim::SpellIdx::from_raw(394_095), 1),
1018 &[385_627],
1019 )
1020}
1021fn aura_finish_the_job(
1022 a: AuraDefinitionDraft,
1023 data: &ResolvedGameData,
1024) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
1025 Ok(
1026 a
1027 .on_player()
1028 .apply_base_from_data(data, 1_249_810)?
1029 .max_stacks(
1030 data
1031 .require_aura_max_stacks(
1032 wowlab_types::sim::SpellIdx::from_raw(1_249_810),
1033 )?,
1034 ),
1035 )
1036}
1037fn aura_implacable_tracker(
1038 a: AuraDefinitionDraft,
1039 data: &ResolvedGameData,
1040) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
1041 Ok(
1042 a
1043 .on_player()
1044 .apply_base_from_data(data, 1_265_389)?
1045 .max_stacks(
1046 data
1047 .require_aura_max_stacks(
1048 wowlab_types::sim::SpellIdx::from_raw(1_265_389),
1049 )?,
1050 ),
1051 )
1052}
1053fn aura_implacable_regen(
1054 a: AuraDefinitionDraft,
1055 data: &ResolvedGameData,
1056) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
1057 a.on_player()
1058 .apply_base_from_data(data, 1_265_391)?
1059 .max_stacks(
1060 data
1061 .require_aura_max_stacks(
1062 wowlab_types::sim::SpellIdx::from_raw(1_265_391),
1063 )?,
1064 )
1065 .regen_percent_per_stack(
1066 data.base_points(wowlab_types::sim::SpellIdx::from_raw(1_265_385), 1),
1067 )
1068}
1069fn aura_implacable_bonus(
1070 a: AuraDefinitionDraft,
1071 data: &ResolvedGameData,
1072) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
1073 a.on_player()
1074 .duration_ms(
1075 wowlab_engine_combat::validated_milliseconds(
1076 5000.0,
1077 1_265_385,
1078 "aura.duration_ms",
1079 )?,
1080 )
1081 .apply_periodic_effect_from_data(data, 1_265_385)?
1082 .max_stacks(
1083 wowlab_engine_combat::validated_max_stacks(
1084 4.0,
1085 1_265_385,
1086 "aura.max_stacks",
1087 )?,
1088 )
1089 .regen_percent_per_stack(
1090 data.base_points(wowlab_types::sim::SpellIdx::from_raw(1_265_385), 2),
1091 )
1092}
1093fn aura_implacable(
1094 a: AuraDefinitionDraft,
1095 data: &ResolvedGameData,
1096) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
1097 Ok(
1098 a
1099 .on_player()
1100 .apply_base_from_data(data, 1_265_385)?
1101 .max_stacks(
1102 data
1103 .require_aura_max_stacks(
1104 wowlab_types::sim::SpellIdx::from_raw(1_265_385),
1105 )?,
1106 ),
1107 )
1108}
1109fn aura_pvp_rules_enabled_hardcoded(
1110 a: AuraDefinitionDraft,
1111 data: &ResolvedGameData,
1112) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
1113 Ok(
1114 a
1115 .on_player()
1116 .apply_base_from_data(data, 134_735)?
1117 .max_stacks(
1118 data
1119 .require_aura_max_stacks(
1120 wowlab_types::sim::SpellIdx::from_raw(134_735),
1121 )?,
1122 ),
1123 )
1124}
1125fn aura_fatebound_coin_heads(
1126 a: AuraDefinitionDraft,
1127 data: &ResolvedGameData,
1128) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
1129 Ok(
1130 a
1131 .on_player()
1132 .apply_base_from_data(data, 452_923)?
1133 .max_stacks(
1134 data
1135 .require_aura_max_stacks(
1136 wowlab_types::sim::SpellIdx::from_raw(452_923),
1137 )?,
1138 ),
1139 )
1140}
1141fn aura_fatebound_coin_tails(
1142 a: AuraDefinitionDraft,
1143 data: &ResolvedGameData,
1144) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
1145 Ok(
1146 a
1147 .on_player()
1148 .apply_base_from_data(data, 452_917)?
1149 .max_stacks(
1150 data
1151 .require_aura_max_stacks(
1152 wowlab_types::sim::SpellIdx::from_raw(452_917),
1153 )?,
1154 ),
1155 )
1156}
1157fn aura_fatebound_lucky_coin(
1158 a: AuraDefinitionDraft,
1159 data: &ResolvedGameData,
1160) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
1161 a.on_player()
1162 .apply_base_from_data(data, 1_248_971)?
1163 .max_stacks(
1164 data
1165 .require_aura_max_stacks(
1166 wowlab_types::sim::SpellIdx::from_raw(1_248_971),
1167 )?,
1168 )
1169 .primary_pct_per_stack(
1170 data.base_points(wowlab_types::sim::SpellIdx::from_raw(1_248_971), 1),
1171 )
1172}
1173fn aura_lucky_coin_counter(
1174 a: AuraDefinitionDraft,
1175 data: &ResolvedGameData,
1176) -> Result<AuraDefinitionDraft, wowlab_engine_combat::BuilderError> {
1177 Ok(
1178 a
1179 .on_player()
1180 .apply_base_from_data(data, 1_249_093)?
1181 .max_stacks(
1182 data
1183 .require_aura_max_stacks(
1184 wowlab_types::sim::SpellIdx::from_raw(1_249_093),
1185 )?,
1186 ),
1187 )
1188}
1189fn spell_mutilate(
1190 s: SpellDefinitionDraft,
1191 data: &ResolvedGameData,
1192) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1193 Ok(
1194 s
1195 .apply_base_from_data(data, 1329)?
1196 .without_primary_data_damage()
1197 .trigger_program_predicate(
1198 3,
1199 crate::hooks::assassination_rogue::hook_owned_damage_trigger_disabled,
1200 )
1201 .trigger_program_predicate(
1202 4,
1203 crate::hooks::assassination_rogue::hook_owned_damage_trigger_disabled,
1204 )
1205 .apply_aoe_from_data(data)
1206 .on_cast(crate::hooks::assassination_rogue::mutilate_hook),
1207 )
1208}
1209fn spell_ambush(
1210 s: SpellDefinitionDraft,
1211 data: &ResolvedGameData,
1212) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1213 Ok(
1214 s
1215 .apply_base_from_data(data, 8676)?
1216 .apply_aoe_from_data(data)
1217 .on_cast(crate::hooks::assassination_rogue::ambush_hook)
1218 .cost_free_when_aura(121_153),
1219 )
1220}
1221fn spell_envenom(
1222 s: SpellDefinitionDraft,
1223 data: &ResolvedGameData,
1224) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1225 Ok(
1226 s
1227 .apply_base_from_data(data, 32645)?
1228 .applies_inferred_aura(AURA_ENVENOM, 32645)
1229 .apply_aoe_from_data(data)
1230 .on_cast(crate::hooks::assassination_rogue::envenom_hook),
1231 )
1232}
1233fn spell_slice_and_dice(
1234 s: SpellDefinitionDraft,
1235 data: &ResolvedGameData,
1236) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1237 Ok(
1238 s
1239 .apply_base_from_data(data, 315_496)?
1240 .applies_inferred_aura(AURA_SLICE_AND_DICE, 315_496)
1241 .apply_aoe_from_data(data),
1242 )
1243}
1244fn spell_fan_of_knives(
1245 s: SpellDefinitionDraft,
1246 data: &ResolvedGameData,
1247) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1248 Ok(s.apply_base_from_data(data, 51723)?.apply_aoe_from_data(data))
1249}
1250fn spell_crimson_tempest(
1251 s: SpellDefinitionDraft,
1252 data: &ResolvedGameData,
1253) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1254 Ok(s.apply_base_from_data(data, 1_247_227)?.apply_aoe_from_data(data))
1255}
1256fn spell_poisoned_knife(
1257 s: SpellDefinitionDraft,
1258 data: &ResolvedGameData,
1259) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1260 Ok(s.apply_base_from_data(data, 185_565)?.apply_aoe_from_data(data))
1261}
1262fn spell_deadly_poison(
1263 s: SpellDefinitionDraft,
1264 data: &ResolvedGameData,
1265) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1266 Ok(
1267 s
1268 .apply_base_from_data(data, 2823)?
1269 .applies_inferred_aura(AURA_DEADLY_POISON, 2823)
1270 .no_stealth_break()
1271 .apply_aoe_from_data(data),
1272 )
1273}
1274fn spell_amplifying_poison(
1275 s: SpellDefinitionDraft,
1276 data: &ResolvedGameData,
1277) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1278 Ok(
1279 s
1280 .apply_base_from_data(data, 381_664)?
1281 .applies_inferred_aura(AURA_AMPLIFYING_POISON, 381_664)
1282 .no_stealth_break()
1283 .apply_aoe_from_data(data),
1284 )
1285}
1286fn spell_instant_poison(
1287 s: SpellDefinitionDraft,
1288 data: &ResolvedGameData,
1289) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1290 Ok(
1291 s
1292 .apply_base_from_data(data, 315_584)?
1293 .applies_inferred_aura(AURA_INSTANT_POISON, 315_584)
1294 .no_stealth_break()
1295 .apply_aoe_from_data(data),
1296 )
1297}
1298fn spell_wound_poison(
1299 s: SpellDefinitionDraft,
1300 data: &ResolvedGameData,
1301) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1302 Ok(
1303 s
1304 .apply_base_from_data(data, 8679)?
1305 .applies_inferred_aura(AURA_WOUND_POISON, 8679)
1306 .no_stealth_break()
1307 .apply_aoe_from_data(data),
1308 )
1309}
1310fn spell_atrophic_poison(
1311 s: SpellDefinitionDraft,
1312 data: &ResolvedGameData,
1313) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1314 Ok(
1315 s
1316 .apply_base_from_data(data, 381_637)?
1317 .applies_inferred_aura(AURA_ATROPHIC_POISON, 381_637)
1318 .no_stealth_break()
1319 .apply_aoe_from_data(data),
1320 )
1321}
1322fn spell_numbing_poison(
1323 s: SpellDefinitionDraft,
1324 data: &ResolvedGameData,
1325) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1326 Ok(
1327 s
1328 .apply_base_from_data(data, 5761)?
1329 .applies_inferred_aura(AURA_NUMBING_POISON, 5761)
1330 .no_stealth_break()
1331 .apply_aoe_from_data(data),
1332 )
1333}
1334fn spell_crippling_poison(
1335 s: SpellDefinitionDraft,
1336 data: &ResolvedGameData,
1337) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1338 Ok(
1339 s
1340 .apply_base_from_data(data, 3408)?
1341 .applies_inferred_aura(AURA_CRIPPLING_POISON, 3408)
1342 .no_stealth_break()
1343 .apply_aoe_from_data(data),
1344 )
1345}
1346fn spell_mutilate_mh(
1347 s: SpellDefinitionDraft,
1348 data: &ResolvedGameData,
1349) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1350 Ok(s.apply_base_from_data(data, 5374)?.apply_aoe_from_data(data))
1351}
1352fn spell_mutilate_oh(
1353 s: SpellDefinitionDraft,
1354 data: &ResolvedGameData,
1355) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1356 Ok(s.apply_base_from_data(data, 27576)?.apply_aoe_from_data(data))
1357}
1358fn spell_deadly_poison_instant(
1359 s: SpellDefinitionDraft,
1360 data: &ResolvedGameData,
1361) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1362 Ok(s.apply_base_from_data(data, 113_780)?.apply_aoe_from_data(data))
1363}
1364fn spell_mutilated_flesh(
1365 s: SpellDefinitionDraft,
1366 data: &ResolvedGameData,
1367) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1368 Ok(s.apply_base_from_data(data, 394_021)?.apply_aoe_from_data(data))
1369}
1370fn spell_garrote(
1371 s: SpellDefinitionDraft,
1372 data: &ResolvedGameData,
1373) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1374 Ok(
1375 s
1376 .apply_base_from_data(data, 703)?
1377 .applies_inferred_aura(AURA_GARROTE, 703)
1378 .apply_aoe_from_data(data)
1379 .on_cast(crate::hooks::assassination_rogue::garrote_hook),
1380 )
1381}
1382fn spell_rupture(
1383 s: SpellDefinitionDraft,
1384 data: &ResolvedGameData,
1385) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1386 Ok(
1387 s
1388 .apply_base_from_data(data, 1943)?
1389 .applies_inferred_aura(AURA_RUPTURE, 1943)
1390 .apply_aoe_from_data(data)
1391 .on_cast(crate::hooks::assassination_rogue::rupture_hook),
1392 )
1393}
1394fn spell_internal_bleeding_driver(
1395 s: SpellDefinitionDraft,
1396 data: &ResolvedGameData,
1397) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1398 Ok(
1399 s
1400 .apply_base_from_data(data, 381_628)?
1401 .applies_inferred_aura(AURA_INTERNAL_BLEEDING, 381_628)
1402 .apply_aoe_from_data(data),
1403 )
1404}
1405fn spell_deathmark(
1406 s: SpellDefinitionDraft,
1407 data: &ResolvedGameData,
1408) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1409 Ok(
1410 s
1411 .apply_base_from_data(data, 360_194)?
1412 .applies_inferred_aura(AURA_DEATHMARK, 360_194)
1413 .apply_aoe_from_data(data)
1414 .on_cast(crate::hooks::assassination_rogue::deathmark_hook),
1415 )
1416}
1417fn spell_kingsbane(
1418 s: SpellDefinitionDraft,
1419 data: &ResolvedGameData,
1420) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1421 Ok(
1422 s
1423 .apply_base_from_data(data, 385_627)?
1424 .applies_inferred_aura(AURA_KINGSBANE, 385_627)
1425 .apply_aoe_from_data(data)
1426 .on_cast(crate::hooks::assassination_rogue::kingsbane_hook),
1427 )
1428}
1429fn spell_implacable_strikes_nature(
1430 s: SpellDefinitionDraft,
1431 data: &ResolvedGameData,
1432) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1433 Ok(s.apply_base_from_data(data, 1_265_794)?.apply_aoe_from_data(data))
1434}
1435fn spell_implacable_strikes_physical(
1436 s: SpellDefinitionDraft,
1437 data: &ResolvedGameData,
1438) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1439 Ok(s.apply_base_from_data(data, 1_265_795)?.apply_aoe_from_data(data))
1440}
1441fn spell_thistle_tea(
1442 s: SpellDefinitionDraft,
1443 data: &ResolvedGameData,
1444) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1445 Ok(
1446 s
1447 .apply_base_from_data(data, 381_623)?
1448 .no_stealth_break()
1449 .apply_aoe_from_data(data),
1450 )
1451}
1452fn spell_vanish(
1453 s: SpellDefinitionDraft,
1454 data: &ResolvedGameData,
1455) -> Result<SpellDefinitionDraft, wowlab_engine_combat::BuilderError> {
1456 Ok(
1457 s
1458 .apply_base_from_data(data, 1856)?
1459 .applies_aura(AURA_STEALTH)
1460 .no_stealth_break()
1461 .apply_aoe_from_data(data)
1462 .on_cast(crate::hooks::assassination_rogue::vanish_hook),
1463 )
1464}
1465pub(crate) fn build_combat_system(
1466 params: &wowlab_engine_ports::HandlerParams<'_>,
1467) -> Result<BuiltCombatSystem, wowlab_engine_ports::EngineError> {
1468 let builder = BuiltCombatSystem::builder(params.stats.clone())
1469 .spec_id(SpecId::Assassination)
1470 .hero_talent_trees(DECLARED_METADATA.hero_talent_trees)
1471 .mastery_spell(76803)
1472 .mastery_hook(crate::hooks::assassination_rogue::mastery)
1473 .resource(
1474 "energy",
1475 params
1476 .game_data
1477 .power_max(3)
1478 .ok_or_else(|| {
1479 wowlab_engine_ports::EngineError::spec_construction(
1480 "missing power-type power_max for type_id 3",
1481 )
1482 })?,
1483 params
1484 .game_data
1485 .power_regen_for_max(
1486 3,
1487 params
1488 .game_data
1489 .power_max(3)
1490 .ok_or_else(|| {
1491 wowlab_engine_ports::EngineError::spec_construction(
1492 "missing power-type power_max for type_id 3",
1493 )
1494 })?,
1495 )
1496 .ok_or_else(|| {
1497 wowlab_engine_ports::EngineError::spec_construction(
1498 "missing power-type power_regen_for_max for type_id 3",
1499 )
1500 })?,
1501 )
1502 .resource_type_id(3)
1503 .resource_start(
1504 params
1505 .game_data
1506 .power_default(3)
1507 .ok_or_else(|| {
1508 wowlab_engine_ports::EngineError::spec_construction(
1509 "missing power-type power_default for type_id 3",
1510 )
1511 })?,
1512 )
1513 .secondary_resource(
1514 "combo_points",
1515 params
1516 .game_data
1517 .power_max(4)
1518 .ok_or_else(|| {
1519 wowlab_engine_ports::EngineError::spec_construction(
1520 "missing power-type power_max for type_id 4",
1521 )
1522 })?,
1523 )
1524 .secondary_resource_type_id(4)
1525 .precombat_aura(AURA_STEALTH)
1526 .precombat_aura(AURA_DEADLY_POISON)
1527 .precombat_aura(AURA_AMPLIFYING_POISON)
1528 .precombat_aura(AURA_ATROPHIC_POISON)
1529 .precombat_aura(AURA_CRIPPLING_POISON)
1530 .stealth_aura(AURA::STEALTH)
1531 .aura("stealth", AURA::STEALTH, |a| aura_stealth(a, ¶ms.game_data))
1532 .aura("vanish", AURA::VANISH, |a| aura_vanish(a, ¶ms.game_data))
1533 .aura(
1534 "deadly_poison",
1535 AURA::DEADLY_POISON,
1536 |a| aura_deadly_poison(a, ¶ms.game_data),
1537 )
1538 .aura(
1539 "amplifying_poison",
1540 AURA::AMPLIFYING_POISON,
1541 |a| aura_amplifying_poison(a, ¶ms.game_data),
1542 )
1543 .aura(
1544 "instant_poison",
1545 AURA::INSTANT_POISON,
1546 |a| aura_instant_poison(a, ¶ms.game_data),
1547 )
1548 .aura(
1549 "wound_poison",
1550 AURA::WOUND_POISON,
1551 |a| aura_wound_poison(a, ¶ms.game_data),
1552 )
1553 .aura(
1554 "atrophic_poison",
1555 AURA::ATROPHIC_POISON,
1556 |a| aura_atrophic_poison(a, ¶ms.game_data),
1557 )
1558 .aura(
1559 "numbing_poison",
1560 AURA::NUMBING_POISON,
1561 |a| aura_numbing_poison(a, ¶ms.game_data),
1562 )
1563 .aura(
1564 "crippling_poison",
1565 AURA::CRIPPLING_POISON,
1566 |a| aura_crippling_poison(a, ¶ms.game_data),
1567 )
1568 .aura(
1569 "deadly_poison_dot",
1570 AURA::DEADLY_POISON_DOT,
1571 |a| aura_deadly_poison_dot(a, ¶ms.game_data),
1572 )
1573 .aura(
1574 "amplifying_poison_debuff",
1575 AURA::AMPLIFYING_POISON_DEBUFF,
1576 |a| aura_amplifying_poison_debuff(a, ¶ms.game_data),
1577 )
1578 .aura("envenom", AURA::ENVENOM, |a| aura_envenom(a, ¶ms.game_data))
1579 .aura(
1580 "slice_and_dice",
1581 AURA::SLICE_AND_DICE,
1582 |a| aura_slice_and_dice(a, ¶ms.game_data),
1583 )
1584 .aura("blindside", AURA::BLINDSIDE, |a| aura_blindside(a, ¶ms.game_data))
1585 .aura("alacrity", AURA::ALACRITY, |a| aura_alacrity(a, ¶ms.game_data))
1586 .aura(
1587 "darkest_night",
1588 AURA::DARKEST_NIGHT,
1589 |a| aura_darkest_night(a, ¶ms.game_data),
1590 )
1591 .aura(
1592 "deeper_stratagem",
1593 AURA::DEEPER_STRATAGEM,
1594 |a| aura_deeper_stratagem(a, ¶ms.game_data),
1595 )
1596 .aura(
1597 "sanguine_stratagem",
1598 AURA::SANGUINE_STRATAGEM,
1599 |a| aura_sanguine_stratagem(a, ¶ms.game_data),
1600 )
1601 .aura(
1602 "dragon_tempered_blades",
1603 AURA::DRAGON_TEMPERED_BLADES,
1604 |a| aura_dragon_tempered_blades(a, ¶ms.game_data),
1605 )
1606 .aura(
1607 "inspiring_strike",
1608 AURA::INSPIRING_STRIKE,
1609 |a| aura_inspiring_strike(a, ¶ms.game_data),
1610 )
1611 .aura(
1612 "regicides_reward",
1613 AURA::REGICIDES_REWARD,
1614 |a| aura_regicides_reward(a, ¶ms.game_data),
1615 )
1616 .aura("garrote", AURA::GARROTE, |a| aura_garrote(a, ¶ms.game_data))
1617 .aura("rupture", AURA::RUPTURE, |a| aura_rupture(a, ¶ms.game_data))
1618 .aura(
1619 "internal_bleeding",
1620 AURA::INTERNAL_BLEEDING,
1621 |a| aura_internal_bleeding(a, ¶ms.game_data),
1622 )
1623 .aura(
1624 "improved_garrote",
1625 AURA::IMPROVED_GARROTE,
1626 |a| aura_improved_garrote(a, ¶ms.game_data),
1627 )
1628 .aura(
1629 "improved_garrote_window",
1630 AURA::IMPROVED_GARROTE_WINDOW,
1631 |a| aura_improved_garrote_window(a, ¶ms.game_data),
1632 )
1633 .aura("deathmark", AURA::DEATHMARK, |a| aura_deathmark(a, ¶ms.game_data))
1634 .aura("kingsbane", AURA::KINGSBANE, |a| aura_kingsbane(a, ¶ms.game_data))
1635 .aura(
1636 "kingsbane_ramp",
1637 AURA::KINGSBANE_RAMP,
1638 |a| aura_kingsbane_ramp(a, ¶ms.game_data),
1639 )
1640 .aura(
1641 "finish_the_job",
1642 AURA::FINISH_THE_JOB,
1643 |a| aura_finish_the_job(a, ¶ms.game_data),
1644 )
1645 .aura(
1646 "implacable_tracker",
1647 AURA::IMPLACABLE_TRACKER,
1648 |a| aura_implacable_tracker(a, ¶ms.game_data),
1649 )
1650 .aura(
1651 "implacable_regen",
1652 AURA::IMPLACABLE_REGEN,
1653 |a| aura_implacable_regen(a, ¶ms.game_data),
1654 )
1655 .aura(
1656 "implacable_bonus",
1657 AURA::IMPLACABLE_BONUS,
1658 |a| aura_implacable_bonus(a, ¶ms.game_data),
1659 )
1660 .aura("implacable", AURA::IMPLACABLE, |a| aura_implacable(a, ¶ms.game_data))
1661 .aura(
1662 "pvp_rules_enabled_hardcoded",
1663 AURA::PVP_RULES_ENABLED_HARDCODED,
1664 |a| aura_pvp_rules_enabled_hardcoded(a, ¶ms.game_data),
1665 )
1666 .aura(
1667 "fatebound_coin_heads",
1668 AURA::FATEBOUND_COIN_HEADS,
1669 |a| aura_fatebound_coin_heads(a, ¶ms.game_data),
1670 )
1671 .aura(
1672 "fatebound_coin_tails",
1673 AURA::FATEBOUND_COIN_TAILS,
1674 |a| aura_fatebound_coin_tails(a, ¶ms.game_data),
1675 )
1676 .aura(
1677 "fatebound_lucky_coin",
1678 AURA::FATEBOUND_LUCKY_COIN,
1679 |a| aura_fatebound_lucky_coin(a, ¶ms.game_data),
1680 )
1681 .aura(
1682 "lucky_coin_counter",
1683 AURA::LUCKY_COIN_COUNTER,
1684 |a| aura_lucky_coin_counter(a, ¶ms.game_data),
1685 )
1686 .spell("mutilate", SPELL::MUTILATE, |s| spell_mutilate(s, ¶ms.game_data))
1687 .spell("ambush", SPELL::AMBUSH, |s| spell_ambush(s, ¶ms.game_data))
1688 .spell("envenom", SPELL::ENVENOM, |s| spell_envenom(s, ¶ms.game_data))
1689 .spell(
1690 "slice_and_dice",
1691 SPELL::SLICE_AND_DICE,
1692 |s| spell_slice_and_dice(s, ¶ms.game_data),
1693 )
1694 .spell(
1695 "fan_of_knives",
1696 SPELL::FAN_OF_KNIVES,
1697 |s| spell_fan_of_knives(s, ¶ms.game_data),
1698 )
1699 .spell(
1700 "crimson_tempest",
1701 SPELL::CRIMSON_TEMPEST,
1702 |s| spell_crimson_tempest(s, ¶ms.game_data),
1703 )
1704 .spell(
1705 "poisoned_knife",
1706 SPELL::POISONED_KNIFE,
1707 |s| spell_poisoned_knife(s, ¶ms.game_data),
1708 )
1709 .spell(
1710 "deadly_poison",
1711 SPELL::DEADLY_POISON,
1712 |s| spell_deadly_poison(s, ¶ms.game_data),
1713 )
1714 .spell(
1715 "amplifying_poison",
1716 SPELL::AMPLIFYING_POISON,
1717 |s| spell_amplifying_poison(s, ¶ms.game_data),
1718 )
1719 .spell(
1720 "instant_poison",
1721 SPELL::INSTANT_POISON,
1722 |s| spell_instant_poison(s, ¶ms.game_data),
1723 )
1724 .spell(
1725 "wound_poison",
1726 SPELL::WOUND_POISON,
1727 |s| spell_wound_poison(s, ¶ms.game_data),
1728 )
1729 .spell(
1730 "atrophic_poison",
1731 SPELL::ATROPHIC_POISON,
1732 |s| spell_atrophic_poison(s, ¶ms.game_data),
1733 )
1734 .spell(
1735 "numbing_poison",
1736 SPELL::NUMBING_POISON,
1737 |s| spell_numbing_poison(s, ¶ms.game_data),
1738 )
1739 .spell(
1740 "crippling_poison",
1741 SPELL::CRIPPLING_POISON,
1742 |s| spell_crippling_poison(s, ¶ms.game_data),
1743 )
1744 .spell(
1745 "mutilate_mh",
1746 SPELL::MUTILATE_MH,
1747 |s| spell_mutilate_mh(s, ¶ms.game_data),
1748 )
1749 .spell(
1750 "mutilate_oh",
1751 SPELL::MUTILATE_OH,
1752 |s| spell_mutilate_oh(s, ¶ms.game_data),
1753 )
1754 .spell(
1755 "deadly_poison_instant",
1756 SPELL::DEADLY_POISON_INSTANT,
1757 |s| spell_deadly_poison_instant(s, ¶ms.game_data),
1758 )
1759 .spell(
1760 "mutilated_flesh",
1761 SPELL::MUTILATED_FLESH,
1762 |s| spell_mutilated_flesh(s, ¶ms.game_data),
1763 )
1764 .spell("garrote", SPELL::GARROTE, |s| spell_garrote(s, ¶ms.game_data))
1765 .spell("rupture", SPELL::RUPTURE, |s| spell_rupture(s, ¶ms.game_data))
1766 .spell(
1767 "internal_bleeding_driver",
1768 SPELL::INTERNAL_BLEEDING_DRIVER,
1769 |s| spell_internal_bleeding_driver(s, ¶ms.game_data),
1770 )
1771 .spell("deathmark", SPELL::DEATHMARK, |s| spell_deathmark(s, ¶ms.game_data))
1772 .spell("kingsbane", SPELL::KINGSBANE, |s| spell_kingsbane(s, ¶ms.game_data))
1773 .spell(
1774 "implacable_strikes_nature",
1775 SPELL::IMPLACABLE_STRIKES_NATURE,
1776 |s| spell_implacable_strikes_nature(s, ¶ms.game_data),
1777 )
1778 .spell(
1779 "implacable_strikes_physical",
1780 SPELL::IMPLACABLE_STRIKES_PHYSICAL,
1781 |s| spell_implacable_strikes_physical(s, ¶ms.game_data),
1782 )
1783 .spell(
1784 "thistle_tea",
1785 SPELL::THISTLE_TEA,
1786 |s| spell_thistle_tea(s, ¶ms.game_data),
1787 )
1788 .spell("vanish", SPELL::VANISH, |s| spell_vanish(s, ¶ms.game_data))
1789 .auto_attack(|a| {
1790 a
1791 .spell_id(6603)
1792 .swing_ms(1800)
1793 .apply_base_from_data(¶ms.game_data)
1794 .on_swing(crate::hooks::assassination_rogue::swing_hook)
1795 })
1796 .game_data(params.game_data.clone())
1797 .talent_spell_ids(TALENTS)
1798 .talent_selections(params.talent_selections)
1799 .talent_companion_aura(TALENT::IMPROVED_GARROTE, AURA_IMPROVED_GARROTE_WINDOW)
1800 .register_impact_effect_proc_if_talent(
1801 TALENT::VENOMOUS_WOUNDS,
1802 wowlab_engine_combat::ImpactEffectProcDefinition::new(
1803 wowlab_engine_combat::ImpactSource::Spell(SPELL::GARROTE),
1804 )
1805 .chance(1.0)
1806 .periodic_only()
1807 .gain(
1808 params
1809 .game_data
1810 .base_points(wowlab_types::sim::SpellIdx::from_raw(79134), 1),
1811 ),
1812 )
1813 .register_impact_effect_proc_if_talent(
1814 TALENT::VENOMOUS_WOUNDS,
1815 wowlab_engine_combat::ImpactEffectProcDefinition::new(
1816 wowlab_engine_combat::ImpactSource::Spell(SPELL::RUPTURE),
1817 )
1818 .chance(1.0)
1819 .periodic_only()
1820 .gain(
1821 params
1822 .game_data
1823 .base_points(wowlab_types::sim::SpellIdx::from_raw(79134), 1),
1824 ),
1825 )
1826 .set_bonus_auras(params.set_bonus_auras)
1827 .encounter(params.encounter.clone());
1828 let builder = crate::generated::items::register_equipped(
1829 builder,
1830 ¶ms.game_data,
1831 params.equipped_items,
1832 )?;
1833
1834 builder
1835 .build(params.rotation)
1836 .map_err(wowlab_engine_ports::EngineError::rotation_compile)
1837}
1838fn new_handler(
1839 params: wowlab_engine_ports::HandlerParams<'_>,
1840) -> Result<Box<dyn SpecHandler>, wowlab_engine_ports::EngineError> {
1841 let handler = crate::composition::compose_handler(
1842 build_combat_system,
1843 ¶ms,
1844 crate::hooks::assassination_rogue::AssassinationHandler::try_new,
1845 )?;
1846
1847 Ok(Box::new(handler))
1848}
1849static DECLARED_METADATA: DeclaredSpecMetadata = DeclaredSpecMetadata {
1850 primary_resource: ResourceType::Energy,
1851 secondary_resource: Some(ResourceType::ComboPoints),
1852 spell_ids: DECLARED_SPELL_IDS,
1853 aura_ids: DECLARED_AURA_IDS,
1854 server_proc_entries: &[],
1855 talents: TALENTS,
1856 rotation_field_schema: &[],
1857 metrics_plugin_id: None,
1858 hero_talent_trees: &[
1859 HeroTalentTreeDesc {
1860 name: "Fatebound",
1861 spells: HERO_TREE_FATEBOUND_SPELLS,
1862 auras: HERO_TREE_FATEBOUND_AURAS,
1863 },
1864 ],
1865 reported_spells: REPORTED_SPELLS,
1866 masked_passive_effects: &[],
1867 passive_effect_overrides: &[],
1868};
1869pub(super) const SPEC_DESCRIPTOR: SpecDescriptor = SpecDescriptor {
1870 spec_id: SpecId::Assassination,
1871 display_name: "Assassination Rogue",
1872 metadata: DECLARED_METADATA,
1873 handler_factory: new_handler,
1874};
1875wowlab_engine_combat::smoke_test!(build_combat_system);