wowlab_engine_content/hooks/subtlety_rogue/
trickster.rs1use wowlab_engine_combat::DamageOps as _;
2use wowlab_engine_combat::AuraOps as _;
3use wowlab_engine_combat::{DamageFlags, HookCtx};
4use wowlab_engine_rng::proc_chance;
5
6use crate::generated::specs::subtlety_rogue::{
7 AURA_COUP_DE_GRACE, AURA_DISORIENTING_STRIKES, AURA_ESCALATING_BLADE, AURA_FAZED,
8 AURA_FLAWLESS_FORM, AURA_UNSEEN_BLADE_CD,
9};
10
11use super::config::SubtletyConfig;
12
13const ESCALATING_BLADE_MAX: i32 = 4;
14
15pub(super) fn trigger_unseen_blade(
17 ctx: &mut HookCtx<'_>,
18 cfg: &SubtletyConfig,
19) {
20 if !cfg.unseen_blade {
21 return;
22 }
23
24 let disoriented = ctx.aura_stacks(AURA_DISORIENTING_STRIKES);
25
26 if ctx.is_aura_active(AURA_UNSEEN_BLADE_CD) && disoriented == 0 {
27 return;
28 }
29
30 deal_unseen_blade(ctx, cfg);
31
32 if cfg.flashing_steel_chance > 0.0 && proc_chance(ctx.rng(), cfg.flashing_steel_chance) {
33 deal_unseen_blade(ctx, cfg);
34 }
35
36 if disoriented > 0 {
37 ctx.consume_aura_stack(AURA_DISORIENTING_STRIKES);
38 } else {
39 ctx.apply_aura(AURA_UNSEEN_BLADE_CD);
40 }
41}
42
43fn deal_unseen_blade(ctx: &mut HookCtx<'_>, cfg: &SubtletyConfig) {
44 ctx.deal_damage_ap(
45 crate::generated::specs::subtlety_rogue::DAMAGE_SPELL::UNSEEN_BLADE,
46 cfg.unseen_blade_coef,
47 DamageFlags::empty(),
48 );
49 ctx.apply_aura(AURA_FAZED);
50
51 if cfg.flawless_form {
52 ctx.apply_aura(AURA_FLAWLESS_FORM);
53 }
54
55 if cfg.coup_de_grace {
56 ctx.apply_aura(AURA_ESCALATING_BLADE);
57
58 if ctx.aura_stacks(AURA_ESCALATING_BLADE) >= ESCALATING_BLADE_MAX {
59 ctx.apply_aura(AURA_COUP_DE_GRACE);
60 }
61 }
62}
63
64pub(super) fn deal_coup_de_grace(
66 ctx: &mut HookCtx<'_>,
67 cfg: &SubtletyConfig,
68 cp: f64,
69 fw_active: bool,
70) {
71 let cdg_cp = cp + cfg.cdg_bonus_cp;
72 let hits = [
73 (
74 crate::generated::specs::subtlety_rogue::DAMAGE_SPELL::COUP_DE_GRACE_DAMAGE_1,
75 crate::generated::specs::subtlety_rogue::DAMAGE_EFFECT::CDG_DAMAGE_1,
76 ),
77 (
78 crate::generated::specs::subtlety_rogue::DAMAGE_SPELL::COUP_DE_GRACE_DAMAGE_2,
79 crate::generated::specs::subtlety_rogue::DAMAGE_EFFECT::CDG_DAMAGE_2,
80 ),
81 (
82 crate::generated::specs::subtlety_rogue::DAMAGE_SPELL::COUP_DE_GRACE_DAMAGE_3,
83 crate::generated::specs::subtlety_rogue::DAMAGE_EFFECT::CDG_DAMAGE_3,
84 ),
85 ];
86 let bonuses = [
87 (crate::generated::specs::subtlety_rogue::DAMAGE_REPORTED::CDG_BONUS_1, crate::generated::specs::subtlety_rogue::DAMAGE_EFFECT::CDG_BONUS_1),
88 (crate::generated::specs::subtlety_rogue::DAMAGE_REPORTED::CDG_BONUS_2, crate::generated::specs::subtlety_rogue::DAMAGE_EFFECT::CDG_BONUS_2),
89 (crate::generated::specs::subtlety_rogue::DAMAGE_REPORTED::CDG_BONUS_3, crate::generated::specs::subtlety_rogue::DAMAGE_EFFECT::CDG_BONUS_3),
90 ];
91
92 for (i, (spell, eff)) in hits.into_iter().enumerate() {
93 let coef = ctx.effect_ap_coefficient(eff);
94
95 ctx.deal_damage_ap(spell, coef * cdg_cp, DamageFlags::PHYSICAL);
96
97 if fw_active && cfg.shadowed_finishers_pct > 0.0 {
98 let (bonus_id, bonus_effect) = bonuses[i];
100 let bonus_coef = ctx.effect_ap_coefficient(bonus_effect);
101
102 ctx.deal_damage_ap(
103 bonus_id,
104 bonus_coef * cfg.shadowed_finishers_pct * cdg_cp,
105 DamageFlags::empty(),
106 );
107 }
108 }
109
110 ctx.expire_aura(AURA_ESCALATING_BLADE);
111
112 if cfg.flawless_form && ctx.is_aura_active(AURA_FAZED) {
113 ctx.apply_aura_n(AURA_FLAWLESS_FORM, cfg.cdg_flawless_stacks);
114 }
115}