mirror of
https://github.com/ppy/osu.git
synced 2024-11-06 06:57:39 +08:00
Implement basic score recalculation
This commit is contained in:
parent
85bda29b71
commit
4d15f0fe52
@ -201,11 +201,11 @@ namespace osu.Game.Beatmaps
|
||||
var calculator = ruleset.CreateDifficultyCalculator(beatmapManager.GetWorkingBeatmap(beatmapInfo));
|
||||
var attributes = calculator.Calculate(key.Mods);
|
||||
|
||||
return difficultyCache[key] = new StarDifficulty(attributes.StarRating);
|
||||
return difficultyCache[key] = new StarDifficulty(attributes.StarRating, attributes.MaxCombo);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return difficultyCache[key] = new StarDifficulty(0);
|
||||
return difficultyCache[key] = new StarDifficulty();
|
||||
}
|
||||
}
|
||||
|
||||
@ -227,7 +227,7 @@ namespace osu.Game.Beatmaps
|
||||
if (beatmapInfo.ID == 0 || rulesetInfo.ID == null)
|
||||
{
|
||||
// If not, fall back to the existing star difficulty (e.g. from an online source).
|
||||
existingDifficulty = new StarDifficulty(beatmapInfo.StarDifficulty);
|
||||
existingDifficulty = new StarDifficulty(beatmapInfo.StarDifficulty, beatmapInfo.MaxCombo ?? 0);
|
||||
key = default;
|
||||
|
||||
return true;
|
||||
@ -292,10 +292,12 @@ namespace osu.Game.Beatmaps
|
||||
public readonly struct StarDifficulty
|
||||
{
|
||||
public readonly double Stars;
|
||||
public readonly int MaxCombo;
|
||||
|
||||
public StarDifficulty(double stars)
|
||||
public StarDifficulty(double stars, int maxCombo)
|
||||
{
|
||||
Stars = stars;
|
||||
MaxCombo = maxCombo;
|
||||
|
||||
// Todo: Add more members (BeatmapInfo.DifficultyRating? Attributes? Etc...)
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ namespace osu.Game.Online.Leaderboards
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(IAPIProvider api, OsuColour colour)
|
||||
private void load(IAPIProvider api, OsuColour colour, ScoreManager scoreManager)
|
||||
{
|
||||
var user = score.User;
|
||||
|
||||
@ -194,7 +194,7 @@ namespace osu.Game.Online.Leaderboards
|
||||
{
|
||||
TextColour = Color4.White,
|
||||
GlowColour = Color4Extensions.FromHex(@"83ccfa"),
|
||||
Text = score.TotalScore.ToString(@"N0"),
|
||||
Text = scoreManager.GetTotalScore(score).ToString(@"N0"),
|
||||
Font = OsuFont.Numeric.With(size: 23),
|
||||
},
|
||||
RankContainer = new Container
|
||||
|
@ -57,6 +57,8 @@ namespace osu.Game
|
||||
|
||||
protected ScoreManager ScoreManager;
|
||||
|
||||
protected BeatmapDifficultyManager DifficultyManager;
|
||||
|
||||
protected SkinManager SkinManager;
|
||||
|
||||
protected RulesetStore RulesetStore;
|
||||
@ -194,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));
|
||||
dependencies.Cache(ScoreManager = new ScoreManager(RulesetStore, () => BeatmapManager, Storage, API, contextFactory, Host, () => DifficultyManager));
|
||||
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
|
||||
@ -218,9 +220,8 @@ namespace osu.Game
|
||||
ScoreManager.Undelete(getBeatmapScores(item), true);
|
||||
});
|
||||
|
||||
var difficultyManager = new BeatmapDifficultyManager();
|
||||
dependencies.Cache(difficultyManager);
|
||||
AddInternal(difficultyManager);
|
||||
dependencies.Cache(DifficultyManager = new BeatmapDifficultyManager());
|
||||
AddInternal(DifficultyManager);
|
||||
|
||||
dependencies.Cache(KeyBindingStore = new KeyBindingStore(contextFactory, RulesetStore));
|
||||
dependencies.Cache(SettingsStore = new SettingsStore(contextFactory));
|
||||
|
@ -25,6 +25,9 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
|
||||
private const float row_height = 22;
|
||||
private const int text_size = 12;
|
||||
|
||||
[Resolved]
|
||||
private ScoreManager scoreManager { get; set; }
|
||||
|
||||
private readonly FillFlowContainer backgroundFlow;
|
||||
|
||||
private Color4 highAccuracyColour;
|
||||
@ -121,7 +124,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
|
||||
new OsuSpriteText
|
||||
{
|
||||
Margin = new MarginPadding { Right = horizontal_inset },
|
||||
Text = $@"{score.TotalScore:N0}",
|
||||
Text = $@"{scoreManager.GetTotalScore(score):N0}",
|
||||
Font = OsuFont.GetFont(size: text_size, weight: index == 0 ? FontWeight.Bold : FontWeight.Medium)
|
||||
},
|
||||
new OsuSpriteText
|
||||
|
@ -203,19 +203,24 @@ namespace osu.Game.Rulesets.Scoring
|
||||
}
|
||||
|
||||
private double getScore(ScoringMode mode)
|
||||
{
|
||||
return GetScore(baseScore / maxBaseScore, HighestCombo.Value / maxHighestCombo, bonusScore, mode);
|
||||
}
|
||||
|
||||
public double GetScore(double accuracyRatio, double comboRatio, double bonus, ScoringMode mode)
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
default:
|
||||
case ScoringMode.Standardised:
|
||||
double accuracyScore = accuracyPortion * baseScore / maxBaseScore;
|
||||
double comboScore = comboPortion * HighestCombo.Value / maxHighestCombo;
|
||||
double accuracyScore = accuracyPortion * accuracyRatio;
|
||||
double comboScore = comboPortion * comboRatio;
|
||||
|
||||
return (max_score * (accuracyScore + comboScore) + bonusScore) * scoreMultiplier;
|
||||
return (max_score * (accuracyScore + comboScore) + bonus) * scoreMultiplier;
|
||||
|
||||
case ScoringMode.Classic:
|
||||
// should emulate osu-stable's scoring as closely as we can (https://osu.ppy.sh/help/wiki/Score/ScoreV1)
|
||||
return bonusScore + baseScore * (1 + Math.Max(0, HighestCombo.Value - 1) * scoreMultiplier / 25);
|
||||
return bonus + (accuracyRatio * maxBaseScore) * (1 + Math.Max(0, (comboRatio * maxHighestCombo) - 1) * scoreMultiplier / 25);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,7 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using JetBrains.Annotations;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Framework.Platform;
|
||||
@ -15,6 +16,7 @@ using osu.Game.IO.Archives;
|
||||
using osu.Game.Online.API;
|
||||
using osu.Game.Online.API.Requests;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Scoring.Legacy;
|
||||
|
||||
namespace osu.Game.Scoring
|
||||
@ -30,11 +32,16 @@ namespace osu.Game.Scoring
|
||||
private readonly RulesetStore rulesets;
|
||||
private readonly Func<BeatmapManager> beatmaps;
|
||||
|
||||
public ScoreManager(RulesetStore rulesets, Func<BeatmapManager> beatmaps, Storage storage, IAPIProvider api, IDatabaseContextFactory contextFactory, IIpcHost importHost = null)
|
||||
[CanBeNull]
|
||||
private readonly Func<BeatmapDifficultyManager> difficulties;
|
||||
|
||||
public ScoreManager(RulesetStore rulesets, Func<BeatmapManager> beatmaps, Storage storage, IAPIProvider api, IDatabaseContextFactory contextFactory, IIpcHost importHost = null,
|
||||
Func<BeatmapDifficultyManager> difficulties = null)
|
||||
: base(storage, contextFactory, api, new ScoreStore(contextFactory, storage), importHost)
|
||||
{
|
||||
this.rulesets = rulesets;
|
||||
this.beatmaps = beatmaps;
|
||||
this.difficulties = difficulties;
|
||||
}
|
||||
|
||||
protected override ScoreInfo CreateModel(ArchiveReader archive)
|
||||
@ -72,5 +79,26 @@ namespace osu.Game.Scoring
|
||||
protected override bool CheckLocalAvailability(ScoreInfo model, IQueryable<ScoreInfo> items)
|
||||
=> base.CheckLocalAvailability(model, items)
|
||||
|| (model.OnlineScoreID != null && items.Any(i => i.OnlineScoreID == model.OnlineScoreID));
|
||||
|
||||
public long GetTotalScore(ScoreInfo score)
|
||||
{
|
||||
int? beatmapMaxCombo = score.Beatmap.MaxCombo;
|
||||
|
||||
if (beatmapMaxCombo == null)
|
||||
{
|
||||
if (score.Beatmap.ID == 0 || difficulties == null)
|
||||
return score.TotalScore; // Can't do anything.
|
||||
|
||||
// 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;
|
||||
|
||||
return (long)Math.Round(scoreProcessor.GetScore(score.Accuracy, (double)score.MaxCombo / beatmapMaxCombo.Value, 0, ScoringMode.Standardised));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user