Skip to content

Commit f59c248

Browse files
authored
Merge pull request #33450 from bdach/freestyle-consistent-compatibility
Disallow selected mods from being valid for freestyle as required mods due to them not being consistently compatible with other mods across rulesets
2 parents c2196ae + e3259f7 commit f59c248

File tree

4 files changed

+37
-8
lines changed

4 files changed

+37
-8
lines changed

osu.Game.Tests/Mods/ModUtilsTest.cs

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -259,9 +259,6 @@ public void TestFormatScoreMultiplier()
259259
new MultiplayerTestScenario(true, true, [new OsuModPerfect()], []),
260260
new MultiplayerTestScenario(true, true, [new OsuModDoubleTime()], []),
261261
new MultiplayerTestScenario(true, true, [new OsuModNightcore()], []),
262-
new MultiplayerTestScenario(true, true, [new OsuModHidden()], []),
263-
new MultiplayerTestScenario(true, true, [new OsuModFlashlight()], []),
264-
new MultiplayerTestScenario(true, true, [new OsuModAccuracyChallenge()], []),
265262
new MultiplayerTestScenario(true, true, [new OsuModDifficultyAdjust()], []),
266263
new MultiplayerTestScenario(true, true, [new ModWindUp()], []),
267264
new MultiplayerTestScenario(true, true, [new ModWindDown()], []),
@@ -347,8 +344,44 @@ public void TestFreestyleRulesetCompatibility()
347344
{
348345
if (mod.ValidForFreestyleAsRequiredMod && mod.UserPlayable && !commonAcronyms.Contains(mod.Acronym))
349346
Assert.Fail($"{mod.GetType().ReadableName()} declares {nameof(Mod.ValidForFreestyleAsRequiredMod)} but does not exist in all four basic rulesets!");
347+
348+
// downgraded to warning, because there are valid reasons why they may still not be specified to be valid for freestyle as required
349+
// (see `TestModsValidForRequiredFreestyleAreConsistentlyCompatibleAcrossRulesets()` test case below).
350350
if (!mod.ValidForFreestyleAsRequiredMod && mod.UserPlayable && commonAcronyms.Contains(mod.Acronym))
351-
Assert.Fail($"{mod.GetType().ReadableName()} does not declare {nameof(Mod.ValidForFreestyleAsRequiredMod)} but exists in all four basic rulesets!");
351+
Assert.Warn($"{mod.GetType().ReadableName()} does not declare {nameof(Mod.ValidForFreestyleAsRequiredMod)} but exists in all four basic rulesets.");
352+
}
353+
}
354+
});
355+
}
356+
357+
[Test]
358+
public void TestModsValidForRequiredFreestyleAreConsistentlyCompatibleAcrossRulesets()
359+
{
360+
Dictionary<(string firstMod, string secondMod), bool> compatibilityMap = new Dictionary<(string, string), bool>();
361+
362+
Assert.Multiple(() =>
363+
{
364+
for (int rulesetId = 0; rulesetId < 4; ++rulesetId)
365+
{
366+
var rulesetStore = new AssemblyRulesetStore();
367+
var ruleset = rulesetStore.GetRuleset(rulesetId)!.CreateInstance();
368+
369+
var modsValidForFreestyleAsRequired = ruleset.CreateAllMods().Where(m => m.ValidForFreestyleAsRequiredMod).OrderBy(m => m.Acronym).ToList();
370+
371+
for (int i = 0; i < modsValidForFreestyleAsRequired.Count; i++)
372+
{
373+
for (int j = i; j < modsValidForFreestyleAsRequired.Count; ++j)
374+
{
375+
var first = modsValidForFreestyleAsRequired[i];
376+
var second = modsValidForFreestyleAsRequired[j];
377+
378+
bool compatible = ModUtils.CheckCompatibleSet([first, second]);
379+
380+
if (!compatibilityMap.TryGetValue((first.Acronym, second.Acronym), out bool previousCompatible))
381+
compatibilityMap[(first.Acronym, second.Acronym)] = compatible;
382+
else if (previousCompatible != compatible)
383+
Assert.Fail($"{first.Acronym} and {second.Acronym} declare {nameof(Mod.ValidForFreestyleAsRequiredMod)} while not being consistently compatible in all four rulesets!");
384+
}
352385
}
353386
}
354387
});

osu.Game/Rulesets/Mods/ModAccuracyChallenge.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,6 @@ public class ModAccuracyChallenge : ModFailCondition, IApplicableToScoreProcesso
3434

3535
public override bool Ranked => true;
3636

37-
public override bool ValidForFreestyleAsRequiredMod => true;
38-
3937
public override IEnumerable<(LocalisableString setting, LocalisableString value)> SettingDescription
4038
{
4139
get

osu.Game/Rulesets/Mods/ModFlashlight.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ public abstract class ModFlashlight : Mod
3737
public override ModType Type => ModType.DifficultyIncrease;
3838
public override LocalisableString Description => "Restricted view area.";
3939
public override bool Ranked => UsesDefaultConfiguration;
40-
public override bool ValidForFreestyleAsRequiredMod => true;
4140

4241
[SettingSource("Flashlight size", "Multiplier applied to the default flashlight size.")]
4342
public abstract BindableFloat SizeMultiplier { get; }

osu.Game/Rulesets/Mods/ModHidden.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ public abstract class ModHidden : ModWithVisibilityAdjustment, IApplicableToScor
1515
public override IconUsage? Icon => OsuIcon.ModHidden;
1616
public override ModType Type => ModType.DifficultyIncrease;
1717
public override bool Ranked => UsesDefaultConfiguration;
18-
public override bool ValidForFreestyleAsRequiredMod => true;
1918

2019
public virtual void ApplyToScoreProcessor(ScoreProcessor scoreProcessor)
2120
{

0 commit comments

Comments
 (0)