1
0
mirror of https://github.com/ppy/osu.git synced 2025-02-21 23:05:34 +08:00

Combine Judgement.HitResults into one.

This commit is contained in:
Dean Herbert 2017-09-05 19:44:59 +09:00 committed by smoogipooo
parent d69b8d7784
commit 84c22df3f5
46 changed files with 265 additions and 467 deletions

View File

@ -6,7 +6,6 @@ using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Timing; using osu.Framework.Timing;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Osu.Judgements;
using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects.Drawables;
using OpenTK; using OpenTK;
@ -110,10 +109,7 @@ namespace osu.Desktop.Tests.Visual
h.Depth = depth++; h.Depth = depth++;
if (auto) if (auto)
{
h.State = ArmedState.Hit; h.State = ArmedState.Hit;
h.Judgement = new OsuJudgement { Result = HitResult.Hit };
}
playfieldContainer.Add(h); playfieldContainer.Add(h);
var proxyable = h as IDrawableHitObjectWithProxiedApproach; var proxyable = h as IDrawableHitObjectWithProxiedApproach;

View File

@ -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) protected override void UpdateState(ArmedState state)
{ {
@ -221,8 +221,6 @@ namespace osu.Desktop.Tests.Visual
private class TestJudgement : Judgement private class TestJudgement : Judgement
{ {
public override string ResultString { get { throw new NotImplementedException(); } }
public override string MaxResultString { get { throw new NotImplementedException(); } }
} }
} }
} }

View File

@ -128,7 +128,7 @@ namespace osu.Desktop.Tests.Visual
private void addHitJudgement(bool kiai) 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(); var cpi = new ControlPointInfo();
cpi.EffectPoints.Add(new EffectControlPoint cpi.EffectPoints.Add(new EffectControlPoint
@ -141,11 +141,10 @@ namespace osu.Desktop.Tests.Visual
var h = new DrawableTestHit(hit) 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 Judgement = new TaikoJudgement
{ {
Result = HitResult.Hit, Result = hitResult,
TaikoResult = hitResult,
TimeOffset = 0 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) protected override void UpdateState(ArmedState state)
{ {

View File

@ -7,8 +7,6 @@ namespace osu.Game.Rulesets.Catch.Judgements
{ {
public class CatchJudgement : Judgement public class CatchJudgement : Judgement
{ {
public override string ResultString => string.Empty; // todo: wangs
public override string MaxResultString => string.Empty;
} }
} }

View File

@ -98,14 +98,12 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable
}; };
} }
protected override CatchJudgement CreateJudgement() => new CatchJudgement();
private const float preempt = 1000; private const float preempt = 1000;
protected override void CheckJudgement(bool userTriggered) protected override void CheckJudgement(bool userTriggered)
{ {
if (Judgement.TimeOffset > 0) 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) protected override void UpdateState(ArmedState state)

View File

@ -55,7 +55,7 @@ namespace osu.Game.Rulesets.Catch.UI
private void Fruit_OnJudgement(DrawableHitObject<CatchBaseHit, CatchJudgement> obj) 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; Vector2 screenPosition = obj.ScreenSpaceDrawQuad.Centre;
Remove(obj); Remove(obj);

View File

@ -2,6 +2,7 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Rulesets.Objects.Drawables;
namespace osu.Game.Rulesets.Mania.Judgements namespace osu.Game.Rulesets.Mania.Judgements
{ {
@ -145,18 +146,18 @@ namespace osu.Game.Rulesets.Mania.Judgements
/// </summary> /// </summary>
/// <param name="hitOffset">The time offset.</param> /// <param name="hitOffset">The time offset.</param>
/// <returns>The hit result, or null if the time offset results in a miss.</returns> /// <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) if (hitOffset <= Perfect / 2)
return ManiaHitResult.Perfect; return HitResult.Perfect;
if (hitOffset <= Great / 2) if (hitOffset <= Great / 2)
return ManiaHitResult.Great; return HitResult.Great;
if (hitOffset <= Good / 2) if (hitOffset <= Good / 2)
return ManiaHitResult.Good; return HitResult.Good;
if (hitOffset <= Ok / 2) if (hitOffset <= Ok / 2)
return ManiaHitResult.Ok; return HitResult.Ok;
if (hitOffset <= Bad / 2) if (hitOffset <= Bad / 2)
return ManiaHitResult.Bad; return HitResult.Meh;
return null; return null;
} }

View File

@ -1,6 +1,8 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // 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 namespace osu.Game.Rulesets.Mania.Judgements
{ {
public class HoldNoteTailJudgement : ManiaJudgement public class HoldNoteTailJudgement : ManiaJudgement
@ -10,27 +12,27 @@ namespace osu.Game.Rulesets.Mania.Judgements
/// </summary> /// </summary>
public bool HasBroken; public bool HasBroken;
public override int NumericResultForScore(ManiaHitResult result) protected override int NumericResultFor(HitResult result)
{ {
switch (result) switch (result)
{ {
default: default:
return base.NumericResultForScore(result); return base.NumericResultFor(result);
case ManiaHitResult.Great: case HitResult.Great:
case ManiaHitResult.Perfect: case HitResult.Perfect:
return base.NumericResultForScore(HasBroken ? ManiaHitResult.Good : result); return base.NumericResultFor(HasBroken ? HitResult.Good : result);
} }
} }
public override int NumericResultForAccuracy(ManiaHitResult result) protected override int NumericResultForAccuracy(HitResult result)
{ {
switch (result) switch (result)
{ {
default: default:
return base.NumericResultForAccuracy(result); return base.NumericResultForAccuracy(result);
case ManiaHitResult.Great: case HitResult.Great:
case ManiaHitResult.Perfect: case HitResult.Perfect:
return base.NumericResultForAccuracy(HasBroken ? ManiaHitResult.Good : result); return base.NumericResultForAccuracy(HasBroken ? HitResult.Good : result);
} }
} }
} }

View File

@ -1,13 +1,15 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // 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 namespace osu.Game.Rulesets.Mania.Judgements
{ {
public class HoldNoteTickJudgement : ManiaJudgement public class HoldNoteTickJudgement : ManiaJudgement
{ {
public override bool AffectsCombo => false; public override bool AffectsCombo => false;
public override int NumericResultForScore(ManiaHitResult result) => 20; protected override int NumericResultFor(HitResult result) => 20;
public override int NumericResultForAccuracy(ManiaHitResult result) => 0; // Don't count ticks into accuracy protected override int NumericResultForAccuracy(HitResult result) => 0; // Don't count ticks into accuracy
} }
} }

View File

@ -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
}
}

