2019-02-18 13:46:32 +08:00
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
using System ;
using System.Collections.Generic ;
using System.Linq ;
using osu.Game.Beatmaps ;
using osu.Game.Rulesets.Catch.Difficulty.Preprocessing ;
using osu.Game.Rulesets.Catch.Difficulty.Skills ;
using osu.Game.Rulesets.Catch.Objects ;
using osu.Game.Rulesets.Catch.UI ;
using osu.Game.Rulesets.Difficulty ;
using osu.Game.Rulesets.Difficulty.Preprocessing ;
using osu.Game.Rulesets.Difficulty.Skills ;
2019-02-19 16:42:24 +08:00
using osu.Game.Rulesets.Mods ;
2019-02-18 13:46:32 +08:00
namespace osu.Game.Rulesets.Catch.Difficulty
{
public class CatchDifficultyCalculator : DifficultyCalculator
{
private const double star_scaling_factor = 0.145 ;
protected override int SectionLength = > 750 ;
private readonly float halfCatchWidth ;
public CatchDifficultyCalculator ( Ruleset ruleset , WorkingBeatmap beatmap )
: base ( ruleset , beatmap )
{
var catcher = new CatcherArea . Catcher ( beatmap . BeatmapInfo . BaseDifficulty ) ;
halfCatchWidth = catcher . CatchWidth * 0.5f ;
}
2019-02-19 16:42:24 +08:00
protected override DifficultyAttributes CreateDifficultyAttributes ( IBeatmap beatmap , Mod [ ] mods , Skill [ ] skills , double clockRate )
2019-02-18 13:46:32 +08:00
{
2019-02-19 16:42:24 +08:00
if ( beatmap . HitObjects . Count = = 0 )
2019-02-19 16:45:52 +08:00
return new CatchDifficultyAttributes { Mods = mods } ;
2019-02-18 13:46:32 +08:00
// this is the same as osu!, so there's potential to share the implementation... maybe
2019-02-19 16:42:24 +08:00
double preempt = BeatmapDifficulty . DifficultyRange ( beatmap . BeatmapInfo . BaseDifficulty . ApproachRate , 1800 , 1200 , 450 ) / clockRate ;
2019-02-18 13:46:32 +08:00
2019-02-19 16:42:24 +08:00
return new CatchDifficultyAttributes
{
StarRating = Math . Sqrt ( skills [ 0 ] . DifficultyValue ( ) ) * star_scaling_factor ,
2019-02-19 16:45:52 +08:00
Mods = mods ,
2019-02-19 16:42:24 +08:00
ApproachRate = preempt > 1200.0 ? - ( preempt - 1800.0 ) / 120.0 : - ( preempt - 1200.0 ) / 150.0 + 5.0 ,
MaxCombo = beatmap . HitObjects . Count ( h = > h is Fruit ) + beatmap . HitObjects . OfType < JuiceStream > ( ) . SelectMany ( j = > j . NestedHitObjects ) . Count ( h = > ! ( h is TinyDroplet ) )
} ;
2019-02-18 13:46:32 +08:00
}
2019-02-19 16:42:24 +08:00
protected override IEnumerable < DifficultyHitObject > CreateDifficultyHitObjects ( IBeatmap beatmap , double clockRate )
2019-02-18 13:46:32 +08:00
{
CatchHitObject lastObject = null ;
foreach ( var hitObject in beatmap . HitObjects . OfType < CatchHitObject > ( ) )
{
if ( lastObject = = null )
{
lastObject = hitObject ;
continue ;
}
switch ( hitObject )
{
// We want to only consider fruits that contribute to the combo. Droplets are addressed as accuracy and spinners are not relevant for "skill" calculations.
case Fruit fruit :
2019-02-19 16:42:24 +08:00
yield return new CatchDifficultyHitObject ( fruit , lastObject , clockRate , halfCatchWidth ) ;
2019-02-18 13:48:19 +08:00
lastObject = hitObject ;
2019-02-18 13:46:32 +08:00
break ;
case JuiceStream _ :
foreach ( var nested in hitObject . NestedHitObjects . OfType < CatchHitObject > ( ) . Where ( o = > ! ( o is TinyDroplet ) ) )
2019-02-18 13:48:19 +08:00
{
2019-02-19 16:42:24 +08:00
yield return new CatchDifficultyHitObject ( nested , lastObject , clockRate , halfCatchWidth ) ;
2019-02-18 13:48:19 +08:00
lastObject = nested ;
}
2019-02-18 13:46:32 +08:00
break ;
}
}
}
2019-02-19 16:54:00 +08:00
protected override Skill [ ] CreateSkills ( IBeatmap beatmap ) = > new Skill [ ]
2019-02-18 13:46:32 +08:00
{
new Movement ( ) ,
} ;
}
}