mirror of
https://github.com/osukey/osukey.git
synced 2025-05-08 15:17:24 +09:00
Merge pull request #10106 from smoogipoo/score-recalc
This commit is contained in:
commit
23b51e8f7f
@ -8,6 +8,5 @@ namespace osu.Game.Rulesets.Catch.Difficulty
|
|||||||
public class CatchDifficultyAttributes : DifficultyAttributes
|
public class CatchDifficultyAttributes : DifficultyAttributes
|
||||||
{
|
{
|
||||||
public double ApproachRate;
|
public double ApproachRate;
|
||||||
public int MaxCombo;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ using osu.Game.Rulesets.Mania.Beatmaps;
|
|||||||
using osu.Game.Rulesets.Mania.Difficulty.Preprocessing;
|
using osu.Game.Rulesets.Mania.Difficulty.Preprocessing;
|
||||||
using osu.Game.Rulesets.Mania.Difficulty.Skills;
|
using osu.Game.Rulesets.Mania.Difficulty.Skills;
|
||||||
using osu.Game.Rulesets.Mania.Mods;
|
using osu.Game.Rulesets.Mania.Mods;
|
||||||
|
using osu.Game.Rulesets.Mania.Objects;
|
||||||
using osu.Game.Rulesets.Mania.Scoring;
|
using osu.Game.Rulesets.Mania.Scoring;
|
||||||
using osu.Game.Rulesets.Mods;
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Rulesets.Scoring;
|
using osu.Game.Rulesets.Scoring;
|
||||||
@ -43,6 +44,7 @@ namespace osu.Game.Rulesets.Mania.Difficulty
|
|||||||
Mods = mods,
|
Mods = mods,
|
||||||
// Todo: This int cast is temporary to achieve 1:1 results with osu!stable, and should be removed in the future
|
// Todo: This int cast is temporary to achieve 1:1 results with osu!stable, and should be removed in the future
|
||||||
GreatHitWindow = (int)(hitWindows.WindowFor(HitResult.Great)) / clockRate,
|
GreatHitWindow = (int)(hitWindows.WindowFor(HitResult.Great)) / clockRate,
|
||||||
|
MaxCombo = beatmap.HitObjects.Sum(h => h is HoldNote ? 2 : 1),
|
||||||
Skills = skills
|
Skills = skills
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,5 @@ namespace osu.Game.Rulesets.Osu.Difficulty
|
|||||||
public double SpeedStrain;
|
public double SpeedStrain;
|
||||||
public double ApproachRate;
|
public double ApproachRate;
|
||||||
public double OverallDifficulty;
|
public double OverallDifficulty;
|
||||||
public int MaxCombo;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,5 @@ namespace osu.Game.Rulesets.Taiko.Difficulty
|
|||||||
public class TaikoDifficultyAttributes : DifficultyAttributes
|
public class TaikoDifficultyAttributes : DifficultyAttributes
|
||||||
{
|
{
|
||||||
public double GreatHitWindow;
|
public double GreatHitWindow;
|
||||||
public int MaxCombo;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -207,11 +207,11 @@ namespace osu.Game.Beatmaps
|
|||||||
var calculator = ruleset.CreateDifficultyCalculator(beatmapManager.GetWorkingBeatmap(beatmapInfo));
|
var calculator = ruleset.CreateDifficultyCalculator(beatmapManager.GetWorkingBeatmap(beatmapInfo));
|
||||||
var attributes = calculator.Calculate(key.Mods);
|
var attributes = calculator.Calculate(key.Mods);
|
||||||
|
|
||||||
return difficultyCache[key] = new StarDifficulty(attributes.StarRating);
|
return difficultyCache[key] = new StarDifficulty(attributes.StarRating, attributes.MaxCombo);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
return difficultyCache[key] = new StarDifficulty(0);
|
return difficultyCache[key] = new StarDifficulty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -233,7 +233,7 @@ namespace osu.Game.Beatmaps
|
|||||||
if (beatmapInfo.ID == 0 || rulesetInfo.ID == null)
|
if (beatmapInfo.ID == 0 || rulesetInfo.ID == null)
|
||||||
{
|
{
|
||||||
// If not, fall back to the existing star difficulty (e.g. from an online source).
|
// 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;
|
key = default;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -298,10 +298,12 @@ namespace osu.Game.Beatmaps
|
|||||||
public readonly struct StarDifficulty
|
public readonly struct StarDifficulty
|
||||||
{
|
{
|
||||||
public readonly double Stars;
|
public readonly double Stars;
|
||||||
|
public readonly int MaxCombo;
|
||||||
|
|
||||||
public StarDifficulty(double stars)
|
public StarDifficulty(double stars, int maxCombo)
|
||||||
{
|
{
|
||||||
Stars = stars;
|
Stars = stars;
|
||||||
|
MaxCombo = maxCombo;
|
||||||
|
|
||||||
// Todo: Add more members (BeatmapInfo.DifficultyRating? Attributes? Etc...)
|
// Todo: Add more members (BeatmapInfo.DifficultyRating? Attributes? Etc...)
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// 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.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Colour;
|
using osu.Framework.Graphics.Colour;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
@ -55,6 +56,12 @@ namespace osu.Game.Graphics.Sprites
|
|||||||
set => spriteText.UseFullGlyphHeight = blurredText.UseFullGlyphHeight = value;
|
set => spriteText.UseFullGlyphHeight = blurredText.UseFullGlyphHeight = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Bindable<string> Current
|
||||||
|
{
|
||||||
|
get => spriteText.Current;
|
||||||
|
set => spriteText.Current = value;
|
||||||
|
}
|
||||||
|
|
||||||
public GlowingSpriteText()
|
public GlowingSpriteText()
|
||||||
{
|
{
|
||||||
AutoSizeAxes = Axes.Both;
|
AutoSizeAxes = Axes.Both;
|
||||||
|
@ -72,7 +72,7 @@ namespace osu.Game.Online.Leaderboards
|
|||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(IAPIProvider api, OsuColour colour)
|
private void load(IAPIProvider api, OsuColour colour, ScoreManager scoreManager)
|
||||||
{
|
{
|
||||||
var user = score.User;
|
var user = score.User;
|
||||||
|
|
||||||
@ -194,7 +194,7 @@ namespace osu.Game.Online.Leaderboards
|
|||||||
{
|
{
|
||||||
TextColour = Color4.White,
|
TextColour = Color4.White,
|
||||||
GlowColour = Color4Extensions.FromHex(@"83ccfa"),
|
GlowColour = Color4Extensions.FromHex(@"83ccfa"),
|
||||||
Text = score.TotalScore.ToString(@"N0"),
|
Current = scoreManager.GetBindableTotalScoreString(score),
|
||||||
Font = OsuFont.Numeric.With(size: 23),
|
Font = OsuFont.Numeric.With(size: 23),
|
||||||
},
|
},
|
||||||
RankContainer = new Container
|
RankContainer = new Container
|
||||||
|
@ -58,6 +58,8 @@ namespace osu.Game
|
|||||||
|
|
||||||
protected ScoreManager ScoreManager;
|
protected ScoreManager ScoreManager;
|
||||||
|
|
||||||
|
protected BeatmapDifficultyManager DifficultyManager;
|
||||||
|
|
||||||
protected SkinManager SkinManager;
|
protected SkinManager SkinManager;
|
||||||
|
|
||||||
protected RulesetStore RulesetStore;
|
protected RulesetStore RulesetStore;
|
||||||
@ -197,7 +199,7 @@ namespace osu.Game
|
|||||||
dependencies.Cache(FileStore = new FileStore(contextFactory, Storage));
|
dependencies.Cache(FileStore = new FileStore(contextFactory, Storage));
|
||||||
|
|
||||||
// ordering is important here to ensure foreign keys rules are not broken in ModelStore.Cleanup()
|
// 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, LocalConfig));
|
||||||
dependencies.Cache(BeatmapManager = new BeatmapManager(Storage, contextFactory, RulesetStore, API, Audio, Host, defaultBeatmap, true));
|
dependencies.Cache(BeatmapManager = new BeatmapManager(Storage, contextFactory, RulesetStore, API, Audio, Host, defaultBeatmap, true));
|
||||||
|
|
||||||
// this should likely be moved to ArchiveModelManager when another case appers where it is necessary
|
// this should likely be moved to ArchiveModelManager when another case appers where it is necessary
|
||||||
@ -221,9 +223,8 @@ namespace osu.Game
|
|||||||
ScoreManager.Undelete(getBeatmapScores(item), true);
|
ScoreManager.Undelete(getBeatmapScores(item), true);
|
||||||
});
|
});
|
||||||
|
|
||||||
var difficultyManager = new BeatmapDifficultyManager();
|
dependencies.Cache(DifficultyManager = new BeatmapDifficultyManager());
|
||||||
dependencies.Cache(difficultyManager);
|
AddInternal(DifficultyManager);
|
||||||
AddInternal(difficultyManager);
|
|
||||||
|
|
||||||
dependencies.Cache(KeyBindingStore = new KeyBindingStore(contextFactory, RulesetStore));
|
dependencies.Cache(KeyBindingStore = new KeyBindingStore(contextFactory, RulesetStore));
|
||||||
dependencies.Cache(SettingsStore = new SettingsStore(contextFactory));
|
dependencies.Cache(SettingsStore = new SettingsStore(contextFactory));
|
||||||
|
@ -25,6 +25,9 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
|
|||||||
private const float row_height = 22;
|
private const float row_height = 22;
|
||||||
private const int text_size = 12;
|
private const int text_size = 12;
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private ScoreManager scoreManager { get; set; }
|
||||||
|
|
||||||
private readonly FillFlowContainer backgroundFlow;
|
private readonly FillFlowContainer backgroundFlow;
|
||||||
|
|
||||||
private Color4 highAccuracyColour;
|
private Color4 highAccuracyColour;
|
||||||
@ -121,7 +124,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
|
|||||||
new OsuSpriteText
|
new OsuSpriteText
|
||||||
{
|
{
|
||||||
Margin = new MarginPadding { Right = horizontal_inset },
|
Margin = new MarginPadding { Right = horizontal_inset },
|
||||||
Text = $@"{score.TotalScore:N0}",
|
Current = scoreManager.GetBindableTotalScoreString(score),
|
||||||
Font = OsuFont.GetFont(size: text_size, weight: index == 0 ? FontWeight.Bold : FontWeight.Medium)
|
Font = OsuFont.GetFont(size: text_size, weight: index == 0 ? FontWeight.Bold : FontWeight.Medium)
|
||||||
},
|
},
|
||||||
new OsuSpriteText
|
new OsuSpriteText
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Extensions;
|
using osu.Framework.Extensions;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
@ -38,6 +39,9 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
|
|||||||
private readonly FillFlowContainer<InfoColumn> statisticsColumns;
|
private readonly FillFlowContainer<InfoColumn> statisticsColumns;
|
||||||
private readonly ModsInfoColumn modsColumn;
|
private readonly ModsInfoColumn modsColumn;
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private ScoreManager scoreManager { get; set; }
|
||||||
|
|
||||||
public TopScoreStatisticsSection()
|
public TopScoreStatisticsSection()
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.X;
|
RelativeSizeAxes = Axes.X;
|
||||||
@ -87,6 +91,15 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load()
|
||||||
|
{
|
||||||
|
if (score != null)
|
||||||
|
totalScoreColumn.Current = scoreManager.GetBindableTotalScoreString(score);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ScoreInfo score;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sets the score to be displayed.
|
/// Sets the score to be displayed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -94,7 +107,11 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
|
|||||||
{
|
{
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
totalScoreColumn.Text = $@"{value.TotalScore:N0}";
|
if (score == value)
|
||||||
|
return;
|
||||||
|
|
||||||
|
score = value;
|
||||||
|
|
||||||
accuracyColumn.Text = value.DisplayAccuracy;
|
accuracyColumn.Text = value.DisplayAccuracy;
|
||||||
maxComboColumn.Text = $@"{value.MaxCombo:N0}x";
|
maxComboColumn.Text = $@"{value.MaxCombo:N0}x";
|
||||||
ppColumn.Alpha = value.Beatmap?.Status == BeatmapSetOnlineStatus.Ranked ? 1 : 0;
|
ppColumn.Alpha = value.Beatmap?.Status == BeatmapSetOnlineStatus.Ranked ? 1 : 0;
|
||||||
@ -102,6 +119,9 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
|
|||||||
|
|
||||||
statisticsColumns.ChildrenEnumerable = value.SortedStatistics.Select(kvp => createStatisticsColumn(kvp.Key, kvp.Value));
|
statisticsColumns.ChildrenEnumerable = value.SortedStatistics.Select(kvp => createStatisticsColumn(kvp.Key, kvp.Value));
|
||||||
modsColumn.Mods = value.Mods;
|
modsColumn.Mods = value.Mods;
|
||||||
|
|
||||||
|
if (scoreManager != null)
|
||||||
|
totalScoreColumn.Current = scoreManager.GetBindableTotalScoreString(value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,6 +210,12 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
|
|||||||
{
|
{
|
||||||
set => text.Text = value;
|
set => text.Text = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Bindable<string> Current
|
||||||
|
{
|
||||||
|
get => text.Current;
|
||||||
|
set => text.Current = value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ModsInfoColumn : InfoColumn
|
private class ModsInfoColumn : InfoColumn
|
||||||
|
@ -12,6 +12,7 @@ namespace osu.Game.Rulesets.Difficulty
|
|||||||
public Skill[] Skills;
|
public Skill[] Skills;
|
||||||
|
|
||||||
public double StarRating;
|
public double StarRating;
|
||||||
|
public int MaxCombo;
|
||||||
|
|
||||||
public DifficultyAttributes()
|
public DifficultyAttributes()
|
||||||
{
|
{
|
||||||
|
@ -67,7 +67,7 @@ namespace osu.Game.Rulesets.Scoring
|
|||||||
private readonly double accuracyPortion;
|
private readonly double accuracyPortion;
|
||||||
private readonly double comboPortion;
|
private readonly double comboPortion;
|
||||||
|
|
||||||
private double maxHighestCombo;
|
private int maxHighestCombo;
|
||||||
private double maxBaseScore;
|
private double maxBaseScore;
|
||||||
private double rollingMaxBaseScore;
|
private double rollingMaxBaseScore;
|
||||||
private double baseScore;
|
private double baseScore;
|
||||||
@ -202,20 +202,31 @@ namespace osu.Game.Rulesets.Scoring
|
|||||||
TotalScore.Value = getScore(Mode.Value);
|
TotalScore.Value = getScore(Mode.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private double getScore(ScoringMode mode)
|
private double getScore(ScoringMode mode) => GetScore(mode, maxHighestCombo, baseScore / maxBaseScore, (double)HighestCombo.Value / maxHighestCombo, bonusScore);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Computes the total score.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="mode">The <see cref="ScoringMode"/> to compute the total score in.</param>
|
||||||
|
/// <param name="maxCombo">The maximum combo achievable in the beatmap.</param>
|
||||||
|
/// <param name="accuracyRatio">The accuracy percentage achieved by the player.</param>
|
||||||
|
/// <param name="comboRatio">The proportion of <paramref name="maxCombo"/> achieved by the player.</param>
|
||||||
|
/// <param name="bonusScore">Any bonus score to be added.</param>
|
||||||
|
/// <returns>The total score.</returns>
|
||||||
|
public double GetScore(ScoringMode mode, int maxCombo, double accuracyRatio, double comboRatio, double bonusScore)
|
||||||
{
|
{
|
||||||
switch (mode)
|
switch (mode)
|
||||||
{
|
{
|
||||||
default:
|
default:
|
||||||
case ScoringMode.Standardised:
|
case ScoringMode.Standardised:
|
||||||
double accuracyScore = accuracyPortion * baseScore / maxBaseScore;
|
double accuracyScore = accuracyPortion * accuracyRatio;
|
||||||
double comboScore = comboPortion * HighestCombo.Value / maxHighestCombo;
|
double comboScore = comboPortion * comboRatio;
|
||||||
|
|
||||||
return (max_score * (accuracyScore + comboScore) + bonusScore) * scoreMultiplier;
|
return (max_score * (accuracyScore + comboScore) + bonusScore) * scoreMultiplier;
|
||||||
|
|
||||||
case ScoringMode.Classic:
|
case ScoringMode.Classic:
|
||||||
// should emulate osu-stable's scoring as closely as we can (https://osu.ppy.sh/help/wiki/Score/ScoreV1)
|
// 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 bonusScore + (accuracyRatio * maxCombo * 300) * (1 + Math.Max(0, (comboRatio * maxCombo) - 1) * scoreMultiplier / 25);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,15 +6,20 @@ using System.Collections.Generic;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Linq.Expressions;
|
using System.Linq.Expressions;
|
||||||
|
using System.Threading;
|
||||||
|
using JetBrains.Annotations;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Logging;
|
using osu.Framework.Logging;
|
||||||
using osu.Framework.Platform;
|
using osu.Framework.Platform;
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Configuration;
|
||||||
using osu.Game.Database;
|
using osu.Game.Database;
|
||||||
using osu.Game.IO.Archives;
|
using osu.Game.IO.Archives;
|
||||||
using osu.Game.Online.API;
|
using osu.Game.Online.API;
|
||||||
using osu.Game.Online.API.Requests;
|
using osu.Game.Online.API.Requests;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
|
using osu.Game.Rulesets.Scoring;
|
||||||
using osu.Game.Scoring.Legacy;
|
using osu.Game.Scoring.Legacy;
|
||||||
|
|
||||||
namespace osu.Game.Scoring
|
namespace osu.Game.Scoring
|
||||||
@ -30,11 +35,20 @@ namespace osu.Game.Scoring
|
|||||||
private readonly RulesetStore rulesets;
|
private readonly RulesetStore rulesets;
|
||||||
private readonly Func<BeatmapManager> beatmaps;
|
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;
|
||||||
|
|
||||||
|
[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, OsuConfigManager configManager = null)
|
||||||
: base(storage, contextFactory, api, new ScoreStore(contextFactory, storage), importHost)
|
: base(storage, contextFactory, api, new ScoreStore(contextFactory, storage), importHost)
|
||||||
{
|
{
|
||||||
this.rulesets = rulesets;
|
this.rulesets = rulesets;
|
||||||
this.beatmaps = beatmaps;
|
this.beatmaps = beatmaps;
|
||||||
|
this.difficulties = difficulties;
|
||||||
|
this.configManager = configManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override ScoreInfo CreateModel(ArchiveReader archive)
|
protected override ScoreInfo CreateModel(ArchiveReader archive)
|
||||||
@ -72,5 +86,118 @@ namespace osu.Game.Scoring
|
|||||||
protected override bool CheckLocalAvailability(ScoreInfo model, IQueryable<ScoreInfo> items)
|
protected override bool CheckLocalAvailability(ScoreInfo model, IQueryable<ScoreInfo> items)
|
||||||
=> base.CheckLocalAvailability(model, items)
|
=> base.CheckLocalAvailability(model, items)
|
||||||
|| (model.OnlineScoreID != null && items.Any(i => i.OnlineScoreID == model.OnlineScoreID));
|
|| (model.OnlineScoreID != null && items.Any(i => i.OnlineScoreID == model.OnlineScoreID));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieves a bindable that represents the total score of a <see cref="ScoreInfo"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Responds to changes in the currently-selected <see cref="ScoringMode"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="score">The <see cref="ScoreInfo"/> to retrieve the bindable for.</param>
|
||||||
|
/// <returns>The bindable containing the total score.</returns>
|
||||||
|
public Bindable<long> GetBindableTotalScore(ScoreInfo score)
|
||||||
|
{
|
||||||
|
var bindable = new TotalScoreBindable(score, difficulties);
|
||||||
|
configManager?.BindWith(OsuSetting.ScoreDisplayMode, bindable.ScoringMode);
|
||||||
|
return bindable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieves a bindable that represents the formatted total score string of a <see cref="ScoreInfo"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Responds to changes in the currently-selected <see cref="ScoringMode"/>.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="score">The <see cref="ScoreInfo"/> to retrieve the bindable for.</param>
|
||||||
|
/// <returns>The bindable containing the formatted total score string.</returns>
|
||||||
|
public Bindable<string> GetBindableTotalScoreString(ScoreInfo score) => new TotalScoreStringBindable(GetBindableTotalScore(score));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Provides the total score of a <see cref="ScoreInfo"/>. Responds to changes in the currently-selected <see cref="ScoringMode"/>.
|
||||||
|
/// </summary>
|
||||||
|
private class TotalScoreBindable : Bindable<long>
|
||||||
|
{
|
||||||
|
public readonly Bindable<ScoringMode> ScoringMode = new Bindable<ScoringMode>();
|
||||||
|
|
||||||
|
private readonly ScoreInfo score;
|
||||||
|
private readonly Func<BeatmapDifficultyManager> difficulties;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new <see cref="TotalScoreBindable"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="score">The <see cref="ScoreInfo"/> to provide the total score of.</param>
|
||||||
|
/// <param name="difficulties">A function to retrieve the <see cref="BeatmapDifficultyManager"/>.</param>
|
||||||
|
public TotalScoreBindable(ScoreInfo score, Func<BeatmapDifficultyManager> difficulties)
|
||||||
|
{
|
||||||
|
this.score = score;
|
||||||
|
this.difficulties = difficulties;
|
||||||
|
|
||||||
|
ScoringMode.BindValueChanged(onScoringModeChanged, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private IBindable<StarDifficulty> difficultyBindable;
|
||||||
|
private CancellationTokenSource difficultyCancellationSource;
|
||||||
|
|
||||||
|
private void onScoringModeChanged(ValueChangedEvent<ScoringMode> mode)
|
||||||
|
{
|
||||||
|
difficultyCancellationSource?.Cancel();
|
||||||
|
difficultyCancellationSource = null;
|
||||||
|
|
||||||
|
if (score.Beatmap == null)
|
||||||
|
{
|
||||||
|
Value = score.TotalScore;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int? beatmapMaxCombo = score.Beatmap.MaxCombo;
|
||||||
|
|
||||||
|
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;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We can compute the max combo locally after the async beatmap difficulty computation.
|
||||||
|
difficultyBindable = difficulties().GetBindableDifficulty(score.Beatmap, score.Ruleset, score.Mods, (difficultyCancellationSource = new CancellationTokenSource()).Token);
|
||||||
|
difficultyBindable.BindValueChanged(d => updateScore(d.NewValue.MaxCombo), true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
updateScore(beatmapMaxCombo.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateScore(int beatmapMaxCombo)
|
||||||
|
{
|
||||||
|
if (beatmapMaxCombo == 0)
|
||||||
|
{
|
||||||
|
Value = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var ruleset = score.Ruleset.CreateInstance();
|
||||||
|
var scoreProcessor = ruleset.CreateScoreProcessor();
|
||||||
|
|
||||||
|
scoreProcessor.Mods.Value = score.Mods;
|
||||||
|
|
||||||
|
Value = (long)Math.Round(scoreProcessor.GetScore(ScoringMode.Value, beatmapMaxCombo, score.Accuracy, (double)score.MaxCombo / beatmapMaxCombo, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Provides the total score of a <see cref="ScoreInfo"/> as a formatted string. Responds to changes in the currently-selected <see cref="ScoringMode"/>.
|
||||||
|
/// </summary>
|
||||||
|
private class TotalScoreStringBindable : Bindable<string>
|
||||||
|
{
|
||||||
|
// ReSharper disable once PrivateFieldCanBeConvertedToLocalVariable (need to hold a reference)
|
||||||
|
private readonly IBindable<long> totalScore;
|
||||||
|
|
||||||
|
public TotalScoreStringBindable(IBindable<long> totalScore)
|
||||||
|
{
|
||||||
|
this.totalScore = totalScore;
|
||||||
|
this.totalScore.BindValueChanged(v => Value = v.NewValue.ToString("N0"), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,9 @@ namespace osu.Game.Screens.Ranking.Contracted
|
|||||||
{
|
{
|
||||||
private readonly ScoreInfo score;
|
private readonly ScoreInfo score;
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private ScoreManager scoreManager { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new <see cref="ContractedPanelMiddleContent"/>.
|
/// Creates a new <see cref="ContractedPanelMiddleContent"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -160,7 +163,7 @@ namespace osu.Game.Screens.Ranking.Contracted
|
|||||||
{
|
{
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
Text = score.TotalScore.ToString("N0"),
|
Current = scoreManager.GetBindableTotalScoreString(score),
|
||||||
Font = OsuFont.GetFont(size: 20, weight: FontWeight.Medium, fixedWidth: true),
|
Font = OsuFont.GetFont(size: 20, weight: FontWeight.Medium, fixedWidth: true),
|
||||||
Spacing = new Vector2(-1, 0)
|
Spacing = new Vector2(-1, 0)
|
||||||
},
|
},
|
||||||
|
@ -25,15 +25,16 @@ namespace osu.Game.Screens.Ranking.Expanded
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class ExpandedPanelMiddleContent : CompositeDrawable
|
public class ExpandedPanelMiddleContent : CompositeDrawable
|
||||||
{
|
{
|
||||||
private readonly ScoreInfo score;
|
private const float padding = 10;
|
||||||
|
|
||||||
|
private readonly ScoreInfo score;
|
||||||
private readonly List<StatisticDisplay> statisticDisplays = new List<StatisticDisplay>();
|
private readonly List<StatisticDisplay> statisticDisplays = new List<StatisticDisplay>();
|
||||||
|
|
||||||
private FillFlowContainer starAndModDisplay;
|
private FillFlowContainer starAndModDisplay;
|
||||||
|
|
||||||
private RollingCounter<long> scoreCounter;
|
private RollingCounter<long> scoreCounter;
|
||||||
|
|
||||||
private const float padding = 10;
|
[Resolved]
|
||||||
|
private ScoreManager scoreManager { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new <see cref="ExpandedPanelMiddleContent"/>.
|
/// Creates a new <see cref="ExpandedPanelMiddleContent"/>.
|
||||||
@ -238,7 +239,7 @@ namespace osu.Game.Screens.Ranking.Expanded
|
|||||||
using (BeginDelayedSequence(AccuracyCircle.ACCURACY_TRANSFORM_DELAY, true))
|
using (BeginDelayedSequence(AccuracyCircle.ACCURACY_TRANSFORM_DELAY, true))
|
||||||
{
|
{
|
||||||
scoreCounter.FadeIn();
|
scoreCounter.FadeIn();
|
||||||
scoreCounter.Current.Value = score.TotalScore;
|
scoreCounter.Current = scoreManager.GetBindableTotalScore(score);
|
||||||
|
|
||||||
double delay = 0;
|
double delay = 0;
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user