feat: remove combo scaling
This commit is contained in:
+13
-11
@@ -376,12 +376,8 @@ impl<'m> OsuPP<'m> {
|
|||||||
aim_value *= len_bonus;
|
aim_value *= len_bonus;
|
||||||
|
|
||||||
// Penalize misses
|
// Penalize misses
|
||||||
let penalty_factor: f32 = if self.mods.rx() { 0.96 } else { 0.97 };
|
if self.n_misses > 0 {
|
||||||
aim_value *= penalty_factor.powi(self.n_misses as i32);
|
aim_value *= self.calculate_miss_penalty(attributes.aim_difficult_strain_count as f32);
|
||||||
|
|
||||||
// Combo scaling
|
|
||||||
if let Some(combo) = self.combo.filter(|_| attributes.max_combo > 0) {
|
|
||||||
aim_value *= ((combo as f32 / attributes.max_combo as f32).powf(0.8)).min(1.0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// AR bonus
|
// AR bonus
|
||||||
@@ -479,12 +475,13 @@ impl<'m> OsuPP<'m> {
|
|||||||
speed_value *= len_bonus;
|
speed_value *= len_bonus;
|
||||||
|
|
||||||
// Penalize misses
|
// Penalize misses
|
||||||
let penalty_factor: f32 = if self.mods.rx() { 0.94 } else { 0.97 };
|
if self.n_misses > 0 {
|
||||||
speed_value *= penalty_factor.powi(self.n_misses as i32);
|
let mut strain_count = attributes.speed_difficult_strain_count as f32;
|
||||||
|
if self.mods.rx() {
|
||||||
|
strain_count *= 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
// Combo scaling
|
speed_value *= self.calculate_miss_penalty(strain_count);
|
||||||
if let Some(combo) = self.combo.filter(|_| attributes.max_combo > 0) {
|
|
||||||
speed_value *= ((combo as f32 / attributes.max_combo as f32).powf(0.8)).min(1.0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// AR bonus
|
// AR bonus
|
||||||
@@ -588,6 +585,11 @@ impl<'m> OsuPP<'m> {
|
|||||||
(self.n300.unwrap_or(0) + self.n100.unwrap_or(0) + self.n50.unwrap_or(0) + self.n_misses)
|
(self.n300.unwrap_or(0) + self.n100.unwrap_or(0) + self.n50.unwrap_or(0) + self.n_misses)
|
||||||
.min(n_objects)
|
.min(n_objects)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn calculate_miss_penalty(&self, strain_count: f32) -> f32 {
|
||||||
|
0.97 / ((self.n_misses as f32 / (2.0 * strain_count.sqrt())) + 1.0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Provides attributes for an osu! beatmap.
|
/// Provides attributes for an osu! beatmap.
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ pub(crate) struct Skill {
|
|||||||
pub(crate) strain_peaks: Vec<f32>,
|
pub(crate) strain_peaks: Vec<f32>,
|
||||||
|
|
||||||
prev_time: Option<f32>,
|
prev_time: Option<f32>,
|
||||||
|
pub(crate) object_strains: Vec<f32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Skill {
|
impl Skill {
|
||||||
@@ -31,6 +32,7 @@ impl Skill {
|
|||||||
strain_peaks: Vec::with_capacity(128),
|
strain_peaks: Vec::with_capacity(128),
|
||||||
|
|
||||||
prev_time: None,
|
prev_time: None,
|
||||||
|
object_strains: Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,6 +50,9 @@ impl Skill {
|
|||||||
pub(crate) fn process(&mut self, current: &DifficultyObject<'_>) {
|
pub(crate) fn process(&mut self, current: &DifficultyObject<'_>) {
|
||||||
self.current_strain *= self.strain_decay(current.delta);
|
self.current_strain *= self.strain_decay(current.delta);
|
||||||
self.current_strain += self.kind.strain_value_of(current) * self.skill_multiplier();
|
self.current_strain += self.kind.strain_value_of(current) * self.skill_multiplier();
|
||||||
|
|
||||||
|
self.object_strains.push(self.current_strain);
|
||||||
|
|
||||||
self.current_section_peak = self.current_section_peak.max(self.current_strain);
|
self.current_section_peak = self.current_section_peak.max(self.current_strain);
|
||||||
self.prev_time.replace(current.base.time);
|
self.prev_time.replace(current.base.time);
|
||||||
}
|
}
|
||||||
@@ -67,6 +72,18 @@ impl Skill {
|
|||||||
difficulty
|
difficulty
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn count_difficult_strains(&mut self) -> f64 {
|
||||||
|
let top_strain = self
|
||||||
|
.object_strains
|
||||||
|
.iter()
|
||||||
|
.fold(f64::NEG_INFINITY, |prev, curr| prev.max(*curr as f64));
|
||||||
|
|
||||||
|
self.object_strains
|
||||||
|
.iter()
|
||||||
|
.map(|strain| (strain / top_strain as f32).powi(4))
|
||||||
|
.sum::<f32>() as f64
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn skill_multiplier(&self) -> f32 {
|
fn skill_multiplier(&self) -> f32 {
|
||||||
match self.kind {
|
match self.kind {
|
||||||
|
|||||||
@@ -126,11 +126,16 @@ pub fn stars(map: &Beatmap, mods: u32, passed_objects: Option<usize>) -> OsuDiff
|
|||||||
let aim_strain = aim.difficulty_value().sqrt() * DIFFICULTY_MULTIPLIER;
|
let aim_strain = aim.difficulty_value().sqrt() * DIFFICULTY_MULTIPLIER;
|
||||||
let speed_strain = speed.difficulty_value().sqrt() * DIFFICULTY_MULTIPLIER;
|
let speed_strain = speed.difficulty_value().sqrt() * DIFFICULTY_MULTIPLIER;
|
||||||
|
|
||||||
|
let aim_difficult_strain_count = aim.count_difficult_strains();
|
||||||
|
let speed_difficult_strain_count = speed.count_difficult_strains();
|
||||||
|
|
||||||
let stars = aim_strain + speed_strain + (aim_strain - speed_strain).abs() / 2.0;
|
let stars = aim_strain + speed_strain + (aim_strain - speed_strain).abs() / 2.0;
|
||||||
|
|
||||||
diff_attributes.stars = stars as f64;
|
diff_attributes.stars = stars as f64;
|
||||||
diff_attributes.speed_strain = speed_strain as f64;
|
diff_attributes.speed_strain = speed_strain as f64;
|
||||||
diff_attributes.aim_strain = aim_strain as f64;
|
diff_attributes.aim_strain = aim_strain as f64;
|
||||||
|
diff_attributes.aim_difficult_strain_count = aim_difficult_strain_count;
|
||||||
|
diff_attributes.speed_difficult_strain_count = speed_difficult_strain_count;
|
||||||
|
|
||||||
diff_attributes
|
diff_attributes
|
||||||
}
|
}
|
||||||
@@ -147,6 +152,8 @@ pub struct OsuDifficultyAttributes {
|
|||||||
pub n_spinners: usize,
|
pub n_spinners: usize,
|
||||||
pub stars: f64,
|
pub stars: f64,
|
||||||
pub max_combo: usize,
|
pub max_combo: usize,
|
||||||
|
pub aim_difficult_strain_count: f64,
|
||||||
|
pub speed_difficult_strain_count: f64,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
|
|||||||
Reference in New Issue
Block a user