View File

@ -8,73 +8,49 @@ namespace osu.Game.Rulesets.Mania.Judgements
{ {
public class ManiaJudgement : Judgement 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> /// <summary>
/// The maximum result value for the accuracy portion of the score. /// The maximum result value for the accuracy portion of the score.
/// </summary> /// </summary>
public int MaxResultValueForAccuracy => NumericResultForAccuracy(MAX_HIT_RESULT); public int MaxNumericAccuracyResult => NumericResultForAccuracy(HitResult.Perfect);
public override string ResultString => string.Empty; protected override int NumericResultFor(HitResult result)
public override string MaxResultString => string.Empty;
/// <summary>
/// The hit result.
/// </summary>
public ManiaHitResult ManiaResult;
public virtual int NumericResultForScore(ManiaHitResult result)
{ {
switch (result) switch (result)
{ {
default: default:
return 0; return 0;
case ManiaHitResult.Bad: case HitResult.Meh:
return 50; return 50;
case ManiaHitResult.Ok: case HitResult.Ok:
return 100; return 100;
case ManiaHitResult.Good: case HitResult.Good:
return 200; return 200;
case ManiaHitResult.Great: case HitResult.Great:
case ManiaHitResult.Perfect: case HitResult.Perfect:
return 300; 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) switch (result)
{ {
default: default:
return 0; return 0;
case ManiaHitResult.Bad: case HitResult.Meh:
return 50; return 50;
case ManiaHitResult.Ok: case HitResult.Ok:
return 100; return 100;
case ManiaHitResult.Good: case HitResult.Good:
return 200; return 200;
case ManiaHitResult.Great: case HitResult.Great:
return 300; return 300;
case ManiaHitResult.Perfect: case HitResult.Perfect:
return 305; return 305;
} }
} }

View File

@ -192,7 +192,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
Y = 0; Y = 0;
} }
protected override ManiaJudgement CreateJudgement() => new HoldNoteTailJudgement(); protected ManiaJudgement CreateJudgement() => new HoldNoteTailJudgement();
protected override void CheckJudgement(bool userTriggered) protected override void CheckJudgement(bool userTriggered)
{ {

View File

@ -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) protected override void CheckJudgement(bool userTriggered)
{ {
@ -93,8 +93,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
if (HoldStartTime?.Invoke() > HitObject.StartTime) if (HoldStartTime?.Invoke() > HitObject.StartTime)
return; return;
Judgement.ManiaResult = ManiaHitResult.Perfect; Judgement.Result = HitResult.Perfect;
Judgement.Result = HitResult.Hit;
} }
protected override void UpdateState(ArmedState state) protected override void UpdateState(ArmedState state)

View File

@ -36,7 +36,5 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
base.AccentColour = value; base.AccentColour = value;
} }
} }
protected override ManiaJudgement CreateJudgement() => new ManiaJudgement();
} }
} }

View File

@ -5,7 +5,6 @@ using System;
using OpenTK.Graphics; using OpenTK.Graphics;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Input.Bindings; using osu.Framework.Input.Bindings;
using osu.Game.Rulesets.Mania.Judgements;
using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces; using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables;
@ -58,15 +57,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
if (offset > HitObject.HitWindows.Miss / 2) if (offset > HitObject.HitWindows.Miss / 2)
return; return;
ManiaHitResult? tmpResult = HitObject.HitWindows.ResultFor(offset); Judgement.Result = HitObject.HitWindows.ResultFor(offset) ?? HitResult.Miss;
if (tmpResult.HasValue)
{
Judgement.Result = HitResult.Hit;
Judgement.ManiaResult = tmpResult.Value;
}
else
Judgement.Result = HitResult.Miss;
} }
protected override void UpdateState(ArmedState state) protected override void UpdateState(ArmedState state)

View File

