osu: handle maps without objects
This commit is contained in:
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
## Upcoming
|
## Upcoming
|
||||||
|
|
||||||
- Nothing as of now
|
- osu: Fix panic on maps with 0 objects
|
||||||
|
|
||||||
# v0.4.0
|
# v0.4.0
|
||||||
|
|
||||||
|
|||||||
+10
-2
@@ -83,7 +83,11 @@ pub fn stars(
|
|||||||
0.0
|
0.0
|
||||||
};
|
};
|
||||||
|
|
||||||
let star_rating = calculate_star_rating(aim_rating, speed_rating, flashlight_rating);
|
let star_rating = if attributes.max_combo == 0 {
|
||||||
|
0.0
|
||||||
|
} else {
|
||||||
|
calculate_star_rating(aim_rating, speed_rating, flashlight_rating)
|
||||||
|
};
|
||||||
|
|
||||||
attributes.aim_strain = aim_rating;
|
attributes.aim_strain = aim_rating;
|
||||||
attributes.speed_strain = speed_rating;
|
attributes.speed_strain = speed_rating;
|
||||||
@@ -284,7 +288,11 @@ fn calculate_skills(
|
|||||||
|
|
||||||
fn stacking(hit_objects: &mut [OsuObject], stack_threshold: f64) {
|
fn stacking(hit_objects: &mut [OsuObject], stack_threshold: f64) {
|
||||||
let mut extended_start_idx = 0;
|
let mut extended_start_idx = 0;
|
||||||
let extended_end_idx = hit_objects.len() - 1;
|
|
||||||
|
let extended_end_idx = match hit_objects.len().checked_sub(1) {
|
||||||
|
Some(idx) => idx,
|
||||||
|
None => return,
|
||||||
|
};
|
||||||
|
|
||||||
// First big `if` in osu!lazer's function can be skipped
|
// First big `if` in osu!lazer's function can be skipped
|
||||||
|
|
||||||
|
|||||||
+36
-29
@@ -337,41 +337,48 @@ struct OsuPPInner {
|
|||||||
|
|
||||||
impl OsuPPInner {
|
impl OsuPPInner {
|
||||||
fn calculate(mut self) -> OsuPerformanceAttributes {
|
fn calculate(mut self) -> OsuPerformanceAttributes {
|
||||||
let mut multiplier = 1.12;
|
let (aim_value, speed_value, acc_value, flashlight_value, pp) =
|
||||||
|
if self.total_hits.abs() <= f64::EPSILON {
|
||||||
|
(0.0, 0.0, 0.0, 0.0, 0.0)
|
||||||
|
} else {
|
||||||
|
let mut multiplier = 1.12;
|
||||||
|
|
||||||
// NF penalty
|
// NF penalty
|
||||||
if self.mods.nf() {
|
if self.mods.nf() {
|
||||||
multiplier *= (1.0 - 0.02 * (self.effective_misses as f64)).max(0.9);
|
multiplier *= (1.0 - 0.02 * (self.effective_misses as f64)).max(0.9);
|
||||||
}
|
}
|
||||||
|
|
||||||
// SO penalty
|
// SO penalty
|
||||||
if self.mods.so() {
|
if self.mods.so() {
|
||||||
let n_spinners = self.attributes.n_spinners;
|
let n_spinners = self.attributes.n_spinners;
|
||||||
multiplier *= 1.0 - (n_spinners as f64 / self.total_hits).powf(0.85);
|
multiplier *= 1.0 - (n_spinners as f64 / self.total_hits).powf(0.85);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Relax penalty
|
// Relax penalty
|
||||||
if self.mods.rx() {
|
if self.mods.rx() {
|
||||||
// * As we're adding 100s and 50s to an approximated number of combo breaks\
|
// * As we're adding 100s and 50s to an approximated number of combo breaks\
|
||||||
// * the result can be higher than total hits in specific scenarios
|
// * the result can be higher than total hits in specific scenarios
|
||||||
// * (which breaks some calculations) so we need to clamp it.
|
// * (which breaks some calculations) so we need to clamp it.
|
||||||
self.effective_misses =
|
self.effective_misses = (self.effective_misses + self.n100 + self.n50)
|
||||||
(self.effective_misses + self.n100 + self.n50).min(self.total_hits as usize);
|
.min(self.total_hits as usize);
|
||||||
|
|
||||||
multiplier *= 0.6;
|
multiplier *= 0.6;
|
||||||
}
|
}
|
||||||
|
|
||||||
let aim_value = self.compute_aim_value();
|
let aim_value = self.compute_aim_value();
|
||||||
let speed_value = self.compute_speed_value();
|
let speed_value = self.compute_speed_value();
|
||||||
let acc_value = self.compute_accuracy_value();
|
let acc_value = self.compute_accuracy_value();
|
||||||
let flashlight_value = self.compute_flashlight_value();
|
let flashlight_value = self.compute_flashlight_value();
|
||||||
|
|
||||||
let pp = (aim_value.powf(1.1)
|
let pp = (aim_value.powf(1.1)
|
||||||
+ speed_value.powf(1.1)
|
+ speed_value.powf(1.1)
|
||||||
+ acc_value.powf(1.1)
|
+ acc_value.powf(1.1)
|
||||||
+ flashlight_value.powf(1.1))
|
+ flashlight_value.powf(1.1))
|
||||||
.powf(1.0 / 1.1)
|
.powf(1.0 / 1.1)
|
||||||
* multiplier;
|
* multiplier;
|
||||||
|
|
||||||
|
(aim_value, speed_value, acc_value, flashlight_value, pp)
|
||||||
|
};
|
||||||
|
|
||||||
OsuPerformanceAttributes {
|
OsuPerformanceAttributes {
|
||||||
difficulty: self.attributes,
|
difficulty: self.attributes,
|
||||||
|
|||||||
Reference in New Issue
Block a user