mirror of
https://github.com/ppy/osu.git
synced 2024-09-21 21:27:24 +08:00
Merge branch 'master' into new-difficulty-creation-v3
This commit is contained in:
commit
b94fe84712
@ -17,7 +17,7 @@ namespace osu.Game.Rulesets.Catch.Mods
|
||||
public override double ScoreMultiplier => 1.12;
|
||||
|
||||
[SettingSource("Flashlight size", "Multiplier applied to the default flashlight size.")]
|
||||
public override BindableNumber<float> SizeMultiplier { get; } = new BindableNumber<float>
|
||||
public override BindableFloat SizeMultiplier { get; } = new BindableFloat
|
||||
{
|
||||
MinValue = 0.5f,
|
||||
MaxValue = 1.5f,
|
||||
|
@ -18,7 +18,7 @@ namespace osu.Game.Rulesets.Mania.Mods
|
||||
public override Type[] IncompatibleMods => new[] { typeof(ModHidden) };
|
||||
|
||||
[SettingSource("Flashlight size", "Multiplier applied to the default flashlight size.")]
|
||||
public override BindableNumber<float> SizeMultiplier { get; } = new BindableNumber<float>
|
||||
public override BindableFloat SizeMultiplier { get; } = new BindableFloat
|
||||
{
|
||||
MinValue = 0.5f,
|
||||
MaxValue = 3f,
|
||||
|
27
osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModAimAssist.cs
Normal file
27
osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModAimAssist.cs
Normal file
@ -0,0 +1,27 @@
|
||||
// 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 NUnit.Framework;
|
||||
using osu.Game.Rulesets.Osu.Mods;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Tests.Mods
|
||||
{
|
||||
public class TestSceneOsuModAimAssist : OsuModTestScene
|
||||
{
|
||||
[TestCase(0.1f)]
|
||||
[TestCase(0.5f)]
|
||||
[TestCase(1)]
|
||||
public void TestAimAssist(float strength)
|
||||
{
|
||||
CreateModTest(new ModTestData
|
||||
{
|
||||
Mod = new OsuModAimAssist
|
||||
{
|
||||
AssistStrength = { Value = strength },
|
||||
},
|
||||
PassCondition = () => true,
|
||||
Autoplay = false,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
154
osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModAlternate.cs
Normal file
154
osu.Game.Rulesets.Osu.Tests/Mods/TestSceneOsuModAlternate.cs
Normal file
@ -0,0 +1,154 @@
|
||||
// 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 NUnit.Framework;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.Timing;
|
||||
using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Osu.Mods;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
using osu.Game.Rulesets.Osu.Replays;
|
||||
using osu.Game.Rulesets.Replays;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Tests.Mods
|
||||
{
|
||||
public class TestSceneOsuModAlternate : OsuModTestScene
|
||||
{
|
||||
[Test]
|
||||
public void TestInputAtIntro() => CreateModTest(new ModTestData
|
||||
{
|
||||
Mod = new OsuModAlternate(),
|
||||
PassCondition = () => Player.ScoreProcessor.Combo.Value == 1,
|
||||
Autoplay = false,
|
||||
Beatmap = new Beatmap
|
||||
{
|
||||
HitObjects = new List<HitObject>
|
||||
{
|
||||
new HitCircle
|
||||
{
|
||||
StartTime = 1000,
|
||||
Position = new Vector2(100),
|
||||
},
|
||||
},
|
||||
},
|
||||
ReplayFrames = new List<ReplayFrame>
|
||||
{
|
||||
new OsuReplayFrame(500, new Vector2(200), OsuAction.LeftButton),
|
||||
new OsuReplayFrame(501, new Vector2(200)),
|
||||
new OsuReplayFrame(1000, new Vector2(100), OsuAction.LeftButton),
|
||||
}
|
||||
});
|
||||
|
||||
[Test]
|
||||
public void TestInputAlternating() => CreateModTest(new ModTestData
|
||||
{
|
||||
Mod = new OsuModAlternate(),
|
||||
PassCondition = () => Player.ScoreProcessor.Combo.Value == 4,
|
||||
Autoplay = false,
|
||||
Beatmap = new Beatmap
|
||||
{
|
||||
HitObjects = new List<HitObject>
|
||||
{
|
||||
new HitCircle
|
||||
{
|
||||
StartTime = 500,
|
||||
Position = new Vector2(100),
|
||||
},
|
||||
new HitCircle
|
||||
{
|
||||
StartTime = 1000,
|
||||
Position = new Vector2(200, 100),
|
||||
},
|
||||
new HitCircle
|
||||
{
|
||||
StartTime = 1500,
|
||||
Position = new Vector2(300, 100),
|
||||
},
|
||||
new HitCircle
|
||||
{
|
||||
StartTime = 2000,
|
||||
Position = new Vector2(400, 100),
|
||||
},
|
||||
},
|
||||
},
|
||||
ReplayFrames = new List<ReplayFrame>
|
||||
{
|
||||
new OsuReplayFrame(500, new Vector2(100), OsuAction.LeftButton),
|
||||
new OsuReplayFrame(501, new Vector2(100)),
|
||||
new OsuReplayFrame(1000, new Vector2(200, 100), OsuAction.RightButton),
|
||||
new OsuReplayFrame(1001, new Vector2(200, 100)),
|
||||
new OsuReplayFrame(1500, new Vector2(300, 100), OsuAction.LeftButton),
|
||||
new OsuReplayFrame(1501, new Vector2(300, 100)),
|
||||
new OsuReplayFrame(2000, new Vector2(400, 100), OsuAction.RightButton),
|
||||
new OsuReplayFrame(2001, new Vector2(400, 100)),
|
||||
}
|
||||
});
|
||||
|
||||
[Test]
|
||||
public void TestInputSingular() => CreateModTest(new ModTestData
|
||||
{
|
||||
Mod = new OsuModAlternate(),
|
||||
PassCondition = () => Player.ScoreProcessor.Combo.Value == 0 && Player.ScoreProcessor.HighestCombo.Value == 1,
|
||||
Autoplay = false,
|
||||
Beatmap = new Beatmap
|
||||
{
|
||||
HitObjects = new List<HitObject>
|
||||
{
|
||||
new HitCircle
|
||||
{
|
||||
StartTime = 500,
|
||||
Position = new Vector2(100),
|
||||
},
|
||||
new HitCircle
|
||||
{
|
||||
StartTime = 1000,
|
||||
Position = new Vector2(200, 100),
|
||||
},
|
||||
},
|
||||
},
|
||||
ReplayFrames = new List<ReplayFrame>
|
||||
{
|
||||
new OsuReplayFrame(500, new Vector2(100), OsuAction.LeftButton),
|
||||
new OsuReplayFrame(501, new Vector2(100)),
|
||||
new OsuReplayFrame(1000, new Vector2(200, 100), OsuAction.LeftButton),
|
||||
}
|
||||
});
|
||||
|
||||
[Test]
|
||||
public void TestInputSingularWithBreak() => CreateModTest(new ModTestData
|
||||
{
|
||||
Mod = new OsuModAlternate(),
|
||||
PassCondition = () => Player.ScoreProcessor.Combo.Value == 2,
|
||||
Autoplay = false,
|
||||
Beatmap = new Beatmap
|
||||
{
|
||||
Breaks = new List<BreakPeriod>
|
||||
{
|
||||
new BreakPeriod(500, 2250),
|
||||
},
|
||||
HitObjects = new List<HitObject>
|
||||
{
|
||||
new HitCircle
|
||||
{
|
||||
StartTime = 500,
|
||||
Position = new Vector2(100),
|
||||
},
|
||||
new HitCircle
|
||||
{
|
||||
StartTime = 2500,
|
||||
Position = new Vector2(100),
|
||||
}
|
||||
}
|
||||
},
|
||||
ReplayFrames = new List<ReplayFrame>
|
||||
{
|
||||
new OsuReplayFrame(500, new Vector2(100), OsuAction.LeftButton),
|
||||
new OsuReplayFrame(501, new Vector2(100)),
|
||||
new OsuReplayFrame(2500, new Vector2(100), OsuAction.LeftButton),
|
||||
new OsuReplayFrame(2501, new Vector2(100)),
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
83
osu.Game.Rulesets.Osu/Mods/OsuModAimAssist.cs
Normal file
83
osu.Game.Rulesets.Osu/Mods/OsuModAimAssist.cs
Normal file
@ -0,0 +1,83 @@
|
||||
// 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 osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Utils;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
using osu.Game.Rulesets.Osu.Objects.Drawables;
|
||||
using osu.Game.Rulesets.Osu.UI;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Mods
|
||||
{
|
||||
internal class OsuModAimAssist : Mod, IUpdatableByPlayfield, IApplicableToDrawableRuleset<OsuHitObject>
|
||||
{
|
||||
public override string Name => "Aim Assist";
|
||||
public override string Acronym => "AA";
|
||||
public override IconUsage? Icon => FontAwesome.Solid.MousePointer;
|
||||
public override ModType Type => ModType.Fun;
|
||||
public override string Description => "No need to chase the circle – the circle chases you!";
|
||||
public override double ScoreMultiplier => 1;
|
||||
public override Type[] IncompatibleMods => new[] { typeof(OsuModAutopilot), typeof(OsuModWiggle), typeof(OsuModTransform), typeof(ModAutoplay) };
|
||||
|
||||
private IFrameStableClock gameplayClock;
|
||||
|
||||
[SettingSource("Assist strength", "How much this mod will assist you.", 0)]
|
||||
public BindableFloat AssistStrength { get; } = new BindableFloat(0.5f)
|
||||
{
|
||||
Precision = 0.05f,
|
||||
MinValue = 0.05f,
|
||||
MaxValue = 1.0f,
|
||||
};
|
||||
|
||||
public void ApplyToDrawableRuleset(DrawableRuleset<OsuHitObject> drawableRuleset)
|
||||
{
|
||||
gameplayClock = drawableRuleset.FrameStableClock;
|
||||
|
||||
// Hide judgment displays and follow points as they won't make any sense.
|
||||
// Judgements can potentially be turned on in a future where they display at a position relative to their drawable counterpart.
|
||||
drawableRuleset.Playfield.DisplayJudgements.Value = false;
|
||||
(drawableRuleset.Playfield as OsuPlayfield)?.FollowPoints.Hide();
|
||||
}
|
||||
|
||||
public void Update(Playfield playfield)
|
||||
{
|
||||
var cursorPos = playfield.Cursor.ActiveCursor.DrawPosition;
|
||||
|
||||
foreach (var drawable in playfield.HitObjectContainer.AliveObjects)
|
||||
{
|
||||
switch (drawable)
|
||||
{
|
||||
case DrawableHitCircle circle:
|
||||
easeTo(circle, cursorPos);
|
||||
break;
|
||||
|
||||
case DrawableSlider slider:
|
||||
|
||||
if (!slider.HeadCircle.Result.HasResult)
|
||||
easeTo(slider, cursorPos);
|
||||
else
|
||||
easeTo(slider, cursorPos - slider.Ball.DrawPosition);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void easeTo(DrawableHitObject hitObject, Vector2 destination)
|
||||
{
|
||||
double dampLength = Interpolation.Lerp(3000, 40, AssistStrength.Value);
|
||||
|
||||
float x = (float)Interpolation.DampContinuously(hitObject.X, destination.X, dampLength, gameplayClock.ElapsedFrameTime);
|
||||
float y = (float)Interpolation.DampContinuously(hitObject.Y, destination.Y, dampLength, gameplayClock.ElapsedFrameTime);
|
||||
|
||||
hitObject.Position = new Vector2(x, y);
|
||||
}
|
||||
}
|
||||
}
|
106
osu.Game.Rulesets.Osu/Mods/OsuModAlternate.cs
Normal file
106
osu.Game.Rulesets.Osu/Mods/OsuModAlternate.cs
Normal file
@ -0,0 +1,106 @@
|
||||
// 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.Linq;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Input.Bindings;
|
||||
using osu.Framework.Input.Events;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using osu.Game.Screens.Play;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Mods
|
||||
{
|
||||
public class OsuModAlternate : Mod, IApplicableToDrawableRuleset<OsuHitObject>, IApplicableToPlayer
|
||||
{
|
||||
public override string Name => @"Alternate";
|
||||
public override string Acronym => @"AL";
|
||||
public override string Description => @"Don't use the same key twice in a row!";
|
||||
public override double ScoreMultiplier => 1.0;
|
||||
public override Type[] IncompatibleMods => new[] { typeof(ModAutoplay) };
|
||||
public override ModType Type => ModType.Conversion;
|
||||
public override IconUsage? Icon => FontAwesome.Solid.Keyboard;
|
||||
|
||||
private double firstObjectValidJudgementTime;
|
||||
private IBindable<bool> isBreakTime;
|
||||
private const double flash_duration = 1000;
|
||||
private OsuAction? lastActionPressed;
|
||||
private DrawableRuleset<OsuHitObject> ruleset;
|
||||
|
||||
private IFrameStableClock gameplayClock;
|
||||
|
||||
public void ApplyToDrawableRuleset(DrawableRuleset<OsuHitObject> drawableRuleset)
|
||||
{
|
||||
ruleset = drawableRuleset;
|
||||
drawableRuleset.KeyBindingInputManager.Add(new InputInterceptor(this));
|
||||
|
||||
var firstHitObject = ruleset.Objects.FirstOrDefault();
|
||||
firstObjectValidJudgementTime = (firstHitObject?.StartTime ?? 0) - (firstHitObject?.HitWindows.WindowFor(HitResult.Meh) ?? 0);
|
||||
|
||||
gameplayClock = drawableRuleset.FrameStableClock;
|
||||
}
|
||||
|
||||
public void ApplyToPlayer(Player player)
|
||||
{
|
||||
isBreakTime = player.IsBreakTime.GetBoundCopy();
|
||||
isBreakTime.ValueChanged += e =>
|
||||
{
|
||||
if (e.NewValue)
|
||||
lastActionPressed = null;
|
||||
};
|
||||
}
|
||||
|
||||
private bool checkCorrectAction(OsuAction action)
|
||||
{
|
||||
if (isBreakTime.Value)
|
||||
return true;
|
||||
|
||||
if (gameplayClock.CurrentTime < firstObjectValidJudgementTime)
|
||||
return true;
|
||||
|
||||
switch (action)
|
||||
{
|
||||
case OsuAction.LeftButton:
|
||||
case OsuAction.RightButton:
|
||||
break;
|
||||
|
||||
// Any action which is not left or right button should be ignored.
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
|
||||
if (lastActionPressed != action)
|
||||
{
|
||||
// User alternated correctly.
|
||||
lastActionPressed = action;
|
||||
return true;
|
||||
}
|
||||
|
||||
ruleset.Cursor.FlashColour(Colour4.Red, flash_duration, Easing.OutQuint);
|
||||
return false;
|
||||
}
|
||||
|
||||
private class InputInterceptor : Component, IKeyBindingHandler<OsuAction>
|
||||
{
|
||||
private readonly OsuModAlternate mod;
|
||||
|
||||
public InputInterceptor(OsuModAlternate mod)
|
||||
{
|
||||
this.mod = mod;
|
||||
}
|
||||
|
||||
public bool OnPressed(KeyBindingPressEvent<OsuAction> e)
|
||||
// if the pressed action is incorrect, block it from reaching gameplay.
|
||||
=> !mod.checkCorrectAction(e.Action);
|
||||
|
||||
public void OnReleased(KeyBindingReleaseEvent<OsuAction> e)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
public override ModType Type => ModType.Automation;
|
||||
public override string Description => @"Automatic cursor movement - just follow the rhythm.";
|
||||
public override double ScoreMultiplier => 1;
|
||||
public override Type[] IncompatibleMods => new[] { typeof(OsuModSpunOut), typeof(ModRelax), typeof(ModFailCondition), typeof(ModNoFail), typeof(ModAutoplay) };
|
||||
public override Type[] IncompatibleMods => new[] { typeof(OsuModSpunOut), typeof(ModRelax), typeof(ModFailCondition), typeof(ModNoFail), typeof(ModAutoplay), typeof(OsuModAimAssist) };
|
||||
|
||||
public bool PerformFail() => false;
|
||||
|
||||
|
@ -14,7 +14,7 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
{
|
||||
public class OsuModAutoplay : ModAutoplay
|
||||
{
|
||||
public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(OsuModAutopilot)).Append(typeof(OsuModSpunOut)).ToArray();
|
||||
public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(OsuModAimAssist), typeof(OsuModAutopilot), typeof(OsuModSpunOut) }).ToArray();
|
||||
|
||||
public override Score CreateReplayScore(IBeatmap beatmap, IReadOnlyList<Mod> mods) => new Score
|
||||
{
|
||||
|
@ -15,7 +15,7 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
{
|
||||
public class OsuModCinema : ModCinema<OsuHitObject>
|
||||
{
|
||||
public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(OsuModAutopilot)).Append(typeof(OsuModSpunOut)).ToArray();
|
||||
public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(OsuModAimAssist), typeof(OsuModAutopilot), typeof(OsuModSpunOut) }).ToArray();
|
||||
|
||||
public override Score CreateReplayScore(IBeatmap beatmap, IReadOnlyList<Mod> mods) => new Score
|
||||
{
|
||||
|
@ -31,7 +31,7 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
};
|
||||
|
||||
[SettingSource("Flashlight size", "Multiplier applied to the default flashlight size.")]
|
||||
public override BindableNumber<float> SizeMultiplier { get; } = new BindableNumber<float>
|
||||
public override BindableFloat SizeMultiplier { get; } = new BindableFloat
|
||||
{
|
||||
MinValue = 0.5f,
|
||||
MaxValue = 2f,
|
||||
|
@ -20,7 +20,7 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
public override ModType Type => ModType.Fun;
|
||||
public override string Description => "Everything rotates. EVERYTHING.";
|
||||
public override double ScoreMultiplier => 1;
|
||||
public override Type[] IncompatibleMods => new[] { typeof(OsuModWiggle) };
|
||||
public override Type[] IncompatibleMods => new[] { typeof(OsuModWiggle), typeof(OsuModAimAssist) };
|
||||
|
||||
private float theta;
|
||||
|
||||
|
@ -20,7 +20,7 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
public override ModType Type => ModType.Fun;
|
||||
public override string Description => "They just won't stay still...";
|
||||
public override double ScoreMultiplier => 1;
|
||||
public override Type[] IncompatibleMods => new[] { typeof(OsuModTransform) };
|
||||
public override Type[] IncompatibleMods => new[] { typeof(OsuModTransform), typeof(OsuModAimAssist) };
|
||||
|
||||
private const int wiggle_duration = 90; // (ms) Higher = fewer wiggles
|
||||
private const int wiggle_strength = 10; // Higher = stronger wiggles
|
||||
|
@ -169,6 +169,7 @@ namespace osu.Game.Rulesets.Osu
|
||||
new OsuModClassic(),
|
||||
new OsuModRandom(),
|
||||
new OsuModMirror(),
|
||||
new OsuModAlternate(),
|
||||
};
|
||||
|
||||
case ModType.Automation:
|
||||
@ -193,6 +194,7 @@ namespace osu.Game.Rulesets.Osu
|
||||
new OsuModApproachDifferent(),
|
||||
new OsuModMuted(),
|
||||
new OsuModNoScope(),
|
||||
new OsuModAimAssist(),
|
||||
};
|
||||
|
||||
case ModType.System:
|
||||
|
@ -31,7 +31,8 @@ namespace osu.Game.Rulesets.Osu.UI
|
||||
private readonly ProxyContainer approachCircles;
|
||||
private readonly ProxyContainer spinnerProxies;
|
||||
private readonly JudgementContainer<DrawableOsuJudgement> judgementLayer;
|
||||
private readonly FollowPointRenderer followPoints;
|
||||
|
||||
public FollowPointRenderer FollowPoints { get; }
|
||||
|
||||
public static readonly Vector2 BASE_SIZE = new Vector2(512, 384);
|
||||
|
||||
@ -50,7 +51,7 @@ namespace osu.Game.Rulesets.Osu.UI
|
||||
{
|
||||
playfieldBorder = new PlayfieldBorder { RelativeSizeAxes = Axes.Both },
|
||||
spinnerProxies = new ProxyContainer { RelativeSizeAxes = Axes.Both },
|
||||
followPoints = new FollowPointRenderer { RelativeSizeAxes = Axes.Both },
|
||||
FollowPoints = new FollowPointRenderer { RelativeSizeAxes = Axes.Both },
|
||||
judgementLayer = new JudgementContainer<DrawableOsuJudgement> { RelativeSizeAxes = Axes.Both },
|
||||
HitObjectContainer,
|
||||
judgementAboveHitObjectLayer = new Container { RelativeSizeAxes = Axes.Both },
|
||||
@ -131,13 +132,13 @@ namespace osu.Game.Rulesets.Osu.UI
|
||||
protected override void OnHitObjectAdded(HitObject hitObject)
|
||||
{
|
||||
base.OnHitObjectAdded(hitObject);
|
||||
followPoints.AddFollowPoints((OsuHitObject)hitObject);
|
||||
FollowPoints.AddFollowPoints((OsuHitObject)hitObject);
|
||||
}
|
||||
|
||||
protected override void OnHitObjectRemoved(HitObject hitObject)
|
||||
{
|
||||
base.OnHitObjectRemoved(hitObject);
|
||||
followPoints.RemoveFollowPoints((OsuHitObject)hitObject);
|
||||
FollowPoints.RemoveFollowPoints((OsuHitObject)hitObject);
|
||||
}
|
||||
|
||||
private void onNewResult(DrawableHitObject judgedObject, JudgementResult result)
|
||||
|
@ -18,7 +18,7 @@ namespace osu.Game.Rulesets.Taiko.Mods
|
||||
public override double ScoreMultiplier => 1.12;
|
||||
|
||||
[SettingSource("Flashlight size", "Multiplier applied to the default flashlight size.")]
|
||||
public override BindableNumber<float> SizeMultiplier { get; } = new BindableNumber<float>
|
||||
public override BindableFloat SizeMultiplier { get; } = new BindableFloat
|
||||
{
|
||||
MinValue = 0.5f,
|
||||
MaxValue = 1.5f,
|
||||
|
@ -34,7 +34,7 @@ namespace osu.Game.Rulesets.Mods
|
||||
public override string Description => "Restricted view area.";
|
||||
|
||||
[SettingSource("Flashlight size", "Multiplier applied to the default flashlight size.")]
|
||||
public abstract BindableNumber<float> SizeMultiplier { get; }
|
||||
public abstract BindableFloat SizeMultiplier { get; }
|
||||
|
||||
[SettingSource("Change size based on combo", "Decrease the flashlight size as combo increases.")]
|
||||
public abstract BindableBool ComboBasedSize { get; }
|
||||
|
@ -5,8 +5,12 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using JetBrains.Annotations;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Replays;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Rulesets.Replays;
|
||||
using osu.Game.Scoring;
|
||||
|
||||
namespace osu.Game.Tests.Visual
|
||||
{
|
||||
@ -50,18 +54,37 @@ namespace osu.Game.Tests.Visual
|
||||
return CreateModPlayer(ruleset);
|
||||
}
|
||||
|
||||
protected virtual TestPlayer CreateModPlayer(Ruleset ruleset) => new ModTestPlayer(AllowFail);
|
||||
protected virtual TestPlayer CreateModPlayer(Ruleset ruleset) => new ModTestPlayer(currentTestData, AllowFail);
|
||||
|
||||
protected class ModTestPlayer : TestPlayer
|
||||
{
|
||||
private readonly bool allowFail;
|
||||
private readonly ModTestData currentTestData;
|
||||
|
||||
protected override bool CheckModsAllowFailure() => allowFail;
|
||||
|
||||
public ModTestPlayer(bool allowFail)
|
||||
public ModTestPlayer(ModTestData data, bool allowFail)
|
||||
: base(false, false)
|
||||
{
|
||||
this.allowFail = allowFail;
|
||||
currentTestData = data;
|
||||
}
|
||||
|
||||
protected override void PrepareReplay()
|
||||
{
|
||||
if (currentTestData.Autoplay && currentTestData.ReplayFrames?.Count > 0)
|
||||
throw new InvalidOperationException(@$"{nameof(ModTestData.Autoplay)} must be false when {nameof(ModTestData.ReplayFrames)} is specified.");
|
||||
|
||||
if (currentTestData.ReplayFrames != null)
|
||||
{
|
||||
DrawableRuleset?.SetReplayScore(new Score
|
||||
{
|
||||
Replay = new Replay { Frames = currentTestData.ReplayFrames },
|
||||
ScoreInfo = new ScoreInfo { User = new APIUser { Username = @"Test" } },
|
||||
});
|
||||
}
|
||||
|
||||
base.PrepareReplay();
|
||||
}
|
||||
}
|
||||
|
||||
@ -72,6 +95,12 @@ namespace osu.Game.Tests.Visual
|
||||
/// </summary>
|
||||
public bool Autoplay = true;
|
||||
|
||||
/// <summary>
|
||||
/// The frames to use for replay. <see cref="Autoplay"/> must be set to false.
|
||||
/// </summary>
|
||||
[CanBeNull]
|
||||
public List<ReplayFrame> ReplayFrames;
|
||||
|
||||
/// <summary>
|
||||
/// The beatmap for this test case.
|
||||
/// </summary>
|
||||
|
Loading…
Reference in New Issue
Block a user