@ -174,37 +174,19 @@ namespace osu.Game.Rulesets.Mania.Scoring
if (obj is Note) if (obj is Note)
{ {
AddJudgement(new ManiaJudgement AddJudgement(new ManiaJudgement { Result = HitResult.Perfect });
{
Result = HitResult.Hit,
ManiaResult = ManiaHitResult.Perfect
});
} }
else if (holdNote != null) else if (holdNote != null)
{ {
// Head // Head
AddJudgement(new ManiaJudgement AddJudgement(new ManiaJudgement { Result = HitResult.Perfect });
{
Result = HitResult.Hit,
ManiaResult = ManiaJudgement.MAX_HIT_RESULT
});
// Ticks // Ticks
int tickCount = holdNote.Ticks.Count(); int tickCount = holdNote.Ticks.Count();
for (int i = 0; i < tickCount; i++) for (int i = 0; i < tickCount; i++)
{ AddJudgement(new HoldNoteTickJudgement { Result = HitResult.Perfect });
AddJudgement(new HoldNoteTickJudgement
{
Result = HitResult.Hit,
ManiaResult = ManiaJudgement.MAX_HIT_RESULT,
});
}
AddJudgement(new HoldNoteTailJudgement AddJudgement(new HoldNoteTailJudgement { Result = HitResult.Perfect });
{
Result = HitResult.Hit,
ManiaResult = ManiaJudgement.MAX_HIT_RESULT
});
} }
} }
@ -225,46 +207,46 @@ namespace osu.Game.Rulesets.Mania.Scoring
{ {
bool isTick = judgement is HoldNoteTickJudgement; bool isTick = judgement is HoldNoteTickJudgement;
if (!isTick) if (isTick)
{
if (judgement.IsHit)
{
Health.Value += hpMultiplier * hp_increase_tick;
bonusScore += judgement.NumericResult;
}
}
else
{
totalHits++; totalHits++;
switch (judgement.Result) switch (judgement.Result)
{ {
case HitResult.Miss: case HitResult.Miss:
Health.Value += hpMissMultiplier * hp_increase_miss; Health.Value += hpMissMultiplier * hp_increase_miss;
break; break;
case HitResult.Hit: case HitResult.Meh:
if (isTick) Health.Value += hpMultiplier * hp_increase_bad;
{ break;
Health.Value += hpMultiplier * hp_increase_tick; case HitResult.Ok:
bonusScore += judgement.ResultValueForScore; Health.Value += hpMultiplier * hp_increase_ok;
} break;
else case HitResult.Good:
{ Health.Value += hpMultiplier * hp_increase_good;
switch (judgement.ManiaResult) break;
{ case HitResult.Great:
case ManiaHitResult.Bad: Health.Value += hpMultiplier * hp_increase_great;
Health.Value += hpMultiplier * hp_increase_bad; break;
break; case HitResult.Perfect:
case ManiaHitResult.Ok: Health.Value += hpMultiplier * hp_increase_perfect;
Health.Value += hpMultiplier * hp_increase_ok; break;
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;
}
// A factor that is applied to make higher combos more relevant if (judgement.IsHit)
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; // 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));
break; comboPortion += judgement.NumericResult * comboRelevance;
}
} }
int scoreForAccuracy = 0; int scoreForAccuracy = 0;
@ -272,8 +254,8 @@ namespace osu.Game.Rulesets.Mania.Scoring
foreach (var j in Judgements) foreach (var j in Judgements)
{ {
scoreForAccuracy += j.ResultValueForAccuracy; scoreForAccuracy += j.NumericAccuracyResult;
maxScoreForAccuracy += j.MaxResultValueForAccuracy; maxScoreForAccuracy += j.MaxNumericAccuracyResult;
} }
Accuracy.Value = (double)scoreForAccuracy / maxScoreForAccuracy; Accuracy.Value = (double)scoreForAccuracy / maxScoreForAccuracy;

View File

@ -60,7 +60,6 @@
<Compile Include="Judgements\HitWindows.cs" /> <Compile Include="Judgements\HitWindows.cs" />
<Compile Include="Judgements\HoldNoteTailJudgement.cs" /> <Compile Include="Judgements\HoldNoteTailJudgement.cs" />
<Compile Include="Judgements\HoldNoteTickJudgement.cs" /> <Compile Include="Judgements\HoldNoteTickJudgement.cs" />
<Compile Include="Judgements\ManiaHitResult.cs" />
<Compile Include="Judgements\ManiaJudgement.cs" /> <Compile Include="Judgements\ManiaJudgement.cs" />
<Compile Include="ManiaDifficultyCalculator.cs" /> <Compile Include="ManiaDifficultyCalculator.cs" />
<Compile Include="Mods\IGenerateSpeedAdjustments.cs" /> <Compile Include="Mods\IGenerateSpeedAdjustments.cs" />

View File

@ -4,10 +4,14 @@
using OpenTK; using OpenTK;
using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects.Drawables;
using osu.Framework.Extensions; using osu.Game.Rulesets.Objects.Drawables;
namespace osu.Game.Rulesets.Osu.Judgements namespace osu.Game.Rulesets.Osu.Judgements
{ {
public class SliderTickJudgement : OsuJudgement
{
}
public class OsuJudgement : Judgement public class OsuJudgement : Judgement
{ {
/// <summary> /// <summary>
@ -15,38 +19,18 @@ namespace osu.Game.Rulesets.Osu.Judgements
/// </summary> /// </summary>
public Vector2 PositionOffset; public Vector2 PositionOffset;
/// <summary> protected override int NumericResultFor(HitResult result)
/// 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)
{ {
switch (result) switch (result)
{ {
default: default:
return 0; return 0;
case OsuScoreResult.Hit50: case HitResult.Meh:
return 50; return 50;
case OsuScoreResult.Hit100: case HitResult.Good:
return 100; return 100;
case OsuScoreResult.Hit300: case HitResult.Great:
return 300; return 300;
case OsuScoreResult.SliderTick:
return 10;
} }
} }

View File

@ -69,20 +69,12 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
{ {
if (!userTriggered) if (!userTriggered)
{ {
if (Judgement.TimeOffset > HitObject.HitWindowFor(OsuScoreResult.Hit50)) if (Judgement.TimeOffset > HitObject.HitWindowFor(HitResult.Meh))
Judgement.Result = HitResult.Miss; Judgement.Result = HitResult.Miss;
return; return;
} }
double hitOffset = Math.Abs(Judgement.TimeOffset); Judgement.Result = HitObject.ScoreResultForOffset(Math.Abs(Judgement.TimeOffset));
if (hitOffset < HitObject.HitWindowFor(OsuScoreResult.Hit50))
{
Judgement.Result = HitResult.Hit;
Judgement.Score = HitObject.ScoreResultForOffset(hitOffset);
}
else
Judgement.Result = HitResult.Miss;
} }
protected override void UpdateInitialState() protected override void UpdateInitialState()

View File

@ -21,8 +21,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
Alpha = 0; Alpha = 0;
} }
protected override OsuJudgement CreateJudgement() => new OsuJudgement { MaxScore = OsuScoreResult.Hit300 };
protected sealed override void UpdateState(ArmedState state) protected sealed override void UpdateState(ArmedState state)
{ {
FinishTransforms(); FinishTransforms();
@ -65,18 +63,4 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
[Description(@"Amazing")] [Description(@"Amazing")]
Perfect Perfect
} }
public enum OsuScoreResult
{
[Description(@"Miss")]
Miss,
[Description(@"50")]
Hit50,
[Description(@"100")]
Hit100,
[Description(@"300")]
Hit300,
[Description(@"10")]
SliderTick
}
} }

View File

@ -114,7 +114,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
bouncer2.Position = slider.Curve.PositionAt(body.SnakedEnd ?? 0); bouncer2.Position = slider.Curve.PositionAt(body.SnakedEnd ?? 0);
//todo: we probably want to reconsider this before adding scoring, but it looks and feels nice. //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); initialCircle.Position = slider.Curve.PositionAt(progress);
foreach (var c in components) c.UpdateProgress(progress, repeat); 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) if (!userTriggered && Time.Current >= slider.EndTime)
{ {
var ticksCount = ticks.Children.Count + 1; var ticksCount = ticks.Children.Count + 1;
var ticksHit = ticks.Children.Count(t => t.Judgement.Result == HitResult.Hit); var ticksHit = ticks.Children.Count(t => t.Judgement.Result > HitResult.Miss);
if (initialCircle.Judgement.Result == HitResult.Hit) if (initialCircle.Judgement.Result > HitResult.Miss)
ticksHit++; ticksHit++;
var hitFraction = (double)ticksHit / ticksCount; var hitFraction = (double)ticksHit / ticksCount;
if (hitFraction == 1 && initialCircle.Judgement.Score == OsuScoreResult.Hit300) if (hitFraction == 1 && initialCircle.Judgement.Result == HitResult.Great)
Judgement.Score = OsuScoreResult.Hit300; Judgement.Result = HitResult.Great;
else if (hitFraction >= 0.5 && initialCircle.Judgement.Score >= OsuScoreResult.Hit100) else if (hitFraction >= 0.5 && initialCircle.Judgement.Result >= HitResult.Good)
Judgement.Score = OsuScoreResult.Hit100; Judgement.Result = HitResult.Good;
else if (hitFraction > 0) else if (hitFraction > 0)
Judgement.Score = OsuScoreResult.Hit50; Judgement.Result = HitResult.Meh;
else else
Judgement.Score = OsuScoreResult.Miss; Judgement.Result = HitResult.Miss;
Judgement.Result = Judgement.Score != OsuScoreResult.Miss ? HitResult.Hit : HitResult.Miss;
} }
} }

