Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions phira/locales/zh-CN/song.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,8 @@ mods-flip-x = X 轴反转
mods-flip-x-sub = 在 X 轴上反转谱面
mods-fade-out = 下隐
mods-fade-out-sub = 音符在靠近判定线时会隐藏
mods-strict-mode = 严判模式
mods-strict-mode-sub = 判定时间缩短为原来的一半

rate-failed = 评分失败
rate-done = 评分成功
Expand Down
1 change: 1 addition & 0 deletions phira/src/scene/song.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1221,6 +1221,7 @@ impl SongScene {
item(tl!("mods-autoplay"), Some(tl!("mods-autoplay-sub")), Mods::AUTOPLAY);
item(tl!("mods-flip-x"), Some(tl!("mods-flip-x-sub")), Mods::FLIP_X);
item(tl!("mods-fade-out"), Some(tl!("mods-fade-out-sub")), Mods::FADE_OUT);
item(tl!("mods-strict-mode"), Some(tl!("mods-strict-mode-sub")), Mods::STRICT);
(width, h)
});
}
Expand Down
6 changes: 6 additions & 0 deletions prpr/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ bitflags! {
const AUTOPLAY = 1;
const FLIP_X = 2;
const FADE_OUT = 4;
const STRICT = 8;
}
}

Expand Down Expand Up @@ -115,4 +116,9 @@ impl Config {
pub fn flip_x(&self) -> bool {
self.has_mod(Mods::FLIP_X)
}

#[inline]
pub fn strict(&self) -> bool {
self.has_mod(Mods::STRICT)
}
}
44 changes: 26 additions & 18 deletions prpr/src/judge.rs
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,14 @@ impl Judge {
}

