Skip to main content

wowlab_engine_combat/systems/periodic/
snapshot.rs

1use super::{
2    ActorId, AuraData, AuraKey, CombatInstance, DamageSnapshot, DynamicTickAction, SimTime,
3    capture_snapshot_for, read_aura_snapshot,
4};
5use crate::state::LocalAuraIdx;
6
7// #t(fn: rust_large_fn_params) periodic snapshots require the finalized aura identity, damage identity, and explicit lifecycle borrows.
8pub(super) fn periodic_damage_snapshot(
9    program: &crate::state::CombatProgram,
10    state: &CombatInstance,
11    aura: &AuraData,
12    local: LocalAuraIdx,
13    key: AuraKey,
14    now: SimTime,
15) -> Option<DamageSnapshot> {
16    let binding = program.damage.periodic_request(local)?;
17
18    match aura.dynamic_tick_action {
19        DynamicTickAction::Update => {
20            let mut live = capture_live_tick_snapshot(program, state, key, binding, now);
21
22            // Dynamic updates leave the application-persistent multiplier frozen. It is stored on
23            // the aura slot by
24            // refresh_aura_snapshot_multiplier, while power, crit, versatility, mastery,
25            // and ordinary damage modifiers remain live.
26
27            if let Some(persistent) = application_persistent_multiplier(program, state, local, key)
28            {
29                live.damage_mult *= persistent;
30            }
31
32            return Some(live);
33        }
34        DynamicTickAction::Snapshot => {
35            // Snapshots capture the application-persistent multiplier, so none is carried
36            // separately from the parent aura state.
37            return Some(capture_live_tick_snapshot(
38                program, state, key, binding, now,
39            ));
40        }
41        DynamicTickAction::None if aura.is_snapshot => {
42            return read_aura_snapshot(program, state, local, key);
43        }
44        DynamicTickAction::None => {}
45    }
46
47    let persistent_multiplier = application_persistent_multiplier(program, state, local, key)?;
48    let mut live = capture_live_tick_snapshot(program, state, key, binding, now);
49
50    live.damage_mult *= persistent_multiplier;
51
52    Some(live)
53}
54
55fn capture_live_tick_snapshot(
56    program: &crate::state::CombatProgram,
57    state: &CombatInstance,
58    key: AuraKey,
59    binding: crate::state::program::PeriodicDamageBinding,
60    now: SimTime,
61) -> DamageSnapshot {
62    let target = match key.affected() {
63        ActorId::Enemy(target) => Some(target),
64        _ => None,
65    };
66
67    capture_snapshot_for(program, state, binding, key.source(), target, now)
68}
69
70fn application_persistent_multiplier(
71    program: &crate::state::CombatProgram,
72    state: &CombatInstance,
73    local: LocalAuraIdx,
74    key: AuraKey,
75) -> Option<f64> {
76    program
77        .buffer_aura(state, local, key)
78        .filter(|slot| slot.snapshot_has != 0)
79        .map(|slot| slot.snapshot_damage_mult)
80}