View File

@ -4,7 +4,6 @@
using System; using System;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Osu.Judgements;
using OpenTK; using OpenTK;
using OpenTK.Graphics; using OpenTK.Graphics;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
@ -22,8 +21,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
public override bool RemoveWhenNotAlive => false; public override bool RemoveWhenNotAlive => false;
protected override OsuJudgement CreateJudgement() => new OsuJudgement { MaxScore = OsuScoreResult.SliderTick };
public DrawableSliderTick(SliderTick sliderTick) : base(sliderTick) public DrawableSliderTick(SliderTick sliderTick) : base(sliderTick)
{ {
this.sliderTick = sliderTick; this.sliderTick = sliderTick;
@ -52,10 +49,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
protected override void CheckJudgement(bool userTriggered) protected override void CheckJudgement(bool userTriggered)
{ {
if (Judgement.TimeOffset >= 0) if (Judgement.TimeOffset >= 0)
{ Judgement.Result = Tracking ? HitResult.Perfect : HitResult.Miss;
Judgement.Result = Tracking ? HitResult.Hit : HitResult.Miss;
Judgement.Score = Tracking ? OsuScoreResult.SliderTick : OsuScoreResult.Miss;
}
} }
protected override void UpdatePreemptState() protected override void UpdatePreemptState()

View File

@ -129,26 +129,13 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
if (!userTriggered && Time.Current >= spinner.EndTime) if (!userTriggered && Time.Current >= spinner.EndTime)
{ {
if (Progress >= 1) if (Progress >= 1)
{ Judgement.Result = HitResult.Great;
Judgement.Score = OsuScoreResult.Hit300;
Judgement.Result = HitResult.Hit;
}
else if (Progress > .9) else if (Progress > .9)
{ Judgement.Result = HitResult.Good;
Judgement.Score = OsuScoreResult.Hit100;
Judgement.Result = HitResult.Hit;
}
else if (Progress > .75) else if (Progress > .75)
{ Judgement.Result = HitResult.Meh;
Judgement.Score = OsuScoreResult.Hit50; else if (Time.Current >= spinner.EndTime)
Judgement.Result = HitResult.Hit; Judgement.Result = HitResult.Miss;
}
else
{
Judgement.Score = OsuScoreResult.Miss;
if (Time.Current >= spinner.EndTime)
Judgement.Result = HitResult.Miss;
}
} }
} }

View File

@ -4,10 +4,10 @@
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects;
using OpenTK; using OpenTK;
using osu.Game.Rulesets.Osu.Objects.Drawables;
using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Objects.Types;
using OpenTK.Graphics; using OpenTK.Graphics;
using osu.Game.Beatmaps.ControlPoints; using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Rulesets.Objects.Drawables;
namespace osu.Game.Rulesets.Osu.Objects namespace osu.Game.Rulesets.Osu.Objects
{ {
@ -42,30 +42,30 @@ namespace osu.Game.Rulesets.Osu.Objects
public virtual bool NewCombo { get; set; } public virtual bool NewCombo { get; set; }
public int ComboIndex { get; set; } public int ComboIndex { get; set; }
public double HitWindowFor(OsuScoreResult result) public double HitWindowFor(HitResult result)
{ {
switch (result) switch (result)
{ {
default: default:
return 300; return 300;
case OsuScoreResult.Hit50: case HitResult.Meh:
return 150; return 150;
case OsuScoreResult.Hit100: case HitResult.Good:
return 80; return 80;
case OsuScoreResult.Hit300: case HitResult.Great:
return 30; return 30;
} }
} }
public OsuScoreResult ScoreResultForOffset(double offset) public HitResult ScoreResultForOffset(double offset)
{ {
if (offset < HitWindowFor(OsuScoreResult.Hit300)) if (offset < HitWindowFor(HitResult.Great))
return OsuScoreResult.Hit300; return HitResult.Great;
if (offset < HitWindowFor(OsuScoreResult.Hit100)) if (offset < HitWindowFor(HitResult.Good))
return OsuScoreResult.Hit100; return HitResult.Good;
if (offset < HitWindowFor(OsuScoreResult.Hit50)) if (offset < HitWindowFor(HitResult.Meh))
return OsuScoreResult.Hit50; return HitResult.Meh;
return OsuScoreResult.Miss; return HitResult.Miss;
} }
public override void ApplyDefaults(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty) public override void ApplyDefaults(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty)

View File

@ -9,6 +9,7 @@ using osu.Game.Rulesets.Osu.Objects.Drawables;
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Objects.Types;
using osu.Game.Rulesets.Replays; using osu.Game.Rulesets.Replays;
@ -89,20 +90,20 @@ namespace osu.Game.Rulesets.Osu.Replays
double endTime = (prev as IHasEndTime)?.EndTime ?? prev.StartTime; double endTime = (prev as IHasEndTime)?.EndTime ?? prev.StartTime;
// Make the cursor stay at a hitObject as long as possible (mainly for autopilot). // 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 (!(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(OsuScoreResult.Miss), h.StackedPosition.X, h.StackedPosition.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 (!(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(OsuScoreResult.Hit50), h.StackedPosition.X, h.StackedPosition.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 (!(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(OsuScoreResult.Hit100), h.StackedPosition.X, h.StackedPosition.Y, ReplayButtonState.None)); if (!(h is Spinner)) AddFrameToReplay(new ReplayFrame(h.StartTime - h.HitWindowFor(HitResult.Good), h.StackedPosition.X, h.StackedPosition.Y, ReplayButtonState.None));
} }
} }

