1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
macro_rules! impl_mods {
    ($func_name:ident, $const_name:ident) => {
        #[inline]
        fn $func_name(self) -> bool {
            self & Self::$const_name > 0
        }
    };
}

/// Abstract type to define mods.
#[allow(missing_docs)]
pub trait Mods: Copy {
    const NF: u32 = 1 << 0;
    const EZ: u32 = 1 << 1;
    const TD: u32 = 1 << 2;
    const HD: u32 = 1 << 3;
    const HR: u32 = 1 << 4;
    const DT: u32 = 1 << 6;
    const RX: u32 = 1 << 7;
    const HT: u32 = 1 << 8;
    const FL: u32 = 1 << 10;
    const SO: u32 = 1 << 12;

    /// If the clock rate is affected by the mods.
    fn change_speed(self) -> bool;
    /// If object time's or positions are affected by the mods.
    fn change_map(self) -> bool;
    /// The clock rate with the mods.
    fn speed(self) -> f64;
    /// Multiplier for beatmap attributes with respect to the mods.
    fn od_ar_hp_multiplier(self) -> f64;
    fn nf(self) -> bool;
    fn ez(self) -> bool;
    fn td(self) -> bool;
    fn hd(self) -> bool;
    fn hr(self) -> bool;
    fn dt(self) -> bool;
    fn rx(self) -> bool;
    fn ht(self) -> bool;
    fn fl(self) -> bool;
    fn so(self) -> bool;
}

impl Mods for u32 {
    #[inline]
    fn change_speed(self) -> bool {
        self & (Self::HT | Self::DT) > 0
    }

    #[inline]
    fn change_map(self) -> bool {
        self & (Self::HT | Self::DT | Self::HR | Self::EZ) > 0
    }

    #[inline]
    fn speed(self) -> f64 {
        if self & Self::DT > 0 {
            1.5
        } else if self & Self::HT > 0 {
            0.75
        } else {
            1.0
        }
    }

    #[inline]
    fn od_ar_hp_multiplier(self) -> f64 {
        if self & Self::HR > 0 {
            1.4
        } else if self & Self::EZ > 0 {
            0.5
        } else {
            1.0
        }
    }

    impl_mods!(nf, NF);
    impl_mods!(ez, EZ);
    impl_mods!(td, TD);
    impl_mods!(hd, HD);
    impl_mods!(hr, HR);
    impl_mods!(dt, DT);
    impl_mods!(rx, RX);
    impl_mods!(ht, HT);
    impl_mods!(fl, FL);
    impl_mods!(so, SO);
}