mirror of
https://github.com/ppy/osu.git
synced 2025-02-20 11:03:05 +08:00
Combine Judgement.HitResults into one.
This commit is contained in:
parent
d69b8d7784
commit
84c22df3f5
@ -6,7 +6,6 @@ using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Timing;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Osu.Judgements;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
using osu.Game.Rulesets.Osu.Objects.Drawables;
|
||||
using OpenTK;
|
||||
@ -110,10 +109,7 @@ namespace osu.Desktop.Tests.Visual
|
||||
h.Depth = depth++;
|
||||
|
||||
if (auto)
|
||||
{
|
||||
h.State = ArmedState.Hit;
|
||||
h.Judgement = new OsuJudgement { Result = HitResult.Hit };
|
||||
}
|
||||
|
||||
playfieldContainer.Add(h);
|
||||
var proxyable = h as IDrawableHitObjectWithProxiedApproach;
|
||||
|
@ -185,7 +185,7 @@ namespace osu.Desktop.Tests.Visual
|
||||
});
|
||||
}
|
||||
|
||||
protected override TestJudgement CreateJudgement() => new TestJudgement();
|
||||
protected TestJudgement CreateJudgement() => new TestJudgement();
|
||||
|
||||
protected override void UpdateState(ArmedState state)
|
||||
{
|
||||
@ -221,8 +221,6 @@ namespace osu.Desktop.Tests.Visual
|
||||
|
||||
private class TestJudgement : Judgement
|
||||
{
|
||||
public override string ResultString { get { throw new NotImplementedException(); } }
|
||||
public override string MaxResultString { get { throw new NotImplementedException(); } }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -128,7 +128,7 @@ namespace osu.Desktop.Tests.Visual
|
||||
|
||||
private void addHitJudgement(bool kiai)
|
||||
{
|
||||
TaikoHitResult hitResult = RNG.Next(2) == 0 ? TaikoHitResult.Good : TaikoHitResult.Great;
|
||||
HitResult hitResult = RNG.Next(2) == 0 ? HitResult.Good : HitResult.Great;
|
||||
|
||||
var cpi = new ControlPointInfo();
|
||||
cpi.EffectPoints.Add(new EffectControlPoint
|
||||
@ -141,11 +141,10 @@ namespace osu.Desktop.Tests.Visual
|
||||
|
||||
var h = new DrawableTestHit(hit)
|
||||
{
|
||||
X = RNG.NextSingle(hitResult == TaikoHitResult.Good ? -0.1f : -0.05f, hitResult == TaikoHitResult.Good ? 0.1f : 0.05f),
|
||||
X = RNG.NextSingle(hitResult == HitResult.Good ? -0.1f : -0.05f, hitResult == HitResult.Good ? 0.1f : 0.05f),
|
||||
Judgement = new TaikoJudgement
|
||||
{
|
||||
Result = HitResult.Hit,
|
||||
TaikoResult = hitResult,
|
||||
Result = hitResult,
|
||||
TimeOffset = 0
|
||||
}
|
||||
};
|
||||
@ -237,7 +236,7 @@ namespace osu.Desktop.Tests.Visual
|
||||
{
|
||||
}
|
||||
|
||||
protected override TaikoJudgement CreateJudgement() => new TaikoJudgement();
|
||||
protected TaikoJudgement CreateJudgement() => new TaikoJudgement();
|
||||
|
||||
protected override void UpdateState(ArmedState state)
|
||||
{
|
||||
|
@ -7,8 +7,6 @@ namespace osu.Game.Rulesets.Catch.Judgements
|
||||
{
|
||||
public class CatchJudgement : Judgement
|
||||
{
|
||||
public override string ResultString => string.Empty;
|
||||
|
||||
public override string MaxResultString => string.Empty;
|
||||
// todo: wangs
|
||||
}
|
||||
}
|
||||
|
@ -98,14 +98,12 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable
|
||||
};
|
||||
}
|
||||
|
||||
protected override CatchJudgement CreateJudgement() => new CatchJudgement();
|
||||
|
||||
private const float preempt = 1000;
|
||||
|
||||
protected override void CheckJudgement(bool userTriggered)
|
||||
{
|
||||
if (Judgement.TimeOffset > 0)
|
||||
Judgement.Result = CheckPosition?.Invoke(HitObject) ?? false ? HitResult.Hit : HitResult.Miss;
|
||||
Judgement.Result = CheckPosition?.Invoke(HitObject) ?? false ? HitResult.Perfect : HitResult.Miss;
|
||||
}
|
||||
|
||||
protected override void UpdateState(ArmedState state)
|
||||
|
@ -55,7 +55,7 @@ namespace osu.Game.Rulesets.Catch.UI
|
||||
|
||||
private void Fruit_OnJudgement(DrawableHitObject<CatchBaseHit, CatchJudgement> obj)
|
||||
{
|
||||
if (obj.Judgement.Result == HitResult.Hit)
|
||||
if (obj.Judgement.Result > HitResult.Miss)
|
||||
{
|
||||
Vector2 screenPosition = obj.ScreenSpaceDrawQuad.Centre;
|
||||
Remove(obj);
|
||||
|
@ -2,6 +2,7 @@
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Judgements
|
||||
{
|
||||
@ -145,18 +146,18 @@ namespace osu.Game.Rulesets.Mania.Judgements
|
||||
/// </summary>
|
||||
/// <param name="hitOffset">The time offset.</param>
|
||||
/// <returns>The hit result, or null if the time offset results in a miss.</returns>
|
||||
public ManiaHitResult? ResultFor(double hitOffset)
|
||||
public HitResult? ResultFor(double hitOffset)
|
||||
{
|
||||
if (hitOffset <= Perfect / 2)
|
||||
return ManiaHitResult.Perfect;
|
||||
return HitResult.Perfect;
|
||||
if (hitOffset <= Great / 2)
|
||||
return ManiaHitResult.Great;
|
||||
return HitResult.Great;
|
||||
if (hitOffset <= Good / 2)
|
||||
return ManiaHitResult.Good;
|
||||
return HitResult.Good;
|
||||
if (hitOffset <= Ok / 2)
|
||||
return ManiaHitResult.Ok;
|
||||
return HitResult.Ok;
|
||||
if (hitOffset <= Bad / 2)
|
||||
return ManiaHitResult.Bad;
|
||||
return HitResult.Meh;
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Judgements
|
||||
{
|
||||
public class HoldNoteTailJudgement : ManiaJudgement
|
||||
@ -10,27 +12,27 @@ namespace osu.Game.Rulesets.Mania.Judgements
|
||||
/// </summary>
|
||||
public bool HasBroken;
|
||||
|
||||
public override int NumericResultForScore(ManiaHitResult result)
|
||||
protected override int NumericResultFor(HitResult result)
|
||||
{
|
||||
switch (result)
|
||||
{
|
||||
default:
|
||||
return base.NumericResultForScore(result);
|
||||
case ManiaHitResult.Great:
|
||||
case ManiaHitResult.Perfect:
|
||||
return base.NumericResultForScore(HasBroken ? ManiaHitResult.Good : result);
|
||||
return base.NumericResultFor(result);
|
||||
case HitResult.Great:
|
||||
case HitResult.Perfect:
|
||||
return base.NumericResultFor(HasBroken ? HitResult.Good : result);
|
||||
}
|
||||
}
|
||||
|
||||
public override int NumericResultForAccuracy(ManiaHitResult result)
|
||||
protected override int NumericResultForAccuracy(HitResult result)
|
||||
{
|
||||
switch (result)
|
||||
{
|
||||
default:
|
||||
return base.NumericResultForAccuracy(result);
|
||||
case ManiaHitResult.Great:
|
||||
case ManiaHitResult.Perfect:
|
||||
return base.NumericResultForAccuracy(HasBroken ? ManiaHitResult.Good : result);
|
||||
case HitResult.Great:
|
||||
case HitResult.Perfect:
|
||||
return base.NumericResultForAccuracy(HasBroken ? HitResult.Good : result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,13 +1,15 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Judgements
|
||||
{
|
||||
public class HoldNoteTickJudgement : ManiaJudgement
|
||||
{
|
||||
public override bool AffectsCombo => false;
|
||||
|
||||
public override int NumericResultForScore(ManiaHitResult result) => 20;
|
||||
public override int NumericResultForAccuracy(ManiaHitResult result) => 0; // Don't count ticks into accuracy
|
||||
protected override int NumericResultFor(HitResult result) => 20;
|
||||
protected override int NumericResultForAccuracy(HitResult result) => 0; // Don't count ticks into accuracy
|
||||
}
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Judgements
|
||||
{
|
||||
public enum ManiaHitResult
|
||||
{
|
||||
[Description("PERFECT")]
|
||||
Perfect,
|
||||
[Description("GREAT")]
|
||||
Great,
|
||||
[Description("GOOD")]
|
||||
Good,
|
||||
[Description("OK")]
|
||||
Ok,
|
||||
[Description("BAD")]
|
||||
Bad
|
||||
}
|
||||
}
|
@ -8,73 +8,49 @@ namespace osu.Game.Rulesets.Mania.Judgements
|
||||
{
|
||||
public class ManiaJudgement : Judgement
|
||||
{
|
||||
/// <summary>
|
||||
/// The maximum possible hit result.
|
||||
/// </summary>
|
||||
public const ManiaHitResult MAX_HIT_RESULT = ManiaHitResult.Perfect;
|
||||
|
||||
/// <summary>
|
||||
/// The result value for the combo portion of the score.
|
||||
/// </summary>
|
||||
public int ResultValueForScore => Result == HitResult.Miss ? 0 : NumericResultForScore(ManiaResult);
|
||||
|
||||
/// <summary>
|
||||
/// The result value for the accuracy portion of the score.
|
||||
/// </summary>
|
||||
public int ResultValueForAccuracy => Result == HitResult.Miss ? 0 : NumericResultForAccuracy(ManiaResult);
|
||||
|
||||
/// <summary>
|
||||
/// The maximum result value for the combo portion of the score.
|
||||
/// </summary>
|
||||
public int MaxResultValueForScore => NumericResultForScore(MAX_HIT_RESULT);
|
||||
|
||||
/// <summary>
|
||||
/// The maximum result value for the accuracy portion of the score.
|
||||
/// </summary>
|
||||
public int MaxResultValueForAccuracy => NumericResultForAccuracy(MAX_HIT_RESULT);
|
||||
public int MaxNumericAccuracyResult => NumericResultForAccuracy(HitResult.Perfect);
|
||||
|
||||
public override string ResultString => string.Empty;
|
||||
|
||||
public override string MaxResultString => string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// The hit result.
|
||||
/// </summary>
|
||||
public ManiaHitResult ManiaResult;
|
||||
|
||||
public virtual int NumericResultForScore(ManiaHitResult result)
|
||||
protected override int NumericResultFor(HitResult result)
|
||||
{
|
||||
switch (result)
|
||||
{
|
||||
default:
|
||||
return 0;
|
||||
case ManiaHitResult.Bad:
|
||||
case HitResult.Meh:
|
||||
return 50;
|
||||
case ManiaHitResult.Ok:
|
||||
case HitResult.Ok:
|
||||
return 100;
|
||||
case ManiaHitResult.Good:
|
||||
case HitResult.Good:
|
||||
return 200;
|
||||
case ManiaHitResult.Great:
|
||||
case ManiaHitResult.Perfect:
|
||||
case HitResult.Great:
|
||||
case HitResult.Perfect:
|
||||
return 300;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual int NumericResultForAccuracy(ManiaHitResult result)
|
||||
public int NumericAccuracyResult => NumericResultForAccuracy(Result);
|
||||
|
||||
/// <summary>
|
||||
/// The result value for the accuracy portion of the score.
|
||||
/// </summary>
|
||||
protected virtual int NumericResultForAccuracy(HitResult result)
|
||||
{
|
||||
switch (result)
|
||||
{
|
||||
default:
|
||||
return 0;
|
||||
case ManiaHitResult.Bad:
|
||||
case HitResult.Meh:
|
||||
return 50;
|
||||
case ManiaHitResult.Ok:
|
||||
case HitResult.Ok:
|
||||
return 100;
|
||||
case ManiaHitResult.Good:
|
||||
case HitResult.Good:
|
||||
return 200;
|
||||
case ManiaHitResult.Great:
|
||||
case HitResult.Great:
|
||||
return 300;
|
||||
case ManiaHitResult.Perfect:
|
||||
case HitResult.Perfect:
|
||||
return 305;
|
||||
}
|
||||
}
|
||||
|
@ -192,7 +192,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
Y = 0;
|
||||
}
|
||||
|
||||
protected override ManiaJudgement CreateJudgement() => new HoldNoteTailJudgement();
|
||||
protected ManiaJudgement CreateJudgement() => new HoldNoteTailJudgement();
|
||||
|
||||
protected override void CheckJudgement(bool userTriggered)
|
||||
{
|
||||
|
@ -80,7 +80,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
}
|
||||
}
|
||||
|
||||
protected override ManiaJudgement CreateJudgement() => new HoldNoteTickJudgement();
|
||||
protected ManiaJudgement CreateJudgement() => new HoldNoteTickJudgement();
|
||||
|
||||
protected override void CheckJudgement(bool userTriggered)
|
||||
{
|
||||
@ -93,8 +93,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
if (HoldStartTime?.Invoke() > HitObject.StartTime)
|
||||
return;
|
||||
|
||||
Judgement.ManiaResult = ManiaHitResult.Perfect;
|
||||
Judgement.Result = HitResult.Hit;
|
||||
Judgement.Result = HitResult.Perfect;
|
||||
}
|
||||
|
||||
protected override void UpdateState(ArmedState state)
|
||||
|
@ -36,7 +36,5 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
base.AccentColour = value;
|
||||
}
|
||||
}
|
||||
|
||||
protected override ManiaJudgement CreateJudgement() => new ManiaJudgement();
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,6 @@ using System;
|
||||
using OpenTK.Graphics;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Input.Bindings;
|
||||
using osu.Game.Rulesets.Mania.Judgements;
|
||||
using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
|
||||
@ -58,15 +57,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
|
||||
if (offset > HitObject.HitWindows.Miss / 2)
|
||||
return;
|
||||
|
||||
ManiaHitResult? tmpResult = HitObject.HitWindows.ResultFor(offset);
|
||||
|
||||
if (tmpResult.HasValue)
|
||||
{
|
||||
Judgement.Result = HitResult.Hit;
|
||||
Judgement.ManiaResult = tmpResult.Value;
|
||||
}
|
||||
else
|
||||
Judgement.Result = HitResult.Miss;
|
||||
Judgement.Result = HitObject.HitWindows.ResultFor(offset) ?? HitResult.Miss;
|
||||
}
|
||||
|
||||
protected override void UpdateState(ArmedState state)
|
||||
|
@ -174,37 +174,19 @@ namespace osu.Game.Rulesets.Mania.Scoring
|
||||
|
||||
if (obj is Note)
|
||||
{
|
||||
AddJudgement(new ManiaJudgement
|
||||
{
|
||||
Result = HitResult.Hit,
|
||||
ManiaResult = ManiaHitResult.Perfect
|
||||
});
|
||||
AddJudgement(new ManiaJudgement { Result = HitResult.Perfect });
|
||||
}
|
||||
else if (holdNote != null)
|
||||
{
|
||||
// Head
|
||||
AddJudgement(new ManiaJudgement
|
||||
{
|
||||
Result = HitResult.Hit,
|
||||
ManiaResult = ManiaJudgement.MAX_HIT_RESULT
|
||||
});
|
||||
AddJudgement(new ManiaJudgement { Result = HitResult.Perfect });
|
||||
|
||||
// Ticks
|
||||
int tickCount = holdNote.Ticks.Count();
|
||||
for (int i = 0; i < tickCount; i++)
|
||||
{
|
||||
AddJudgement(new HoldNoteTickJudgement
|
||||
{
|
||||
Result = HitResult.Hit,
|
||||
ManiaResult = ManiaJudgement.MAX_HIT_RESULT,
|
||||
});
|
||||
}
|
||||
AddJudgement(new HoldNoteTickJudgement { Result = HitResult.Perfect });
|
||||
|
||||
AddJudgement(new HoldNoteTailJudgement
|
||||
{
|
||||
Result = HitResult.Hit,
|
||||
ManiaResult = ManiaJudgement.MAX_HIT_RESULT
|
||||
});
|
||||
AddJudgement(new HoldNoteTailJudgement { Result = HitResult.Perfect });
|
||||
}
|
||||
}
|
||||
|
||||
@ -225,46 +207,46 @@ namespace osu.Game.Rulesets.Mania.Scoring
|
||||
{
|
||||
bool isTick = judgement is HoldNoteTickJudgement;
|
||||
|
||||
if (!isTick)
|
||||
if (isTick)
|
||||
{
|
||||
if (judgement.IsHit)
|
||||
{
|
||||
Health.Value += hpMultiplier * hp_increase_tick;
|
||||
bonusScore += judgement.NumericResult;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
totalHits++;
|
||||
|
||||
switch (judgement.Result)
|
||||
{
|
||||
case HitResult.Miss:
|
||||
Health.Value += hpMissMultiplier * hp_increase_miss;
|
||||
break;
|
||||
case HitResult.Hit:
|
||||
if (isTick)
|
||||
{
|
||||
Health.Value += hpMultiplier * hp_increase_tick;
|
||||
bonusScore += judgement.ResultValueForScore;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (judgement.ManiaResult)
|
||||
{
|
||||
case ManiaHitResult.Bad:
|
||||
Health.Value += hpMultiplier * hp_increase_bad;
|
||||
break;
|
||||
case ManiaHitResult.Ok:
|
||||
Health.Value += hpMultiplier * hp_increase_ok;
|
||||
break;
|
||||
case ManiaHitResult.Good:
|
||||
Health.Value += hpMultiplier * hp_increase_good;
|
||||
break;
|
||||
case ManiaHitResult.Great:
|
||||
Health.Value += hpMultiplier * hp_increase_great;
|
||||
break;
|
||||
case ManiaHitResult.Perfect:
|
||||
Health.Value += hpMultiplier * hp_increase_perfect;
|
||||
break;
|
||||
}
|
||||
switch (judgement.Result)
|
||||
{
|
||||
case HitResult.Miss:
|
||||
Health.Value += hpMissMultiplier * hp_increase_miss;
|
||||
break;
|
||||
case HitResult.Meh:
|
||||
Health.Value += hpMultiplier * hp_increase_bad;
|
||||
break;
|
||||
case HitResult.Ok:
|
||||
Health.Value += hpMultiplier * hp_increase_ok;
|
||||
break;
|
||||
case HitResult.Good:
|
||||
Health.Value += hpMultiplier * hp_increase_good;
|
||||
break;
|
||||
case HitResult.Great:
|
||||
Health.Value += hpMultiplier * hp_increase_great;
|
||||
break;
|
||||
case HitResult.Perfect:
|
||||
Health.Value += hpMultiplier * hp_increase_perfect;
|
||||
break;
|
||||
}
|
||||
|
||||
// A factor that is applied to make higher combos more relevant
|
||||
double comboRelevance = Math.Min(Math.Max(0.5, Math.Log(Combo.Value, combo_base)), Math.Log(combo_relevance_cap, combo_base));
|
||||
comboPortion += judgement.ResultValueForScore * comboRelevance;
|
||||
}
|
||||
break;
|
||||
if (judgement.IsHit)
|
||||
{
|
||||
// A factor that is applied to make higher combos more relevant
|
||||
double comboRelevance = Math.Min(Math.Max(0.5, Math.Log(Combo.Value, combo_base)), Math.Log(combo_relevance_cap, combo_base));
|
||||
comboPortion += judgement.NumericResult * comboRelevance;
|
||||
}
|
||||
}
|
||||
|
||||
int scoreForAccuracy = 0;
|
||||
@ -272,8 +254,8 @@ namespace osu.Game.Rulesets.Mania.Scoring
|
||||
|
||||
foreach (var j in Judgements)
|
||||
{
|
||||
scoreForAccuracy += j.ResultValueForAccuracy;
|
||||
maxScoreForAccuracy += j.MaxResultValueForAccuracy;
|
||||
scoreForAccuracy += j.NumericAccuracyResult;
|
||||
maxScoreForAccuracy += j.MaxNumericAccuracyResult;
|
||||
}
|
||||
|
||||
Accuracy.Value = (double)scoreForAccuracy / maxScoreForAccuracy;
|
||||
|
@ -60,7 +60,6 @@
|
||||
<Compile Include="Judgements\HitWindows.cs" />
|
||||
<Compile Include="Judgements\HoldNoteTailJudgement.cs" />
|
||||
<Compile Include="Judgements\HoldNoteTickJudgement.cs" />
|
||||
<Compile Include="Judgements\ManiaHitResult.cs" />
|
||||
<Compile Include="Judgements\ManiaJudgement.cs" />
|
||||
<Compile Include="ManiaDifficultyCalculator.cs" />
|
||||
<Compile Include="Mods\IGenerateSpeedAdjustments.cs" />
|
||||
|
@ -4,10 +4,14 @@
|
||||
using OpenTK;
|
||||
using osu.Game.Rulesets.Judgements;
|
||||
using osu.Game.Rulesets.Osu.Objects.Drawables;
|
||||
using osu.Framework.Extensions;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Judgements
|
||||
{
|
||||
public class SliderTickJudgement : OsuJudgement
|
||||
{
|
||||
}
|
||||
|
||||
public class OsuJudgement : Judgement
|
||||
{
|
||||
/// <summary>
|
||||
@ -15,38 +19,18 @@ namespace osu.Game.Rulesets.Osu.Judgements
|
||||
/// </summary>
|
||||
public Vector2 PositionOffset;
|
||||
|
||||
/// <summary>
|
||||
/// The score the user achieved.
|
||||
/// </summary>
|
||||
public OsuScoreResult Score;
|
||||
|
||||
/// <summary>
|
||||
/// The score which would be achievable on a perfect hit.
|
||||
/// </summary>
|
||||
public OsuScoreResult MaxScore = OsuScoreResult.Hit300;
|
||||
|
||||
public override string ResultString => Score.GetDescription();
|
||||
|
||||
public override string MaxResultString => MaxScore.GetDescription();
|
||||
|
||||
public int ScoreValue => scoreToInt(Score);
|
||||
|
||||
public int MaxScoreValue => scoreToInt(MaxScore);
|
||||
|
||||
private int scoreToInt(OsuScoreResult result)
|
||||
protected override int NumericResultFor(HitResult result)
|
||||
{
|
||||
switch (result)
|
||||
{
|
||||
default:
|
||||
return 0;
|
||||
case OsuScoreResult.Hit50:
|
||||
case HitResult.Meh:
|
||||
return 50;
|
||||
case OsuScoreResult.Hit100:
|
||||
case HitResult.Good:
|
||||
return 100;
|
||||
case OsuScoreResult.Hit300:
|
||||
case HitResult.Great:
|
||||
return 300;
|
||||
case OsuScoreResult.SliderTick:
|
||||
return 10;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -69,20 +69,12 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
{
|
||||
if (!userTriggered)
|
||||
{
|
||||
if (Judgement.TimeOffset > HitObject.HitWindowFor(OsuScoreResult.Hit50))
|
||||
if (Judgement.TimeOffset > HitObject.HitWindowFor(HitResult.Meh))
|
||||
Judgement.Result = HitResult.Miss;
|
||||
return;
|
||||
}
|
||||
|
||||
double hitOffset = Math.Abs(Judgement.TimeOffset);
|
||||
|
||||
if (hitOffset < HitObject.HitWindowFor(OsuScoreResult.Hit50))
|
||||
{
|
||||
Judgement.Result = HitResult.Hit;
|
||||
Judgement.Score = HitObject.ScoreResultForOffset(hitOffset);
|
||||
}
|
||||
else
|
||||
Judgement.Result = HitResult.Miss;
|
||||
Judgement.Result = HitObject.ScoreResultForOffset(Math.Abs(Judgement.TimeOffset));
|
||||
}
|
||||
|
||||
protected override void UpdateInitialState()
|
||||
|
@ -21,8 +21,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
Alpha = 0;
|
||||
}
|
||||
|
||||
protected override OsuJudgement CreateJudgement() => new OsuJudgement { MaxScore = OsuScoreResult.Hit300 };
|
||||
|
||||
protected sealed override void UpdateState(ArmedState state)
|
||||
{
|
||||
FinishTransforms();
|
||||
@ -65,18 +63,4 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
[Description(@"Amazing")]
|
||||
Perfect
|
||||
}
|
||||
|
||||
public enum OsuScoreResult
|
||||
{
|
||||
[Description(@"Miss")]
|
||||
Miss,
|
||||
[Description(@"50")]
|
||||
Hit50,
|
||||
[Description(@"100")]
|
||||
Hit100,
|
||||
[Description(@"300")]
|
||||
Hit300,
|
||||
[Description(@"10")]
|
||||
SliderTick
|
||||
}
|
||||
}
|
||||
|
@ -114,7 +114,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
bouncer2.Position = slider.Curve.PositionAt(body.SnakedEnd ?? 0);
|
||||
|
||||
//todo: we probably want to reconsider this before adding scoring, but it looks and feels nice.
|
||||
if (initialCircle.Judgement?.Result != HitResult.Hit)
|
||||
if (initialCircle.Judgement?.Result <= HitResult.Miss)
|
||||
initialCircle.Position = slider.Curve.PositionAt(progress);
|
||||
|
||||
foreach (var c in components) c.UpdateProgress(progress, repeat);
|
||||
@ -126,21 +126,19 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
if (!userTriggered && Time.Current >= slider.EndTime)
|
||||
{
|
||||
var ticksCount = ticks.Children.Count + 1;
|
||||
var ticksHit = ticks.Children.Count(t => t.Judgement.Result == HitResult.Hit);
|
||||
if (initialCircle.Judgement.Result == HitResult.Hit)
|
||||
var ticksHit = ticks.Children.Count(t => t.Judgement.Result > HitResult.Miss);
|
||||
if (initialCircle.Judgement.Result > HitResult.Miss)
|
||||
ticksHit++;
|
||||
|
||||
var hitFraction = (double)ticksHit / ticksCount;
|
||||
if (hitFraction == 1 && initialCircle.Judgement.Score == OsuScoreResult.Hit300)
|
||||
Judgement.Score = OsuScoreResult.Hit300;
|
||||
else if (hitFraction >= 0.5 && initialCircle.Judgement.Score >= OsuScoreResult.Hit100)
|
||||
Judgement.Score = OsuScoreResult.Hit100;
|
||||
if (hitFraction == 1 && initialCircle.Judgement.Result == HitResult.Great)
|
||||
Judgement.Result = HitResult.Great;
|
||||
else if (hitFraction >= 0.5 && initialCircle.Judgement.Result >= HitResult.Good)
|
||||
Judgement.Result = HitResult.Good;
|
||||
else if (hitFraction > 0)
|
||||
Judgement.Score = OsuScoreResult.Hit50;
|
||||
Judgement.Result = HitResult.Meh;
|
||||
else
|
||||
Judgement.Score = OsuScoreResult.Miss;
|
||||
|
||||
Judgement.Result = Judgement.Score != OsuScoreResult.Miss ? HitResult.Hit : HitResult.Miss;
|
||||
Judgement.Result = HitResult.Miss;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,6 @@
|
||||
using System;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Osu.Judgements;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
@ -22,8 +21,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
|
||||
public override bool RemoveWhenNotAlive => false;
|
||||
|
||||
protected override OsuJudgement CreateJudgement() => new OsuJudgement { MaxScore = OsuScoreResult.SliderTick };
|
||||
|
||||
public DrawableSliderTick(SliderTick sliderTick) : base(sliderTick)
|
||||
{
|
||||
this.sliderTick = sliderTick;
|
||||
@ -52,10 +49,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
protected override void CheckJudgement(bool userTriggered)
|
||||
{
|
||||
if (Judgement.TimeOffset >= 0)
|
||||
{
|
||||
Judgement.Result = Tracking ? HitResult.Hit : HitResult.Miss;
|
||||
Judgement.Score = Tracking ? OsuScoreResult.SliderTick : OsuScoreResult.Miss;
|
||||
}
|
||||
Judgement.Result = Tracking ? HitResult.Perfect : HitResult.Miss;
|
||||
}
|
||||
|
||||
protected override void UpdatePreemptState()
|
||||
|
@ -129,26 +129,13 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
|
||||
if (!userTriggered && Time.Current >= spinner.EndTime)
|
||||
{
|
||||
if (Progress >= 1)
|
||||
{
|
||||
Judgement.Score = OsuScoreResult.Hit300;
|
||||
Judgement.Result = HitResult.Hit;
|
||||
}
|
||||
Judgement.Result = HitResult.Great;
|
||||
else if (Progress > .9)
|
||||
{
|
||||
Judgement.Score = OsuScoreResult.Hit100;
|
||||
Judgement.Result = HitResult.Hit;
|
||||
}
|
||||
Judgement.Result = HitResult.Good;
|
||||
else if (Progress > .75)
|
||||
{
|
||||
Judgement.Score = OsuScoreResult.Hit50;
|
||||
Judgement.Result = HitResult.Hit;
|
||||
}
|
||||
else
|
||||
{
|
||||
Judgement.Score = OsuScoreResult.Miss;
|
||||
if (Time.Current >= spinner.EndTime)
|
||||
Judgement.Result = HitResult.Miss;
|
||||
}
|
||||
Judgement.Result = HitResult.Meh;
|
||||
else if (Time.Current >= spinner.EndTime)
|
||||
Judgement.Result = HitResult.Miss;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,10 +4,10 @@
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using OpenTK;
|
||||
using osu.Game.Rulesets.Osu.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using OpenTK.Graphics;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Objects
|
||||
{
|
||||
@ -42,30 +42,30 @@ namespace osu.Game.Rulesets.Osu.Objects
|
||||
public virtual bool NewCombo { get; set; }
|
||||
public int ComboIndex { get; set; }
|
||||
|
||||
public double HitWindowFor(OsuScoreResult result)
|
||||
public double HitWindowFor(HitResult result)
|
||||
{
|
||||
switch (result)
|
||||
{
|
||||
default:
|
||||
return 300;
|
||||
case OsuScoreResult.Hit50:
|
||||
case HitResult.Meh:
|
||||
return 150;
|
||||
case OsuScoreResult.Hit100:
|
||||
case HitResult.Good:
|
||||
return 80;
|
||||
case OsuScoreResult.Hit300:
|
||||
case HitResult.Great:
|
||||
return 30;
|
||||
}
|
||||
}
|
||||
|
||||
public OsuScoreResult ScoreResultForOffset(double offset)
|
||||
public HitResult ScoreResultForOffset(double offset)
|
||||
{
|
||||
if (offset < HitWindowFor(OsuScoreResult.Hit300))
|
||||
return OsuScoreResult.Hit300;
|
||||
if (offset < HitWindowFor(OsuScoreResult.Hit100))
|
||||
return OsuScoreResult.Hit100;
|
||||
if (offset < HitWindowFor(OsuScoreResult.Hit50))
|
||||
return OsuScoreResult.Hit50;
|
||||
return OsuScoreResult.Miss;
|
||||
if (offset < HitWindowFor(HitResult.Great))
|
||||
return HitResult.Great;
|
||||
if (offset < HitWindowFor(HitResult.Good))
|
||||
return HitResult.Good;
|
||||
if (offset < HitWindowFor(HitResult.Meh))
|
||||
return HitResult.Meh;
|
||||
return HitResult.Miss;
|
||||
}
|
||||
|
||||
public override void ApplyDefaults(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty)
|
||||
|
@ -9,6 +9,7 @@ using osu.Game.Rulesets.Osu.Objects.Drawables;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using osu.Game.Rulesets.Replays;
|
||||
|
||||
@ -89,20 +90,20 @@ namespace osu.Game.Rulesets.Osu.Replays
|
||||
double endTime = (prev as IHasEndTime)?.EndTime ?? prev.StartTime;
|
||||
|
||||
// Make the cursor stay at a hitObject as long as possible (mainly for autopilot).
|
||||
if (h.StartTime - h.HitWindowFor(OsuScoreResult.Miss) > endTime + h.HitWindowFor(OsuScoreResult.Hit50) + 50)
|
||||
if (h.StartTime - h.HitWindowFor(HitResult.Miss) > endTime + h.HitWindowFor(HitResult.Meh) + 50)
|
||||
{
|
||||
if (!(prev is Spinner) && h.StartTime - endTime < 1000) AddFrameToReplay(new ReplayFrame(endTime + h.HitWindowFor(OsuScoreResult.Hit50), prev.StackedEndPosition.X, prev.StackedEndPosition.Y, ReplayButtonState.None));
|
||||
if (!(h is Spinner)) AddFrameToReplay(new ReplayFrame(h.StartTime - h.HitWindowFor(OsuScoreResult.Miss), h.StackedPosition.X, h.StackedPosition.Y, ReplayButtonState.None));
|
||||
if (!(prev is Spinner) && h.StartTime - endTime < 1000) AddFrameToReplay(new ReplayFrame(endTime + h.HitWindowFor(HitResult.Meh), prev.StackedEndPosition.X, prev.StackedEndPosition.Y, ReplayButtonState.None));
|
||||
if (!(h is Spinner)) AddFrameToReplay(new ReplayFrame(h.StartTime - h.HitWindowFor(HitResult.Miss), h.StackedPosition.X, h.StackedPosition.Y, ReplayButtonState.None));
|
||||
}
|
||||
else if (h.StartTime - h.HitWindowFor(OsuScoreResult.Hit50) > endTime + h.HitWindowFor(OsuScoreResult.Hit50) + 50)
|
||||
else if (h.StartTime - h.HitWindowFor(HitResult.Meh) > endTime + h.HitWindowFor(HitResult.Meh) + 50)
|
||||
{
|
||||
if (!(prev is Spinner) && h.StartTime - endTime < 1000) AddFrameToReplay(new ReplayFrame(endTime + h.HitWindowFor(OsuScoreResult.Hit50), prev.StackedEndPosition.X, prev.StackedEndPosition.Y, ReplayButtonState.None));
|
||||
if (!(h is Spinner)) AddFrameToReplay(new ReplayFrame(h.StartTime - h.HitWindowFor(OsuScoreResult.Hit50), h.StackedPosition.X, h.StackedPosition.Y, ReplayButtonState.None));
|
||||
if (!(prev is Spinner) && h.StartTime - endTime < 1000) AddFrameToReplay(new ReplayFrame(endTime + h.HitWindowFor(HitResult.Meh), prev.StackedEndPosition.X, prev.StackedEndPosition.Y, ReplayButtonState.None));
|
||||
if (!(h is Spinner)) AddFrameToReplay(new ReplayFrame(h.StartTime - h.HitWindowFor(HitResult.Meh), h.StackedPosition.X, h.StackedPosition.Y, ReplayButtonState.None));
|
||||
}
|
||||
else if (h.StartTime - h.HitWindowFor(OsuScoreResult.Hit100) > endTime + h.HitWindowFor(OsuScoreResult.Hit100) + 50)
|
||||
else if (h.StartTime - h.HitWindowFor(HitResult.Good) > endTime + h.HitWindowFor(HitResult.Good) + 50)
|
||||
{
|
||||
if (!(prev is Spinner) && h.StartTime - endTime < 1000) AddFrameToReplay(new ReplayFrame(endTime + h.HitWindowFor(OsuScoreResult.Hit100), prev.StackedEndPosition.X, prev.StackedEndPosition.Y, ReplayButtonState.None));
|
||||
if (!(h is Spinner)) AddFrameToReplay(new ReplayFrame(h.StartTime - h.HitWindowFor(OsuScoreResult.Hit100), h.StackedPosition.X, h.StackedPosition.Y, ReplayButtonState.None));
|
||||
if (!(prev is Spinner) && h.StartTime - endTime < 1000) AddFrameToReplay(new ReplayFrame(endTime + h.HitWindowFor(HitResult.Good), prev.StackedEndPosition.X, prev.StackedEndPosition.Y, ReplayButtonState.None));
|
||||
if (!(h is Spinner)) AddFrameToReplay(new ReplayFrame(h.StartTime - h.HitWindowFor(HitResult.Good), h.StackedPosition.X, h.StackedPosition.Y, ReplayButtonState.None));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -32,7 +32,7 @@ namespace osu.Game.Rulesets.Osu.Scoring
|
||||
|
||||
private int totalAccurateJudgements;
|
||||
|
||||
private readonly Dictionary<OsuScoreResult, int> scoreResultCounts = new Dictionary<OsuScoreResult, int>();
|
||||
private readonly Dictionary<HitResult, int> scoreResultCounts = new Dictionary<HitResult, int>();
|
||||
private readonly Dictionary<ComboResult, int> comboResultCounts = new Dictionary<ComboResult, int>();
|
||||
|
||||
private double comboMaxScore;
|
||||
@ -45,12 +45,7 @@ namespace osu.Game.Rulesets.Osu.Scoring
|
||||
foreach (var h in beatmap.HitObjects)
|
||||
{
|
||||
// TODO: add support for other object types.
|
||||
AddJudgement(new OsuJudgement
|
||||
{
|
||||
MaxScore = OsuScoreResult.Hit300,
|
||||
Score = OsuScoreResult.Hit300,
|
||||
Result = HitResult.Hit
|
||||
});
|
||||
AddJudgement(new OsuJudgement { Result = HitResult.Great });
|
||||
}
|
||||
}
|
||||
|
||||
@ -69,10 +64,10 @@ namespace osu.Game.Rulesets.Osu.Scoring
|
||||
{
|
||||
base.PopulateScore(score);
|
||||
|
||||
score.Statistics[@"300"] = scoreResultCounts.GetOrDefault(OsuScoreResult.Hit300);
|
||||
score.Statistics[@"100"] = scoreResultCounts.GetOrDefault(OsuScoreResult.Hit100);
|
||||
score.Statistics[@"50"] = scoreResultCounts.GetOrDefault(OsuScoreResult.Hit50);
|
||||
score.Statistics[@"x"] = scoreResultCounts.GetOrDefault(OsuScoreResult.Miss);
|
||||
score.Statistics[@"300"] = scoreResultCounts.GetOrDefault(HitResult.Great);
|
||||
score.Statistics[@"100"] = scoreResultCounts.GetOrDefault(HitResult.Good);
|
||||
score.Statistics[@"50"] = scoreResultCounts.GetOrDefault(HitResult.Meh);
|
||||
score.Statistics[@"x"] = scoreResultCounts.GetOrDefault(HitResult.Miss);
|
||||
}
|
||||
|
||||
protected override void OnNewJudgement(OsuJudgement judgement)
|
||||
@ -81,29 +76,29 @@ namespace osu.Game.Rulesets.Osu.Scoring
|
||||
{
|
||||
if (judgement.Result != HitResult.None)
|
||||
{
|
||||
scoreResultCounts[judgement.Score] = scoreResultCounts.GetOrDefault(judgement.Score) + 1;
|
||||
scoreResultCounts[judgement.Result] = scoreResultCounts.GetOrDefault(judgement.Result) + 1;
|
||||
comboResultCounts[judgement.Combo] = comboResultCounts.GetOrDefault(judgement.Combo) + 1;
|
||||
}
|
||||
|
||||
switch (judgement.Score)
|
||||
switch (judgement.Result)
|
||||
{
|
||||
case OsuScoreResult.Hit300:
|
||||
case HitResult.Great:
|
||||
Health.Value += (10.2 - hpDrainRate) * 0.02;
|
||||
break;
|
||||
|
||||
case OsuScoreResult.Hit100:
|
||||
case HitResult.Good:
|
||||
Health.Value += (8 - hpDrainRate) * 0.02;
|
||||
break;
|
||||
|
||||
case OsuScoreResult.Hit50:
|
||||
case HitResult.Meh:
|
||||
Health.Value += (4 - hpDrainRate) * 0.02;
|
||||
break;
|
||||
|
||||
case OsuScoreResult.SliderTick:
|
||||
/*case HitResult.SliderTick:
|
||||
Health.Value += Math.Max(7 - hpDrainRate, 0) * 0.01;
|
||||
break;
|
||||
break;*/
|
||||
|
||||
case OsuScoreResult.Miss:
|
||||
case HitResult.Miss:
|
||||
Health.Value -= hpDrainRate * 0.04;
|
||||
break;
|
||||
}
|
||||
@ -123,10 +118,10 @@ namespace osu.Game.Rulesets.Osu.Scoring
|
||||
|
||||
foreach (var j in Judgements)
|
||||
{
|
||||
baseScore += j.ScoreValue;
|
||||
baseMaxScore += j.MaxScoreValue;
|
||||
baseScore += j.NumericResult;
|
||||
baseMaxScore += j.MaxNumericResult;
|
||||
|
||||
comboScore += j.ScoreValue * (1 + Combo.Value / 10d);
|
||||
comboScore += j.NumericResult * (1 + Combo.Value / 10d);
|
||||
}
|
||||
|
||||
Accuracy.Value = (double)baseScore / baseMaxScore;
|
||||
|
@ -1,34 +1,26 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
|
||||
namespace osu.Game.Rulesets.Taiko.Judgements
|
||||
{
|
||||
public class TaikoDrumRollTickJudgement : TaikoJudgement
|
||||
{
|
||||
/// <summary>
|
||||
/// Drum roll ticks don't display judgement text.
|
||||
/// </summary>
|
||||
public override string ResultString => string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Drum roll ticks don't display judgement text.
|
||||
/// </summary>
|
||||
public override string MaxResultString => string.Empty;
|
||||
|
||||
public override bool AffectsCombo => false;
|
||||
|
||||
protected override int NumericResultForScore(TaikoHitResult result)
|
||||
protected override int NumericResultFor(HitResult result)
|
||||
{
|
||||
switch (result)
|
||||
{
|
||||
default:
|
||||
return 0;
|
||||
case TaikoHitResult.Great:
|
||||
case HitResult.Great:
|
||||
return 200;
|
||||
}
|
||||
}
|
||||
|
||||
protected override int NumericResultForAccuracy(TaikoHitResult result)
|
||||
protected override int NumericResultForAccuracy(HitResult result)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,15 +0,0 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace osu.Game.Rulesets.Taiko.Judgements
|
||||
{
|
||||
public enum TaikoHitResult
|
||||
{
|
||||
[Description("GOOD")]
|
||||
Good,
|
||||
[Description("GREAT")]
|
||||
Great
|
||||
}
|
||||
}
|
@ -2,46 +2,21 @@
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Game.Rulesets.Judgements;
|
||||
using osu.Framework.Extensions;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
|
||||
namespace osu.Game.Rulesets.Taiko.Judgements
|
||||
{
|
||||
public class TaikoJudgement : Judgement
|
||||
{
|
||||
/// <summary>
|
||||
/// The maximum result.
|
||||
/// </summary>
|
||||
public const TaikoHitResult MAX_HIT_RESULT = TaikoHitResult.Great;
|
||||
|
||||
/// <summary>
|
||||
/// The result.
|
||||
/// </summary>
|
||||
public TaikoHitResult TaikoResult;
|
||||
|
||||
/// <summary>
|
||||
/// The result value for the combo portion of the score.
|
||||
/// </summary>
|
||||
public int ResultValueForScore => Result == HitResult.Miss ? 0 : NumericResultForScore(TaikoResult);
|
||||
|
||||
/// <summary>
|
||||
/// The result value for the accuracy portion of the score.
|
||||
/// </summary>
|
||||
public int ResultValueForAccuracy => Result == HitResult.Miss ? 0 : NumericResultForAccuracy(TaikoResult);
|
||||
|
||||
/// <summary>
|
||||
/// The maximum result value for the combo portion of the score.
|
||||
/// </summary>
|
||||
public int MaxResultValueForScore => NumericResultForScore(MAX_HIT_RESULT);
|
||||
public int ResultNumericForAccuracy => Result == HitResult.Miss ? 0 : NumericResultForAccuracy(Result);
|
||||
|
||||
/// <summary>
|
||||
/// The maximum result value for the accuracy portion of the score.
|
||||
/// </summary>
|
||||
public int MaxResultValueForAccuracy => NumericResultForAccuracy(MAX_HIT_RESULT);
|
||||
|
||||
public override string ResultString => TaikoResult.GetDescription();
|
||||
|
||||
public override string MaxResultString => MAX_HIT_RESULT.GetDescription();
|
||||
public int MaxResultValueForAccuracy => NumericResultForAccuracy(HitResult.Great);
|
||||
|
||||
/// <summary>
|
||||
/// Whether this Judgement has a secondary hit in the case of strong hits.
|
||||
@ -50,38 +25,38 @@ namespace osu.Game.Rulesets.Taiko.Judgements
|
||||
|
||||
/// <summary>
|
||||
/// Computes the numeric result value for the combo portion of the score.
|
||||
/// For the accuracy portion of the score (including accuracy percentage), see <see cref="NumericResultForAccuracy(TaikoHitResult)"/>.
|
||||
/// For the accuracy portion of the score (including accuracy percentage), see <see cref="NumericResultForAccuracy(HitResult)"/>.
|
||||
/// </summary>
|
||||
/// <param name="result">The result to compute the value for.</param>
|
||||
/// <returns>The numeric result value.</returns>
|
||||
protected virtual int NumericResultForScore(TaikoHitResult result)
|
||||
protected override int NumericResultFor(HitResult result)
|
||||
{
|
||||
switch (result)
|
||||
{
|
||||
default:
|
||||
return 0;
|
||||
case TaikoHitResult.Good:
|
||||
case HitResult.Good:
|
||||
return 100;
|
||||
case TaikoHitResult.Great:
|
||||
case HitResult.Great:
|
||||
return 300;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Computes the numeric result value for the accuracy portion of the score.
|
||||
/// For the combo portion of the score, see <see cref="NumericResultForScore(TaikoHitResult)"/>.
|
||||
/// For the combo portion of the score, see <see cref="NumericResultFor(HitResult)"/>.
|
||||
/// </summary>
|
||||
/// <param name="result">The result to compute the value for.</param>
|
||||
/// <returns>The numeric result value.</returns>
|
||||
protected virtual int NumericResultForAccuracy(TaikoHitResult result)
|
||||
protected virtual int NumericResultForAccuracy(HitResult result)
|
||||
{
|
||||
switch (result)
|
||||
{
|
||||
default:
|
||||
return 0;
|
||||
case TaikoHitResult.Good:
|
||||
case HitResult.Good:
|
||||
return 150;
|
||||
case TaikoHitResult.Great:
|
||||
case HitResult.Great:
|
||||
return 300;
|
||||
}
|
||||
}
|
||||
|
@ -58,8 +58,6 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
|
||||
};
|
||||
}
|
||||
|
||||
protected override TaikoJudgement CreateJudgement() => null;
|
||||
|
||||
protected override void UpdateState(ArmedState state)
|
||||
{
|
||||
}
|
||||
|
@ -52,7 +52,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
|
||||
}
|
||||
}
|
||||
|
||||
protected override TaikoJudgement CreateJudgement() => new TaikoJudgement { SecondHit = HitObject.IsStrong };
|
||||
protected TaikoJudgement CreateJudgement() => new TaikoJudgement { SecondHit = HitObject.IsStrong };
|
||||
|
||||
protected override TaikoPiece CreateMainPiece() => new ElongatedCirclePiece();
|
||||
|
||||
@ -67,7 +67,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
|
||||
|
||||
private void onTickJudgement(DrawableHitObject<TaikoHitObject, TaikoJudgement> obj)
|
||||
{
|
||||
if (obj.Judgement.Result == HitResult.Hit)
|
||||
if (obj.Judgement.Result > HitResult.Miss)
|
||||
rollingHits++;
|
||||
else
|
||||
rollingHits--;
|
||||
@ -86,12 +86,11 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
|
||||
if (Judgement.TimeOffset < 0)
|
||||
return;
|
||||
|
||||
int countHit = NestedHitObjects.Count(o => o.Judgement.Result == HitResult.Hit);
|
||||
int countHit = NestedHitObjects.Count(o => o.Judgement.Result > HitResult.Miss);
|
||||
|
||||
if (countHit > HitObject.RequiredGoodHits)
|
||||
{
|
||||
Judgement.Result = HitResult.Hit;
|
||||
Judgement.TaikoResult = countHit >= HitObject.RequiredGreatHits ? TaikoHitResult.Great : TaikoHitResult.Good;
|
||||
Judgement.Result = countHit >= HitObject.RequiredGreatHits ? HitResult.Great : HitResult.Good;
|
||||
}
|
||||
else
|
||||
Judgement.Result = HitResult.Miss;
|
||||
|
@ -34,7 +34,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
|
||||
Filled = HitObject.FirstTick
|
||||
};
|
||||
|
||||
protected override TaikoJudgement CreateJudgement() => new TaikoDrumRollTickJudgement { SecondHit = HitObject.IsStrong };
|
||||
protected TaikoJudgement CreateJudgement() => new TaikoDrumRollTickJudgement { SecondHit = HitObject.IsStrong };
|
||||
|
||||
protected override void CheckJudgement(bool userTriggered)
|
||||
{
|
||||
@ -42,10 +42,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
|
||||
return;
|
||||
|
||||
if (Math.Abs(Judgement.TimeOffset) < HitObject.HitWindow)
|
||||
{
|
||||
Judgement.Result = HitResult.Hit;
|
||||
Judgement.TaikoResult = TaikoHitResult.Great;
|
||||
}
|
||||
Judgement.Result = HitResult.Great;
|
||||
}
|
||||
|
||||
protected override void UpdateState(ArmedState state)
|
||||
|
@ -5,7 +5,6 @@ using System;
|
||||
using System.Linq;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Taiko.Judgements;
|
||||
using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces;
|
||||
|
||||
namespace osu.Game.Rulesets.Taiko.Objects.Drawables
|
||||
@ -45,10 +44,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
|
||||
if (!validKeyPressed)
|
||||
Judgement.Result = HitResult.Miss;
|
||||
else if (hitOffset < HitObject.HitWindowGood)
|
||||
{
|
||||
Judgement.Result = HitResult.Hit;
|
||||
Judgement.TaikoResult = hitOffset < HitObject.HitWindowGreat ? TaikoHitResult.Great : TaikoHitResult.Good;
|
||||
}
|
||||
Judgement.Result = hitOffset < HitObject.HitWindowGreat ? HitResult.Great : HitResult.Good;
|
||||
else
|
||||
Judgement.Result = HitResult.Miss;
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
|
||||
{
|
||||
}
|
||||
|
||||
protected override TaikoJudgement CreateJudgement() => new TaikoStrongHitJudgement();
|
||||
protected TaikoJudgement CreateJudgement() => new TaikoStrongHitJudgement();
|
||||
|
||||
protected override void CheckJudgement(bool userTriggered)
|
||||
{
|
||||
|
@ -9,7 +9,6 @@ using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Taiko.Judgements;
|
||||
using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
@ -153,10 +152,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
|
||||
expandingRing.ScaleTo(1f + Math.Min(target_ring_scale - 1f, (target_ring_scale - 1f) * completion * 1.3f), 260, Easing.OutQuint);
|
||||
|
||||
if (userHits == HitObject.RequiredHits)
|
||||
{
|
||||
Judgement.Result = HitResult.Hit;
|
||||
Judgement.TaikoResult = TaikoHitResult.Great;
|
||||
}
|
||||
Judgement.Result = HitResult.Great;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -165,10 +161,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
|
||||
|
||||
//TODO: THIS IS SHIT AND CAN'T EXIST POST-TAIKO WORLD CUP
|
||||
if (userHits > HitObject.RequiredHits / 2)
|
||||
{
|
||||
Judgement.Result = HitResult.Hit;
|
||||
Judgement.TaikoResult = TaikoHitResult.Good;
|
||||
}
|
||||
Judgement.Result = HitResult.Good;
|
||||
else
|
||||
Judgement.Result = HitResult.Miss;
|
||||
}
|
||||
|
@ -37,8 +37,6 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
|
||||
MainPiece.KiaiMode = HitObject.Kiai;
|
||||
}
|
||||
|
||||
protected override TaikoJudgement CreateJudgement() => new TaikoJudgement();
|
||||
|
||||
protected virtual TaikoPiece CreateMainPiece() => new CirclePiece();
|
||||
|
||||
public abstract bool OnPressed(TaikoAction action);
|
||||
|
@ -36,12 +36,12 @@ namespace osu.Game.Rulesets.Taiko.Scoring
|
||||
private const double combo_base = 4;
|
||||
|
||||
/// <summary>
|
||||
/// The HP awarded by a <see cref="TaikoHitResult.Great"/> hit.
|
||||
/// The HP awarded by a <see cref="HitResult.Great"/> hit.
|
||||
/// </summary>
|
||||
private const double hp_hit_great = 0.03;
|
||||
|
||||
/// <summary>
|
||||
/// The HP awarded for a <see cref="TaikoHitResult.Good"/> hit.
|
||||
/// The HP awarded for a <see cref="HitResult.Good"/> hit.
|
||||
/// </summary>
|
||||
private const double hp_hit_good = 0.011;
|
||||
|
||||
@ -140,8 +140,7 @@ namespace osu.Game.Rulesets.Taiko.Scoring
|
||||
{
|
||||
AddJudgement(new TaikoJudgement
|
||||
{
|
||||
Result = HitResult.Hit,
|
||||
TaikoResult = TaikoHitResult.Great,
|
||||
Result = HitResult.Great,
|
||||
SecondHit = obj.IsStrong
|
||||
});
|
||||
}
|
||||
@ -151,26 +150,20 @@ namespace osu.Game.Rulesets.Taiko.Scoring
|
||||
{
|
||||
AddJudgement(new TaikoDrumRollTickJudgement
|
||||
{
|
||||
Result = HitResult.Hit,
|
||||
TaikoResult = TaikoHitResult.Great,
|
||||
Result = HitResult.Great,
|
||||
SecondHit = obj.IsStrong
|
||||
});
|
||||
}
|
||||
|
||||
AddJudgement(new TaikoJudgement
|
||||
{
|
||||
Result = HitResult.Hit,
|
||||
TaikoResult = TaikoHitResult.Great,
|
||||
Result = HitResult.Great,
|
||||
SecondHit = obj.IsStrong
|
||||
});
|
||||
}
|
||||
else if (obj is Swell)
|
||||
{
|
||||
AddJudgement(new TaikoJudgement
|
||||
{
|
||||
Result = HitResult.Hit,
|
||||
TaikoResult = TaikoHitResult.Great
|
||||
});
|
||||
AddJudgement(new TaikoJudgement { Result = HitResult.Great });
|
||||
}
|
||||
}
|
||||
|
||||
@ -197,19 +190,14 @@ namespace osu.Game.Rulesets.Taiko.Scoring
|
||||
if (!isTick)
|
||||
Health.Value += hpIncreaseMiss;
|
||||
break;
|
||||
case HitResult.Hit:
|
||||
switch (judgement.TaikoResult)
|
||||
{
|
||||
case TaikoHitResult.Good:
|
||||
Health.Value += hpIncreaseGood;
|
||||
break;
|
||||
case TaikoHitResult.Great:
|
||||
if (isTick)
|
||||
Health.Value += hpIncreaseTick;
|
||||
else
|
||||
Health.Value += hpIncreaseGreat;
|
||||
break;
|
||||
}
|
||||
case HitResult.Good:
|
||||
Health.Value += hpIncreaseGood;
|
||||
break;
|
||||
case HitResult.Great:
|
||||
if (isTick)
|
||||
Health.Value += hpIncreaseTick;
|
||||
else
|
||||
Health.Value += hpIncreaseGreat;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -226,10 +214,10 @@ namespace osu.Game.Rulesets.Taiko.Scoring
|
||||
|
||||
private void addHitScore(TaikoJudgement judgement)
|
||||
{
|
||||
if (judgement.Result != HitResult.Hit)
|
||||
if (!judgement.IsHit)
|
||||
return;
|
||||
|
||||
double baseValue = judgement.ResultValueForScore;
|
||||
double baseValue = judgement.NumericResult;
|
||||
|
||||
// Add increased score for hitting a strong hit object with the second key
|
||||
if (judgement.SecondHit)
|
||||
@ -255,7 +243,7 @@ namespace osu.Game.Rulesets.Taiko.Scoring
|
||||
|
||||
foreach (var j in Judgements)
|
||||
{
|
||||
scoreForAccuracy += j.ResultValueForAccuracy;
|
||||
scoreForAccuracy += j.ResultNumericForAccuracy;
|
||||
maxScoreForAccuracy += j.MaxResultValueForAccuracy;
|
||||
}
|
||||
|
||||
|
@ -29,28 +29,19 @@ namespace osu.Game.Rulesets.Taiko.UI
|
||||
{
|
||||
switch (Judgement.Result)
|
||||
{
|
||||
case HitResult.Hit:
|
||||
switch (Judgement.TaikoResult)
|
||||
{
|
||||
case TaikoHitResult.Good:
|
||||
Colour = colours.GreenLight;
|
||||
break;
|
||||
case TaikoHitResult.Great:
|
||||
Colour = colours.BlueLight;
|
||||
break;
|
||||
}
|
||||
case HitResult.Good:
|
||||
Colour = colours.GreenLight;
|
||||
break;
|
||||
case HitResult.Great:
|
||||
Colour = colours.BlueLight;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
switch (Judgement.Result)
|
||||
{
|
||||
case HitResult.Hit:
|
||||
this.MoveToY(-100, 500);
|
||||
break;
|
||||
}
|
||||
if (Judgement.IsHit)
|
||||
this.MoveToY(-100, 500);
|
||||
|
||||
base.LoadComplete();
|
||||
}
|
||||
|
@ -220,7 +220,7 @@ namespace osu.Game.Rulesets.Taiko.UI
|
||||
|
||||
public override void OnJudgement(DrawableHitObject<TaikoHitObject, TaikoJudgement> judgedObject)
|
||||
{
|
||||
bool wasHit = judgedObject.Judgement.Result == HitResult.Hit;
|
||||
bool wasHit = judgedObject.Judgement.Result > HitResult.Miss;
|
||||
bool secondHit = judgedObject.Judgement.SecondHit;
|
||||
|
||||
judgementContainer.Add(new DrawableTaikoJudgement(judgedObject.Judgement)
|
||||
|
@ -52,7 +52,6 @@
|
||||
<Compile Include="Judgements\TaikoDrumRollTickJudgement.cs" />
|
||||
<Compile Include="Judgements\TaikoStrongHitJudgement.cs" />
|
||||
<Compile Include="Judgements\TaikoJudgement.cs" />
|
||||
<Compile Include="Judgements\TaikoHitResult.cs" />
|
||||
<Compile Include="Objects\BarLine.cs" />
|
||||
<Compile Include="Objects\Drawables\DrawableBarLine.cs" />
|
||||
<Compile Include="Objects\Drawables\DrawableBarLineMajor.cs" />
|
||||
|
@ -34,15 +34,13 @@ namespace osu.Game.Rulesets.Judgements
|
||||
|
||||
AutoSizeAxes = Axes.Both;
|
||||
|
||||
string resultString = judgement.Result == HitResult.Hit ? judgement.ResultString : judgement.Result.GetDescription();
|
||||
|
||||
Children = new[]
|
||||
{
|
||||
JudgementText = new OsuSpriteText
|
||||
{
|
||||
Origin = Anchor.Centre,
|
||||
Anchor = Anchor.Centre,
|
||||
Text = resultString.ToUpper(),
|
||||
Text = judgement.Result.GetDescription().ToUpper(),
|
||||
Font = @"Venera",
|
||||
TextSize = 16
|
||||
}
|
||||
@ -68,6 +66,8 @@ namespace osu.Game.Rulesets.Judgements
|
||||
|
||||
switch (Judgement.Result)
|
||||
{
|
||||
case HitResult.None:
|
||||
break;
|
||||
case HitResult.Miss:
|
||||
this.ScaleTo(1.6f);
|
||||
this.ScaleTo(1, 100, Easing.In);
|
||||
@ -77,7 +77,7 @@ namespace osu.Game.Rulesets.Judgements
|
||||
|
||||
this.Delay(600).FadeOut(200);
|
||||
break;
|
||||
case HitResult.Hit:
|
||||
default:
|
||||
this.ScaleTo(0.9f);
|
||||
this.ScaleTo(1, 500, Easing.OutElastic);
|
||||
|
||||
|
@ -5,13 +5,20 @@ using osu.Game.Rulesets.Objects.Drawables;
|
||||
|
||||
namespace osu.Game.Rulesets.Judgements
|
||||
{
|
||||
public abstract class Judgement
|
||||
public class Judgement
|
||||
{
|
||||
/// <summary>
|
||||
/// Whether this judgement is the result of a hit or a miss.
|
||||
/// </summary>
|
||||
public HitResult Result;
|
||||
|
||||
/// <summary>
|
||||
/// The maximum <see cref="HitResult"/> that can be achieved.
|
||||
/// </summary>
|
||||
public virtual HitResult MaxResult => HitResult.Perfect;
|
||||
|
||||
public bool IsHit => Result > HitResult.Miss;
|
||||
|
||||
/// <summary>
|
||||
/// The offset at which this judgement occurred.
|
||||
/// </summary>
|
||||
@ -20,13 +27,20 @@ namespace osu.Game.Rulesets.Judgements
|
||||
public virtual bool AffectsCombo => true;
|
||||
|
||||
/// <summary>
|
||||
/// The string representation for the result achieved.
|
||||
/// The numeric representation for the result achieved.
|
||||
/// </summary>
|
||||
public abstract string ResultString { get; }
|
||||
public int NumericResult => NumericResultFor(Result);
|
||||
|
||||
/// <summary>
|
||||
/// The string representation for the max result achievable.
|
||||
/// The numeric representation for the maximum achievable result.
|
||||
/// </summary>
|
||||
public abstract string MaxResultString { get; }
|
||||
public int MaxNumericResult => NumericResultFor(MaxResult);
|
||||
|
||||
/// <summary>
|
||||
/// Convert a <see cref="HitResult"/> to a numeric score representation.
|
||||
/// </summary>
|
||||
/// <param name="result">The value to convert.</param>
|
||||
/// <returns>The number.</returns>
|
||||
protected virtual int NumericResultFor(HitResult result) => result > HitResult.Miss ? 1 : 0;
|
||||
}
|
||||
}
|
@ -178,10 +178,6 @@ namespace osu.Game.Rulesets.Objects.Drawables
|
||||
channel.Volume.Value = sample.Volume;
|
||||
Samples.Add(channel);
|
||||
}
|
||||
|
||||
//we may be setting a custom judgement in test cases or what not.
|
||||
if (Judgement == null)
|
||||
Judgement = CreateJudgement();
|
||||
}
|
||||
|
||||
private List<DrawableHitObject<TObject, TJudgement>> nestedHitObjects;
|
||||
@ -196,7 +192,6 @@ namespace osu.Game.Rulesets.Objects.Drawables
|
||||
nestedHitObjects.Add(h);
|
||||
}
|
||||
|
||||
protected abstract TJudgement CreateJudgement();
|
||||
protected abstract void UpdateState(ArmedState state);
|
||||
}
|
||||
}
|
||||
|
@ -10,17 +10,34 @@ namespace osu.Game.Rulesets.Objects.Drawables
|
||||
/// <summary>
|
||||
/// Indicates that the object has not been judged yet.
|
||||
/// </summary>
|
||||
[Description("")]
|
||||
[Description(@"")]
|
||||
None,
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that the object has been judged as a miss.
|
||||
/// </summary>
|
||||
[Description(@"Miss")]
|
||||
Miss,
|
||||
|
||||
[Description(@"Meh")]
|
||||
Meh,
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that the object has been judged as a hit.
|
||||
/// Optional judgement.
|
||||
/// </summary>
|
||||
[Description(@"Hit")]
|
||||
Hit,
|
||||
[Description(@"OK")]
|
||||
Ok,
|
||||
|
||||
[Description(@"Good")]
|
||||
Good,
|
||||
|
||||
[Description(@"Great")]
|
||||
Great,
|
||||
|
||||
/// <summary>
|
||||
/// Optional judgement.
|
||||
/// </summary>
|
||||
[Description(@"Perfect")]
|
||||
Perfect,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,11 @@
|
||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Collections.Generic;
|
||||
using osu.Game.Audio;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Rulesets.Judgements;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
|
||||
namespace osu.Game.Rulesets.Objects
|
||||
@ -30,6 +32,10 @@ namespace osu.Game.Rulesets.Objects
|
||||
/// </summary>
|
||||
public SampleInfoList Samples = new SampleInfoList();
|
||||
|
||||
public virtual IEnumerable<Judgement> CreateJudgements() => new[] { new Judgement() };
|
||||
|
||||
public readonly List<HitObject> Children = new List<HitObject>();
|
||||
|
||||
/// <summary>
|
||||
/// Applies default values to this HitObject.
|
||||
/// </summary>
|
||||
|
@ -181,10 +181,12 @@ namespace osu.Game.Rulesets.Scoring
|
||||
{
|
||||
switch (judgement.Result)
|
||||
{
|
||||
case HitResult.None:
|
||||
break;
|
||||
case HitResult.Miss:
|
||||
Combo.Value = 0;
|
||||
break;
|
||||
case HitResult.Hit:
|
||||
default:
|
||||
Combo.Value++;
|
||||
break;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user