View File

@ -32,7 +32,7 @@ namespace osu.Game.Rulesets.Osu.Scoring
private int totalAccurateJudgements; 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 readonly Dictionary<ComboResult, int> comboResultCounts = new Dictionary<ComboResult, int>();
private double comboMaxScore; private double comboMaxScore;
@ -45,12 +45,7 @@ namespace osu.Game.Rulesets.Osu.Scoring
foreach (var h in beatmap.HitObjects) foreach (var h in beatmap.HitObjects)
{ {
// TODO: add support for other object types. // TODO: add support for other object types.
AddJudgement(new OsuJudgement AddJudgement(new OsuJudgement { Result = HitResult.Great });
{
MaxScore = OsuScoreResult.Hit300,
Score = OsuScoreResult.Hit300,
Result = HitResult.Hit
});
} }
} }
@ -69,10 +64,10 @@ namespace osu.Game.Rulesets.Osu.Scoring
{ {
base.PopulateScore(score); base.PopulateScore(score);
score.Statistics[@"300"] = scoreResultCounts.GetOrDefault(OsuScoreResult.Hit300); score.Statistics[@"300"] = scoreResultCounts.GetOrDefault(HitResult.Great);
score.Statistics[@"100"] = scoreResultCounts.GetOrDefault(OsuScoreResult.Hit100); score.Statistics[@"100"] = scoreResultCounts.GetOrDefault(HitResult.Good);
score.Statistics[@"50"] = scoreResultCounts.GetOrDefault(OsuScoreResult.Hit50); score.Statistics[@"50"] = scoreResultCounts.GetOrDefault(HitResult.Meh);
score.Statistics[@"x"] = scoreResultCounts.GetOrDefault(OsuScoreResult.Miss); score.Statistics[@"x"] = scoreResultCounts.GetOrDefault(HitResult.Miss);
} }
protected override void OnNewJudgement(OsuJudgement judgement) protected override void OnNewJudgement(OsuJudgement judgement)
@ -81,29 +76,29 @@ namespace osu.Game.Rulesets.Osu.Scoring
{ {
if (judgement.Result != HitResult.None) 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; 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; Health.Value += (10.2 - hpDrainRate) * 0.02;
break; break;
case OsuScoreResult.Hit100: case HitResult.Good:
Health.Value += (8 - hpDrainRate) * 0.02; Health.Value += (8 - hpDrainRate) * 0.02;
break; break;
case OsuScoreResult.Hit50: case HitResult.Meh:
Health.Value += (4 - hpDrainRate) * 0.02; Health.Value += (4 - hpDrainRate) * 0.02;
break; break;
case OsuScoreResult.SliderTick: /*case HitResult.SliderTick:
Health.Value += Math.Max(7 - hpDrainRate, 0) * 0.01; Health.Value += Math.Max(7 - hpDrainRate, 0) * 0.01;
break; break;*/
case OsuScoreResult.Miss: case HitResult.Miss:
Health.Value -= hpDrainRate * 0.04; Health.Value -= hpDrainRate * 0.04;
break; break;
} }
@ -123,10 +118,10 @@ namespace osu.Game.Rulesets.Osu.Scoring
foreach (var j in Judgements) foreach (var j in Judgements)
{ {
baseScore += j.ScoreValue; baseScore += j.NumericResult;
baseMaxScore += j.MaxScoreValue; baseMaxScore += j.MaxNumericResult;
comboScore += j.ScoreValue * (1 + Combo.Value / 10d); comboScore += j.NumericResult * (1 + Combo.Value / 10d);
} }
Accuracy.Value = (double)baseScore / baseMaxScore; Accuracy.Value = (double)baseScore / baseMaxScore;

View File

@ -1,34 +1,26 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // 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 namespace osu.Game.Rulesets.Taiko.Judgements
{ {
public class TaikoDrumRollTickJudgement : TaikoJudgement 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; public override bool AffectsCombo => false;
protected override int NumericResultForScore(TaikoHitResult result) protected override int NumericResultFor(HitResult result)
{ {
switch (result) switch (result)
{ {
default: default:
return 0; return 0;
case TaikoHitResult.Great: case HitResult.Great:
return 200; return 200;
} }
} }
protected override int NumericResultForAccuracy(TaikoHitResult result) protected override int NumericResultForAccuracy(HitResult result)
{ {
return 0; return 0;
} }

View File

@ -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
}
}

View File

