wowlab_engine_domain/rotation/buffer/
cooldown.rs1wowlab_engine_macros::define_slot! {
2 #[slot(domain = "cooldown", kind = keyed, key_domain = "spell")]
3 pub struct CooldownSlot {
4 #[expr("remaining", Float, TimestampRemaining)]
5 #[expr("is_ready", Float, CooldownReady)]
6 #[expr("full_recharge_time", Float, CooldownFullRecharge)]
7 pub ready_at: f64,
8
9 #[expr("duration", Float, Direct)]
10 pub duration: f64,
11
12 #[expr("charges", Int, Direct)]
13 pub current_charges: i32,
14
15 #[expr("charges_max", Int, Direct)]
16 pub max_charges: i32,
17
18 #[expr("charges_fractional", Float, TimestampRemaining)]
19 pub next_charge_at: f64,
20
21 #[expr("recharge_time", Float, Direct)]
22 pub recharge_time: f64,
23 }
24
25 impl {
26 #[inline]
27 #[must_use]
28 pub fn is_ready(&self, now: f64) -> bool {
29 crate::rotation::lower::ops::eval_cooldown_ready(
30 &mut crate::rotation::lower::ops::ScalarEvalOps,
31 self.ready_at,
32 self.current_charges,
33 self.max_charges,
34 now,
35 false,
36 )
37 }
38 }
39}
40
41#[cfg(test)]
42mod tests {
43 use googletest::prelude::*;
44 use rstest::rstest;
45
46 use super::*;
47
48 #[gtest]
49 #[rstest]
50 #[case(1, 0, 12.0, false)]
51 #[case(1, 0, 8.0, true)]
52 #[case(2, 1, 999.0, true)]
53 #[case(2, 1, 8.0, true)]
54 #[case(2, 0, 999.0, false)]
55 fn is_ready_covers_time_and_charge_branches(
56 #[case] max_charges: i32,
57 #[case] current_charges: i32,
58 #[case] ready_at: f64,
59 #[case] expected: bool,
60 ) -> Result<()> {
61 let slot = CooldownSlot {
62 ready_at,
63 current_charges,
64 max_charges,
65 ..Default::default()
66 };
67
68 verify_that!(slot.is_ready(10.0), eq(expected))
69 }
70}