mirror of
https://github.com/ppy/osu.git
synced 2024-11-11 11:37:28 +08:00
Merge remote-tracking branch 'refs/remotes/ppy/master' into profile-overlay-graph-new
This commit is contained in:
commit
42741895e6
@ -5,7 +5,7 @@ using osu.Game.Rulesets.Mods;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Mods
|
||||
{
|
||||
public class CatchModEasy : ModEasy
|
||||
public class CatchModEasy : ModEasyWithExtraLives
|
||||
{
|
||||
public override string Description => @"Larger fruits, more forgiving HP drain, less accuracy required, and three lives!";
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ using osu.Game.Rulesets.Mods;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Mods
|
||||
{
|
||||
public class ManiaModEasy : ModEasy
|
||||
public class ManiaModEasy : ModEasyWithExtraLives
|
||||
{
|
||||
public override string Description => @"More forgiving HP drain, less accuracy required, and three lives!";
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ using osu.Game.Rulesets.Mods;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Mods
|
||||
{
|
||||
public class OsuModEasy : ModEasy
|
||||
public class OsuModEasy : ModEasyWithExtraLives
|
||||
{
|
||||
public override string Description => @"Larger circles, more forgiving HP drain, less accuracy required, and three lives!";
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
// 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 osu.Framework.Bindables;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
@ -47,6 +48,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections
|
||||
});
|
||||
}
|
||||
|
||||
public double AnimationStartTime { get; set; }
|
||||
public Bindable<double> AnimationStartTime { get; } = new BindableDouble();
|
||||
}
|
||||
}
|
||||
|
@ -80,7 +80,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Connections
|
||||
fp.Alpha = 0;
|
||||
fp.Scale = new Vector2(1.5f * end.Scale);
|
||||
|
||||
fp.AnimationStartTime = fadeInTime;
|
||||
fp.AnimationStartTime.Value = fadeInTime;
|
||||
|
||||
using (fp.BeginAbsoluteSequence(fadeInTime))
|
||||
{
|
||||
|
@ -7,6 +7,6 @@ namespace osu.Game.Rulesets.Taiko.Mods
|
||||
{
|
||||
public class TaikoModEasy : ModEasy
|
||||
{
|
||||
public override string Description => @"Beats move slower, less accuracy required, and three lives!";
|
||||
public override string Description => @"Beats move slower, and less accuracy required!";
|
||||
}
|
||||
}
|
||||
|
79
osu.Game.Tests/NonVisual/Skinning/LegacySkinAnimationTest.cs
Normal file
79
osu.Game.Tests/NonVisual/Skinning/LegacySkinAnimationTest.cs
Normal file
@ -0,0 +1,79 @@
|
||||
// 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 NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Audio.Sample;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Animations;
|
||||
using osu.Framework.Graphics.OpenGL.Textures;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Framework.Timing;
|
||||
using osu.Game.Audio;
|
||||
using osu.Game.Skinning;
|
||||
using osu.Game.Tests.Visual;
|
||||
|
||||
namespace osu.Game.Tests.NonVisual.Skinning
|
||||
{
|
||||
[HeadlessTest]
|
||||
public class LegacySkinAnimationTest : OsuTestScene
|
||||
{
|
||||
private const string animation_name = "animation";
|
||||
private const int frame_count = 6;
|
||||
|
||||
[Cached(typeof(IAnimationTimeReference))]
|
||||
private TestAnimationTimeReference animationTimeReference = new TestAnimationTimeReference();
|
||||
|
||||
private TextureAnimation animation;
|
||||
|
||||
[Test]
|
||||
public void TestAnimationTimeReferenceChange()
|
||||
{
|
||||
ISkin skin = new TestSkin();
|
||||
|
||||
AddStep("get animation", () => Add(animation = (TextureAnimation)skin.GetAnimation(animation_name, true, false)));
|
||||
AddAssert("frame count correct", () => animation.FrameCount == frame_count);
|
||||
assertPlaybackPosition(0);
|
||||
|
||||
AddStep("set start time to 1000", () => animationTimeReference.AnimationStartTime.Value = 1000);
|
||||
assertPlaybackPosition(-1000);
|
||||
|
||||
AddStep("set current time to 500", () => animationTimeReference.ManualClock.CurrentTime = 500);
|
||||
assertPlaybackPosition(-500);
|
||||
}
|
||||
|
||||
private void assertPlaybackPosition(double expectedPosition)
|
||||
=> AddAssert($"playback position is {expectedPosition}", () => animation.PlaybackPosition == expectedPosition);
|
||||
|
||||
private class TestSkin : ISkin
|
||||
{
|
||||
private static readonly string[] lookup_names = Enumerable.Range(0, frame_count).Select(frame => $"{animation_name}-{frame}").ToArray();
|
||||
|
||||
public Texture GetTexture(string componentName, WrapMode wrapModeS, WrapMode wrapModeT)
|
||||
{
|
||||
return lookup_names.Contains(componentName) ? Texture.WhitePixel : null;
|
||||
}
|
||||
|
||||
public Drawable GetDrawableComponent(ISkinComponent component) => throw new NotSupportedException();
|
||||
public SampleChannel GetSample(ISampleInfo sampleInfo) => throw new NotSupportedException();
|
||||
public IBindable<TValue> GetConfig<TLookup, TValue>(TLookup lookup) => throw new NotSupportedException();
|
||||
}
|
||||
|
||||
private class TestAnimationTimeReference : IAnimationTimeReference
|
||||
{
|
||||
public ManualClock ManualClock { get; }
|
||||
public IFrameBasedClock Clock { get; }
|
||||
public Bindable<double> AnimationStartTime { get; } = new BindableDouble();
|
||||
|
||||
public TestAnimationTimeReference()
|
||||
{
|
||||
ManualClock = new ManualClock();
|
||||
Clock = new FramedClock(ManualClock);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -318,7 +318,7 @@ namespace osu.Game.Tests.Visual.Background
|
||||
private class FadeAccessibleResults : ResultsScreen
|
||||
{
|
||||
public FadeAccessibleResults(ScoreInfo score)
|
||||
: base(score)
|
||||
: base(score, true)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -256,7 +256,7 @@ namespace osu.Game.Tests.Visual.Ranking
|
||||
public HotkeyRetryOverlay RetryOverlay;
|
||||
|
||||
public TestResultsScreen(ScoreInfo score)
|
||||
: base(score)
|
||||
: base(score, true)
|
||||
{
|
||||
}
|
||||
|
||||
@ -326,7 +326,7 @@ namespace osu.Game.Tests.Visual.Ranking
|
||||
public HotkeyRetryOverlay RetryOverlay;
|
||||
|
||||
public UnrankedSoloResultsScreen(ScoreInfo score)
|
||||
: base(score)
|
||||
: base(score, true)
|
||||
{
|
||||
Score.Beatmap.OnlineBeatmapID = 0;
|
||||
Score.Beatmap.Status = BeatmapSetOnlineStatus.Pending;
|
||||
|
@ -420,7 +420,7 @@ namespace osu.Game
|
||||
break;
|
||||
|
||||
case ScorePresentType.Results:
|
||||
screen.Push(new SoloResultsScreen(databasedScore.ScoreInfo));
|
||||
screen.Push(new SoloResultsScreen(databasedScore.ScoreInfo, false));
|
||||
break;
|
||||
}
|
||||
}, validScreens: new[] { typeof(PlaySongSelect) });
|
||||
|
@ -2,17 +2,13 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using Humanizer;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
|
||||
namespace osu.Game.Rulesets.Mods
|
||||
{
|
||||
public abstract class ModEasy : Mod, IApplicableToDifficulty, IApplicableFailOverride, IApplicableToHealthProcessor
|
||||
public abstract class ModEasy : Mod, IApplicableToDifficulty
|
||||
{
|
||||
public override string Name => "Easy";
|
||||
public override string Acronym => "EZ";
|
||||
@ -22,49 +18,17 @@ namespace osu.Game.Rulesets.Mods
|
||||
public override bool Ranked => true;
|
||||
public override Type[] IncompatibleMods => new[] { typeof(ModHardRock), typeof(ModDifficultyAdjust) };
|
||||
|
||||
[SettingSource("Extra Lives", "Number of extra lives")]
|
||||
public Bindable<int> Retries { get; } = new BindableInt(2)
|
||||
{
|
||||
MinValue = 0,
|
||||
MaxValue = 10
|
||||
};
|
||||
|
||||
public override string SettingDescription => Retries.IsDefault ? string.Empty : $"{"lives".ToQuantity(Retries.Value)}";
|
||||
|
||||
private int retries;
|
||||
|
||||
private BindableNumber<double> health;
|
||||
|
||||
public void ReadFromDifficulty(BeatmapDifficulty difficulty)
|
||||
public virtual void ReadFromDifficulty(BeatmapDifficulty difficulty)
|
||||
{
|
||||
}
|
||||
|
||||
public void ApplyToDifficulty(BeatmapDifficulty difficulty)
|
||||
public virtual void ApplyToDifficulty(BeatmapDifficulty difficulty)
|
||||
{
|
||||
const float ratio = 0.5f;
|
||||
difficulty.CircleSize *= ratio;
|
||||
difficulty.ApproachRate *= ratio;
|
||||
difficulty.DrainRate *= ratio;
|
||||
difficulty.OverallDifficulty *= ratio;
|
||||
|
||||
retries = Retries.Value;
|
||||
}
|
||||
|
||||
public bool PerformFail()
|
||||
{
|
||||
if (retries == 0) return true;
|
||||
|
||||
health.Value = health.MaxValue;
|
||||
retries--;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool RestartOnFail => false;
|
||||
|
||||
public void ApplyToHealthProcessor(HealthProcessor healthProcessor)
|
||||
{
|
||||
health = healthProcessor.Health.GetBoundCopy();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
50
osu.Game/Rulesets/Mods/ModEasyWithExtraLives.cs
Normal file
50
osu.Game/Rulesets/Mods/ModEasyWithExtraLives.cs
Normal file
@ -0,0 +1,50 @@
|
||||
// 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 Humanizer;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Rulesets.Scoring;
|
||||
|
||||
namespace osu.Game.Rulesets.Mods
|
||||
{
|
||||
public abstract class ModEasyWithExtraLives : ModEasy, IApplicableFailOverride, IApplicableToHealthProcessor
|
||||
{
|
||||
[SettingSource("Extra Lives", "Number of extra lives")]
|
||||
public Bindable<int> Retries { get; } = new BindableInt(2)
|
||||
{
|
||||
MinValue = 0,
|
||||
MaxValue = 10
|
||||
};
|
||||
|
||||
public override string SettingDescription => Retries.IsDefault ? string.Empty : $"{"lives".ToQuantity(Retries.Value)}";
|
||||
|
||||
private int retries;
|
||||
|
||||
private BindableNumber<double> health;
|
||||
|
||||
public override void ApplyToDifficulty(BeatmapDifficulty difficulty)
|
||||
{
|
||||
base.ApplyToDifficulty(difficulty);
|
||||
retries = Retries.Value;
|
||||
}
|
||||
|
||||
public bool PerformFail()
|
||||
{
|
||||
if (retries == 0) return true;
|
||||
|
||||
health.Value = health.MaxValue;
|
||||
retries--;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool RestartOnFail => false;
|
||||
|
||||
public void ApplyToHealthProcessor(HealthProcessor healthProcessor)
|
||||
{
|
||||
health = healthProcessor.Health.GetBoundCopy();
|
||||
}
|
||||
}
|
||||
}
|
@ -92,7 +92,7 @@ namespace osu.Game.Screens.Multi.Play
|
||||
protected override ResultsScreen CreateResults(ScoreInfo score)
|
||||
{
|
||||
Debug.Assert(roomId.Value != null);
|
||||
return new TimeshiftResultsScreen(score, roomId.Value.Value, playlistItem);
|
||||
return new TimeshiftResultsScreen(score, roomId.Value.Value, playlistItem, true);
|
||||
}
|
||||
|
||||
protected override ScoreInfo CreateScore()
|
||||
|
@ -32,7 +32,7 @@ namespace osu.Game.Screens.Multi.Ranking
|
||||
[Resolved]
|
||||
private IAPIProvider api { get; set; }
|
||||
|
||||
public TimeshiftResultsScreen(ScoreInfo score, int roomId, PlaylistItem playlistItem, bool allowRetry = true)
|
||||
public TimeshiftResultsScreen(ScoreInfo score, int roomId, PlaylistItem playlistItem, bool allowRetry)
|
||||
: base(score, allowRetry)
|
||||
{
|
||||
this.roomId = roomId;
|
||||
|
@ -545,7 +545,7 @@ namespace osu.Game.Screens.Play
|
||||
|
||||
protected override bool OnScroll(ScrollEvent e) => mouseWheelDisabled.Value && !GameplayClockContainer.IsPaused.Value;
|
||||
|
||||
protected virtual ResultsScreen CreateResults(ScoreInfo score) => new SoloResultsScreen(score);
|
||||
protected virtual ResultsScreen CreateResults(ScoreInfo score) => new SoloResultsScreen(score, true);
|
||||
|
||||
#region Fail Logic
|
||||
|
||||
|
@ -12,7 +12,7 @@ namespace osu.Game.Screens.Play
|
||||
public class SpectatorResultsScreen : SoloResultsScreen
|
||||
{
|
||||
public SpectatorResultsScreen(ScoreInfo score)
|
||||
: base(score)
|
||||
: base(score, false)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -58,7 +58,7 @@ namespace osu.Game.Screens.Ranking
|
||||
|
||||
private readonly bool allowRetry;
|
||||
|
||||
protected ResultsScreen(ScoreInfo score, bool allowRetry = true)
|
||||
protected ResultsScreen(ScoreInfo score, bool allowRetry)
|
||||
{
|
||||
Score = score;
|
||||
this.allowRetry = allowRetry;
|
||||
|
@ -18,7 +18,7 @@ namespace osu.Game.Screens.Ranking
|
||||
[Resolved]
|
||||
private RulesetStore rulesets { get; set; }
|
||||
|
||||
public SoloResultsScreen(ScoreInfo score, bool allowRetry = true)
|
||||
public SoloResultsScreen(ScoreInfo score, bool allowRetry)
|
||||
: base(score, allowRetry)
|
||||
{
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ namespace osu.Game.Screens.Select
|
||||
}
|
||||
|
||||
protected void PresentScore(ScoreInfo score) =>
|
||||
FinaliseSelection(score.Beatmap, score.Ruleset, () => this.Push(new SoloResultsScreen(score)));
|
||||
FinaliseSelection(score.Beatmap, score.Ruleset, () => this.Push(new SoloResultsScreen(score, false)));
|
||||
|
||||
protected override BeatmapDetailArea CreateBeatmapDetailArea() => new PlayBeatmapDetailArea();
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics.OpenGL.Textures;
|
||||
using osu.Framework.Timing;
|
||||
|
||||
@ -25,6 +26,6 @@ namespace osu.Game.Skinning
|
||||
/// <summary>
|
||||
/// The time which animations should be started from, relative to <see cref="Clock"/>.
|
||||
/// </summary>
|
||||
double AnimationStartTime { get; }
|
||||
Bindable<double> AnimationStartTime { get; }
|
||||
}
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Animations;
|
||||
using osu.Framework.Graphics.OpenGL.Textures;
|
||||
@ -70,6 +71,8 @@ namespace osu.Game.Skinning
|
||||
[Resolved(canBeNull: true)]
|
||||
private IAnimationTimeReference timeReference { get; set; }
|
||||
|
||||
private readonly Bindable<double> animationStartTime = new BindableDouble();
|
||||
|
||||
public SkinnableTextureAnimation(bool startAtCurrentTime = true)
|
||||
: base(startAtCurrentTime)
|
||||
{
|
||||
@ -82,8 +85,18 @@ namespace osu.Game.Skinning
|
||||
if (timeReference != null)
|
||||
{
|
||||
Clock = timeReference.Clock;
|
||||
PlaybackPosition = timeReference.Clock.CurrentTime - timeReference.AnimationStartTime;
|
||||
animationStartTime.BindTo(timeReference.AnimationStartTime);
|
||||
}
|
||||
|
||||
animationStartTime.BindValueChanged(_ => updatePlaybackPosition(), true);
|
||||
}
|
||||
|
||||
private void updatePlaybackPosition()
|
||||
{
|
||||
if (timeReference == null)
|
||||
return;
|
||||
|
||||
PlaybackPosition = timeReference.Clock.CurrentTime - timeReference.AnimationStartTime.Value;
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user