@ -2,46 +2,21 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Judgements;
using osu.Framework.Extensions;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables;
namespace osu.Game.Rulesets.Taiko.Judgements namespace osu.Game.Rulesets.Taiko.Judgements
{ {
public class TaikoJudgement : Judgement 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> /// <summary>
/// The result value for the accuracy portion of the score. /// The result value for the accuracy portion of the score.
/// </summary> /// </summary>
public int ResultValueForAccuracy => Result == HitResult.Miss ? 0 : NumericResultForAccuracy(TaikoResult); public int ResultNumericForAccuracy => Result == HitResult.Miss ? 0 : NumericResultForAccuracy(Result);
/// <summary>
/// The maximum result value for the combo portion of the score.
/// </summary>
public int MaxResultValueForScore => NumericResultForScore(MAX_HIT_RESULT);
/// <summary> /// <summary>
/// The maximum result value for the accuracy portion of the score. /// The maximum result value for the accuracy portion of the score.
/// </summary> /// </summary>
public int MaxResultValueForAccuracy => NumericResultForAccuracy(MAX_HIT_RESULT); public int MaxResultValueForAccuracy => NumericResultForAccuracy(HitResult.Great);
public override string ResultString => TaikoResult.GetDescription();
public override string MaxResultString => MAX_HIT_RESULT.GetDescription();
/// <summary> /// <summary>
/// Whether this Judgement has a secondary hit in the case of strong hits. /// Whether this Judgement has a secondary hit in the case of strong hits.
@ -50,38 +25,38 @@ namespace osu.Game.Rulesets.Taiko.Judgements
/// <summary> /// <summary>
/// Computes the numeric result value for the combo portion of the score. /// 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> /// </summary>
/// <param name="result">The result to compute the value for.</param> /// <param name="result">The result to compute the value for.</param>
/// <returns>The numeric result value.</returns> /// <returns>The numeric result value.</returns>
protected virtual int NumericResultForScore(TaikoHitResult result) protected override int NumericResultFor(HitResult result)
{ {
switch (result) switch (result)
{ {
default: default:
return 0; return 0;
case TaikoHitResult.Good: case HitResult.Good:
return 100; return 100;
case TaikoHitResult.Great: case HitResult.Great:
return 300; return 300;
} }
} }
/// <summary> /// <summary>
/// Computes the numeric result value for the accuracy portion of the score. /// 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> /// </summary>
/// <param name="result">The result to compute the value for.</param> /// <param name="result">The result to compute the value for.</param>
/// <returns>The numeric result value.</returns> /// <returns>The numeric result value.</returns>
protected virtual int NumericResultForAccuracy(TaikoHitResult result) protected virtual int NumericResultForAccuracy(HitResult result)
{ {
switch (result) switch (result)
{ {
default: default:
return 0; return 0;
case TaikoHitResult.Good: case HitResult.Good:
return 150; return 150;
case TaikoHitResult.Great: case HitResult.Great:
return 300; return 300;
} }
} }

View File

@ -58,8 +58,6 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
}; };
} }
protected override TaikoJudgement CreateJudgement() => null;
protected override void UpdateState(ArmedState state) protected override void UpdateState(ArmedState state)
{ {
} }

View File

@ -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(); protected override TaikoPiece CreateMainPiece() => new ElongatedCirclePiece();
@ -67,7 +67,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
private void onTickJudgement(DrawableHitObject<TaikoHitObject, TaikoJudgement> obj) private void onTickJudgement(DrawableHitObject<TaikoHitObject, TaikoJudgement> obj)
{ {
if (obj.Judgement.Result == HitResult.Hit) if (obj.Judgement.Result > HitResult.Miss)
rollingHits++; rollingHits++;
else else
rollingHits--; rollingHits--;
@ -86,12 +86,11 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
if (Judgement.TimeOffset < 0) if (Judgement.TimeOffset < 0)
return; 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) if (countHit > HitObject.RequiredGoodHits)
{ {
Judgement.Result = HitResult.Hit; Judgement.Result = countHit >= HitObject.RequiredGreatHits ? HitResult.Great : HitResult.Good;
Judgement.TaikoResult = countHit >= HitObject.RequiredGreatHits ? TaikoHitResult.Great : TaikoHitResult.Good;
} }
else else
Judgement.Result = HitResult.Miss; Judgement.Result = HitResult.Miss;

View File

@ -34,7 +34,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
Filled = HitObject.FirstTick 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) protected override void CheckJudgement(bool userTriggered)
{ {
@ -42,10 +42,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
return; return;
if (Math.Abs(Judgement.TimeOffset) < HitObject.HitWindow) if (Math.Abs(Judgement.TimeOffset) < HitObject.HitWindow)
{ Judgement.Result = HitResult.Great;
Judgement.Result = HitResult.Hit;
Judgement.TaikoResult = TaikoHitResult.Great;
}
} }
protected override void UpdateState(ArmedState state) protected override void UpdateState(ArmedState state)

View File

@ -5,7 +5,6 @@ using System;
using System.Linq; using System.Linq;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Taiko.Judgements;
using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces; using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces;
namespace osu.Game.Rulesets.Taiko.Objects.Drawables namespace osu.Game.Rulesets.Taiko.Objects.Drawables
@ -45,10 +44,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
if (!validKeyPressed) if (!validKeyPressed)
Judgement.Result = HitResult.Miss; Judgement.Result = HitResult.Miss;
else if (hitOffset < HitObject.HitWindowGood) else if (hitOffset < HitObject.HitWindowGood)
{ Judgement.Result = hitOffset < HitObject.HitWindowGreat ? HitResult.Great : HitResult.Good;
Judgement.Result = HitResult.Hit;
Judgement.TaikoResult = hitOffset < HitObject.HitWindowGreat ? TaikoHitResult.Great : TaikoHitResult.Good;
}
else else
Judgement.Result = HitResult.Miss; Judgement.Result = HitResult.Miss;
} }

View File

@ -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) protected override void CheckJudgement(bool userTriggered)
{ {

View File

@ -9,7 +9,6 @@ using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Taiko.Judgements;
using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces; using osu.Game.Rulesets.Taiko.Objects.Drawables.Pieces;
using OpenTK; using OpenTK;
using OpenTK.Graphics; 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); expandingRing.ScaleTo(1f + Math.Min(target_ring_scale - 1f, (target_ring_scale - 1f) * completion * 1.3f), 260, Easing.OutQuint);
if (userHits == HitObject.RequiredHits) if (userHits == HitObject.RequiredHits)
{ Judgement.Result = HitResult.Great;
Judgement.Result = HitResult.Hit;
Judgement.TaikoResult = TaikoHitResult.Great;
}
} }
else else
{ {
@ -165,10 +161,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
//TODO: THIS IS SHIT AND CAN'T EXIST POST-TAIKO WORLD CUP //TODO: THIS IS SHIT AND CAN'T EXIST POST-TAIKO WORLD CUP
if (userHits > HitObject.RequiredHits / 2) if (userHits > HitObject.RequiredHits / 2)
{ Judgement.Result = HitResult.Good;
Judgement.Result = HitResult.Hit;
Judgement.TaikoResult = TaikoHitResult.Good;
}
else else
Judgement.Result = HitResult.Miss; Judgement.Result = HitResult.Miss;
} }

