1
0
mirror of https://github.com/ppy/osu.git synced 2024-09-23 00:47:24 +08:00
osu-lazer/osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs

122 lines
4.8 KiB
C#
Raw Normal View History

// 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.
2018-04-13 17:19:50 +08:00
using System;
using osu.Game.Rulesets.Difficulty.Preprocessing;
using osu.Game.Rulesets.Mods;
2018-05-15 16:36:29 +08:00
using osu.Game.Rulesets.Osu.Difficulty.Preprocessing;
2019-02-18 13:58:33 +08:00
using osu.Game.Rulesets.Osu.Objects;
2021-09-25 11:02:33 +08:00
using osu.Framework.Utils;
using osuTK;
2018-04-13 17:19:50 +08:00
2018-05-15 16:36:29 +08:00
namespace osu.Game.Rulesets.Osu.Difficulty.Skills
2018-04-13 17:19:50 +08:00
{
/// <summary>
/// Represents the skill required to correctly aim at every object in the map with a uniform CircleSize and normalized distances.
/// </summary>
2021-06-15 01:18:49 +08:00
public class Aim : OsuStrainSkill
2018-04-13 17:19:50 +08:00
{
public Aim(Mod[] mods)
: base(mods)
{
}
2021-09-25 11:02:33 +08:00
protected override int HistoryLength => 2;
protected override double SkillMultiplier => 24.75;
2018-04-13 17:19:50 +08:00
protected override double StrainDecayBase => 0.15;
2021-09-25 11:02:33 +08:00
private const double wide_angle_multiplier = 1.0;
private const double acute_angle_multiplier = 1.0;
private const double rhythm_variance_multiplier = 1.0;
private const double slider_multiplier = 4.25;
2021-09-25 11:02:33 +08:00
protected override double StrainValueOf(DifficultyHitObject current)
2018-12-08 14:01:26 +08:00
{
2021-09-25 11:02:33 +08:00
if (current.BaseObject is Spinner || Previous.Count <= 1)
2019-02-18 13:58:33 +08:00
return 0;
2021-09-25 11:02:33 +08:00
var osuCurrObj = (OsuDifficultyHitObject)current;
var osuPrevObj = (OsuDifficultyHitObject)Previous[0];
var osuLastObj = (OsuDifficultyHitObject)Previous[1];
2018-12-24 11:41:04 +08:00
2021-09-25 11:02:33 +08:00
var currVector = Vector2.Divide(osuCurrObj.JumpVector, (float)osuCurrObj.StrainTime);
var prevVector = Vector2.Divide(osuPrevObj.JumpVector, (float)osuPrevObj.StrainTime);
2019-01-29 15:35:20 +08:00
2021-09-25 11:02:33 +08:00
// Start with regular velocity.
double aimStrain = currVector.Length;
2021-09-25 11:02:33 +08:00
if (Precision.AlmostEquals(osuCurrObj.StrainTime, osuPrevObj.StrainTime, 10)) // Rhythms are the same.
{
if (osuCurrObj.Angle != null)
2018-12-21 21:52:27 +08:00
{
2021-09-25 11:02:33 +08:00
double angle = osuCurrObj.Angle.Value;
// Rewarding angles, take the smaller velocity as base.
double angleBonus = Math.Min(currVector.Length, prevVector.Length);
2021-09-25 11:02:33 +08:00
double wideAngleBonus = calcWideAngleBonus(angle);
double acuteAngleBonus = calcAcuteAngleBonus(angle);
if (osuCurrObj.StrainTime > 100)
acuteAngleBonus = 0;
else
{
acuteAngleBonus *= Math.Min(2, Math.Pow((100 - osuCurrObj.StrainTime) / 15, 1.5));
wideAngleBonus *= Math.Pow(osuCurrObj.StrainTime / 100, 6);
}
if (acuteAngleBonus > wideAngleBonus)
angleBonus = Math.Min(angleBonus, 150 / osuCurrObj.StrainTime) * Math.Min(1, Math.Pow(Math.Min(osuCurrObj.JumpDistance, osuPrevObj.JumpDistance) / 150, 2));
angleBonus *= Math.Max(acuteAngleBonus * acute_angle_multiplier, wideAngleBonus * wide_angle_multiplier);
// add in angle velocity.
aimStrain += angleBonus;
2018-12-21 21:52:27 +08:00
}
2018-12-21 13:52:43 +08:00
}
2021-09-25 11:02:33 +08:00
else // There is a rhythm change
{
// Rewarding rhythm, take the smaller velocity as base.
double rhythmBonus = Math.Min(currVector.Length, prevVector.Length);
2018-12-21 13:52:43 +08:00
2021-09-25 11:02:33 +08:00
if (osuCurrObj.StrainTime + 10 < osuPrevObj.StrainTime && osuPrevObj.StrainTime > osuLastObj.StrainTime + 10)
// Don't want to reward for a rhythm change back to back (unless its a double, which is why this only checks for fast -> slow -> fast).
rhythmBonus = 0;
2019-01-29 15:35:20 +08:00
2021-09-25 11:02:33 +08:00
aimStrain += rhythmBonus * rhythm_variance_multiplier; // add in rhythm velocity.
}
2021-09-25 11:04:22 +08:00
if (osuCurrObj.TravelDistance != 0)
{
double sliderBonus = (Math.Max(0, Vector2.Subtract(osuCurrObj.TravelVector, osuCurrObj.JumpVector).Length - osuCurrObj.JumpDistance) + osuCurrObj.TravelDistance) / osuCurrObj.StrainTime;
2021-09-25 11:04:22 +08:00
// Add in slider velocity.
aimStrain += sliderBonus * slider_multiplier;
}
2021-09-25 11:02:33 +08:00
return aimStrain;
}
private double calcWideAngleBonus(double angle)
{
if (angle < Math.PI / 3)
return 0;
if (angle < 2 * Math.PI / 3)
return Math.Pow(Math.Sin(1.5 * (angle - Math.PI / 3)), 2);
return 0.25 + 0.75 * Math.Pow(Math.Sin(1.5 * (Math.PI - angle)), 2);
2018-12-08 14:01:26 +08:00
}
2021-09-25 11:02:33 +08:00
private double calcAcuteAngleBonus(double angle)
{
if (angle < Math.PI / 3)
return 0.5 + 0.5 * Math.Pow(Math.Sin(1.5 * angle), 2);
if (angle < 2 * Math.PI / 3)
return Math.Pow(Math.Sin(1.5 * (2 * Math.PI / 3 - angle)), 2);
return 0;
}
2018-04-13 17:19:50 +08:00
}
}