mirror of
https://github.com/ppy/osu.git
synced 2026-05-15 15:32:53 +08:00
Compare commits
60 Commits
+1
-1
Submodule osu-framework updated: f807997301...fac688633b
@@ -14,7 +14,7 @@ using osu.Game.Tests.Beatmaps;
|
||||
|
||||
namespace osu.Game.Rulesets.Catch.Tests
|
||||
{
|
||||
public class CatchBeatmapConversionTest : BeatmapConversionTest<TestCatchRuleset, ConvertValue>
|
||||
internal class CatchBeatmapConversionTest : BeatmapConversionTest<TestCatchRuleset, ConvertValue>
|
||||
{
|
||||
protected override string ResourceAssembly => "osu.Game.Rulesets.Catch";
|
||||
|
||||
@@ -50,7 +50,7 @@ namespace osu.Game.Rulesets.Catch.Tests
|
||||
protected override IBeatmapConverter CreateConverter(IBeatmap beatmap) => new CatchBeatmapConverter(beatmap);
|
||||
}
|
||||
|
||||
public struct ConvertValue : IEquatable<ConvertValue>
|
||||
internal struct ConvertValue : IEquatable<ConvertValue>
|
||||
{
|
||||
/// <summary>
|
||||
/// A sane value to account for osu!stable using ints everwhere.
|
||||
@@ -65,7 +65,7 @@ namespace osu.Game.Rulesets.Catch.Tests
|
||||
&& Precision.AlmostEquals(Position, other.Position, conversion_lenience);
|
||||
}
|
||||
|
||||
public class TestCatchRuleset : CatchRuleset
|
||||
internal class TestCatchRuleset : CatchRuleset
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ using osu.Game.Tests.Beatmaps;
|
||||
|
||||
namespace osu.Game.Rulesets.Mania.Tests
|
||||
{
|
||||
public class ManiaBeatmapConversionTest : BeatmapConversionTest<TestManiaRuleset, ConvertValue>
|
||||
internal class ManiaBeatmapConversionTest : BeatmapConversionTest<TestManiaRuleset, ConvertValue>
|
||||
{
|
||||
protected override string ResourceAssembly => "osu.Game.Rulesets.Mania";
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace osu.Game.Rulesets.Mania.Tests
|
||||
protected override IBeatmapConverter CreateConverter(IBeatmap beatmap) => new ManiaBeatmapConverter(beatmap);
|
||||
}
|
||||
|
||||
public struct ConvertValue : IEquatable<ConvertValue>
|
||||
internal struct ConvertValue : IEquatable<ConvertValue>
|
||||
{
|
||||
/// <summary>
|
||||
/// A sane value to account for osu!stable using ints everwhere.
|
||||
@@ -55,7 +55,7 @@ namespace osu.Game.Rulesets.Mania.Tests
|
||||
&& Column == other.Column;
|
||||
}
|
||||
|
||||
public class TestManiaRuleset : ManiaRuleset
|
||||
internal class TestManiaRuleset : ManiaRuleset
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ using OpenTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Tests
|
||||
{
|
||||
public class OsuBeatmapConversionTest : BeatmapConversionTest<TestOsuRuleset, ConvertValue>
|
||||
internal class OsuBeatmapConversionTest : BeatmapConversionTest<TestOsuRuleset, ConvertValue>
|
||||
{
|
||||
protected override string ResourceAssembly => "osu.Game.Rulesets.Osu";
|
||||
|
||||
@@ -45,7 +45,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
protected override IBeatmapConverter CreateConverter(IBeatmap beatmap) => new OsuBeatmapConverter(beatmap);
|
||||
}
|
||||
|
||||
public struct ConvertValue : IEquatable<ConvertValue>
|
||||
internal struct ConvertValue : IEquatable<ConvertValue>
|
||||
{
|
||||
/// <summary>
|
||||
/// A sane value to account for osu!stable using ints everwhere.
|
||||
@@ -68,7 +68,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
&& Precision.AlmostEquals(EndY, other.EndY, conversion_lenience);
|
||||
}
|
||||
|
||||
public class TestOsuRuleset : OsuRuleset
|
||||
internal class TestOsuRuleset : OsuRuleset
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,17 @@ namespace osu.Game.Rulesets.Osu.Scoring
|
||||
private readonly int beatmapMaxCombo;
|
||||
|
||||
private Mod[] mods;
|
||||
|
||||
/// <summary>
|
||||
/// Approach rate adjusted by mods.
|
||||
/// </summary>
|
||||
private double realApproachRate;
|
||||
|
||||
/// <summary>
|
||||
/// Overall difficulty adjusted by mods.
|
||||
/// </summary>
|
||||
private double realOverallDifficulty;
|
||||
|
||||
private double accuracy;
|
||||
private int scoreMaxCombo;
|
||||
private int count300;
|
||||
@@ -32,7 +42,8 @@ namespace osu.Game.Rulesets.Osu.Scoring
|
||||
countHitCircles = Beatmap.HitObjects.Count(h => h is HitCircle);
|
||||
|
||||
beatmapMaxCombo = Beatmap.HitObjects.Count();
|
||||
beatmapMaxCombo += Beatmap.HitObjects.OfType<Slider>().Sum(s => s.NestedHitObjects.Count) + 1;
|
||||
// Add the ticks + tail of the slider. 1 is subtracted because the "headcircle" would be counted twice (once for the slider itself in the line above)
|
||||
beatmapMaxCombo += Beatmap.HitObjects.OfType<Slider>().Sum(s => s.NestedHitObjects.Count - 1);
|
||||
}
|
||||
|
||||
public override double Calculate(Dictionary<string, double> categoryRatings = null)
|
||||
@@ -57,8 +68,12 @@ namespace osu.Game.Rulesets.Osu.Scoring
|
||||
ar = Math.Min(10, ar * 1.4);
|
||||
if (mods.Any(m => m is OsuModEasy))
|
||||
ar = Math.Max(0, ar / 2);
|
||||
double preEmpt = BeatmapDifficulty.DifficultyRange(ar, 1800, 1200, 450);
|
||||
|
||||
double preEmpt = BeatmapDifficulty.DifficultyRange(ar, 1800, 1200, 450) / TimeRate;
|
||||
double hitWindow300 = (Beatmap.HitObjects.First().HitWindows.Great / 2 - 0.5) / TimeRate;
|
||||
|
||||
realApproachRate = preEmpt > 1200 ? (1800 - preEmpt) / 120 : (1200 - preEmpt) / 150 + 5;
|
||||
realOverallDifficulty = (80 - 0.5 - hitWindow300) / 6;
|
||||
|
||||
// Custom multipliers for NoFail and SpunOut.
|
||||
double multiplier = 1.12f; // This is being adjusted to keep the final pp value scaled around what it used to be when changing things
|
||||
@@ -84,6 +99,9 @@ namespace osu.Game.Rulesets.Osu.Scoring
|
||||
categoryRatings.Add("Aim", aimValue);
|
||||
categoryRatings.Add("Speed", speedValue);
|
||||
categoryRatings.Add("Accuracy", accuracyValue);
|
||||
categoryRatings.Add("OD", realOverallDifficulty);
|
||||
categoryRatings.Add("AR", realApproachRate);
|
||||
categoryRatings.Add("Max Combo", beatmapMaxCombo);
|
||||
}
|
||||
|
||||
return totalValue;
|
||||
@@ -121,7 +139,7 @@ namespace osu.Game.Rulesets.Osu.Scoring
|
||||
aimValue *= approachRateFactor;
|
||||
|
||||
if (mods.Any(h => h is OsuModHidden))
|
||||
aimValue *= 1.18f;
|
||||
aimValue *= 1.03f;
|
||||
|
||||
if (mods.Any(h => h is OsuModFlashlight))
|
||||
{
|
||||
@@ -132,7 +150,7 @@ namespace osu.Game.Rulesets.Osu.Scoring
|
||||
// Scale the aim value with accuracy _slightly_
|
||||
aimValue *= 0.5f + accuracy / 2.0f;
|
||||
// It is important to also consider accuracy difficulty when doing that
|
||||
aimValue *= 0.98f + Math.Pow(Beatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty, 2) / 2500;
|
||||
aimValue *= 0.98f + Math.Pow(realOverallDifficulty, 2) / 2500;
|
||||
|
||||
return aimValue;
|
||||
}
|
||||
@@ -152,10 +170,13 @@ namespace osu.Game.Rulesets.Osu.Scoring
|
||||
if (beatmapMaxCombo > 0)
|
||||
speedValue *= Math.Min(Math.Pow(scoreMaxCombo, 0.8f) / Math.Pow(beatmapMaxCombo, 0.8f), 1.0f);
|
||||
|
||||
if (mods.Any(m => m is OsuModHidden))
|
||||
speedValue *= 1.18f;
|
||||
|
||||
// Scale the speed value with accuracy _slightly_
|
||||
speedValue *= 0.5f + accuracy / 2.0f;
|
||||
// It is important to also consider accuracy difficulty when doing that
|
||||
speedValue *= 0.98f + Math.Pow(Beatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty, 2) / 2500;
|
||||
speedValue *= 0.98f + Math.Pow(realOverallDifficulty, 2) / 2500;
|
||||
|
||||
return speedValue;
|
||||
}
|
||||
@@ -177,7 +198,7 @@ namespace osu.Game.Rulesets.Osu.Scoring
|
||||
|
||||
// Lots of arbitrary values from testing.
|
||||
// Considering to use derivation from perfect accuracy in a probabilistic manner - assume normal distribution
|
||||
double accuracyValue = Math.Pow(1.52163f, Beatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty) * Math.Pow(betterAccuracyPercentage, 24) * 2.83f;
|
||||
double accuracyValue = Math.Pow(1.52163f, realOverallDifficulty) * Math.Pow(betterAccuracyPercentage, 24) * 2.83f;
|
||||
|
||||
// Bonus for many hitcircles - it's harder to keep good accuracy up for longer
|
||||
accuracyValue *= Math.Min(1.15f, Math.Pow(amountHitObjectsWithAccuracy / 1000.0f, 0.3f));
|
||||
|
||||
@@ -14,7 +14,7 @@ using osu.Game.Tests.Beatmaps;
|
||||
|
||||
namespace osu.Game.Rulesets.Taiko.Tests
|
||||
{
|
||||
public class TaikoBeatmapConversionTest : BeatmapConversionTest<TestTaikoRuleset, ConvertValue>
|
||||
internal class TaikoBeatmapConversionTest : BeatmapConversionTest<TestTaikoRuleset, ConvertValue>
|
||||
{
|
||||
protected override string ResourceAssembly => "osu.Game.Rulesets.Taiko";
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace osu.Game.Rulesets.Taiko.Tests
|
||||
protected override IBeatmapConverter CreateConverter(IBeatmap beatmap) => new TaikoBeatmapConverter(beatmap);
|
||||
}
|
||||
|
||||
public struct ConvertValue : IEquatable<ConvertValue>
|
||||
internal struct ConvertValue : IEquatable<ConvertValue>
|
||||
{
|
||||
/// <summary>
|
||||
/// A sane value to account for osu!stable using ints everwhere.
|
||||
@@ -68,7 +68,7 @@ namespace osu.Game.Rulesets.Taiko.Tests
|
||||
&& IsStrong == other.IsStrong;
|
||||
}
|
||||
|
||||
public class TestTaikoRuleset : TaikoRuleset
|
||||
internal class TestTaikoRuleset : TaikoRuleset
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,6 +40,8 @@ namespace osu.Game.Rulesets.Taiko.Objects
|
||||
/// </summary>
|
||||
private double tickSpacing = 100;
|
||||
|
||||
private float overallDifficulty = BeatmapDifficulty.DEFAULT_DIFFICULTY;
|
||||
|
||||
protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty)
|
||||
{
|
||||
base.ApplyDefaultsToSelf(controlPointInfo, difficulty);
|
||||
@@ -47,9 +49,7 @@ namespace osu.Game.Rulesets.Taiko.Objects
|
||||
TimingControlPoint timingPoint = controlPointInfo.TimingPointAt(StartTime);
|
||||
|
||||
tickSpacing = timingPoint.BeatLength / TickRate;
|
||||
|
||||
RequiredGoodHits = NestedHitObjects.Count * Math.Min(0.15, 0.05 + 0.10 / 6 * difficulty.OverallDifficulty);
|
||||
RequiredGreatHits = NestedHitObjects.Count * Math.Min(0.30, 0.10 + 0.20 / 6 * difficulty.OverallDifficulty);
|
||||
overallDifficulty = difficulty.OverallDifficulty;
|
||||
}
|
||||
|
||||
protected override void CreateNestedHitObjects()
|
||||
@@ -57,6 +57,9 @@ namespace osu.Game.Rulesets.Taiko.Objects
|
||||
base.CreateNestedHitObjects();
|
||||
|
||||
createTicks();
|
||||
|
||||
RequiredGoodHits = NestedHitObjects.Count * Math.Min(0.15, 0.05 + 0.10 / 6 * overallDifficulty);
|
||||
RequiredGreatHits = NestedHitObjects.Count * Math.Min(0.30, 0.10 + 0.20 / 6 * overallDifficulty);
|
||||
}
|
||||
|
||||
private void createTicks()
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Screens.Menu;
|
||||
|
||||
namespace osu.Game.Tests.Visual
|
||||
{
|
||||
public class TestCaseHoldToConfirmOverlay : OsuTestCase
|
||||
{
|
||||
public override IReadOnlyList<Type> RequiredTypes => new[] { typeof(ExitConfirmOverlay) };
|
||||
|
||||
public TestCaseHoldToConfirmOverlay()
|
||||
{
|
||||
bool fired = false;
|
||||
|
||||
var firedText = new OsuSpriteText
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Text = "Fired!",
|
||||
TextSize = 50,
|
||||
Alpha = 0,
|
||||
};
|
||||
|
||||
var overlay = new TestHoldToConfirmOverlay
|
||||
{
|
||||
Action = () =>
|
||||
{
|
||||
fired = true;
|
||||
firedText.FadeTo(1).Then().FadeOut(1000);
|
||||
}
|
||||
};
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
overlay,
|
||||
firedText
|
||||
};
|
||||
|
||||
AddStep("start confirming", () => overlay.Begin());
|
||||
AddStep("abort confirming", () => overlay.Abort());
|
||||
|
||||
AddAssert("ensure aborted", () => !fired);
|
||||
|
||||
AddStep("start confirming", () => overlay.Begin());
|
||||
|
||||
AddUntilStep(() => fired, "wait until confirmed");
|
||||
}
|
||||
|
||||
private class TestHoldToConfirmOverlay : ExitConfirmOverlay
|
||||
{
|
||||
protected override bool AllowMultipleFires => true;
|
||||
|
||||
public void Begin() => BeginConfirm();
|
||||
public void Abort() => AbortConfirm();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,7 @@ namespace osu.Game.Beatmaps
|
||||
protected readonly IBeatmap Beatmap;
|
||||
protected readonly Mod[] Mods;
|
||||
|
||||
protected double TimeRate = 1;
|
||||
protected double TimeRate { get; private set; } = 1;
|
||||
|
||||
protected DifficultyCalculator(IBeatmap beatmap, Mod[] mods = null)
|
||||
{
|
||||
|
||||
@@ -44,19 +44,6 @@ namespace osu.Game.Graphics.Containers
|
||||
return base.OnClick(state);
|
||||
}
|
||||
|
||||
protected override bool OnDragStart(InputState state)
|
||||
{
|
||||
if (!base.ReceiveMouseInputAt(state.Mouse.NativeState.Position))
|
||||
{
|
||||
State = Visibility.Hidden;
|
||||
return true;
|
||||
}
|
||||
|
||||
return base.OnDragStart(state);
|
||||
}
|
||||
|
||||
protected override bool OnDrag(InputState state) => State == Visibility.Hidden;
|
||||
|
||||
private void onStateChanged(Visibility visibility)
|
||||
{
|
||||
switch (visibility)
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using OpenTK.Graphics;
|
||||
|
||||
namespace osu.Game.Overlays
|
||||
{
|
||||
/// <summary>
|
||||
/// An overlay which will display a black screen that dims over a period before confirming an exit action.
|
||||
/// Action is BYO (derived class will need to call <see cref="BeginConfirm"/> and <see cref="AbortConfirm"/> from a user event).
|
||||
/// </summary>
|
||||
public abstract class HoldToConfirmOverlay : Container
|
||||
{
|
||||
public Action Action;
|
||||
|
||||
private Box overlay;
|
||||
|
||||
private const int activate_delay = 400;
|
||||
private const int fadeout_delay = 200;
|
||||
|
||||
private bool fired;
|
||||
|
||||
/// <summary>
|
||||
/// Whether the overlay should be allowed to return from a fired state.
|
||||
/// </summary>
|
||||
protected virtual bool AllowMultipleFires => false;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
AlwaysPresent = true;
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
overlay = new Box
|
||||
{
|
||||
Alpha = 0,
|
||||
Colour = Color4.Black,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected void BeginConfirm()
|
||||
{
|
||||
if (!AllowMultipleFires && fired) return;
|
||||
overlay.FadeIn(activate_delay * (1 - overlay.Alpha), Easing.Out).OnComplete(_ =>
|
||||
{
|
||||
Action?.Invoke();
|
||||
fired = true;
|
||||
});
|
||||
}
|
||||
|
||||
protected void AbortConfirm()
|
||||
{
|
||||
if (!AllowMultipleFires && fired) return;
|
||||
overlay.FadeOut(fadeout_delay, Easing.Out);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,7 @@ using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Input;
|
||||
using osu.Framework.Input.Bindings;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Input;
|
||||
using OpenTK.Graphics;
|
||||
@@ -43,7 +44,7 @@ namespace osu.Game.Overlays.KeyBinding
|
||||
}
|
||||
|
||||
private OsuSpriteText text;
|
||||
private OsuSpriteText pressAKey;
|
||||
private OsuTextFlowContainer pressAKey;
|
||||
|
||||
private FillFlowContainer<KeyButton> buttons;
|
||||
|
||||
@@ -95,10 +96,11 @@ namespace osu.Game.Overlays.KeyBinding
|
||||
Anchor = Anchor.TopRight,
|
||||
Origin = Anchor.TopRight
|
||||
},
|
||||
pressAKey = new OsuSpriteText
|
||||
pressAKey = new OsuTextFlowContainer
|
||||
{
|
||||
Text = "Press a key to change binding, DEL to delete, ESC to cancel.",
|
||||
Y = height,
|
||||
Text = "Press a key to change binding, Shift+Delete to delete, Escape to cancel.",
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
Margin = new MarginPadding(padding),
|
||||
Alpha = 0,
|
||||
Colour = colours.YellowDark
|
||||
@@ -204,9 +206,16 @@ namespace osu.Game.Overlays.KeyBinding
|
||||
finalise();
|
||||
return true;
|
||||
case Key.Delete:
|
||||
bindTarget.UpdateKeyCombination(InputKey.None);
|
||||
finalise();
|
||||
return true;
|
||||
{
|
||||
if (state.Keyboard.ShiftPressed)
|
||||
{
|
||||
bindTarget.UpdateKeyCombination(InputKey.None);
|
||||
finalise();
|
||||
return true;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bindTarget.UpdateKeyCombination(KeyCombination.FromInputState(state));
|
||||
@@ -223,6 +232,26 @@ namespace osu.Game.Overlays.KeyBinding
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override bool OnJoystickPress(InputState state, Framework.Input.JoystickEventArgs args)
|
||||
{
|
||||
if (!HasFocus)
|
||||
return false;
|
||||
|
||||
bindTarget.UpdateKeyCombination(KeyCombination.FromInputState(state));
|
||||
finalise();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override bool OnJoystickRelease(InputState state, Framework.Input.JoystickEventArgs args)
|
||||
{
|
||||
if (!HasFocus)
|
||||
return base.OnJoystickRelease(state, args);
|
||||
|
||||
finalise();
|
||||
return true;
|
||||
}
|
||||
|
||||
private void finalise()
|
||||
{
|
||||
if (bindTarget != null)
|
||||
@@ -241,7 +270,7 @@ namespace osu.Game.Overlays.KeyBinding
|
||||
GetContainingInputManager().ChangeFocus(null);
|
||||
|
||||
pressAKey.FadeOut(300, Easing.OutQuint);
|
||||
pressAKey.Padding = new MarginPadding { Bottom = -pressAKey.DrawHeight };
|
||||
pressAKey.Padding = new MarginPadding { Top = height, Bottom = -pressAKey.DrawHeight };
|
||||
}
|
||||
|
||||
protected override void OnFocus(InputState state)
|
||||
@@ -250,7 +279,7 @@ namespace osu.Game.Overlays.KeyBinding
|
||||
AutoSizeEasing = Easing.OutQuint;
|
||||
|
||||
pressAKey.FadeIn(300, Easing.OutQuint);
|
||||
pressAKey.Padding = new MarginPadding();
|
||||
pressAKey.Padding = new MarginPadding { Top = height };
|
||||
|
||||
updateBindTarget();
|
||||
base.OnFocus(state);
|
||||
|
||||
@@ -100,6 +100,8 @@ namespace osu.Game.Overlays
|
||||
|
||||
public bool Adjust(GlobalAction action)
|
||||
{
|
||||
if (!IsLoaded) return false;
|
||||
|
||||
switch (action)
|
||||
{
|
||||
case GlobalAction.DecreaseVolume:
|
||||
|
||||
@@ -112,7 +112,7 @@ namespace osu.Game.Rulesets
|
||||
try
|
||||
{
|
||||
var assembly = Assembly.LoadFrom(file);
|
||||
loaded_assemblies[assembly] = assembly.GetTypes().First(t => t.IsSubclassOf(typeof(Ruleset)));
|
||||
loaded_assemblies[assembly] = assembly.GetTypes().First(t => t.IsPublic && t.IsSubclassOf(typeof(Ruleset)));
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
|
||||
@@ -49,18 +49,21 @@ namespace osu.Game.Rulesets.Scoring.Legacy
|
||||
score.User = new User { Username = sr.ReadString() };
|
||||
/* var localScoreChecksum = */
|
||||
sr.ReadString();
|
||||
/* score.Count300 = */
|
||||
sr.ReadUInt16();
|
||||
/* score.Count100 = */
|
||||
sr.ReadUInt16();
|
||||
/* score.Count50 = */
|
||||
sr.ReadUInt16();
|
||||
/* score.CountGeki = */
|
||||
sr.ReadUInt16();
|
||||
/* score.CountKatu = */
|
||||
sr.ReadUInt16();
|
||||
/* score.CountMiss = */
|
||||
sr.ReadUInt16();
|
||||
|
||||
var count300 = sr.ReadUInt16();
|
||||
var count100 = sr.ReadUInt16();
|
||||
var count50 = sr.ReadUInt16();
|
||||
var countGeki = sr.ReadUInt16();
|
||||
var countKatu = sr.ReadUInt16();
|
||||
var countMiss = sr.ReadUInt16();
|
||||
|
||||
score.Statistics[HitResult.Great] = count300;
|
||||
score.Statistics[HitResult.Good] = count100;
|
||||
score.Statistics[HitResult.Meh] = count50;
|
||||
score.Statistics[HitResult.Perfect] = countGeki;
|
||||
score.Statistics[HitResult.Ok] = countKatu;
|
||||
score.Statistics[HitResult.Miss] = countMiss;
|
||||
|
||||
score.TotalScore = sr.ReadInt32();
|
||||
score.MaxCombo = sr.ReadUInt16();
|
||||
/* score.Perfect = */
|
||||
@@ -81,6 +84,34 @@ namespace osu.Game.Rulesets.Scoring.Legacy
|
||||
/*OnlineId =*/
|
||||
sr.ReadInt32();
|
||||
|
||||
switch (score.Ruleset.ID)
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
int totalHits = count50 + count100 + count300 + countMiss;
|
||||
score.Accuracy = totalHits > 0 ? (double)(count50 * 50 + count100 * 100 + count300 * 300) / (totalHits * 300) : 1;
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
{
|
||||
int totalHits = count50 + count100 + count300 + countMiss;
|
||||
score.Accuracy = totalHits > 0 ? (double)(count100 * 150 + count300 * 300) / (totalHits * 300) : 1;
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
int totalHits = count50 + count100 + count300 + countMiss + countKatu;
|
||||
score.Accuracy = totalHits > 0 ? (double)(count50 + count100 + count300 ) / totalHits : 1;
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
int totalHits = count50 + count100 + count300 + countMiss + countGeki + countKatu;
|
||||
score.Accuracy = totalHits > 0 ? (double)(count50 * 50 + count100 * 100 + countKatu * 200 + (count300 + countGeki) * 300) / (totalHits * 300) : 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
using (var replayInStream = new MemoryStream(compressedReplay))
|
||||
{
|
||||
byte[] properties = new byte[5];
|
||||
|
||||
@@ -2,7 +2,11 @@
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Extensions.IEnumerableExtensions;
|
||||
using osu.Framework.Timing;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
|
||||
namespace osu.Game.Rulesets.Scoring
|
||||
{
|
||||
@@ -14,6 +18,8 @@ namespace osu.Game.Rulesets.Scoring
|
||||
protected readonly IBeatmap Beatmap;
|
||||
protected readonly Score Score;
|
||||
|
||||
protected double TimeRate { get; private set; } = 1;
|
||||
|
||||
protected PerformanceCalculator(Ruleset ruleset, IBeatmap beatmap, Score score)
|
||||
{
|
||||
Score = score;
|
||||
@@ -22,6 +28,15 @@ namespace osu.Game.Rulesets.Scoring
|
||||
|
||||
var diffCalc = ruleset.CreateDifficultyCalculator(beatmap, score.Mods);
|
||||
diffCalc.Calculate(attributes);
|
||||
|
||||
ApplyMods(score.Mods);
|
||||
}
|
||||
|
||||
protected virtual void ApplyMods(Mod[] mods)
|
||||
{
|
||||
var clock = new StopwatchClock();
|
||||
mods.OfType<IApplicableToClock>().ForEach(m => m.ApplyToClock(clock));
|
||||
TimeRate = clock.Rate;
|
||||
}
|
||||
|
||||
public abstract double Calculate(Dictionary<string, double> categoryDifficulty = null);
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Input;
|
||||
using osu.Game.Overlays;
|
||||
using OpenTK.Input;
|
||||
|
||||
namespace osu.Game.Screens.Menu
|
||||
{
|
||||
public class ExitConfirmOverlay : HoldToConfirmOverlay
|
||||
{
|
||||
protected override bool OnKeyDown(InputState state, KeyDownEventArgs args)
|
||||
{
|
||||
if (args.Key == Key.Escape && !args.Repeat)
|
||||
{
|
||||
BeginConfirm();
|
||||
return true;
|
||||
}
|
||||
|
||||
return base.OnKeyDown(state, args);
|
||||
}
|
||||
|
||||
protected override bool OnKeyUp(InputState state, KeyUpEventArgs args)
|
||||
{
|
||||
if (args.Key == Key.Escape)
|
||||
{
|
||||
AbortConfirm();
|
||||
return true;
|
||||
}
|
||||
|
||||
return base.OnKeyUp(state, args);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -39,6 +39,10 @@ namespace osu.Game.Screens.Menu
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
new ExitConfirmOverlay
|
||||
{
|
||||
Action = Exit,
|
||||
},
|
||||
new ParallaxContainer
|
||||
{
|
||||
ParallaxAmount = 0.01f,
|
||||
|
||||
@@ -1,50 +1,19 @@
|
||||
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
|
||||
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
|
||||
|
||||
using osu.Framework.Allocation;
|
||||
using System;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Framework.Input.Bindings;
|
||||
using osu.Game.Input.Bindings;
|
||||
using OpenTK.Graphics;
|
||||
using osu.Game.Overlays;
|
||||
|
||||
namespace osu.Game.Screens.Play
|
||||
{
|
||||
public class HotkeyRetryOverlay : Container, IKeyBindingHandler<GlobalAction>
|
||||
public class HotkeyRetryOverlay : HoldToConfirmOverlay, IKeyBindingHandler<GlobalAction>
|
||||
{
|
||||
public Action Action;
|
||||
|
||||
private Box overlay;
|
||||
|
||||
private const int activate_delay = 400;
|
||||
private const int fadeout_delay = 200;
|
||||
|
||||
private bool fired;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
AlwaysPresent = true;
|
||||
|
||||
Children = new Drawable[]
|
||||
{
|
||||
overlay = new Box
|
||||
{
|
||||
Alpha = 0,
|
||||
Colour = Color4.Black,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public bool OnPressed(GlobalAction action)
|
||||
{
|
||||
if (action != GlobalAction.QuickRetry) return false;
|
||||
|
||||
overlay.FadeIn(activate_delay, Easing.Out);
|
||||
BeginConfirm();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -52,18 +21,8 @@ namespace osu.Game.Screens.Play
|
||||
{
|
||||
if (action != GlobalAction.QuickRetry) return false;
|
||||
|
||||
overlay.FadeOut(fadeout_delay, Easing.Out);
|
||||
AbortConfirm();
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
{
|
||||
base.Update();
|
||||
if (!fired && overlay.Alpha == 1)
|
||||
{
|
||||
fired = true;
|
||||
Action?.Invoke();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,7 +162,7 @@ namespace osu.Game.Screens.Play
|
||||
hudOverlay.KeyCounter.IsCounting = pauseContainer.IsPaused;
|
||||
},
|
||||
OnResume = () => hudOverlay.KeyCounter.IsCounting = true,
|
||||
Children = new Drawable[]
|
||||
Children = new[]
|
||||
{
|
||||
storyboardContainer = new Container
|
||||
{
|
||||
@@ -174,12 +174,12 @@ namespace osu.Game.Screens.Play
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Child = RulesetContainer
|
||||
},
|
||||
new SkipOverlay(firstObjectTime)
|
||||
new BreakOverlay(beatmap.BeatmapInfo.LetterboxInBreaks, scoreProcessor)
|
||||
{
|
||||
Clock = Clock, // skip button doesn't want to use the audio clock directly
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
ProcessCustomClock = false,
|
||||
AdjustableClock = adjustableClock,
|
||||
FramedClock = offsetClock,
|
||||
Breaks = beatmap.Breaks
|
||||
},
|
||||
hudOverlay = new HUDOverlay(scoreProcessor, RulesetContainer, working, offsetClock, adjustableClock)
|
||||
{
|
||||
@@ -188,13 +188,14 @@ namespace osu.Game.Screens.Play
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre
|
||||
},
|
||||
new BreakOverlay(beatmap.BeatmapInfo.LetterboxInBreaks, scoreProcessor)
|
||||
RulesetContainer.Cursor?.CreateProxy() ?? new Container(),
|
||||
new SkipOverlay(firstObjectTime)
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Clock = Clock, // skip button doesn't want to use the audio clock directly
|
||||
ProcessCustomClock = false,
|
||||
Breaks = beatmap.Breaks
|
||||
}
|
||||
AdjustableClock = adjustableClock,
|
||||
FramedClock = offsetClock,
|
||||
},
|
||||
}
|
||||
},
|
||||
failOverlay = new FailOverlay
|
||||
|
||||
@@ -85,11 +85,13 @@ namespace osu.Game.Screens.Play
|
||||
|
||||
if (currentSecond != previousSecond && songCurrentTime < songLength)
|
||||
{
|
||||
timeCurrent.Text = TimeSpan.FromSeconds(currentSecond).ToString(songCurrentTime < 0 ? @"\-m\:ss" : @"m\:ss");
|
||||
timeLeft.Text = TimeSpan.FromMilliseconds(endTime - AudioClock.CurrentTime).ToString(@"\-m\:ss");
|
||||
timeCurrent.Text = formatTime(TimeSpan.FromSeconds(currentSecond));
|
||||
timeLeft.Text = formatTime(TimeSpan.FromMilliseconds(endTime - AudioClock.CurrentTime));
|
||||
|
||||
previousSecond = currentSecond;
|
||||
}
|
||||
}
|
||||
|
||||
private string formatTime(TimeSpan timeSpan) => $"{(timeSpan < TimeSpan.Zero ? "-" : "")}{timeSpan.Duration().TotalMinutes:N0}:{timeSpan.Duration().Seconds:D2}";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,17 +88,27 @@ namespace osu.Game.Screens.Select
|
||||
|
||||
private void loadBeatmap()
|
||||
{
|
||||
void updateState()
|
||||
{
|
||||
State = beatmap == null ? Visibility.Hidden : Visibility.Visible;
|
||||
|
||||
Info?.FadeOut(250);
|
||||
Info?.Expire();
|
||||
}
|
||||
|
||||
if (beatmap == null)
|
||||
{
|
||||
updateState();
|
||||
return;
|
||||
}
|
||||
|
||||
LoadComponentAsync(new BufferedWedgeInfo(beatmap, ruleset.Value)
|
||||
{
|
||||
Shear = -Shear,
|
||||
Depth = Info?.Depth + 1 ?? 0,
|
||||
}, newInfo =>
|
||||
{
|
||||
State = beatmap == null ? Visibility.Hidden : Visibility.Visible;
|
||||
|
||||
Info?.FadeOut(250);
|
||||
Info?.Expire();
|
||||
|
||||
updateState();
|
||||
Add(Info = newInfo);
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user