1
0
mirror of https://github.com/ppy/osu.git synced 2024-09-22 05:27:23 +08:00

Implement Score Processor Mod Interface

- Add a delegate whenever we want to register an additional fail condition
This commit is contained in:
Brayzure 2017-11-20 02:15:29 -05:00
parent de4d8eb196
commit da30d76f9b
6 changed files with 74 additions and 28 deletions

View File

@ -0,0 +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.Scoring;
namespace osu.Game.Rulesets.Mods
{
/// <summary>
/// An interface for mods that make general adjustments to score processor.
/// </summary>
public interface IApplicableToScoreProcessor
{
void ApplyToScoreProcessor(ScoreProcessor scoreProcessor);
}
}

View File

@ -1,12 +1,24 @@
// 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.Scoring;
namespace osu.Game.Rulesets.Mods
{
public abstract class ModPerfect : ModSuddenDeath
public abstract class ModPerfect : ModSuddenDeath, IApplicableToScoreProcessor
{
public override string Name => "Perfect";
public override string ShortenedName => "PF";
public override string Description => "SS or quit.";
public bool onFailCheck(ScoreProcessor scoreProcessor)
{
return scoreProcessor.Accuracy.Value != 1;
}
public virtual void ApplyToScoreProcessor(ScoreProcessor scoreProcessor)
{
scoreProcessor.FailChecker += onFailCheck;
}
}
}
}

View File

@ -3,10 +3,11 @@
using System;
using osu.Game.Graphics;
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Mods
{
public abstract class ModSuddenDeath : Mod
public abstract class ModSuddenDeath : Mod, IApplicableToScoreProcessor
{
public override string Name => "Sudden Death";
public override string ShortenedName => "SD";
@ -16,5 +17,15 @@ namespace osu.Game.Rulesets.Mods
public override double ScoreMultiplier => 1;
public override bool Ranked => true;
public override Type[] IncompatibleMods => new[] { typeof(ModNoFail), typeof(ModRelax), typeof(ModAutoplay) };
public bool onFailCheck(ScoreProcessor scoreProcessor)
{
return scoreProcessor.Combo.Value != scoreProcessor.HighestCombo.Value;
}
public virtual void ApplyToScoreProcessor(ScoreProcessor scoreProcessor)
{
scoreProcessor.FailChecker += onFailCheck;
}
}
}
}

View File

@ -3,6 +3,7 @@
using System;
using System.Diagnostics;
using System.Collections.Generic;
using osu.Framework.Configuration;
using osu.Game.Beatmaps;
using osu.Game.Rulesets.Judgements;
@ -31,6 +32,11 @@ namespace osu.Game.Rulesets.Scoring
/// </summary>
public event Action<Judgement> NewJudgement;
/// <summary>
/// Invoked when we want to check if a failure condition has been fulfilled
/// </summary>
public event Func<ScoreProcessor, bool> FailChecker;
/// <summary>
/// The current total score.
/// </summary>
@ -66,8 +72,6 @@ namespace osu.Game.Rulesets.Scoring
/// </summary>
protected virtual bool HasCompleted => false;
public int strictFail = 0;
/// <summary>
/// Whether this ScoreProcessor has already triggered the failed state.
/// </summary>
@ -78,16 +82,6 @@ namespace osu.Game.Rulesets.Scoring
/// </summary>
protected virtual bool FailCondition => Health.Value == Health.MinValue;
/// <summary>
/// The conditions for failing if the Sudden Death mod is enabled.
/// </summary>
protected virtual bool SuddenDeathFailCondition => Combo.Value != HighestCombo.Value;
/// <summary>
/// The conditions for failing if the Perfect mod is enabled.
/// </summary>
protected virtual bool PerfectFailCondition => Accuracy.Value != 1;
protected ScoreProcessor()
{
Combo.ValueChanged += delegate { HighestCombo.Value = Math.Max(HighestCombo.Value, Combo.Value); };
@ -133,16 +127,11 @@ namespace osu.Game.Rulesets.Scoring
/// </summary>
protected void UpdateFailed()
{
if (HasFailed)
if (HasFailed || !FailCondition)
return;
if(FailCondition ||
(strictFail==1 && SuddenDeathFailCondition) ||
(strictFail==2 && PerfectFailCondition))
{
if (Failed?.Invoke() != false)
HasFailed = true;
}
if (Failed?.Invoke() != false)
HasFailed = true;
}
/// <summary>
@ -157,6 +146,18 @@ namespace osu.Game.Rulesets.Scoring
AllJudged?.Invoke();
}
protected void CheckAlternateFailConditions()
{
if (HasFailed)
return;
if (FailChecker?.Invoke(this) == true)
{
if (Failed?.Invoke() != false)
HasFailed = true;
}
}
/// <summary>
/// Retrieve a score populated with data for the current play this processor is responsible for.
/// </summary>
@ -233,6 +234,8 @@ namespace osu.Game.Rulesets.Scoring
OnNewJudgement(judgement);
updateScore();
CheckAlternateFailConditions();
NotifyNewJudgement(judgement);
UpdateFailed();
}

View File

@ -228,11 +228,15 @@ namespace osu.Game.Screens.Play
scoreProcessor.AllJudged += onCompletion;
scoreProcessor.Failed += onFail;
if (Beatmap.Value.Mods.Value.Any(m => m.Name == "Sudden Death"))
scoreProcessor.strictFail = 1;
applyAlternateFailConditions();
}
if (Beatmap.Value.Mods.Value.Any(m => m.Name == "Perfect"))
scoreProcessor.strictFail = 2;
private void applyAlternateFailConditions()
{
foreach(var mod in Beatmap.Value.Mods.Value.OfType<IApplicableToScoreProcessor>())
{
mod.ApplyToScoreProcessor(scoreProcessor);
}
}
private void applyRateFromMods()

View File

@ -294,6 +294,7 @@
<Compile Include="Overlays\Profile\Sections\Ranks\DrawableTotalScore.cs" />
<Compile Include="Overlays\Profile\Sections\Ranks\ScoreModsContainer.cs" />
<Compile Include="Overlays\Settings\SettingsButton.cs" />
<Compile Include="Rulesets\Mods\IApplicableToScoreProcessor.cs" />
<Compile Include="Screens\Edit\Screens\Compose\Timeline\BeatmapWaveformGraph.cs" />
<Compile Include="Beatmaps\Drawables\DifficultyColouredContainer.cs" />
<Compile Include="Beatmaps\Drawables\DifficultyIcon.cs" />