quaver_rs/enums/
mod_identifier.rs

1use bitflags::bitflags;
2
3bitflags! {
4    #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
5    pub struct ModIdentifier: u64 {
6        const NONE = 1 << 63; // -1L in C# becomes 1 << 63
7        const NO_SLIDER_VELOCITY = 1 << 0; // No Slider Velocity
8        const SPEED_05X = 1 << 1; // Speed 0.5x
9        const SPEED_06X = 1 << 2; // Speed 0.6x
10        const SPEED_07X = 1 << 3; // Speed 0.7x
11        const SPEED_08X = 1 << 4; // Speed 0.8x
12        const SPEED_09X = 1 << 5; // Speed 0.9x
13        const SPEED_11X = 1 << 6; // Speed 1.1x
14        const SPEED_12X = 1 << 7; // Speed 1.2x
15        const SPEED_13X = 1 << 8; // Speed 1.3x
16        const SPEED_14X = 1 << 9; // Speed 1.4x
17        const SPEED_15X = 1 << 10; // Speed 1.5x
18        const SPEED_16X = 1 << 11; // Speed 1.6x
19        const SPEED_17X = 1 << 12; // Speed 1.7x
20        const SPEED_18X = 1 << 13; // Speed 1.8x
21        const SPEED_19X = 1 << 14; // Speed 1.9x
22        const SPEED_20X = 1 << 15; // Speed 2.0x
23        const STRICT = 1 << 16; // Makes the accuracy hit windows harder
24        const CHILL = 1 << 17; // Makes the accuracy hit windows easier
25        const NO_PAUSE = 1 << 18; // Disallows pausing
26        const AUTOPLAY = 1 << 19; // The game automatically plays it
27        const PAUSED = 1 << 20; // The user paused during gameplay
28        const NO_FAIL = 1 << 21; // Unable to fail during gameplay
29        const NO_LONG_NOTES = 1 << 22; // Converts LNs into regular notes
30        const RANDOMIZE = 1 << 23; // Randomizes the playfield's lanes
31        const SPEED_055X = 1 << 24; // Speed 0.55x
32        const SPEED_065X = 1 << 25; // Speed 0.65x
33        const SPEED_075X = 1 << 26; // Speed 0.75x
34        const SPEED_085X = 1 << 27; // Speed 0.85x
35        const SPEED_095X = 1 << 28; // Speed 0.95x
36        const INVERSE = 1 << 29; // Converts regular notes into LNs and LNs into gaps
37        const FULL_LN = 1 << 30; // Converts regular notes into LNs, keeps existing LNs
38        const MIRROR = 1 << 31; // Flips the map horizontally
39        const COOP = 1 << 32; // Allows multiple people to play together on one client
40        const SPEED_105X = 1 << 33; // Speed 1.05x
41        const SPEED_115X = 1 << 34; // Speed 1.15x
42        const SPEED_125X = 1 << 35; // Speed 1.25x
43        const SPEED_135X = 1 << 36; // Speed 1.35x
44        const SPEED_145X = 1 << 37; // Speed 1.45x
45        const SPEED_155X = 1 << 38; // Speed 1.55x
46        const SPEED_165X = 1 << 39; // Speed 1.65x
47        const SPEED_175X = 1 << 40; // Speed 1.75x
48        const SPEED_185X = 1 << 41; // Speed 1.85x
49        const SPEED_195X = 1 << 42; // Speed 1.95x
50        const HEALTH_ADJUST = 1 << 43; // Test mod for making long note windows easier
51        const NO_MISS = 1 << 44; // You miss, you die
52    }
53}
54
55impl ModIdentifier {
56    /// Get the audio rate from selected mods
57    pub fn get_rate_from_mods(&self) -> f32 {
58        if self.contains(ModIdentifier::NONE) {
59            return 1.0;
60        }
61
62        if self.contains(ModIdentifier::SPEED_05X) { 0.5 }
63        else if self.contains(ModIdentifier::SPEED_055X) { 0.55 }
64        else if self.contains(ModIdentifier::SPEED_06X) { 0.6 }
65        else if self.contains(ModIdentifier::SPEED_065X) { 0.65 }
66        else if self.contains(ModIdentifier::SPEED_07X) { 0.7 }
67        else if self.contains(ModIdentifier::SPEED_075X) { 0.75 }
68        else if self.contains(ModIdentifier::SPEED_08X) { 0.8 }
69        else if self.contains(ModIdentifier::SPEED_085X) { 0.85 }
70        else if self.contains(ModIdentifier::SPEED_09X) { 0.9 }
71        else if self.contains(ModIdentifier::SPEED_095X) { 0.95 }
72        else if self.contains(ModIdentifier::SPEED_105X) { 1.05 }
73        else if self.contains(ModIdentifier::SPEED_11X) { 1.1 }
74        else if self.contains(ModIdentifier::SPEED_115X) { 1.15 }
75        else if self.contains(ModIdentifier::SPEED_12X) { 1.2 }
76        else if self.contains(ModIdentifier::SPEED_125X) { 1.25 }
77        else if self.contains(ModIdentifier::SPEED_13X) { 1.3 }
78        else if self.contains(ModIdentifier::SPEED_135X) { 1.35 }
79        else if self.contains(ModIdentifier::SPEED_14X) { 1.4 }
80        else if self.contains(ModIdentifier::SPEED_145X) { 1.45 }
81        else if self.contains(ModIdentifier::SPEED_15X) { 1.5 }
82        else if self.contains(ModIdentifier::SPEED_155X) { 1.55 }
83        else if self.contains(ModIdentifier::SPEED_16X) { 1.6 }
84        else if self.contains(ModIdentifier::SPEED_165X) { 1.65 }
85        else if self.contains(ModIdentifier::SPEED_17X) { 1.7 }
86        else if self.contains(ModIdentifier::SPEED_175X) { 1.75 }
87        else if self.contains(ModIdentifier::SPEED_18X) { 1.8 }
88        else if self.contains(ModIdentifier::SPEED_185X) { 1.85 }
89        else if self.contains(ModIdentifier::SPEED_19X) { 1.9 }
90        else if self.contains(ModIdentifier::SPEED_195X) { 1.95 }
91        else if self.contains(ModIdentifier::SPEED_20X) { 2.0 }
92        else { 1.0 }
93    }
94
95    /// Get mods from a given rate
96    pub fn from_rate(rate: f32) -> ModIdentifier {
97        match rate {
98            0.5 => ModIdentifier::SPEED_05X,
99            0.55 => ModIdentifier::SPEED_055X,
100            0.6 => ModIdentifier::SPEED_06X,
101            0.65 => ModIdentifier::SPEED_065X,
102            0.7 => ModIdentifier::SPEED_07X,
103            0.75 => ModIdentifier::SPEED_075X,
104            0.8 => ModIdentifier::SPEED_08X,
105            0.85 => ModIdentifier::SPEED_085X,
106            0.9 => ModIdentifier::SPEED_09X,
107            0.95 => ModIdentifier::SPEED_095X,
108            1.05 => ModIdentifier::SPEED_105X,
109            1.1 => ModIdentifier::SPEED_11X,
110            1.15 => ModIdentifier::SPEED_115X,
111            1.2 => ModIdentifier::SPEED_12X,
112            1.25 => ModIdentifier::SPEED_125X,
113            1.3 => ModIdentifier::SPEED_13X,
114            1.35 => ModIdentifier::SPEED_135X,
115            1.4 => ModIdentifier::SPEED_14X,
116            1.45 => ModIdentifier::SPEED_145X,
117            1.5 => ModIdentifier::SPEED_15X,
118            1.55 => ModIdentifier::SPEED_155X,
119            1.6 => ModIdentifier::SPEED_16X,
120            1.65 => ModIdentifier::SPEED_165X,
121            1.7 => ModIdentifier::SPEED_17X,
122            1.75 => ModIdentifier::SPEED_175X,
123            1.8 => ModIdentifier::SPEED_18X,
124            1.85 => ModIdentifier::SPEED_185X,
125            1.9 => ModIdentifier::SPEED_19X,
126            1.95 => ModIdentifier::SPEED_195X,
127            2.0 => ModIdentifier::SPEED_20X,
128            _ => ModIdentifier::NONE,
129        }
130    }
131
132    /// Get mods string representation
133    pub fn to_string(&self) -> String {
134        if self.is_empty() || self.contains(ModIdentifier::NONE) {
135            return "None".to_string();
136        }
137
138        let mut mod_strings = Vec::new();
139
140        // Speed mods (insert at beginning)
141        if self.contains(ModIdentifier::SPEED_05X) { mod_strings.insert(0, "0.5x".to_string()); }
142        if self.contains(ModIdentifier::SPEED_055X) { mod_strings.insert(0, "0.55x".to_string()); }
143        if self.contains(ModIdentifier::SPEED_06X) { mod_strings.insert(0, "0.6x".to_string()); }
144        if self.contains(ModIdentifier::SPEED_065X) { mod_strings.insert(0, "0.65x".to_string()); }
145        if self.contains(ModIdentifier::SPEED_07X) { mod_strings.insert(0, "0.7x".to_string()); }
146        if self.contains(ModIdentifier::SPEED_075X) { mod_strings.insert(0, "0.75x".to_string()); }
147        if self.contains(ModIdentifier::SPEED_08X) { mod_strings.insert(0, "0.8x".to_string()); }
148        if self.contains(ModIdentifier::SPEED_085X) { mod_strings.insert(0, "0.85x".to_string()); }
149        if self.contains(ModIdentifier::SPEED_09X) { mod_strings.insert(0, "0.9x".to_string()); }
150        if self.contains(ModIdentifier::SPEED_095X) { mod_strings.insert(0, "0.95x".to_string()); }
151        if self.contains(ModIdentifier::SPEED_105X) { mod_strings.insert(0, "1.05x".to_string()); }
152        if self.contains(ModIdentifier::SPEED_11X) { mod_strings.insert(0, "1.1x".to_string()); }
153        if self.contains(ModIdentifier::SPEED_115X) { mod_strings.insert(0, "1.15x".to_string()); }
154        if self.contains(ModIdentifier::SPEED_12X) { mod_strings.insert(0, "1.2x".to_string()); }
155        if self.contains(ModIdentifier::SPEED_125X) { mod_strings.insert(0, "1.25x".to_string()); }
156        if self.contains(ModIdentifier::SPEED_13X) { mod_strings.insert(0, "1.3x".to_string()); }
157        if self.contains(ModIdentifier::SPEED_135X) { mod_strings.insert(0, "1.35x".to_string()); }
158        if self.contains(ModIdentifier::SPEED_14X) { mod_strings.insert(0, "1.4x".to_string()); }
159        if self.contains(ModIdentifier::SPEED_145X) { mod_strings.insert(0, "1.45x".to_string()); }
160        if self.contains(ModIdentifier::SPEED_15X) { mod_strings.insert(0, "1.5x".to_string()); }
161        if self.contains(ModIdentifier::SPEED_155X) { mod_strings.insert(0, "1.55x".to_string()); }
162        if self.contains(ModIdentifier::SPEED_16X) { mod_strings.insert(0, "1.6x".to_string()); }
163        if self.contains(ModIdentifier::SPEED_165X) { mod_strings.insert(0, "1.65x".to_string()); }
164        if self.contains(ModIdentifier::SPEED_17X) { mod_strings.insert(0, "1.7x".to_string()); }
165        if self.contains(ModIdentifier::SPEED_175X) { mod_strings.insert(0, "1.75x".to_string()); }
166        if self.contains(ModIdentifier::SPEED_18X) { mod_strings.insert(0, "1.8x".to_string()); }
167        if self.contains(ModIdentifier::SPEED_185X) { mod_strings.insert(0, "1.85x".to_string()); }
168        if self.contains(ModIdentifier::SPEED_19X) { mod_strings.insert(0, "1.9x".to_string()); }
169        if self.contains(ModIdentifier::SPEED_195X) { mod_strings.insert(0, "1.95x".to_string()); }
170        if self.contains(ModIdentifier::SPEED_20X) { mod_strings.insert(0, "2.0x".to_string()); }
171
172        // Other mods
173        if self.contains(ModIdentifier::NO_SLIDER_VELOCITY) { mod_strings.push("NSV".to_string()); }
174        if self.contains(ModIdentifier::STRICT) { mod_strings.push("ST".to_string()); }
175        if self.contains(ModIdentifier::CHILL) { mod_strings.push("CH".to_string()); }
176        if self.contains(ModIdentifier::NO_PAUSE) { mod_strings.push("NP".to_string()); }
177        if self.contains(ModIdentifier::AUTOPLAY) { mod_strings.push("AP".to_string()); }
178        if self.contains(ModIdentifier::PAUSED) { mod_strings.push("PS".to_string()); }
179        if self.contains(ModIdentifier::NO_FAIL) { mod_strings.push("NF".to_string()); }
180        if self.contains(ModIdentifier::NO_LONG_NOTES) { mod_strings.push("NLN".to_string()); }
181        if self.contains(ModIdentifier::RANDOMIZE) { mod_strings.push("RND".to_string()); }
182        if self.contains(ModIdentifier::INVERSE) { mod_strings.push("INV".to_string()); }
183        if self.contains(ModIdentifier::FULL_LN) { mod_strings.push("FLN".to_string()); }
184        if self.contains(ModIdentifier::MIRROR) { mod_strings.push("MR".to_string()); }
185        if self.contains(ModIdentifier::COOP) { mod_strings.push("Co-op".to_string()); }
186        if self.contains(ModIdentifier::HEALTH_ADJUST) { mod_strings.push("HPA".to_string()); }
187        if self.contains(ModIdentifier::NO_MISS) { mod_strings.push("NM".to_string()); }
188
189        mod_strings.join(", ")
190    }
191}