wowlab_engine_content/hooks/assassination_rogue/
poisons.rs1use wowlab_engine_combat::DamageOps as _;
2use wowlab_engine_combat::ResourceOps as _;
3use wowlab_engine_combat::AuraOps as _;
4use wowlab_engine_combat::{DamageFlags, HookCtx};
5use wowlab_engine_domain::dbc::ResolvedGameDataEffectExt as _;
6use wowlab_engine_rng::proc_chance;
7use wowlab_types::{constants::HUNDRED, sim::SpellIdx};
8
9use crate::generated::specs::assassination_rogue::{
10 AURA, AURA_AMPLIFYING_POISON_DEBUFF, AURA_DEADLY_POISON_DOT, AURA_DEATHMARK, AURA_ENVENOM,
11 AURA_KINGSBANE, AURA_KINGSBANE_RAMP, EFFECT, SPELL,
12};
13
14use super::config::sin_config;
15
16pub(super) fn proc_poisons(ctx: &mut HookCtx<'_>) {
17 let cfg = sin_config(ctx);
18 let envenom_bonus = if ctx.is_aura_active(AURA_ENVENOM.raw()) {
19 cfg.envenom_poison_bonus
20 } else {
21 0.0
22 };
23 let deadly_chance = ctx
24 .game_data()
25 .proc_chance_with_flat_bonus(SpellIdx::from_raw(AURA::DEADLY_POISON), envenom_bonus)
26 .unwrap_or(0.0);
27
28 if cfg.has_deadly_poison && proc_chance(ctx.rng(), deadly_chance) {
29 deal_deadly_poison(ctx);
30 }
31
32 let amplifying_chance = ctx
33 .game_data()
34 .proc_chance_with_flat_bonus(SpellIdx::from_raw(AURA::AMPLIFYING_POISON), envenom_bonus)
35 .unwrap_or(0.0);
36
37 if cfg.has_amplifying_poison && proc_chance(ctx.rng(), amplifying_chance) {
38 deal_amplifying_poison(ctx);
39 }
40}
41
42const DEATHMARK_LETHAL_EXECUTIONS: u32 = 2;
44
45fn lethal_executions(ctx: &HookCtx<'_>) -> u32 {
46 if ctx.is_aura_active(AURA_DEATHMARK.raw()) {
47 DEATHMARK_LETHAL_EXECUTIONS
48 } else {
49 1
50 }
51}
52
53fn ramp_kingsbane(ctx: &mut HookCtx<'_>) {
54 if ctx.is_aura_active(AURA_KINGSBANE.raw()) {
55 ctx.apply_aura(AURA_KINGSBANE_RAMP.raw());
56 }
57}
58
59pub(super) fn deal_deadly_poison(ctx: &mut HookCtx<'_>) {
60 for _ in 0..lethal_executions(ctx) {
61 if ctx.is_aura_active(AURA_DEADLY_POISON_DOT.raw()) {
62 let coef = ctx
63 .game_data()
64 .effect_ap_coefficient(EFFECT::DEADLY_POISON_INSTANT_DMG);
65
66 ctx.deal_damage_ap(SPELL::DEADLY_POISON_INSTANT, coef, DamageFlags::empty());
67 dashing_scoundrel(ctx);
68 }
69
70 ctx.apply_aura(AURA_DEADLY_POISON_DOT.raw());
71 ramp_kingsbane(ctx);
72 }
73}
74
75pub(super) fn deal_amplifying_poison(ctx: &mut HookCtx<'_>) {
76 let coef = ctx
77 .game_data()
78 .effect_ap_coefficient(EFFECT::AMPLIFYING_POISON_DMG);
79
80 for _ in 0..lethal_executions(ctx) {
81 ctx.deal_damage_ap(EFFECT::AMPLIFYING_POISON_DMG.0, coef, DamageFlags::empty());
82 ctx.apply_aura(AURA_AMPLIFYING_POISON_DEBUFF.raw());
83 ramp_kingsbane(ctx);
84 dashing_scoundrel(ctx);
85 }
86}
87
88fn dashing_scoundrel(ctx: &mut HookCtx<'_>) {
90 let cfg = sin_config(ctx);
91
92 if cfg.dashing_scoundrel_energy <= 0.0 || !ctx.is_aura_active(AURA_ENVENOM.raw()) {
93 return;
94 }
95
96 let crit = ctx.buf().player().crit / HUNDRED;
97
98 if proc_chance(ctx.rng(), crit) {
99 ctx.gain_resource(cfg.dashing_scoundrel_energy);
100 }
101}
102
103pub(super) fn seal_fate(ctx: &mut HookCtx<'_>) {
105 let cfg = sin_config(ctx);
106
107 if cfg.seal_fate_chance <= 0.0 {
108 return;
109 }
110
111 let crit = ctx.buf().player().crit / HUNDRED;
112
113 if !proc_chance(ctx.rng(), crit * cfg.seal_fate_chance) {
114 return;
115 }
116
117 ctx.gain_secondary_resource(cfg.seal_fate_cp);
118
119 if cfg.deal_fate_cp > 0.0 {
120 ctx.gain_secondary_resource(cfg.deal_fate_cp);
121 }
122}