updated osu tests & more bugfixing for osu

This commit is contained in:
MaxOhn
2021-07-24 18:18:18 +02:00
parent 9ffd6ad1b6
commit 61620d6b25
11 changed files with 186 additions and 270 deletions
+3 -4
View File
@@ -334,7 +334,7 @@ impl<'m> OsuPP<'m> {
}
// AR bonus
let mut ar_factor = if attributes.ar > 10.33 {
let ar_factor = if attributes.ar > 10.33 {
attributes.ar - 10.33
} else if attributes.ar < 8.0 {
0.025 * (8.0 - attributes.ar)
@@ -343,8 +343,7 @@ impl<'m> OsuPP<'m> {
};
let ar_total_hits_factor = (1.0 + (-(0.007 * (total_hits - 400.0))).exp()).recip();
ar_factor *= 1.0 + (0.03 + 0.37 * ar_total_hits_factor) * ar_factor;
let ar_bonus = 1.0 + (0.03 + 0.37 * ar_total_hits_factor) * ar_factor;
// HD bonus
if self.mods.hd() {
@@ -360,7 +359,7 @@ impl<'m> OsuPP<'m> {
1.0
};
aim_value *= ar_factor.max(fl_bonus);
aim_value *= ar_bonus.max(fl_bonus);
// Scale with accuracy
aim_value *= 0.5 + self.acc.unwrap() / 2.0;
@@ -18,10 +18,9 @@ impl<'h> DifficultyObject<'h> {
prev: &OsuObject,
prev_vals: Option<(f32, f32)>, // (jump_dist, strain_time)
prev_prev: Option<OsuObject>,
clock_rate: f32,
scaling_factor: f32,
) -> Self {
let delta = (base.time - prev.time) / clock_rate;
let delta = base.time - prev.time;
let strain_time = delta.max(50.0);
let pos = base.pos; // stacked position
+47 -82
View File
@@ -62,8 +62,6 @@ pub fn stars(map: &Beatmap, mods: impl Mods, passed_objects: Option<usize>) -> S
}
let time_preempt = difficulty_range_ar(raw_ar);
let section_len = SECTION_LEN * map_attributes.clock_rate;
let scale = (1.0 - 0.7 * (map_attributes.cs - 5.0) / 5.0) / 2.0;
let radius = OBJECT_RADIUS * scale;
let mut scaling_factor = NORMALIZED_RADIUS / radius;
@@ -76,23 +74,21 @@ pub fn stars(map: &Beatmap, mods: impl Mods, passed_objects: Option<usize>) -> S
let mut slider_state = SliderState::new(map);
let mut ticks_buf = Vec::new();
let mut hit_objects: Vec<_> = map
.hit_objects
.iter()
.take(take)
.filter_map(|h| {
OsuObject::new(
h,
map,
radius,
scaling_factor,
hr,
&mut ticks_buf,
&mut diff_attributes,
&mut slider_state,
)
})
.collect();
let hit_objects_iter = map.hit_objects.iter().take(take).filter_map(|h| {
OsuObject::new(
h,
map,
radius,
scaling_factor,
hr,
&mut ticks_buf,
&mut diff_attributes,
&mut slider_state,
)
});
let mut hit_objects = Vec::with_capacity(take);
hit_objects.extend(hit_objects_iter);
let stack_threshold = time_preempt * map.stack_leniency;
@@ -107,6 +103,7 @@ pub fn stars(map: &Beatmap, mods: impl Mods, passed_objects: Option<usize>) -> S
let mut hit_objects = hit_objects.into_iter().map(|mut h| {
let stack_offset = h.stack_height * scale_factor;
h.time /= map_attributes.clock_rate;
h.pos += Pos2 {
x: stack_offset,
y: stack_offset,
@@ -118,27 +115,19 @@ pub fn stars(map: &Beatmap, mods: impl Mods, passed_objects: Option<usize>) -> S
let mut aim = Skill::new(SkillKind::Aim);
let mut speed = Skill::new(SkillKind::Speed);
// First object has no predecessor and thus no strain, handle distinctly
let mut current_section_end =
(map.hit_objects[0].start_time / section_len).ceil() * section_len;
let mut prev_prev = None;
let mut prev = hit_objects.next().unwrap();
let mut prev_vals = None;
// First object has no predecessor and thus no strain, handle distinctly
let mut current_section_end = (prev.time / SECTION_LEN).ceil() * SECTION_LEN;
// Handle second object separately to remove later if-branching
let curr = hit_objects.next().unwrap();
let h = DifficultyObject::new(
&curr,
&prev,
prev_vals,
prev_prev,
map_attributes.clock_rate,
scaling_factor,
);
let h = DifficultyObject::new(&curr, &prev, prev_vals, prev_prev, scaling_factor);
while h.base.time > current_section_end {
current_section_end += section_len;
current_section_end += SECTION_LEN;
}
aim.process(&h);
@@ -150,14 +139,7 @@ pub fn stars(map: &Beatmap, mods: impl Mods, passed_objects: Option<usize>) -> S
// Handle all other objects
for curr in hit_objects {
let h = DifficultyObject::new(
&curr,
&prev,
prev_vals,
prev_prev,
map_attributes.clock_rate,
scaling_factor,
);
let h = DifficultyObject::new(&curr, &prev, prev_vals, prev_prev, scaling_factor);
while h.base.time > current_section_end {
aim.save_current_peak();
@@ -165,7 +147,7 @@ pub fn stars(map: &Beatmap, mods: impl Mods, passed_objects: Option<usize>) -> S
speed.save_current_peak();
speed.start_new_section_from(current_section_end);
current_section_end += section_len;
current_section_end += SECTION_LEN;
}
aim.process(&h);
@@ -222,8 +204,6 @@ pub fn strains(map: &Beatmap, mods: impl Mods) -> Strains {
}
let time_preempt = difficulty_range_ar(raw_ar);
let section_len = SECTION_LEN * map_attributes.clock_rate;
let scale = (1.0 - 0.7 * (map_attributes.cs - 5.0) / 5.0) / 2.0;
let radius = OBJECT_RADIUS * scale;
let mut scaling_factor = NORMALIZED_RADIUS / radius;
@@ -236,22 +216,21 @@ pub fn strains(map: &Beatmap, mods: impl Mods) -> Strains {
let mut slider_state = SliderState::new(map);
let mut ticks_buf = Vec::new();
let mut hit_objects: Vec<_> = map
.hit_objects
.iter()
.filter_map(|h| {
OsuObject::new(
h,
map,
radius,
scaling_factor,
hr,
&mut ticks_buf,
&mut diff_attributes,
&mut slider_state,
)
})
.collect();
let hit_objects_iter = map.hit_objects.iter().filter_map(|h| {
OsuObject::new(
h,
map,
radius,
scaling_factor,
hr,
&mut ticks_buf,
&mut diff_attributes,
&mut slider_state,
)
});
let mut hit_objects = Vec::with_capacity(map.hit_objects.len());
hit_objects.extend(hit_objects_iter);
let stack_threshold = time_preempt * map.stack_leniency;
@@ -266,6 +245,7 @@ pub fn strains(map: &Beatmap, mods: impl Mods) -> Strains {
let mut hit_objects = hit_objects.into_iter().map(|mut h| {
let stack_offset = h.stack_height * scale_factor;
h.time /= map_attributes.clock_rate;
h.pos += Pos2 {
x: stack_offset,
y: stack_offset,
@@ -277,27 +257,19 @@ pub fn strains(map: &Beatmap, mods: impl Mods) -> Strains {
let mut aim = Skill::new(SkillKind::Aim);
let mut speed = Skill::new(SkillKind::Speed);
// First object has no predecessor and thus no strain, handle distinctly
let mut current_section_end =
(map.hit_objects[0].start_time / section_len).ceil() * section_len;
let mut prev_prev = None;
let mut prev = hit_objects.next().unwrap();
let mut prev_vals = None;
// First object has no predecessor and thus no strain, handle distinctly
let mut current_section_end = (prev.time / SECTION_LEN).ceil() * SECTION_LEN;
// Handle second object separately to remove later if-branching
let curr = hit_objects.next().unwrap();
let h = DifficultyObject::new(
&curr,
&prev,
prev_vals,
prev_prev,
map_attributes.clock_rate,
scaling_factor,
);
let h = DifficultyObject::new(&curr, &prev, prev_vals, prev_prev, scaling_factor);
while h.base.time > current_section_end {
current_section_end += section_len;
current_section_end += SECTION_LEN;
}
aim.process(&h);
@@ -309,14 +281,7 @@ pub fn strains(map: &Beatmap, mods: impl Mods) -> Strains {
// Handle all other objects
for curr in hit_objects {
let h = DifficultyObject::new(
&curr,
&prev,
prev_vals,
prev_prev,
map_attributes.clock_rate,
scaling_factor,
);
let h = DifficultyObject::new(&curr, &prev, prev_vals, prev_prev, scaling_factor);
while h.base.time > current_section_end {
aim.save_current_peak();
@@ -324,7 +289,7 @@ pub fn strains(map: &Beatmap, mods: impl Mods) -> Strains {
speed.save_current_peak();
speed.start_new_section_from(current_section_end);
current_section_end += section_len;
current_section_end += SECTION_LEN;
}
aim.process(&h);
@@ -346,7 +311,7 @@ pub fn strains(map: &Beatmap, mods: impl Mods) -> Strains {
.collect();
Strains {
section_length: section_len,
section_length: SECTION_LEN,
strains,
}
}
@@ -18,10 +18,9 @@ impl<'h> DifficultyObject<'h> {
prev: &OsuObject,
prev_vals: Option<(f32, f32)>, // (jump_dist, strain_time)
prev_prev: Option<OsuObject>,
clock_rate: f32,
scaling_factor: f32,
) -> Self {
let delta = (base.time - prev.time) / clock_rate;
let delta = base.time - prev.time;
let strain_time = delta.max(50.0);
let pos = base.pos;
+35 -58
View File
@@ -52,7 +52,6 @@ pub fn stars(map: &Beatmap, mods: impl Mods, passed_objects: Option<usize>) -> S
return StarResult::Osu(diff_attributes);
}
let section_len = SECTION_LEN * map_attributes.clock_rate;
let radius = OBJECT_RADIUS * (1.0 - 0.7 * (map_attributes.cs - 5.0) / 5.0) / 2.0;
let mut scaling_factor = NORMALIZED_RADIUS / radius;
@@ -64,42 +63,43 @@ pub fn stars(map: &Beatmap, mods: impl Mods, passed_objects: Option<usize>) -> S
let mut slider_state = SliderState::new(map);
let mut ticks_buf = Vec::new();
let mut hit_objects = map.hit_objects.iter().take(take).filter_map(|h| {
OsuObject::new(
h,
map,
radius,
scaling_factor,
&mut ticks_buf,
&mut diff_attributes,
&mut slider_state,
)
});
let mut hit_objects = map
.hit_objects
.iter()
.take(take)
.filter_map(|h| {
OsuObject::new(
h,
map,
radius,
scaling_factor,
&mut ticks_buf,
&mut diff_attributes,
&mut slider_state,
)
})
.map(|mut h| {
h.time /= map_attributes.clock_rate;
h
});
let mut aim = Skill::new(SkillKind::Aim);
let mut speed = Skill::new(SkillKind::Speed);
// First object has no predecessor and thus no strain, handle distinctly
let mut current_section_end =
(map.hit_objects[0].start_time / section_len).ceil() * section_len;
let mut prev_prev = None;
let mut prev = hit_objects.next().unwrap();
let mut prev_vals = None;
// First object has no predecessor and thus no strain, handle distinctly
let mut current_section_end = (prev.time / SECTION_LEN).ceil() * SECTION_LEN;
// Handle second object separately to remove later if-branching
let curr = hit_objects.next().unwrap();
let h = DifficultyObject::new(
&curr,
&prev,
prev_vals,
prev_prev,
map_attributes.clock_rate,
scaling_factor,
);
let h = DifficultyObject::new(&curr, &prev, prev_vals, prev_prev, scaling_factor);
while h.base.time > current_section_end {
current_section_end += section_len;
current_section_end += SECTION_LEN;
}
aim.process(&h);
@@ -111,14 +111,7 @@ pub fn stars(map: &Beatmap, mods: impl Mods, passed_objects: Option<usize>) -> S
// Handle all other objects
for curr in hit_objects {
let h = DifficultyObject::new(
&curr,
&prev,
prev_vals,
prev_prev,
map_attributes.clock_rate,
scaling_factor,
);
let h = DifficultyObject::new(&curr, &prev, prev_vals, prev_prev, scaling_factor);
while h.base.time > current_section_end {
aim.save_current_peak();
@@ -126,7 +119,7 @@ pub fn stars(map: &Beatmap, mods: impl Mods, passed_objects: Option<usize>) -> S
speed.save_current_peak();
speed.start_new_section_from(current_section_end);
current_section_end += section_len;
current_section_end += SECTION_LEN;
}
aim.process(&h);
@@ -173,7 +166,6 @@ pub fn strains(map: &Beatmap, mods: impl Mods) -> Strains {
return Strains::default();
}
let section_len = SECTION_LEN * map_attributes.clock_rate;
let radius = OBJECT_RADIUS * (1.0 - 0.7 * (map_attributes.cs - 5.0) / 5.0) / 2.0;
let mut scaling_factor = NORMALIZED_RADIUS / radius;
@@ -200,27 +192,19 @@ pub fn strains(map: &Beatmap, mods: impl Mods) -> Strains {
let mut aim = Skill::new(SkillKind::Aim);
let mut speed = Skill::new(SkillKind::Speed);
// First object has no predecessor and thus no strain, handle distinctly
let mut current_section_end =
(map.hit_objects[0].start_time / section_len).ceil() * section_len;
let mut prev_prev = None;
let mut prev = hit_objects.next().unwrap();
let mut prev_vals = None;
// First object has no predecessor and thus no strain, handle distinctly
let mut current_section_end = (prev.time / SECTION_LEN).ceil() * SECTION_LEN;
// Handle second object separately to remove later if-branching
let curr = hit_objects.next().unwrap();
let h = DifficultyObject::new(
&curr,
&prev,
prev_vals,
prev_prev,
map_attributes.clock_rate,
scaling_factor,
);
let h = DifficultyObject::new(&curr, &prev, prev_vals, prev_prev, scaling_factor);
while h.base.time > current_section_end {
current_section_end += section_len;
current_section_end += SECTION_LEN;
}
aim.process(&h);
@@ -232,14 +216,7 @@ pub fn strains(map: &Beatmap, mods: impl Mods) -> Strains {
// Handle all other objects
for curr in hit_objects {
let h = DifficultyObject::new(
&curr,
&prev,
prev_vals,
prev_prev,
map_attributes.clock_rate,
scaling_factor,
);
let h = DifficultyObject::new(&curr, &prev, prev_vals, prev_prev, scaling_factor);
while h.base.time > current_section_end {
aim.save_current_peak();
@@ -247,7 +224,7 @@ pub fn strains(map: &Beatmap, mods: impl Mods) -> Strains {
speed.save_current_peak();
speed.start_new_section_from(current_section_end);
current_section_end += section_len;
current_section_end += SECTION_LEN;
}
aim.process(&h);
@@ -269,7 +246,7 @@ pub fn strains(map: &Beatmap, mods: impl Mods) -> Strains {
.collect();
Strains {
section_length: section_len,
section_length: SECTION_LEN,
strains,
}
}
@@ -1,9 +1,7 @@
use crate::parse::HitObject;
use std::borrow::Cow;
use super::OsuObject;
pub(crate) struct DifficultyObject<'h> {
pub(crate) base: &'h HitObject,
pub(crate) base: &'h OsuObject,
pub(crate) prev: Option<(f32, f32)>, // (jump_dist, strain_time)
pub(crate) jump_dist: f32,
@@ -15,17 +13,16 @@ pub(crate) struct DifficultyObject<'h> {
impl<'h> DifficultyObject<'h> {
pub(crate) fn new(
base: &'h HitObject,
prev: &HitObject,
base: &'h OsuObject,
prev: &OsuObject,
prev_vals: Option<(f32, f32)>, // (jump_dist, strain_time)
prev_prev: Option<Cow<HitObject>>,
clock_rate: f32,
prev_prev: Option<OsuObject>,
scaling_factor: f32,
) -> Self {
let delta = (base.start_time - prev.start_time) / clock_rate;
let delta = base.time - prev.time;
let strain_time = delta.max(50.0);
let jump_dist = if base.is_spinner() {
let jump_dist = if base.is_spinner {
0.0
} else {
((base.pos - prev.pos) * scaling_factor).length()
+35 -73
View File
@@ -7,21 +7,18 @@
use super::super::DifficultyAttributes;
mod difficulty_object;
mod osu_object;
mod skill;
mod skill_kind;
mod slider_state;
use difficulty_object::DifficultyObject;
use osu_object::OsuObject;
use skill::Skill;
use skill_kind::SkillKind;
use slider_state::SliderState;
use crate::{
parse::{HitObject, HitObjectKind},
Beatmap, Mods, StarResult, Strains,
};
use std::borrow::Cow;
use crate::{parse::HitObjectKind, Beatmap, Mods, StarResult, Strains};
const OBJECT_RADIUS: f32 = 64.0;
const SECTION_LEN: f32 = 400.0;
@@ -50,7 +47,6 @@ pub fn stars(map: &Beatmap, mods: impl Mods, passed_objects: Option<usize>) -> S
});
}
let section_len = SECTION_LEN * attributes.clock_rate;
let radius = OBJECT_RADIUS * (1.0 - 0.7 * (attributes.cs - 5.0) / 5.0) / 2.0;
let mut scaling_factor = NORMALIZED_RADIUS / radius;
@@ -59,6 +55,8 @@ pub fn stars(map: &Beatmap, mods: impl Mods, passed_objects: Option<usize>) -> S
scaling_factor *= 1.0 + small_circle_bonus;
}
let clock_rate = attributes.clock_rate;
let mut max_combo = 0;
let mut state = SliderState::new(&map);
@@ -70,24 +68,19 @@ pub fn stars(map: &Beatmap, mods: impl Mods, passed_objects: Option<usize>) -> S
HitObjectKind::Circle => {
max_combo += 1;
Some(Cow::Borrowed(h))
Some(OsuObject::new(h.pos, h.start_time, false, clock_rate))
}
HitObjectKind::Slider {
pixel_len, repeats, ..
} => {
max_combo += state.count_ticks(h.start_time, *pixel_len, *repeats, &map);
Some(Cow::Owned(HitObject {
pos: h.pos,
start_time: h.start_time,
kind: HitObjectKind::Circle,
sound: h.sound,
}))
Some(OsuObject::new(h.pos, h.start_time, false, clock_rate))
}
HitObjectKind::Spinner { .. } => {
max_combo += 1;
Some(Cow::Borrowed(h))
Some(OsuObject::new(h.pos, h.start_time, true, clock_rate))
}
HitObjectKind::Hold { .. } => None,
});
@@ -95,27 +88,19 @@ pub fn stars(map: &Beatmap, mods: impl Mods, passed_objects: Option<usize>) -> S
let mut aim = Skill::new(SkillKind::Aim);
let mut speed = Skill::new(SkillKind::Speed);
// First object has no predecessor and thus no strain, handle distinctly
let mut current_section_end =
(map.hit_objects[0].start_time / section_len).ceil() * section_len;
let mut prev_prev = None;
let mut prev = hit_objects.next().unwrap();
let mut prev_vals = None;
// First object has no predecessor and thus no strain, handle distinctly
let mut current_section_end = (prev.time / SECTION_LEN).ceil() * SECTION_LEN;
// Handle second object separately to remove later if-branching
let curr = hit_objects.next().unwrap();
let h = DifficultyObject::new(
curr.as_ref(),
prev.as_ref(),
prev_vals,
prev_prev,
attributes.clock_rate,
scaling_factor,
);
let h = DifficultyObject::new(&curr, &prev, prev_vals, prev_prev, scaling_factor);
while h.base.start_time > current_section_end {
current_section_end += section_len;
while h.base.time > current_section_end {
current_section_end += SECTION_LEN;
}
aim.process(&h);
@@ -127,22 +112,15 @@ pub fn stars(map: &Beatmap, mods: impl Mods, passed_objects: Option<usize>) -> S
// Handle all other objects
for curr in hit_objects {
let h = DifficultyObject::new(
curr.as_ref(),
prev.as_ref(),
prev_vals,
prev_prev,
attributes.clock_rate,
scaling_factor,
);
let h = DifficultyObject::new(&curr, &prev, prev_vals, prev_prev, scaling_factor);
while h.base.start_time > current_section_end {
while h.base.time > current_section_end {
aim.save_current_peak();
aim.start_new_section_from(current_section_end);
speed.save_current_peak();
speed.start_new_section_from(current_section_end);
current_section_end += section_len;
current_section_end += SECTION_LEN;
}
aim.process(&h);
@@ -184,7 +162,6 @@ pub fn strains(map: &Beatmap, mods: impl Mods) -> Strains {
return Strains::default();
}
let section_len = SECTION_LEN * attributes.clock_rate;
let radius = OBJECT_RADIUS * (1.0 - 0.7 * (attributes.cs - 5.0) / 5.0) / 2.0;
let mut scaling_factor = NORMALIZED_RADIUS / radius;
@@ -193,42 +170,34 @@ pub fn strains(map: &Beatmap, mods: impl Mods) -> Strains {
scaling_factor *= 1.0 + small_circle_bonus;
}
let clock_rate = attributes.clock_rate;
let mut hit_objects = map.hit_objects.iter().filter_map(|h| match &h.kind {
HitObjectKind::Circle => Some(Cow::Borrowed(h)),
HitObjectKind::Slider { .. } => Some(Cow::Owned(HitObject {
pos: h.pos,
start_time: h.start_time,
kind: HitObjectKind::Circle,
sound: h.sound,
})),
HitObjectKind::Spinner { .. } => Some(Cow::Borrowed(h)),
HitObjectKind::Circle | HitObjectKind::Slider { .. } => {
Some(OsuObject::new(h.pos, h.start_time, false, clock_rate))
}
HitObjectKind::Spinner { .. } => {
Some(OsuObject::new(h.pos, h.start_time, true, clock_rate))
}
HitObjectKind::Hold { .. } => None,
});
let mut aim = Skill::new(SkillKind::Aim);
let mut speed = Skill::new(SkillKind::Speed);
// First object has no predecessor and thus no strain, handle distinctly
let mut current_section_end =
(map.hit_objects[0].start_time / section_len).ceil() * section_len;
let mut prev_prev = None;
let mut prev = hit_objects.next().unwrap();
let mut prev_vals = None;
// First object has no predecessor and thus no strain, handle distinctly
let mut current_section_end = (prev.time / SECTION_LEN).ceil() * SECTION_LEN;
// Handle second object separately to remove later if-branching
let curr = hit_objects.next().unwrap();
let h = DifficultyObject::new(
curr.as_ref(),
prev.as_ref(),
prev_vals,
prev_prev,
attributes.clock_rate,
scaling_factor,
);
let h = DifficultyObject::new(&curr, &prev, prev_vals, prev_prev, scaling_factor);
while h.base.start_time > current_section_end {
current_section_end += section_len;
while h.base.time > current_section_end {
current_section_end += SECTION_LEN;
}
aim.process(&h);
@@ -240,22 +209,15 @@ pub fn strains(map: &Beatmap, mods: impl Mods) -> Strains {
// Handle all other objects
for curr in hit_objects {
let h = DifficultyObject::new(
curr.as_ref(),
prev.as_ref(),
prev_vals,
prev_prev,
attributes.clock_rate,
scaling_factor,
);
let h = DifficultyObject::new(&curr, &prev, prev_vals, prev_prev, scaling_factor);
while h.base.start_time > current_section_end {
while h.base.time > current_section_end {
aim.save_current_peak();
aim.start_new_section_from(current_section_end);
speed.save_current_peak();
speed.start_new_section_from(current_section_end);
current_section_end += section_len;
current_section_end += SECTION_LEN;
}
aim.process(&h);
@@ -277,7 +239,7 @@ pub fn strains(map: &Beatmap, mods: impl Mods) -> Strains {
.collect();
Strains {
section_length: section_len,
section_length: SECTION_LEN,
strains,
}
}
@@ -0,0 +1,18 @@
use crate::parse::Pos2;
pub(crate) struct OsuObject {
pub(crate) pos: Pos2,
pub(crate) time: f32,
pub(crate) is_spinner: bool,
}
impl OsuObject {
#[inline]
pub(crate) fn new(pos: Pos2, time: f32, is_spinner: bool, clock_rate: f32) -> Self {
Self {
pos,
time: time / clock_rate,
is_spinner,
}
}
}
@@ -52,7 +52,7 @@ impl Skill {
self.current_strain *= self.strain_decay(current.delta);
self.current_strain += self.kind.strain_value_of(&current) * self.skill_multiplier();
self.current_section_peak = self.current_section_peak.max(self.current_strain);
self.prev_time.replace(current.base.start_time);
self.prev_time.replace(current.base.time);
}
pub(crate) fn difficulty_value(&mut self) -> f32 {
@@ -28,7 +28,7 @@ impl SkillKind {
pub(crate) fn strain_value_of(self, current: &DifficultyObject) -> f32 {
match self {
Self::Aim => {
if current.base.is_spinner() {
if current.base.is_spinner {
return 0.0;
}
@@ -54,7 +54,7 @@ impl SkillKind {
.max(jump_dist_exp / current.strain_time)
}
Self::Speed => {
if current.base.is_spinner() {
if current.base.is_spinner {
return 0.0;
}