pub fn update(&mut self, res: &mut Resource, chart: &mut Chart, bad_notes: &mut Vec<BadNote>) {

let (LIMIT_BAD_R, LIMIT_GOOD_R, LIMIT_PERFECT_R) =
if res.config.strict() {
(LIMIT_BAD*0.5, LIMIT_GOOD*0.5, LIMIT_PERFECT*0.5)
} else {
(LIMIT_BAD, LIMIT_GOOD, LIMIT_PERFECT)
};

if res.config.autoplay() {
self.auto_play_update(res, chart);
return;
Expand Down Expand Up @@ -513,7 +521,7 @@ impl Judge {
continue;
}
let t = time_of(touch);
let mut closest = (None, X_DIFF_MAX, LIMIT_BAD, LIMIT_BAD + (X_DIFF_MAX / NOTE_WIDTH_RATIO_BASE - 1.).max(0.) * DIST_FACTOR);
let mut closest = (None, X_DIFF_MAX, LIMIT_BAD_R, LIMIT_BAD_R + (X_DIFF_MAX / NOTE_WIDTH_RATIO_BASE - 1.).max(0.) * DIST_FACTOR);
for (line_id, ((line, pos), (idx, st))) in chart.lines.iter_mut().zip(pos.iter()).zip(self.notes.iter_mut()).enumerate() {
let Some(pos) = pos[id] else {
continue;
Expand All @@ -539,15 +547,15 @@ impl Judge {
}
if dt
> if matches!(note.kind, NoteKind::Click) {
LIMIT_BAD - LIMIT_PERFECT * (dist - 0.9).max(0.)
LIMIT_BAD_R - LIMIT_PERFECT_R * (dist - 0.9).max(0.)
} else {
LIMIT_GOOD
LIMIT_GOOD_R
}
{
continue;
}
let dt = if matches!(note.kind, NoteKind::Flick | NoteKind::Drag) {
dt + LIMIT_GOOD
dt + LIMIT_GOOD_R
} else {
dt
};
Expand All @@ -569,16 +577,16 @@ impl Judge {
if matches!(note.kind, NoteKind::Flick) {
continue; // to next loop
}
if dt <= LIMIT_GOOD || matches!(note.kind, NoteKind::Hold { .. }) {
if dt <= LIMIT_GOOD_R || matches!(note.kind, NoteKind::Hold { .. }) {
match note.kind {
NoteKind::Click => {
note.judge = JudgeStatus::Judged;
judgements.push((if dt <= LIMIT_PERFECT { Judgement::Perfect } else { Judgement::Good }, line_id, id, Some(t)));
judgements.push((if dt <= LIMIT_PERFECT_R { Judgement::Perfect } else { Judgement::Good }, line_id, id, Some(t)));
}
NoteKind::Hold { .. } => {
note.hitsound.play(res);
self.judgements.borrow_mut().push((t, line_id as _, id, Err(dt <= LIMIT_PERFECT)));
note.judge = JudgeStatus::Hold(dt <= LIMIT_PERFECT, t, t, false, f32::INFINITY);
self.judgements.borrow_mut().push((t, line_id as _, id, Err(dt <= LIMIT_PERFECT_R)));
note.judge = JudgeStatus::Hold(dt <= LIMIT_PERFECT_R, t, t, false, f32::INFINITY);
}
_ => unreachable!(),
};
Expand Down Expand Up @@ -620,14 +628,14 @@ impl Judge {
{
let note = &mut chart.lines[line_id].notes[id as usize];
let dt = (t - note.time).abs() / spd;
if dt <= if matches!(note.kind, NoteKind::Click) { LIMIT_BAD } else { LIMIT_GOOD } {
if dt <= if matches!(note.kind, NoteKind::Click) { LIMIT_BAD_R } else { LIMIT_GOOD_R } {
match note.kind {
NoteKind::Click => {
note.judge = JudgeStatus::Judged;
judgements.push((
if dt <= LIMIT_PERFECT {
if dt <= LIMIT_PERFECT_R {
Judgement::Perfect
} else if dt <= LIMIT_GOOD {
} else if dt <= LIMIT_GOOD_R {
Judgement::Good
} else {
Judgement::Bad
Expand All @@ -639,8 +647,8 @@ impl Judge {
}
NoteKind::Hold { .. } => {
note.hitsound.play(res);
self.judgements.borrow_mut().push((t, line_id as _, id, Err(dt <= LIMIT_PERFECT)));
note.judge = JudgeStatus::Hold(dt <= LIMIT_PERFECT, t, (t - note.time) / spd, false, f32::INFINITY);
self.judgements.borrow_mut().push((t, line_id as _, id, Err(dt <= LIMIT_PERFECT_R)));
note.judge = JudgeStatus::Hold(dt <= LIMIT_PERFECT_R, t, (t - note.time) / spd, false, f32::INFINITY);
}
_ => unreachable!(),
};
Expand All @@ -655,7 +663,7 @@ impl Judge {
let note = &mut line.notes[*id as usize];
if let NoteKind::Hold { end_time, .. } = &note.kind {
if let JudgeStatus::Hold(.., ref mut pre_judge, ref mut up_time) = note.judge {
if (*end_time - t) / spd <= LIMIT_BAD {
if (*end_time - t) / spd <= LIMIT_BAD_R {
*pre_judge = true;
continue;
}
Expand All @@ -680,12 +688,12 @@ impl Judge {
}
// process miss
let dt = (t - note.time) / spd;
if dt > LIMIT_BAD {
if dt > LIMIT_BAD_R {
note.judge = JudgeStatus::Judged;
judgements.push((Judgement::Miss, line_id, *id, None));
continue;
}
if -dt > LIMIT_BAD {
if -dt > LIMIT_BAD_R {
break;
}
if !matches!(note.kind, NoteKind::Drag) && (self.key_down_count == 0 || !matches!(note.kind, NoteKind::Flick)) {
Expand All @@ -699,7 +707,7 @@ impl Judge {
|| pos.iter().any(|it| {
it.map_or(false, |it| {
let dx = (it.x - x).abs();
dx <= X_DIFF_MAX && dt <= (LIMIT_BAD - LIMIT_PERFECT * (dx - 0.9).max(0.))
dx <= X_DIFF_MAX && dt <= (LIMIT_BAD_R - LIMIT_PERFECT_R * (dx - 0.9).max(0.))
})
})
{
Expand All @@ -722,7 +730,7 @@ impl Judge {
}
}
// TODO adjust
let ghost_t = t + LIMIT_GOOD;
let ghost_t = t + LIMIT_GOOD_R;
if matches!(note.kind, NoteKind::Click) {
if ghost_t < note.time {
break;
Expand Down