wowlab_engine_combat/state/
aura_state.rs1use wowlab_types::sim::{ActorId, SimTime};
2
3use super::CombatInstance;
4
5#[rustfmt::skip]
6pub(crate) use wowlab_engine_domain::dbc::AuraState;
7
8const WOUNDED_20_THRESHOLD: f64 = 0.20;
9const WOUNDED_25_THRESHOLD: f64 = 0.25;
10const WOUNDED_35_THRESHOLD: f64 = 0.35;
11const WOUNDED_50_THRESHOLD: f64 = 0.50;
12const HEALTHY_75_THRESHOLD: f64 = 0.75;
13const HEALTHY_80_THRESHOLD: f64 = 0.80;
14
15impl CombatInstance {
16 #[must_use]
18 pub fn has_aura_state(
19 &self,
20 program: &crate::state::CombatProgram,
21 actor: ActorId,
22 required: AuraState,
23 now: SimTime,
24 ) -> bool {
25 let health = self.actor_health_fraction(program, actor, now);
26 let health_state = match required {
27 AuraState::Wounded20 => health.is_some_and(|value| value < WOUNDED_20_THRESHOLD),
28 AuraState::Wounded25 => health.is_some_and(|value| value < WOUNDED_25_THRESHOLD),
29 AuraState::Wounded35 => health.is_some_and(|value| value < WOUNDED_35_THRESHOLD),
30 AuraState::Wounded50 => health.is_some_and(|value| value < WOUNDED_50_THRESHOLD),
31 AuraState::Healthy75 => health.is_some_and(|value| value > HEALTHY_75_THRESHOLD),
32 AuraState::WoundHealth20OrAbove80 => health.is_some_and(|value| {
33 !(WOUNDED_20_THRESHOLD..=HEALTHY_80_THRESHOLD).contains(&value)
34 }),
35 AuraState::WoundHealth35OrAbove80 => health.is_some_and(|value| {
36 !(WOUNDED_35_THRESHOLD..=HEALTHY_80_THRESHOLD).contains(&value)
37 }),
38 _ => false,
39 };
40
41 if health_state {
42 return true;
43 }
44
45 program
46 .effects
47 .aura_state_auras(actor, required)
48 .iter()
49 .any(|entry| {
50 self.buffer
51 .aura_at(entry.handle)
52 .is_active(now.as_secs_f64())
53 })
54 }
55}
56
57#[cfg(test)]
58mod tests;