diff --git a/osu.Game/Rulesets/Judgements/DrawableJudgement.cs b/osu.Game/Rulesets/Judgements/DrawableJudgement.cs
index 5de14ae579..65b2ef75c4 100644
--- a/osu.Game/Rulesets/Judgements/DrawableJudgement.cs
+++ b/osu.Game/Rulesets/Judgements/DrawableJudgement.cs
@@ -25,7 +25,7 @@ public class DrawableJudgement : Container
private OsuColour colours;
- protected readonly Judgement Judgement;
+ protected readonly JudgementResult Result;
public readonly DrawableHitObject JudgedObject;
@@ -34,11 +34,11 @@ public class DrawableJudgement : Container
///
/// Creates a drawable which visualises a .
///
- /// The judgement to visualise.
+ /// The judgement to visualise.
/// The object which was judged.
- public DrawableJudgement(Judgement judgement, DrawableHitObject judgedObject)
+ public DrawableJudgement(JudgementResult result, DrawableHitObject judgedObject)
{
- Judgement = judgement;
+ Result = result;
JudgedObject = judgedObject;
Size = new Vector2(judgement_size);
@@ -49,11 +49,11 @@ private void load(OsuColour colours)
{
this.colours = colours;
- Child = new SkinnableDrawable($"Play/{Judgement.Result}", _ => JudgementText = new OsuSpriteText
+ Child = new SkinnableDrawable($"Play/{Result.Type}", _ => JudgementText = new OsuSpriteText
{
- Text = Judgement.Result.GetDescription().ToUpperInvariant(),
+ Text = Result.Type.GetDescription().ToUpperInvariant(),
Font = @"Venera",
- Colour = judgementColour(Judgement.Result),
+ Colour = judgementColour(Result.Type),
Scale = new Vector2(0.85f, 1),
TextSize = 12
}, restrictSize: false);
@@ -65,7 +65,7 @@ protected override void LoadComplete()
this.FadeInFromZero(100, Easing.OutQuint);
- switch (Judgement.Result)
+ switch (Result.Type)
{
case HitResult.None:
break;
diff --git a/osu.Game/Rulesets/Judgements/Judgement.cs b/osu.Game/Rulesets/Judgements/Judgement.cs
index 63378e57cc..5fddbe0b0a 100644
--- a/osu.Game/Rulesets/Judgements/Judgement.cs
+++ b/osu.Game/Rulesets/Judgements/Judgement.cs
@@ -1,74 +1,44 @@
// Copyright (c) 2007-2018 ppy Pty Ltd .
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
-using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Judgements
{
public class Judgement
{
- ///
- /// Whether this judgement is the result of a hit or a miss.
- ///
- public HitResult Result;
-
///
/// The maximum that can be achieved.
///
public virtual HitResult MaxResult => HitResult.Perfect;
///
- /// The combo prior to this judgement occurring.
- ///
- public int ComboAtJudgement;
-
- ///
- /// The highest combo achieved prior to this judgement occurring.
- ///
- public int HighestComboAtJudgement;
-
- ///
- /// Whether this has a result.
- ///
- public bool HasResult => Result > HitResult.None;
-
- ///
- /// Whether a successful hit occurred.
- ///
- public bool IsHit => Result > HitResult.Miss;
-
- ///
- /// The offset from a perfect hit at which this judgement occurred.
- /// Populated when added via .
- ///
- public double TimeOffset { get; set; }
-
- ///
- /// Whether the should affect the current combo.
+ /// Whether this should affect the current combo.
///
public virtual bool AffectsCombo => true;
///
- /// Whether the should be counted as base (combo) or bonus score.
+ /// Whether this should be counted as base (combo) or bonus score.
///
public virtual bool IsBonus => !AffectsCombo;
///
- /// The numeric representation for the result achieved.
- ///
- public int NumericResult => NumericResultFor(Result);
-
- ///
- /// The numeric representation for the maximum achievable result.
+ /// The numeric score representation for the maximum achievable result.
///
public int MaxNumericResult => NumericResultFor(MaxResult);
///
- /// Convert a to a numeric score representation.
+ /// Retrieves the numeric score representation of a .
///
- /// The value to convert.
- /// The number.
+ /// The to find the numeric score representation for.
+ /// The numeric score representation of .
protected virtual int NumericResultFor(HitResult result) => result > HitResult.Miss ? 1 : 0;
+
+ ///
+ /// Retrieves the numeric score representation of a .
+ ///
+ /// The to find the numeric score representation for.
+ /// The numeric score representation of .
+ public int NumericResultFor(JudgementResult result) => NumericResultFor(result.Type);
}
}
diff --git a/osu.Game/Rulesets/Judgements/JudgementResult.cs b/osu.Game/Rulesets/Judgements/JudgementResult.cs
new file mode 100644
index 0000000000..6971fcf593
--- /dev/null
+++ b/osu.Game/Rulesets/Judgements/JudgementResult.cs
@@ -0,0 +1,51 @@
+// Copyright (c) 2007-2018 ppy Pty Ltd .
+// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
+
+using osu.Game.Rulesets.Scoring;
+
+namespace osu.Game.Rulesets.Judgements
+{
+ public class JudgementResult
+ {
+ ///
+ /// Whether this is the result of a hit or a miss.
+ ///
+ public HitResult Type;
+
+ ///
+ /// The which this applies for.
+ ///
+ public readonly Judgement Judgement;
+
+ ///
+ /// The offset from a perfect hit at which this occurred.
+ /// Populated when added via .
+ ///
+ public double TimeOffset { get; internal set; }
+
+ ///
+ /// The combo prior to this judgement occurring.
+ ///
+ public int ComboAtJudgement { get; internal set; }
+
+ ///
+ /// The highest combo achieved prior to this judgement occurring.
+ ///
+ public int HighestComboAtJudgement { get; internal set; }
+
+ ///
+ /// Whether this has a result.
+ ///
+ public bool HasResult => Type > HitResult.None;
+
+ ///
+ /// Whether a successful hit occurred.
+ ///
+ public bool IsHit => Type > HitResult.Miss;
+
+ public JudgementResult(Judgement judgement)
+ {
+ Judgement = judgement;
+ }
+ }
+}
diff --git a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs
index b767834e5d..27de18177f 100644
--- a/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs
+++ b/osu.Game/Rulesets/Objects/Drawables/DrawableHitObject.cs
@@ -35,8 +35,8 @@ public abstract class DrawableHitObject : SkinReloadableDrawable, IHasAccentColo
private readonly Lazy> nestedHitObjects = new Lazy>();
public IEnumerable NestedHitObjects => nestedHitObjects.IsValueCreated ? nestedHitObjects.Value : Enumerable.Empty();
- public event Action OnJudgement;
- public event Action OnJudgementRemoved;
+ public event Action OnJudgement;
+ public event Action OnJudgementRemoved;
///
/// Whether a visible judgement should be displayed when this representation is hit.
@@ -46,7 +46,7 @@ public abstract class DrawableHitObject : SkinReloadableDrawable, IHasAccentColo
///
/// Whether this and all of its nested s have been hit.
///
- public bool IsHit => HitObject.Judgements.All(j => j.IsHit) && NestedHitObjects.All(n => n.IsHit);
+ public bool IsHit => Results.All(j => j.IsHit) && NestedHitObjects.All(n => n.IsHit);
///
/// Whether this and all of its nested s have been judged.
@@ -57,7 +57,10 @@ public abstract class DrawableHitObject : SkinReloadableDrawable, IHasAccentColo
/// Whether this has been judged.
/// Note: This does NOT include nested hitobjects.
///
- public bool Judged => HitObject.Judgements.All(h => h.HasResult);
+ public bool Judged => Results.All(h => h.HasResult);
+
+ private readonly List results = new List();
+ public IReadOnlyList Results => results;
private bool judgementOccurred;
@@ -74,6 +77,9 @@ public abstract class DrawableHitObject : SkinReloadableDrawable, IHasAccentColo
protected DrawableHitObject(HitObject hitObject)
{
HitObject = hitObject;
+
+ foreach (var j in hitObject.Judgements)
+ results.Add(CreateJudgementResult(j));
}
[BackgroundDependencyLoader]
@@ -135,17 +141,17 @@ protected override void Update()
{
var endTime = (HitObject as IHasEndTime)?.EndTime ?? HitObject.StartTime;
- for (int i = HitObject.Judgements.Count - 1; i >= 0; i--)
+ for (int i = Results.Count - 1; i >= 0; i--)
{
- var judgement = HitObject.Judgements[i];
+ var judgement = Results[i];
if (judgement.TimeOffset + endTime <= Time.Current)
break;
- judgement.Result = HitResult.None;
- State.Value = ArmedState.Idle;
-
OnJudgementRemoved?.Invoke(this, judgement);
+
+ judgement.Type = HitResult.None;
+ State.Value = ArmedState.Idle;
}
}
@@ -161,8 +167,8 @@ protected override void UpdateAfterChildren()
protected virtual void AddNested(DrawableHitObject h)
{
- h.OnJudgement += (d, j) => OnJudgement?.Invoke(d, j);
- h.OnJudgementRemoved += (d, j) => OnJudgementRemoved?.Invoke(d, j);
+ h.OnJudgement += (d, r) => OnJudgement?.Invoke(d, r);
+ h.OnJudgementRemoved += (d, r) => OnJudgementRemoved?.Invoke(d, r);
h.ApplyCustomUpdateState += (d, j) => ApplyCustomUpdateState?.Invoke(d, j);
nestedHitObjects.Value.Add(h);
@@ -172,18 +178,21 @@ protected virtual void AddNested(DrawableHitObject h)
/// Notifies that a new judgement has occurred for this .
///
/// The .
- protected void ApplyJudgement(T judgement, Action application)
- where T : Judgement
+ protected void ApplyResult(JudgementResult result, Action application)
{
- judgementOccurred = true;
+ // Todo: Unsure if we want to keep this
+ if (!Results.Contains(result))
+ throw new ArgumentException($"The applied judgement result must be a part of {Results}.");
- application?.Invoke(judgement);
+ application?.Invoke(result);
+
+ judgementOccurred = true;
// Ensure that the judgement is given a valid time offset, because this may not get set by the caller
var endTime = (HitObject as IHasEndTime)?.EndTime ?? HitObject.StartTime;
- judgement.TimeOffset = Time.Current - endTime;
+ result.TimeOffset = Time.Current - endTime;
- switch (judgement.Result)
+ switch (result.Type)
{
case HitResult.None:
break;
@@ -195,7 +204,7 @@ protected void ApplyJudgement(T judgement, Action application)
break;
}
- OnJudgement?.Invoke(this, judgement);
+ OnJudgement?.Invoke(this, result);
}
///
@@ -224,7 +233,7 @@ protected bool UpdateJudgement(bool userTriggered)
///
/// Checks if any judgements have occurred for this . This method must construct
- /// all s and notify of them through .
+ /// all s and notify of them through .
///
/// Whether the user triggered this check.
/// The offset from the end time at which this check occurred. A > 0
@@ -232,6 +241,8 @@ protected bool UpdateJudgement(bool userTriggered)
protected virtual void CheckForJudgements(bool userTriggered, double timeOffset)
{
}
+
+ protected virtual JudgementResult CreateJudgementResult(Judgement judgement) => new JudgementResult(judgement);
}
public abstract class DrawableHitObject : DrawableHitObject
diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs
index fa8c11df7f..ccd3fb6e69 100644
--- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs
+++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs
@@ -28,7 +28,7 @@ public abstract class ScoreProcessor
///
/// Invoked when a new judgement has occurred. This occurs after the judgement has been processed by the .
///
- public event Action NewJudgement;
+ public event Action NewJudgement;
///
/// Additional conditions on top of that cause a failing state.
@@ -144,9 +144,10 @@ protected void UpdateFailed()
/// Notifies subscribers of that a new judgement has occurred.
///
/// The judgement to notify subscribers of.
- protected void NotifyNewJudgement(Judgement judgement)
+ /// The judgement scoring result to notify subscribers of.
+ protected void NotifyNewJudgement(JudgementResult result)
{
- NewJudgement?.Invoke(judgement);
+ NewJudgement?.Invoke(result);
if (HasCompleted)
AllJudged?.Invoke();
@@ -209,32 +210,47 @@ public ScoreProcessor(RulesetContainer rulesetContainer)
Mode.ValueChanged += _ => updateScore();
}
- ///
- /// Simulates an autoplay of s that will be judged by this
- /// by adding s for each in the .
- ///
- /// This is required for to work, otherwise will be used.
- ///
- ///
- /// The containing the s that will be judged by this .
- protected virtual void SimulateAutoplay(Beatmap beatmap) { }
+ protected virtual void ApplyBeatmap(Beatmap beatmap)
+ {
+ }
+
+ protected virtual void SimulateAutoplay(Beatmap beatmap)
+ {
+ foreach (var obj in beatmap.HitObjects)
+ simulate(obj);
+
+ void simulate(HitObject obj)
+ {
+ foreach (var nested in obj.NestedHitObjects)
+ simulate(nested);
+
+ foreach (var judgement in obj.Judgements)
+ AddJudgement(new JudgementResult(judgement) { Type = judgement.MaxResult });
+ }
+ }
///
/// Adds a judgement to this ScoreProcessor.
///
/// The judgement to add.
- protected void AddJudgement(Judgement judgement)
+ /// The judgement scoring result.
+ protected void AddJudgement(JudgementResult result)
{
- OnNewJudgement(judgement);
+ OnNewJudgement(result);
updateScore();
UpdateFailed();
- NotifyNewJudgement(judgement);
+ NotifyNewJudgement(result);
}
- protected void RemoveJudgement(Judgement judgement)
+ ///
+ /// Removes a judgement from this ScoreProcessor.
+ ///
+ /// The judgement to remove.
+ /// The judgement scoring result.
+ protected void RemoveJudgement(JudgementResult result)
{
- OnJudgementRemoved(judgement);
+ OnJudgementRemoved(result);
updateScore();
}
@@ -242,16 +258,17 @@ protected void RemoveJudgement(Judgement judgement)
/// Applies a judgement.
///
/// The judgement to apply/
- protected virtual void OnNewJudgement(Judgement judgement)
+ /// The judgement scoring result.
+ protected virtual void OnNewJudgement(JudgementResult result)
{
- judgement.ComboAtJudgement = Combo;
- judgement.HighestComboAtJudgement = HighestCombo;
+ result.ComboAtJudgement = Combo;
+ result.HighestComboAtJudgement = HighestCombo;
JudgedHits++;
- if (judgement.AffectsCombo)
+ if (result.Judgement.AffectsCombo)
{
- switch (judgement.Result)
+ switch (result.Type)
{
case HitResult.None:
break;
@@ -264,15 +281,15 @@ protected virtual void OnNewJudgement(Judgement judgement)
}
}
- if (judgement.IsBonus)
+ if (result.Judgement.IsBonus)
{
- if (judgement.IsHit)
- bonusScore += judgement.NumericResult;
+ if (result.IsHit)
+ bonusScore += result.Judgement.NumericResultFor(result);
}
else
{
- baseScore += judgement.NumericResult;
- rollingMaxBaseScore += judgement.MaxNumericResult;
+ baseScore += result.Judgement.NumericResultFor(result);
+ rollingMaxBaseScore += result.Judgement.MaxNumericResult;
}
}
@@ -280,22 +297,23 @@ protected virtual void OnNewJudgement(Judgement judgement)
/// Removes a judgement. This should reverse everything in .
///
/// The judgement to remove.
- protected virtual void OnJudgementRemoved(Judgement judgement)
+ /// The judgement scoring result.
+ protected virtual void OnJudgementRemoved(JudgementResult result)
{
- Combo.Value = judgement.ComboAtJudgement;
- HighestCombo.Value = judgement.HighestComboAtJudgement;
+ Combo.Value = result.ComboAtJudgement;
+ HighestCombo.Value = result.HighestComboAtJudgement;
JudgedHits--;
- if (judgement.IsBonus)
+ if (result.Judgement.IsBonus)
{
- if (judgement.IsHit)
- bonusScore -= judgement.NumericResult;
+ if (result.IsHit)
+ bonusScore -= result.Judgement.NumericResultFor(result);
}
else
{
- baseScore -= judgement.NumericResult;
- rollingMaxBaseScore -= judgement.MaxNumericResult;
+ baseScore -= result.Judgement.NumericResultFor(result);
+ rollingMaxBaseScore -= result.Judgement.MaxNumericResult;
}
}
diff --git a/osu.Game/Rulesets/UI/RulesetContainer.cs b/osu.Game/Rulesets/UI/RulesetContainer.cs
index ee34e2df04..e890cccc3c 100644
--- a/osu.Game/Rulesets/UI/RulesetContainer.cs
+++ b/osu.Game/Rulesets/UI/RulesetContainer.cs
@@ -182,8 +182,8 @@ protected override void Dispose(bool isDisposing)
public abstract class RulesetContainer : RulesetContainer
where TObject : HitObject
{
- public event Action OnJudgement;
- public event Action OnJudgementRemoved;
+ public event Action OnJudgement;
+ public event Action OnJudgementRemoved;
///
/// The Beatmap
@@ -290,8 +290,8 @@ private void loadObjects()
if (drawableObject == null)
continue;
- drawableObject.OnJudgement += (d, j) => OnJudgement?.Invoke(j);
- drawableObject.OnJudgementRemoved += (d, j) => OnJudgementRemoved?.Invoke(j);
+ drawableObject.OnJudgement += (_, r) => OnJudgement?.Invoke(r);
+ drawableObject.OnJudgementRemoved += (_, r) => OnJudgementRemoved?.Invoke(r);
Playfield.Add(drawableObject);
}
diff --git a/osu.Game/Screens/Play/HUD/StandardHealthDisplay.cs b/osu.Game/Screens/Play/HUD/StandardHealthDisplay.cs
index ab446550a6..b551b1f7a6 100644
--- a/osu.Game/Screens/Play/HUD/StandardHealthDisplay.cs
+++ b/osu.Game/Screens/Play/HUD/StandardHealthDisplay.cs
@@ -92,9 +92,9 @@ public StandardHealthDisplay()
};
}
- public void Flash(Judgement judgement)
+ public void Flash(JudgementResult result)
{
- if (judgement.Result == HitResult.Miss)
+ if (result.Type == HitResult.Miss)
return;
fill.FadeEdgeEffectTo(Math.Min(1, fill.EdgeEffect.Colour.Linear.A + (1f - base_glow_opacity) / glow_max_hits), 50, Easing.OutQuint)