1
0
mirror of https://github.com/ppy/osu.git synced 2026-06-05 20:24:45 +08:00
Files
osu-lazer/osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModDifficultyAdjust.cs
T
James Wilson c83737bec5 Implement new score multipliers (#37967)
- Part of https://github.com/ppy/osu/issues/37818

Updates score multipliers to latest proposals, and bumps replay version
ready for recalculation.

---

For anyone following along, **please wait for the incoming news post
before sharing this publicly**. This is intended for internal
development use at this point. There's still some time before these go
live.

---------

Co-authored-by: Bartłomiej Dach <dach.bartlomiej@gmail.com>
2026-06-05 14:57:23 +09:00

183 lines
6.0 KiB
C#

// 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.Collections.Generic;
using System.Linq;
using NUnit.Framework;
using osu.Framework.Graphics.Containers;
using osu.Framework.Testing;
using osu.Framework.Utils;
using osu.Game.Beatmaps;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Osu.Mods;
using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Rulesets.Osu.Objects.Drawables;
namespace osu.Game.Rulesets.Osu.Tests.Mods
{
public partial class TestSceneOsuModDifficultyAdjust : OsuModTestScene
{
protected override bool AllowFail => true;
[Test]
public void TestNoAdjustment() => CreateModTest(new ModTestData
{
Mod = new OsuModDifficultyAdjust(),
CreateBeatmap = () => new Beatmap
{
BeatmapInfo = new BeatmapInfo
{
Difficulty = new BeatmapDifficulty
{
CircleSize = 8
}
},
HitObjects = new List<HitObject>
{
new HitCircle { StartTime = 1000 },
new HitCircle { StartTime = 2000 }
}
},
Autoplay = true,
PassCondition = () => checkSomeHit() && checkObjectsScale(0.29f)
});
[Test]
public void TestCircleSize1() => CreateModTest(new ModTestData
{
Mod = new OsuModDifficultyAdjust { CircleSize = { Value = 1 } },
Autoplay = true,
PassCondition = () => checkSomeHit() && checkObjectsScale(0.78f)
});
[Test]
public void TestCircleSize10() => CreateModTest(new ModTestData
{
Mod = new OsuModDifficultyAdjust { CircleSize = { Value = 10 } },
Autoplay = true,
PassCondition = () => checkSomeHit() && checkObjectsScale(0.15f)
});
[Test]
public void TestApproachRate1() => CreateModTest(new ModTestData
{
Mod = new OsuModDifficultyAdjust { ApproachRate = { Value = 1 } },
Autoplay = true,
PassCondition = () => checkSomeHit() && checkObjectsPreempt(1680)
});
[Test]
public void TestApproachRate10() => CreateModTest(new ModTestData
{
Mod = new OsuModDifficultyAdjust { ApproachRate = { Value = 10 } },
Autoplay = true,
PassCondition = () => checkSomeHit() && checkObjectsPreempt(450)
});
[Test]
public void TestScoreMultiplierCorrectWithNoAdjustment() => CreateModTest(new ModTestData
{
Mod = new OsuModDifficultyAdjust(),
CreateBeatmap = () => new Beatmap
{
BeatmapInfo = new BeatmapInfo
{
Difficulty = new BeatmapDifficulty
{
CircleSize = 8
}
},
HitObjects = new List<HitObject>
{
new HitCircle { StartTime = 1000 },
new HitCircle { StartTime = 2000 }
}
},
Autoplay = true,
PassCondition = () => Player.ScoreProcessor.TotalScore.Value == 1_000_000,
});
[Test]
public void TestScoreMultiplierCorrectWithSingleAdjustment() => CreateModTest(new ModTestData
{
Mod = new OsuModDifficultyAdjust
{
ApproachRate = { Value = 7.3f }
},
CreateBeatmap = () => new Beatmap
{
BeatmapInfo = new BeatmapInfo
{
Difficulty = new BeatmapDifficulty
{
CircleSize = 8,
ApproachRate = 7,
OverallDifficulty = 6,
DrainRate = 5,
}
},
HitObjects = new List<HitObject>
{
new HitCircle { StartTime = 1000 },
new HitCircle { StartTime = 2000 }
}
},
Autoplay = true,
PassCondition = () => Player.ScoreProcessor.TotalScore.Value == 850_000,
});
[Test]
public void TestScoreMultiplierCorrectWithMultipleAdjustments() => CreateModTest(new ModTestData
{
Mod = new OsuModDifficultyAdjust
{
ApproachRate = { Value = 6.8f },
OverallDifficulty = { Value = 6.6f }
},
CreateBeatmap = () => new Beatmap
{
BeatmapInfo = new BeatmapInfo
{
Difficulty = new BeatmapDifficulty
{
CircleSize = 8,
ApproachRate = 7,
OverallDifficulty = 6,
DrainRate = 5,
}
},
HitObjects = new List<HitObject>
{
new HitCircle { StartTime = 1000 },
new HitCircle { StartTime = 2000 }
}
},
Autoplay = true,
PassCondition = () => Player.ScoreProcessor.TotalScore.Value == 630_000,
});
private bool checkObjectsPreempt(double target)
{
var objects = Player.ChildrenOfType<DrawableHitCircle>();
if (!objects.Any())
return false;
return objects.All(o => o.HitObject.TimePreempt == target);
}
private bool checkObjectsScale(float target)
{
var objects = Player.ChildrenOfType<DrawableHitCircle>();
if (!objects.Any())
return false;
return objects.All(o => Precision.AlmostEquals(o.ChildrenOfType<Container>().First().Scale.X, target));
}
private bool checkSomeHit()
{
return Player.ScoreProcessor.JudgedHits >= 2;
}
}
}