Add support for standardised -> classic changes

This commit is contained in:
smoogipoo
2020-08-28 21:34:34 +09:00
parent 4d15f0fe52
commit 1e5e5cae0c
6 changed files with 62 additions and 19 deletions

View File

@ -1,6 +1,7 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using osu.Framework.Bindables;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Colour;
using osu.Framework.Graphics.Containers;
@ -55,6 +56,12 @@ namespace osu.Game.Graphics.Sprites
set => spriteText.UseFullGlyphHeight = blurredText.UseFullGlyphHeight = value;
}
public Bindable<string> Current
{
get => spriteText.Current;
set => spriteText.Current = value;
}
public GlowingSpriteText()
{
AutoSizeAxes = Axes.Both;

View File

@ -194,7 +194,7 @@ namespace osu.Game.Online.Leaderboards
{
TextColour = Color4.White,
GlowColour = Color4Extensions.FromHex(@"83ccfa"),
Text = scoreManager.GetTotalScore(score).ToString(@"N0"),
Current = scoreManager.GetTotalScore(score),
Font = OsuFont.Numeric.With(size: 23),
},
RankContainer = new Container

View File

@ -196,7 +196,7 @@ namespace osu.Game
dependencies.Cache(FileStore = new FileStore(contextFactory, Storage));
// ordering is important here to ensure foreign keys rules are not broken in ModelStore.Cleanup()
dependencies.Cache(ScoreManager = new ScoreManager(RulesetStore, () => BeatmapManager, Storage, API, contextFactory, Host, () => DifficultyManager));
dependencies.Cache(ScoreManager = new ScoreManager(RulesetStore, () => BeatmapManager, Storage, API, contextFactory, Host, () => DifficultyManager, LocalConfig));
dependencies.Cache(BeatmapManager = new BeatmapManager(Storage, contextFactory, RulesetStore, API, Audio, Host, defaultBeatmap));
// this should likely be moved to ArchiveModelManager when another case appers where it is necessary

View File

@ -124,7 +124,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
new OsuSpriteText
{
Margin = new MarginPadding { Right = horizontal_inset },
Text = $@"{scoreManager.GetTotalScore(score):N0}",
Current = scoreManager.GetTotalScore(score),
Font = OsuFont.GetFont(size: text_size, weight: index == 0 ? FontWeight.Bold : FontWeight.Medium)
},
new OsuSpriteText

View File

@ -204,10 +204,10 @@ namespace osu.Game.Rulesets.Scoring
private double getScore(ScoringMode mode)
{
return GetScore(baseScore / maxBaseScore, HighestCombo.Value / maxHighestCombo, bonusScore, mode);
return GetScore(mode, maxBaseScore, maxHighestCombo, baseScore / maxBaseScore, HighestCombo.Value / maxHighestCombo, bonusScore);
}
public double GetScore(double accuracyRatio, double comboRatio, double bonus, ScoringMode mode)
public double GetScore(ScoringMode mode, double maxBaseScore, double maxHighestCombo, double accuracyRatio, double comboRatio, double bonusScore)
{
switch (mode)
{
@ -216,11 +216,11 @@ namespace osu.Game.Rulesets.Scoring
double accuracyScore = accuracyPortion * accuracyRatio;
double comboScore = comboPortion * comboRatio;
return (max_score * (accuracyScore + comboScore) + bonus) * scoreMultiplier;
return (max_score * (accuracyScore + comboScore) + bonusScore) * scoreMultiplier;
case ScoringMode.Classic:
// should emulate osu-stable's scoring as closely as we can (https://osu.ppy.sh/help/wiki/Score/ScoreV1)
return bonus + (accuracyRatio * maxBaseScore) * (1 + Math.Max(0, (comboRatio * maxHighestCombo) - 1) * scoreMultiplier / 25);
return bonusScore + (accuracyRatio * maxBaseScore) * (1 + Math.Max(0, (comboRatio * maxHighestCombo) - 1) * scoreMultiplier / 25);
}
}

View File

@ -8,9 +8,11 @@ using System.Linq;
using System.Linq.Expressions;
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore;
using osu.Framework.Bindables;
using osu.Framework.Logging;
using osu.Framework.Platform;
using osu.Game.Beatmaps;
using osu.Game.Configuration;
using osu.Game.Database;
using osu.Game.IO.Archives;
using osu.Game.Online.API;
@ -35,13 +37,17 @@ namespace osu.Game.Scoring
[CanBeNull]
private readonly Func<BeatmapDifficultyManager> difficulties;
[CanBeNull]
private readonly OsuConfigManager configManager;
public ScoreManager(RulesetStore rulesets, Func<BeatmapManager> beatmaps, Storage storage, IAPIProvider api, IDatabaseContextFactory contextFactory, IIpcHost importHost = null,
Func<BeatmapDifficultyManager> difficulties = null)
Func<BeatmapDifficultyManager> difficulties = null, OsuConfigManager configManager = null)
: base(storage, contextFactory, api, new ScoreStore(contextFactory, storage), importHost)
{
this.rulesets = rulesets;
this.beatmaps = beatmaps;
this.difficulties = difficulties;
this.configManager = configManager;
}
protected override ScoreInfo CreateModel(ArchiveReader archive)
@ -80,25 +86,55 @@ namespace osu.Game.Scoring
=> base.CheckLocalAvailability(model, items)
|| (model.OnlineScoreID != null && items.Any(i => i.OnlineScoreID == model.OnlineScoreID));
public long GetTotalScore(ScoreInfo score)
public Bindable<string> GetTotalScore(ScoreInfo score)
{
int? beatmapMaxCombo = score.Beatmap.MaxCombo;
var bindable = new TotalScoreBindable(score, difficulties);
configManager?.BindWith(OsuSetting.ScoreDisplayMode, bindable.ScoringMode);
return bindable;
}
if (beatmapMaxCombo == null)
private class TotalScoreBindable : Bindable<string>
{
public readonly Bindable<ScoringMode> ScoringMode = new Bindable<ScoringMode>();
private readonly ScoreInfo score;
private readonly Func<BeatmapDifficultyManager> difficulties;
public TotalScoreBindable(ScoreInfo score, Func<BeatmapDifficultyManager> difficulties)
{
if (score.Beatmap.ID == 0 || difficulties == null)
return score.TotalScore; // Can't do anything.
this.score = score;
this.difficulties = difficulties;
// We can compute the max combo locally.
beatmapMaxCombo = difficulties().GetDifficulty(score.Beatmap, score.Ruleset, score.Mods).MaxCombo;
ScoringMode.BindValueChanged(onScoringModeChanged, true);
}
var ruleset = score.Ruleset.CreateInstance();
var scoreProcessor = ruleset.CreateScoreProcessor();
private void onScoringModeChanged(ValueChangedEvent<ScoringMode> mode)
{
int? beatmapMaxCombo = score.Beatmap.MaxCombo;
scoreProcessor.Mods.Value = score.Mods;
if (beatmapMaxCombo == null)
{
if (score.Beatmap.ID == 0 || difficulties == null)
{
// We don't have enough information (max combo) to compute the score, so let's use the provided score.
Value = score.TotalScore.ToString("N0");
return;
}
return (long)Math.Round(scoreProcessor.GetScore(score.Accuracy, (double)score.MaxCombo / beatmapMaxCombo.Value, 0, ScoringMode.Standardised));
// We can compute the max combo locally.
beatmapMaxCombo = difficulties().GetDifficulty(score.Beatmap, score.Ruleset, score.Mods).MaxCombo;
}
var ruleset = score.Ruleset.CreateInstance();
var scoreProcessor = ruleset.CreateScoreProcessor();
scoreProcessor.Mods.Value = score.Mods;
double maxBaseScore = 300 * beatmapMaxCombo.Value;
double maxHighestCombo = beatmapMaxCombo.Value;
Value = Math.Round(scoreProcessor.GetScore(mode.NewValue, maxBaseScore, maxHighestCombo, score.Accuracy, score.MaxCombo / maxHighestCombo, 0)).ToString("N0");
}
}
}
}