View File

@ -37,8 +37,6 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
MainPiece.KiaiMode = HitObject.Kiai; MainPiece.KiaiMode = HitObject.Kiai;
} }
protected override TaikoJudgement CreateJudgement() => new TaikoJudgement();
protected virtual TaikoPiece CreateMainPiece() => new CirclePiece(); protected virtual TaikoPiece CreateMainPiece() => new CirclePiece();
public abstract bool OnPressed(TaikoAction action); public abstract bool OnPressed(TaikoAction action);

View File

@ -36,12 +36,12 @@ namespace osu.Game.Rulesets.Taiko.Scoring
private const double combo_base = 4; private const double combo_base = 4;
/// <summary> /// <summary>
/// The HP awarded by a <see cref="TaikoHitResult.Great"/> hit. /// The HP awarded by a <see cref="HitResult.Great"/> hit.
/// </summary> /// </summary>
private const double hp_hit_great = 0.03; private const double hp_hit_great = 0.03;
/// <summary> /// <summary>
/// The HP awarded for a <see cref="TaikoHitResult.Good"/> hit. /// The HP awarded for a <see cref="HitResult.Good"/> hit.
/// </summary> /// </summary>
private const double hp_hit_good = 0.011; private const double hp_hit_good = 0.011;
@ -140,8 +140,7 @@ namespace osu.Game.Rulesets.Taiko.Scoring
{ {
AddJudgement(new TaikoJudgement AddJudgement(new TaikoJudgement
{ {
Result = HitResult.Hit, Result = HitResult.Great,
TaikoResult = TaikoHitResult.Great,
SecondHit = obj.IsStrong SecondHit = obj.IsStrong
}); });
} }
@ -151,26 +150,20 @@ namespace osu.Game.Rulesets.Taiko.Scoring
{ {
AddJudgement(new TaikoDrumRollTickJudgement AddJudgement(new TaikoDrumRollTickJudgement
{ {
Result = HitResult.Hit, Result = HitResult.Great,
TaikoResult = TaikoHitResult.Great,
SecondHit = obj.IsStrong SecondHit = obj.IsStrong
}); });
} }
AddJudgement(new TaikoJudgement AddJudgement(new TaikoJudgement
{ {
Result = HitResult.Hit, Result = HitResult.Great,
TaikoResult = TaikoHitResult.Great,
SecondHit = obj.IsStrong SecondHit = obj.IsStrong
}); });
} }
else if (obj is Swell) else if (obj is Swell)
{ {
AddJudgement(new TaikoJudgement AddJudgement(new TaikoJudgement { Result = HitResult.Great });
{
Result = HitResult.Hit,
TaikoResult = TaikoHitResult.Great
});
} }
} }
@ -197,19 +190,14 @@ namespace osu.Game.Rulesets.Taiko.Scoring
if (!isTick) if (!isTick)
Health.Value += hpIncreaseMiss; Health.Value += hpIncreaseMiss;
break; break;
case HitResult.Hit: case HitResult.Good:
switch (judgement.TaikoResult) Health.Value += hpIncreaseGood;
{ break;
case TaikoHitResult.Good: case HitResult.Great:
Health.Value += hpIncreaseGood; if (isTick)
break; Health.Value += hpIncreaseTick;
case TaikoHitResult.Great: else
if (isTick) Health.Value += hpIncreaseGreat;
Health.Value += hpIncreaseTick;
else
Health.Value += hpIncreaseGreat;
break;
}
break; break;
} }
@ -226,10 +214,10 @@ namespace osu.Game.Rulesets.Taiko.Scoring
private void addHitScore(TaikoJudgement judgement) private void addHitScore(TaikoJudgement judgement)
{ {
if (judgement.Result != HitResult.Hit) if (!judgement.IsHit)
return; return;
double baseValue = judgement.ResultValueForScore; double baseValue = judgement.NumericResult;
// Add increased score for hitting a strong hit object with the second key // Add increased score for hitting a strong hit object with the second key
if (judgement.SecondHit) if (judgement.SecondHit)
@ -255,7 +243,7 @@ namespace osu.Game.Rulesets.Taiko.Scoring
foreach (var j in Judgements) foreach (var j in Judgements)
{ {
scoreForAccuracy += j.ResultValueForAccuracy; scoreForAccuracy += j.ResultNumericForAccuracy;
maxScoreForAccuracy += j.MaxResultValueForAccuracy; maxScoreForAccuracy += j.MaxResultValueForAccuracy;
} }

View File

@ -29,28 +29,19 @@ namespace osu.Game.Rulesets.Taiko.UI
{ {
switch (Judgement.Result) switch (Judgement.Result)
{ {
case HitResult.Hit: case HitResult.Good:
switch (Judgement.TaikoResult) Colour = colours.GreenLight;
{ break;
case TaikoHitResult.Good: case HitResult.Great:
Colour = colours.GreenLight; Colour = colours.BlueLight;
break;
case TaikoHitResult.Great:
Colour = colours.BlueLight;
break;
}
break; break;
} }
} }
protected override void LoadComplete() protected override void LoadComplete()
{ {
switch (Judgement.Result) if (Judgement.IsHit)
{ this.MoveToY(-100, 500);
case HitResult.Hit:
this.MoveToY(-100, 500);
break;
}
base.LoadComplete(); base.LoadComplete();
} }

View File

@ -220,7 +220,7 @@ namespace osu.Game.Rulesets.Taiko.UI
public override void OnJudgement(DrawableHitObject<TaikoHitObject, TaikoJudgement> judgedObject) 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; bool secondHit = judgedObject.Judgement.SecondHit;
judgementContainer.Add(new DrawableTaikoJudgement(judgedObject.Judgement) judgementContainer.Add(new DrawableTaikoJudgement(judgedObject.Judgement)

View File

@ -52,7 +52,6 @@
<Compile Include="Judgements\TaikoDrumRollTickJudgement.cs" /> <Compile Include="Judgements\TaikoDrumRollTickJudgement.cs" />
<Compile Include="Judgements\TaikoStrongHitJudgement.cs" /> <Compile Include="Judgements\TaikoStrongHitJudgement.cs" />
<Compile Include="Judgements\TaikoJudgement.cs" /> <Compile Include="Judgements\TaikoJudgement.cs" />
<Compile Include="Judgements\TaikoHitResult.cs" />
<Compile Include="Objects\BarLine.cs" /> <Compile Include="Objects\BarLine.cs" />
<Compile Include="Objects\Drawables\DrawableBarLine.cs" /> <Compile Include="Objects\Drawables\DrawableBarLine.cs" />
<Compile Include="Objects\Drawables\DrawableBarLineMajor.cs" /> <Compile Include="Objects\Drawables\DrawableBarLineMajor.cs" />

View File

@ -34,15 +34,13 @@ namespace osu.Game.Rulesets.Judgements
AutoSizeAxes = Axes.Both; AutoSizeAxes = Axes.Both;
string resultString = judgement.Result == HitResult.Hit ? judgement.ResultString : judgement.Result.GetDescription();
Children = new[] Children = new[]
{ {
JudgementText = new OsuSpriteText JudgementText = new OsuSpriteText
{ {
Origin = Anchor.Centre, Origin = Anchor.Centre,
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Text = resultString.ToUpper(), Text = judgement.Result.GetDescription().ToUpper(),
Font = @"Venera", Font = @"Venera",
TextSize = 16 TextSize = 16
} }
@ -68,6 +66,8 @@ namespace osu.Game.Rulesets.Judgements
switch (Judgement.Result) switch (Judgement.Result)
{ {
case HitResult.None:
break;
case HitResult.Miss: case HitResult.Miss:
this.ScaleTo(1.6f); this.ScaleTo(1.6f);
this.ScaleTo(1, 100, Easing.In); this.ScaleTo(1, 100, Easing.In);
@ -77,7 +77,7 @@ namespace osu.Game.Rulesets.Judgements
this.Delay(600).FadeOut(200); this.Delay(600).FadeOut(200);
break; break;
case HitResult.Hit: default:
this.ScaleTo(0.9f); this.ScaleTo(0.9f);
this.ScaleTo(1, 500, Easing.OutElastic); this.ScaleTo(1, 500, Easing.OutElastic);

View File

@ -5,13 +5,20 @@ using osu.Game.Rulesets.Objects.Drawables;
namespace osu.Game.Rulesets.Judgements namespace osu.Game.Rulesets.Judgements
{ {
public abstract class Judgement public class Judgement
{ {
/// <summary> /// <summary>
/// Whether this judgement is the result of a hit or a miss. /// Whether this judgement is the result of a hit or a miss.
/// </summary> /// </summary>
public HitResult Result; 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> /// <summary>
/// The offset at which this judgement occurred. /// The offset at which this judgement occurred.
/// </summary> /// </summary>
@ -20,13 +27,20 @@ namespace osu.Game.Rulesets.Judgements
public virtual bool AffectsCombo => true; public virtual bool AffectsCombo => true;
/// <summary> /// <summary>
/// The string representation for the result achieved. /// The numeric representation for the result achieved.
/// </summary> /// </summary>
public abstract string ResultString { get; } public int NumericResult => NumericResultFor(Result);
/// <summary> /// <summary>
/// The string representation for the max result achievable. /// The numeric representation for the maximum achievable result.
/// </summary> /// </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;
} }
} }

View File

@ -178,10 +178,6 @@ namespace osu.Game.Rulesets.Objects.Drawables
channel.Volume.Value = sample.Volume; channel.Volume.Value = sample.Volume;
Samples.Add(channel); 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; private List<DrawableHitObject<TObject, TJudgement>> nestedHitObjects;
@ -196,7 +192,6 @@ namespace osu.Game.Rulesets.Objects.Drawables
nestedHitObjects.Add(h); nestedHitObjects.Add(h);
} }
protected abstract TJudgement CreateJudgement();
protected abstract void UpdateState(ArmedState state); protected abstract void UpdateState(ArmedState state);
} }
} }

View File

@ -10,17 +10,34 @@ namespace osu.Game.Rulesets.Objects.Drawables
/// <summary> /// <summary>
/// Indicates that the object has not been judged yet. /// Indicates that the object has not been judged yet.
/// </summary> /// </summary>
[Description("")] [Description(@"")]
None, None,
/// <summary> /// <summary>
/// Indicates that the object has been judged as a miss. /// Indicates that the object has been judged as a miss.
/// </summary> /// </summary>
[Description(@"Miss")] [Description(@"Miss")]
Miss, Miss,
[Description(@"Meh")]
Meh,
/// <summary> /// <summary>
/// Indicates that the object has been judged as a hit. /// Optional judgement.
/// </summary> /// </summary>
[Description(@"Hit")] [Description(@"OK")]
Hit, Ok,
[Description(@"Good")]
Good,
[Description(@"Great")]
Great,
/// <summary>
/// Optional judgement.
/// </summary>
[Description(@"Perfect")]
Perfect,
} }
} }

View File

@ -1,9 +1,11 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System.Collections.Generic;
using osu.Game.Audio; using osu.Game.Audio;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Beatmaps.ControlPoints; using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Objects.Types;
namespace osu.Game.Rulesets.Objects namespace osu.Game.Rulesets.Objects
@ -30,6 +32,10 @@ namespace osu.Game.Rulesets.Objects
/// </summary> /// </summary>
public SampleInfoList Samples = new SampleInfoList(); public SampleInfoList Samples = new SampleInfoList();
public virtual IEnumerable<Judgement> CreateJudgements() => new[] { new Judgement() };
public readonly List<HitObject> Children = new List<HitObject>();
/// <summary> /// <summary>
/// Applies default values to this HitObject. /// Applies default values to this HitObject.
/// </summary> /// </summary>

View File

@ -181,10 +181,12 @@ namespace osu.Game.Rulesets.Scoring
{ {
switch (judgement.Result) switch (judgement.Result)
{ {
case HitResult.None:
break;
case HitResult.Miss: case HitResult.Miss:
Combo.Value = 0; Combo.Value = 0;
break; break;
case HitResult.Hit: default:
Combo.Value++; Combo.Value++;
break; break;
} }