wowlab_engine_combat/systems/
procs.rs1use wowlab_engine_domain::rotation::DenseBuffer;
4use wowlab_engine_telemetry::{
5 RESOURCE_SOURCE_AUTO_ATTACK, ResourceEvent, ResourceEventKind, ResourceObservation,
6 ResourceValues, TelemetrySink,
7};
8use wowlab_types::{combat::ResourceType, sim::SimTime};
9
10use super::{EffectExecution, execute_proc_effect_range_for_actor};
11use crate::{
12 context::{CombatCtx, HookCtx},
13 state::{
14 AuraApplicationEvent, CombatState, ImpactActorFilter, ImpactChanceScale, ImpactEffectProc,
15 ImpactEffectRngState, ImpactEvent, ImpactProc, ImpactSource, ProcDriver, ProcEventKind,
16 ProcHitMask, ProcPhaseMask, ProcSourceKind, ProcTriggerSide, ResourceGain,
17 ResourceGainEvent, ResourceGainProcAttempts, ScratchDisposition, with_scratch,
18 },
19};
20
21const RANDOM_CONTRIBUTION_RANGE_MULTIPLIER: f64 = 2.0;
22
23#[derive(Clone, Copy)]
24enum PeriodicImpactFilter {
25 Any,
26 Only,
27 Exclude,
28 Never,
29}
30
31#[derive(Clone, Copy)]
32struct PeriodicImpactPolicy {
33 periodic_only: bool,
34 skip_periodic: bool,
35}
36
37impl PeriodicImpactFilter {
38 const fn matches(self, is_periodic: bool) -> bool {
39 match self {
40 Self::Any => true,
41 Self::Only => is_periodic,
42 Self::Exclude => !is_periodic,
43 Self::Never => false,
44 }
45 }
46}
47
48impl From<PeriodicImpactPolicy> for PeriodicImpactFilter {
49 fn from(policy: PeriodicImpactPolicy) -> Self {
50 match (policy.periodic_only, policy.skip_periodic) {
51 (false, false) => Self::Any,
52 (true, false) => Self::Only,
53 (false, true) => Self::Exclude,
54 (true, true) => Self::Never,
55 }
56 }
57}
58
59#[derive(Clone, Copy)]
60struct ImpactFilter {
61 actor: ImpactActorFilter,
62 spell: Option<fn(u32) -> bool>,
63 periodic: PeriodicImpactFilter,
64 physical_only: bool,
65 crit_only: bool,
66}
67
68#[derive(Clone, Copy)]
69pub(crate) struct ResourceTelemetry {
70 pub(crate) kind: ResourceEventKind,
71 pub(crate) amount: f64,
72 pub(crate) secondary: bool,
73 pub(crate) now: SimTime,
74 pub(crate) source_spell_id: u32,
75}
76
77mod accumulating;
78mod impact;
79mod impact_effect;
80mod phase;
81mod resource_gain;
82
83#[cfg(test)]
84use accumulating::advance_threshold_accumulator;
85use accumulating::fire_accumulating_impact_procs;
86pub(crate) use impact::{
87 attempt_weapon_enchants, fire_aura_application_procs, fire_impact_procs,
88 fire_landed_impact_batch, weapon_enchants_on_player_impact,
89};
90use impact::{impact_filter_matches, proc_policy_allows};
91pub(super) use impact_effect::effective_proc_charges;
92use impact_effect::fire_impact_effect_procs;
93use phase::proc_type_mask_matches;
94pub(crate) use phase::{
95 fire_dispel_procs, fire_heartbeat_procs, fire_kill_procs, fire_spell_phase_procs,
96};
97#[cfg(test)]
98use resource_gain::fire_resource_gain_procs;
99pub(crate) use resource_gain::{
100 emit_resource, gain_hook_resource_with_procs, gain_resource_with_procs,
101};
102
103#[cfg(test)]
104#[path = "procs/tests.rs"]
105mod tests;