Compare commits
681 Commits
@@ -21,7 +21,7 @@
|
||||
]
|
||||
},
|
||||
"ppy.localisationanalyser.tools": {
|
||||
"version": "2024.802.0",
|
||||
"version": "2025.1208.0",
|
||||
"commands": [
|
||||
"localisation"
|
||||
]
|
||||
|
||||
@@ -73,6 +73,9 @@ Aside from the above, below is a brief checklist of things to watch out when you
|
||||
After you're done with your changes and you wish to open the PR, please observe the following recommendations:
|
||||
|
||||
- Please submit the pull request from a [topic branch](https://git-scm.com/book/en/v2/Git-Branching-Branching-Workflows#_topic_branch) (not `master`), and keep the *Allow edits from maintainers* check box selected, so that we can push fixes to your PR if necessary.
|
||||
- Please pick the following target branch for your pull request:
|
||||
- `pp-dev`, if the change impacts star rating or performance points calculations for any of the rulesets,
|
||||
- `master`, otherwise.
|
||||
- Please avoid pushing untested or incomplete code.
|
||||
- Please do not force-push or rebase unless we ask you to.
|
||||
- Please do not merge `master` continually if there are no conflicts to resolve. We will do this for you when the change is ready for merge.
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<EmbedAssembliesIntoApk>true</EmbedAssembliesIntoApk>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ppy.osu.Framework.Android" Version="2025.1008.0" />
|
||||
<PackageReference Include="ppy.osu.Framework.Android" Version="2025.1229.0" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup>
|
||||
<!-- Fody does not handle Android build well, and warns when unchanged.
|
||||
|
||||
@@ -189,7 +189,7 @@ namespace osu.Desktop
|
||||
}
|
||||
|
||||
// user party
|
||||
if (!hideIdentifiableInformation && multiplayerClient.Room != null)
|
||||
if (!hideIdentifiableInformation && multiplayerClient.Room != null && multiplayerClient.Room.Settings.MatchType != MatchType.Matchmaking)
|
||||
{
|
||||
MultiplayerRoom room = multiplayerClient.Room;
|
||||
|
||||
|
||||
@@ -300,7 +300,7 @@ namespace osu.Game.Rulesets.Catch
|
||||
Description = "Affects how early fruits fade in on the screen.",
|
||||
AdditionalMetrics =
|
||||
[
|
||||
new RulesetBeatmapAttribute.AdditionalMetric("Fade-in time", LocalisableString.Interpolate($@"{IBeatmapDifficultyInfo.DifficultyRange(effectiveDifficulty.ApproachRate, CatchHitObject.PREEMPT_RANGE):#,0.##} ms"))
|
||||
new RulesetBeatmapAttribute.AdditionalMetric("Fade-in time", LocalisableString.Interpolate($@"{IBeatmapDifficultyInfo.DifficultyRangeInt(effectiveDifficulty.ApproachRate, CatchHitObject.PREEMPT_RANGE):#,0.##} ms"))
|
||||
]
|
||||
};
|
||||
yield return new RulesetBeatmapAttribute(SongSelectStrings.HPDrain, @"HP", originalDifficulty.DrainRate, effectiveDifficulty.DrainRate, 10)
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace osu.Game.Rulesets.Catch.Difficulty
|
||||
|
||||
private float halfCatcherWidth;
|
||||
|
||||
public override int Version => 20250306;
|
||||
public override int Version => 20251020;
|
||||
|
||||
public CatchDifficultyCalculator(IRulesetInfo ruleset, IWorkingBeatmap beatmap)
|
||||
: base(ruleset, beatmap)
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace osu.Game.Rulesets.Catch.Edit.Blueprints
|
||||
private double placementStartTime;
|
||||
private double placementEndTime;
|
||||
|
||||
protected override bool IsValidForPlacement => Precision.DefinitelyBigger(HitObject.Duration, 0);
|
||||
protected override bool IsValidForPlacement => base.IsValidForPlacement && (PlacementActive == PlacementState.Waiting || Precision.DefinitelyBigger(HitObject.Duration, 0));
|
||||
|
||||
public BananaShowerPlacementBlueprint()
|
||||
{
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace osu.Game.Rulesets.Catch.Edit.Blueprints
|
||||
|
||||
private InputManager inputManager = null!;
|
||||
|
||||
protected override bool IsValidForPlacement => Precision.DefinitelyBigger(HitObject.Duration, 0);
|
||||
protected override bool IsValidForPlacement => base.IsValidForPlacement && (PlacementActive == PlacementState.Waiting || Precision.DefinitelyBigger(HitObject.Duration, 0));
|
||||
|
||||
public JuiceStreamPlacementBlueprint()
|
||||
{
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using osu.Framework.Allocation;
|
||||
@@ -224,7 +225,8 @@ namespace osu.Game.Rulesets.Catch.Edit
|
||||
#region Clipboard handling
|
||||
|
||||
public override string ConvertSelectionToString()
|
||||
=> string.Join(',', EditorBeatmap.SelectedHitObjects.Cast<CatchHitObject>().OrderBy(h => h.StartTime).Select(h => (h.IndexInCurrentCombo + 1).ToString()));
|
||||
=> string.Join(',', EditorBeatmap.SelectedHitObjects.Cast<CatchHitObject>().OrderBy(h => h.StartTime)
|
||||
.Select(h => (h.IndexInCurrentCombo + 1).ToString(CultureInfo.InvariantCulture)));
|
||||
|
||||
// 1,2,3,4 ...
|
||||
private static readonly Regex selection_regex = new Regex(@"^\d+(,\d+)*$", RegexOptions.Compiled);
|
||||
|
||||
@@ -51,7 +51,8 @@ namespace osu.Game.Rulesets.Catch.Mods
|
||||
|
||||
return string.Empty;
|
||||
|
||||
string format(string acronym, DifficultyBindable bindable) => $"{acronym}{bindable.Value!.Value.ToStandardFormattedString(1)}";
|
||||
string format(string acronym, DifficultyBindable bindable)
|
||||
=> $"{acronym}{bindable.Value!.Value.ToStandardFormattedString(1)}";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using osu.Game.Audio;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Rulesets.Catch.Judgements;
|
||||
using osu.Game.Rulesets.Judgements;
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
@@ -53,13 +54,25 @@ namespace osu.Game.Rulesets.Catch.Objects
|
||||
|
||||
public override IEnumerable<string> LookupNames => lookup_names;
|
||||
|
||||
public BananaHitSampleInfo(int volume = 100)
|
||||
: base(string.Empty, volume: volume)
|
||||
public BananaHitSampleInfo()
|
||||
: this(string.Empty)
|
||||
{
|
||||
}
|
||||
|
||||
public sealed override HitSampleInfo With(Optional<string> newName = default, Optional<string> newBank = default, Optional<string?> newSuffix = default, Optional<int> newVolume = default, Optional<bool> newEditorAutoBank = default)
|
||||
=> new BananaHitSampleInfo(newVolume.GetOr(Volume));
|
||||
public BananaHitSampleInfo(HitSampleInfo info)
|
||||
: this(info.Name, info.Bank, info.Suffix, info.Volume, info.EditorAutoBank, info.UseBeatmapSamples)
|
||||
{
|
||||
}
|
||||
|
||||
private BananaHitSampleInfo(string name, string bank = SampleControlPoint.DEFAULT_BANK, string? suffix = null, int volume = 100, bool editorAutoBank = true, bool useBeatmapSamples = false)
|
||||
: base(name, bank, suffix, volume, editorAutoBank, useBeatmapSamples)
|
||||
{
|
||||
}
|
||||
|
||||
public sealed override HitSampleInfo With(Optional<string> newName = default, Optional<string> newBank = default, Optional<string?> newSuffix = default, Optional<int> newVolume = default,
|
||||
Optional<bool> newEditorAutoBank = default, Optional<bool> newUseBeatmapSamples = default)
|
||||
=> new BananaHitSampleInfo(newName.GetOr(Name), newBank.GetOr(Bank), newSuffix.GetOr(Suffix), newVolume.GetOr(Volume),
|
||||
newEditorAutoBank.GetOr(EditorAutoBank), newUseBeatmapSamples.GetOr(UseBeatmapSamples));
|
||||
|
||||
public bool Equals(BananaHitSampleInfo? other)
|
||||
=> other != null;
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace osu.Game.Rulesets.Catch.Objects
|
||||
{
|
||||
StartTime = time,
|
||||
BananaIndex = count,
|
||||
Samples = new List<HitSampleInfo> { new Banana.BananaHitSampleInfo(CreateHitSampleInfo().Volume) }
|
||||
Samples = new List<HitSampleInfo> { new Banana.BananaHitSampleInfo(CreateHitSampleInfo()) }
|
||||
});
|
||||
|
||||
count++;
|
||||
|
||||
@@ -150,7 +150,7 @@ namespace osu.Game.Rulesets.Catch.Objects
|
||||
{
|
||||
base.ApplyDefaultsToSelf(controlPointInfo, difficulty);
|
||||
|
||||
TimePreempt = (float)IBeatmapDifficultyInfo.DifficultyRange(difficulty.ApproachRate, PREEMPT_RANGE);
|
||||
TimePreempt = IBeatmapDifficultyInfo.DifficultyRangeInt(difficulty.ApproachRate, PREEMPT_RANGE);
|
||||
|
||||
Scale = LegacyRulesetExtensions.CalculateScaleFromCircleSize(difficulty.CircleSize);
|
||||
}
|
||||
|
||||
@@ -72,6 +72,9 @@ namespace osu.Game.Rulesets.Catch.Skinning.Legacy
|
||||
leaderboard.Origin = Anchor.CentreLeft;
|
||||
leaderboard.X = 10;
|
||||
}
|
||||
|
||||
foreach (var d in container.OfType<ISerialisableDrawable>())
|
||||
d.UsesFixedAnchor = true;
|
||||
})
|
||||
{
|
||||
Children = new Drawable[]
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Extensions.IEnumerableExtensions;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Rulesets.Edit;
|
||||
@@ -16,6 +17,7 @@ using osu.Game.Rulesets.Objects;
|
||||
using osu.Game.Rulesets.Objects.Drawables;
|
||||
using osu.Game.Rulesets.UI;
|
||||
using osu.Game.Rulesets.UI.Scrolling;
|
||||
using osu.Game.Screens.Edit;
|
||||
using osu.Game.Tests.Visual;
|
||||
using osuTK.Input;
|
||||
|
||||
@@ -36,21 +38,8 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor
|
||||
[Test]
|
||||
public void TestPlaceBeforeCurrentTimeDownwards()
|
||||
{
|
||||
AddStep("seek to 200", () => HitObjectContainer.Dependencies.Get<EditorClock>().Seek(200));
|
||||
AddStep("move mouse before current time", () =>
|
||||
{
|
||||
var column = this.ChildrenOfType<Column>().Single();
|
||||
InputManager.MoveMouseTo(column.ScreenSpacePositionAtTime(-100));
|
||||
});
|
||||
|
||||
AddStep("click", () => InputManager.Click(MouseButton.Left));
|
||||
|
||||
AddAssert("note start time < 0", () => getNote().StartTime < 0);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestPlaceAfterCurrentTimeDownwards()
|
||||
{
|
||||
AddStep("move mouse after current time", () =>
|
||||
{
|
||||
var column = this.ChildrenOfType<Column>().Single();
|
||||
InputManager.MoveMouseTo(column.ScreenSpacePositionAtTime(100));
|
||||
@@ -58,7 +47,22 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor
|
||||
|
||||
AddStep("click", () => InputManager.Click(MouseButton.Left));
|
||||
|
||||
AddAssert("note start time > 0", () => getNote().StartTime > 0);
|
||||
AddAssert("note start time < 200", () => getNote().StartTime < 200);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestPlaceAfterCurrentTimeDownwards()
|
||||
{
|
||||
AddStep("seek to 200", () => HitObjectContainer.Dependencies.Get<EditorClock>().Seek(200));
|
||||
AddStep("move mouse after current time", () =>
|
||||
{
|
||||
var column = this.ChildrenOfType<Column>().Single();
|
||||
InputManager.MoveMouseTo(column.ScreenSpacePositionAtTime(300));
|
||||
});
|
||||
|
||||
AddStep("click", () => InputManager.Click(MouseButton.Left));
|
||||
|
||||
AddAssert("note start time > 200", () => getNote().StartTime > 200);
|
||||
}
|
||||
|
||||
private Note getNote() => this.ChildrenOfType<DrawableNote>().FirstOrDefault()?.HitObject;
|
||||
|
||||
@@ -18,15 +18,11 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor
|
||||
public void TestNormalSelection()
|
||||
{
|
||||
addStepClickLink("00:05:920 (5920|3,6623|3,6857|2,7326|1)");
|
||||
AddAssert("selected group", () => checkSnapAndSelectColumn(5_920, new List<(int, int)>
|
||||
{ (5_920, 3), (6_623, 3), (6_857, 2), (7_326, 1) }
|
||||
));
|
||||
AddAssert("selected group", () => checkSnapAndSelectColumn(5_920, [(5_920, 3), (6_623, 3), (6_857, 2), (7_326, 1)]));
|
||||
|
||||
addReset();
|
||||
addStepClickLink("00:42:716 (42716|3,43420|2,44123|0,44357|1,45295|1)");
|
||||
AddAssert("selected ungrouped", () => checkSnapAndSelectColumn(42_716, new List<(int, int)>
|
||||
{ (42_716, 3), (43_420, 2), (44_123, 0), (44_357, 1), (45_295, 1) }
|
||||
));
|
||||
AddAssert("selected ungrouped", () => checkSnapAndSelectColumn(42_716, [(42_716, 3), (43_420, 2), (44_123, 0), (44_357, 1), (45_295, 1)]));
|
||||
|
||||
addReset();
|
||||
AddStep("add notes to row", () =>
|
||||
@@ -41,15 +37,20 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor
|
||||
EditorBeatmap.AddRange(new[] { second, third, forth });
|
||||
});
|
||||
addStepClickLink("00:11:545 (11545|0,11545|1,11545|2,11545|3)");
|
||||
AddAssert("selected in row", () => checkSnapAndSelectColumn(11_545, new List<(int, int)>
|
||||
{ (11_545, 0), (11_545, 1), (11_545, 2), (11_545, 3) }
|
||||
));
|
||||
AddAssert("selected in row", () => checkSnapAndSelectColumn(11_545, [(11_545, 0), (11_545, 1), (11_545, 2), (11_545, 3)]));
|
||||
|
||||
addReset();
|
||||
addStepClickLink("01:36:623 (96623|1,97560|1,97677|1,97795|1,98966|1)");
|
||||
AddAssert("selected in column", () => checkSnapAndSelectColumn(96_623, new List<(int, int)>
|
||||
{ (96_623, 1), (97_560, 1), (97_677, 1), (97_795, 1), (98_966, 1) }
|
||||
));
|
||||
AddAssert("selected in column", () => checkSnapAndSelectColumn(96_623, [(96_623, 1), (97_560, 1), (97_677, 1), (97_795, 1), (98_966, 1)]));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestRoundingToNearestMillisecondApplied()
|
||||
{
|
||||
AddStep("resnap note to have fractional coordinates",
|
||||
() => EditorBeatmap.HitObjects.OfType<ManiaHitObject>().Single(ho => ho.StartTime == 85_373 && ho.Column == 1).StartTime = 85_373.125);
|
||||
addStepClickLink("01:25:373 (85373|1)");
|
||||
AddAssert("selected note", () => checkSnapAndSelectColumn(85_373.125, [(85_373.125, 1)]));
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -75,7 +76,7 @@ namespace osu.Game.Rulesets.Mania.Tests.Editor
|
||||
|
||||
private void addReset() => addStepClickLink("00:00:000", "reset", false);
|
||||
|
||||
private bool checkSnapAndSelectColumn(double startTime, IReadOnlyCollection<(int, int)>? columnPairs = null)
|
||||
private bool checkSnapAndSelectColumn(double startTime, IReadOnlyCollection<(double, int)>? columnPairs = null)
|
||||
{
|
||||
bool checkColumns = columnPairs != null
|
||||
? EditorBeatmap.SelectedHitObjects.All(x => columnPairs.Any(col => isNoteAt(x, col.Item1, col.Item2)))
|
||||
|
||||
@@ -24,6 +24,7 @@ namespace osu.Game.Rulesets.Mania.Tests
|
||||
[TestCase("mania-samples")]
|
||||
[TestCase("mania-slider")] // e.g. second and fourth notes of https://osu.ppy.sh/beatmapsets/73883#mania/216407
|
||||
[TestCase("slider-convert-samples")]
|
||||
[TestCase("spinner-convert-samples")]
|
||||
public void Test(string name) => base.Test(name);
|
||||
|
||||
protected override IEnumerable<SampleConvertValue> CreateConvertValue(HitObject hitObject)
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
osu file format v14
|
||||
|
||||
[General]
|
||||
Mode: 0
|
||||
|
||||
[TimingPoints]
|
||||
0,300,4,0,2,100,1,0
|
||||
|
||||
[HitObjects]
|
||||
444,320,1000,5,2,0:0:0:0:
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"Mappings": [{
|
||||
"StartTime": 1000.0,
|
||||
"Objects": [{
|
||||
"StartTime": 1000.0,
|
||||
"EndTime": 8000.0,
|
||||
"Column": 0,
|
||||
"PlaySlidingSamples": false,
|
||||
"NodeSamples": [
|
||||
["Gameplay/soft-hitnormal"],
|
||||
["Gameplay/soft-hitnormal", "Gameplay/soft-hitfinish"]
|
||||
],
|
||||
"Samples": ["Gameplay/soft-hitnormal", "Gameplay/soft-hitfinish"],
|
||||
}]
|
||||
}]
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
osu file format v14
|
||||
|
||||
[General]
|
||||
Mode: 0
|
||||
|
||||
[Difficulty]
|
||||
HPDrainRate:5
|
||||
CircleSize:5
|
||||
OverallDifficulty:5
|
||||
ApproachRate:5
|
||||
SliderMultiplier:1.4
|
||||
SliderTickRate:1
|
||||
|
||||
[TimingPoints]
|
||||
0,500,4,2,0,100,1,0
|
||||
|
||||
[HitObjects]
|
||||
256,192,1000,8,4,8000,0:2:0:0:
|
||||
@@ -45,5 +45,19 @@ namespace osu.Game.Rulesets.Mania.Tests
|
||||
AssertBeatmapLookup(expected_sample);
|
||||
AssertNoLookup(unwanted_sample);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestConvertHitObjectCustomSampleBank()
|
||||
{
|
||||
const string beatmap_sample = "normal-hitwhistle2";
|
||||
const string user_skin_sample = "normal-hitnormal";
|
||||
|
||||
SetupSkins(beatmap_sample, user_skin_sample);
|
||||
|
||||
CreateTestWithBeatmap("convert-beatmap-custom-sample-bank.osu");
|
||||
|
||||
AssertBeatmapLookup(beatmap_sample);
|
||||
AssertUserLookup(user_skin_sample);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,7 +85,11 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
|
||||
Duration = endTime - HitObject.StartTime,
|
||||
Column = column,
|
||||
Samples = HitObject.Samples,
|
||||
NodeSamples = (HitObject as IHasRepeats)?.NodeSamples
|
||||
NodeSamples =
|
||||
[
|
||||
HitObject.Samples.Where(s => s.Name == HitSampleInfo.HIT_NORMAL).ToList(),
|
||||
HitObject.Samples
|
||||
]
|
||||
};
|
||||
}
|
||||
else
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace osu.Game.Rulesets.Mania.Edit.Blueprints
|
||||
[Resolved]
|
||||
private IScrollingInfo scrollingInfo { get; set; } = null!;
|
||||
|
||||
protected override bool IsValidForPlacement => Precision.DefinitelyBigger(HitObject.Duration, 0);
|
||||
protected override bool IsValidForPlacement => base.IsValidForPlacement && (PlacementActive == PlacementState.Waiting || Precision.DefinitelyBigger(HitObject.Duration, 0));
|
||||
|
||||
public HoldNotePlacementBlueprint()
|
||||
: base(new HoldNote())
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
// 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.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Utils;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Rulesets.Edit;
|
||||
using osu.Game.Rulesets.Edit.Tools;
|
||||
@@ -54,7 +56,8 @@ namespace osu.Game.Rulesets.Mania.Edit
|
||||
};
|
||||
|
||||
public override string ConvertSelectionToString()
|
||||
=> string.Join(',', EditorBeatmap.SelectedHitObjects.Cast<ManiaHitObject>().OrderBy(h => h.StartTime).Select(h => $"{h.StartTime}|{h.Column}"));
|
||||
=> string.Join(',', EditorBeatmap.SelectedHitObjects.Cast<ManiaHitObject>().OrderBy(h => h.StartTime)
|
||||
.Select(h => FormattableString.Invariant($"{Math.Round(h.StartTime)}|{h.Column}")));
|
||||
|
||||
// 123|0,456|1,789|2 ...
|
||||
private static readonly Regex selection_regex = new Regex(@"^\d+\|\d+(,\d+\|\d+)*$", RegexOptions.Compiled);
|
||||
@@ -73,10 +76,10 @@ namespace osu.Game.Rulesets.Mania.Edit
|
||||
if (split.Length != 2)
|
||||
continue;
|
||||
|
||||
if (!double.TryParse(split[0], out double time) || !int.TryParse(split[1], out int column))
|
||||
if (!int.TryParse(split[0], out int time) || !int.TryParse(split[1], out int column))
|
||||
continue;
|
||||
|
||||
ManiaHitObject? current = remainingHitObjects.FirstOrDefault(h => h.StartTime == time && h.Column == column);
|
||||
ManiaHitObject? current = remainingHitObjects.FirstOrDefault(h => Precision.AlmostEquals(h.StartTime, time, 0.5) && h.Column == column);
|
||||
|
||||
if (current == null)
|
||||
continue;
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace osu.Game.Rulesets.Mania.Mods
|
||||
typeof(ManiaModFadeIn)
|
||||
}).ToArray();
|
||||
|
||||
public override bool Ranked => false;
|
||||
public override bool Ranked => true;
|
||||
|
||||
public override bool ValidForFreestyleAsRequiredMod => false;
|
||||
|
||||
|
||||
@@ -7,5 +7,15 @@ namespace osu.Game.Rulesets.Mania.Mods
|
||||
{
|
||||
public class ManiaModDifficultyAdjust : ModDifficultyAdjust
|
||||
{
|
||||
public override DifficultyBindable OverallDifficulty { get; } = new DifficultyBindable
|
||||
{
|
||||
Precision = 0.1f,
|
||||
MinValue = 0,
|
||||
MaxValue = 10,
|
||||
// Use larger extended limits for mania to include OD values that occur with EZ or HR enabled
|
||||
ExtendedMaxValue = 15,
|
||||
ExtendedMinValue = -15,
|
||||
ReadCurrentFromDifficulty = diff => diff.OverallDifficulty,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ using osu.Game.Rulesets.Mods;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Localisation;
|
||||
using osu.Framework.Utils;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets.Mania.Beatmaps;
|
||||
|
||||
@@ -34,6 +35,8 @@ namespace osu.Game.Rulesets.Mania.Mods
|
||||
{
|
||||
var maniaBeatmap = (ManiaBeatmap)beatmap;
|
||||
|
||||
double mostCommonBeatLengthBefore = beatmap.GetMostCommonBeatLength();
|
||||
|
||||
var newObjects = new List<ManiaHitObject>();
|
||||
|
||||
foreach (var h in beatmap.HitObjects.OfType<HoldNote>())
|
||||
@@ -48,6 +51,17 @@ namespace osu.Game.Rulesets.Mania.Mods
|
||||
}
|
||||
|
||||
maniaBeatmap.HitObjects = maniaBeatmap.HitObjects.OfType<Note>().Concat(newObjects).OrderBy(h => h.StartTime).ToList();
|
||||
|
||||
double mostCommonBeatLengthAfter = beatmap.GetMostCommonBeatLength();
|
||||
|
||||
// the process of removing hold notes can result in shortening the beatmap's play time,
|
||||
// and therefore, as a side effect, changing the most common BPM, which will change scroll speed.
|
||||
// to compensate for this, apply a multiplier to effect points in order to maintain the beatmap's original intended scroll speed.
|
||||
if (!Precision.AlmostEquals(mostCommonBeatLengthBefore, mostCommonBeatLengthAfter))
|
||||
{
|
||||
foreach (var effectPoint in beatmap.ControlPointInfo.EffectPoints)
|
||||
effectPoint.ScrollSpeed *= mostCommonBeatLengthBefore / mostCommonBeatLengthAfter;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,6 +57,9 @@ namespace osu.Game.Rulesets.Mania.Skinning.Argon
|
||||
|
||||
if (spectatorList != null)
|
||||
spectatorList.Position = new Vector2(36, -66);
|
||||
|
||||
foreach (var d in container.OfType<ISerialisableDrawable>())
|
||||
d.UsesFixedAnchor = true;
|
||||
})
|
||||
{
|
||||
new DrawableGameplayLeaderboard(),
|
||||
|
||||
@@ -64,11 +64,13 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy
|
||||
private readonly Lazy<bool> hasKeyTexture;
|
||||
|
||||
private readonly ManiaBeatmap beatmap;
|
||||
private readonly bool isBeatmapConverted;
|
||||
|
||||
public ManiaLegacySkinTransformer(ISkin skin, IBeatmap beatmap)
|
||||
: base(skin)
|
||||
{
|
||||
this.beatmap = (ManiaBeatmap)beatmap;
|
||||
isBeatmapConverted = !beatmap.BeatmapInfo.Ruleset.Equals(new ManiaRuleset().RulesetInfo);
|
||||
|
||||
isLegacySkin = new Lazy<bool>(() => GetConfig<SkinConfiguration.LegacySetting, decimal>(SkinConfiguration.LegacySetting.Version) != null);
|
||||
hasKeyTexture = new Lazy<bool>(() =>
|
||||
@@ -120,6 +122,9 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy
|
||||
leaderboard.Origin = Anchor.CentreLeft;
|
||||
leaderboard.X = 10;
|
||||
}
|
||||
|
||||
foreach (var d in container.OfType<ISerialisableDrawable>())
|
||||
d.UsesFixedAnchor = true;
|
||||
})
|
||||
{
|
||||
new LegacyManiaComboCounter(),
|
||||
@@ -196,8 +201,8 @@ namespace osu.Game.Rulesets.Mania.Skinning.Legacy
|
||||
|
||||
public override ISample GetSample(ISampleInfo sampleInfo)
|
||||
{
|
||||
// layered hit sounds never play in mania
|
||||
if (sampleInfo is ConvertHitObjectParser.LegacyHitSampleInfo legacySample && legacySample.IsLayered)
|
||||
// layered hit sounds never play in mania-native beatmaps (but do play on converts)
|
||||
if (sampleInfo is ConvertHitObjectParser.LegacyHitSampleInfo legacySample && legacySample.IsLayered && !isBeatmapConverted)
|
||||
return new SampleVirtual();
|
||||
|
||||
return base.GetSample(sampleInfo);
|
||||
|
||||
@@ -245,13 +245,13 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor
|
||||
AddAssert("grid spacing is distance to slider tail", () =>
|
||||
{
|
||||
var composer = Editor.ChildrenOfType<RectangularPositionSnapGrid>().Single();
|
||||
return Precision.AlmostEquals(composer.Spacing.Value.X, 32.05, 0.01)
|
||||
return Precision.AlmostEquals(composer.Spacing.Value.X, 32.05, 0.1)
|
||||
&& Precision.AlmostEquals(composer.Spacing.Value.X, composer.Spacing.Value.Y);
|
||||
});
|
||||
AddAssert("grid rotation points to slider tail", () =>
|
||||
{
|
||||
var composer = Editor.ChildrenOfType<RectangularPositionSnapGrid>().Single();
|
||||
return Precision.AlmostEquals(composer.GridLineRotation.Value, 0.09, 0.01);
|
||||
return Precision.AlmostEquals(composer.GridLineRotation.Value, 0.09, 0.1);
|
||||
});
|
||||
|
||||
AddStep("start grid placement", () => InputManager.Key(Key.Number5));
|
||||
@@ -280,9 +280,9 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor
|
||||
AddAssert("grid spacing and rotation unchanged", () =>
|
||||
{
|
||||
var composer = Editor.ChildrenOfType<RectangularPositionSnapGrid>().Single();
|
||||
return Precision.AlmostEquals(composer.Spacing.Value.X, 32.05, 0.01)
|
||||
return Precision.AlmostEquals(composer.Spacing.Value.X, 32.05, 0.1)
|
||||
&& Precision.AlmostEquals(composer.Spacing.Value.X, composer.Spacing.Value.Y)
|
||||
&& Precision.AlmostEquals(composer.GridLineRotation.Value, 0.09, 0.01);
|
||||
&& Precision.AlmostEquals(composer.GridLineRotation.Value, 0.09, 0.1);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Input;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders;
|
||||
using osu.Game.Rulesets.Osu.Objects;
|
||||
using osu.Game.Rulesets.UI;
|
||||
@@ -22,7 +23,12 @@ namespace osu.Game.Rulesets.Osu.Tests.Editor
|
||||
[TestFixture]
|
||||
public partial class TestSceneSliderDrawing : TestSceneOsuEditor
|
||||
{
|
||||
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) => new TestBeatmap(ruleset, false);
|
||||
protected override IBeatmap CreateBeatmap(RulesetInfo ruleset)
|
||||
{
|
||||
var beatmap = new TestBeatmap(ruleset, false);
|
||||
beatmap.ControlPointInfo.Add(0, new TimingControlPoint());
|
||||
return beatmap;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestTouchInputPlaceHitCircleDirectly()
|
||||
|
||||
@@ -27,6 +27,9 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
[TestCase("multi-segment-slider")]
|
||||
[TestCase("nan-slider")]
|
||||
[TestCase("1124896")]
|
||||
[TestCase("1341554")]
|
||||
[TestCase("2593923")]
|
||||
[TestCase("801165")]
|
||||
public void Test(string name) => base.Test(name);
|
||||
|
||||
protected override IEnumerable<ConvertValue> CreateConvertValue(HitObject hitObject)
|
||||
|
||||
@@ -0,0 +1,941 @@
|
||||
osu file format v14
|
||||
|
||||
[General]
|
||||
AudioLeadIn: 0
|
||||
PreviewTime: 76429
|
||||
Countdown: 0
|
||||
SampleSet: Soft
|
||||
StackLeniency: 0.2
|
||||
Mode: 0
|
||||
LetterboxInBreaks: 0
|
||||
WidescreenStoryboard: 1
|
||||
|
||||
[Difficulty]
|
||||
HPDrainRate:5
|
||||
CircleSize:4.3
|
||||
OverallDifficulty:8
|
||||
ApproachRate:9.3
|
||||
SliderMultiplier:2.99999995231628
|
||||
SliderTickRate:1
|
||||
|
||||
[Events]
|
||||
//Background and Video events
|
||||
//Break Periods
|
||||
//Storyboard Layer 0 (Background)
|
||||
//Storyboard Layer 1 (Fail)
|
||||
//Storyboard Layer 2 (Pass)
|
||||
//Storyboard Layer 3 (Foreground)
|
||||
//Storyboard Sound Samples
|
||||
|
||||
[TimingPoints]
|
||||
763,444.444444444444,4,2,1,60,1,0
|
||||
763,-111.111111111111,4,2,1,60,0,0
|
||||
1929,-100,4,2,1,5,0,0
|
||||
1985,-100,4,2,1,60,0,0
|
||||
2040,-100,4,2,1,5,0,0
|
||||
2096,-153.846153846153,4,2,1,60,0,0
|
||||
2429,-133.333333333333,4,2,1,5,0,0
|
||||
2540,-71.4285714285714,4,2,1,70,0,1
|
||||
2985,-100,4,2,1,70,0,1
|
||||
4485,-100,4,2,1,5,0,1
|
||||
4540,-100,4,2,1,70,0,1
|
||||
4707,-100,4,2,1,5,0,1
|
||||
4762,-100,4,2,1,70,0,1
|
||||
4929,-100,4,2,1,5,0,1
|
||||
4985,-100,4,2,1,70,0,1
|
||||
5096,-83.3333333333333,4,2,1,70,0,1
|
||||
5429,-133.333333333333,4,2,1,70,0,1
|
||||
5596,-133.333333333333,4,2,1,70,0,1
|
||||
5652,-133.333333333333,4,2,1,70,0,1
|
||||
5818,-133.333333333333,4,2,1,70,0,1
|
||||
5874,-133.333333333333,4,2,1,70,0,1
|
||||
6040,-133.333333333333,4,2,1,70,0,1
|
||||
6096,-100,4,2,1,70,0,1
|
||||
6540,-100,4,2,1,70,0,1
|
||||
8040,-100,4,2,1,5,0,1
|
||||
8096,-100,4,2,1,70,0,1
|
||||
8262,-100,4,2,1,5,0,1
|
||||
8318,-100,4,2,1,70,0,1
|
||||
8485,-100,4,2,1,5,0,1
|
||||
8540,-133.333333333333,4,2,1,70,0,1
|
||||
8874,-100,4,2,1,5,0,1
|
||||
8985,-100,4,2,1,70,0,1
|
||||
9651,-100,4,2,1,70,0,1
|
||||
10096,-100,4,2,1,70,0,1
|
||||
11596,-100,4,2,1,5,0,1
|
||||
11651,-100,4,2,1,70,0,1
|
||||
11818,-100,4,2,1,5,0,1
|
||||
11873,-100,4,2,1,70,0,1
|
||||
11874,-80,4,2,1,70,0,1
|
||||
12040,-80,4,2,1,5,0,1
|
||||
12096,-80,4,2,1,70,0,1
|
||||
12207,-133.333333333333,4,2,1,70,0,1
|
||||
12429,-100,4,2,1,5,0,1
|
||||
12540,-100,4,2,1,70,0,1
|
||||
12707,-100,4,2,1,70,0,1
|
||||
12763,-100,4,2,1,70,0,1
|
||||
12929,-100,4,2,1,70,0,1
|
||||
12985,-100,4,2,1,70,0,1
|
||||
13429,-300,4,2,1,70,0,1
|
||||
13651,-83.3333333333333,4,2,1,70,0,1
|
||||
13874,-100,4,2,1,70,0,1
|
||||
15151,-100,4,2,1,5,0,1
|
||||
15207,-100,4,2,1,70,0,1
|
||||
15373,-100,4,2,1,5,0,1
|
||||
15429,-100,4,2,1,70,0,1
|
||||
15596,-100,4,2,1,5,0,1
|
||||
15651,-100,4,2,1,70,0,1
|
||||
15985,-100,4,2,1,5,0,1
|
||||
16096,-100,4,2,1,70,0,1
|
||||
16262,-100,4,2,1,70,0,1
|
||||
16318,-83.3333333333333,4,2,1,70,0,1
|
||||
16651,-100,4,2,1,70,0,1
|
||||
16762,-133.333333333333,4,2,1,60,0,0
|
||||
17096,-133.333333333333,4,2,1,5,0,0
|
||||
17207,-200,4,2,1,60,0,0
|
||||
18096,-66.6666666666667,4,2,1,60,0,0
|
||||
18262,-66.6666666666667,4,2,1,5,0,0
|
||||
18318,-66.6666666666667,4,2,1,60,0,0
|
||||
18540,-100,4,2,1,60,0,0
|
||||
18874,-100,4,2,1,5,0,0
|
||||
18985,-100,4,2,1,60,0,0
|
||||
19985,-100,4,2,1,60,0,0
|
||||
20485,-100,4,2,1,5,0,0
|
||||
20540,-100,4,2,1,60,0,0
|
||||
20707,-100,4,2,1,5,0,0
|
||||
20762,-200,4,2,1,60,0,0
|
||||
20985,-100,4,2,1,60,0,0
|
||||
21095,-100,4,2,1,60,0,0
|
||||
21374,-100,4,2,1,5,0,0
|
||||
21429,-100,4,2,1,60,0,0
|
||||
21596,-100,4,2,1,5,0,0
|
||||
21651,-100,4,2,1,60,0,0
|
||||
21818,-100,4,2,1,5,0,0
|
||||
21874,-66.6666666666667,4,2,1,60,0,0
|
||||
21985,-100,4,2,1,60,0,0
|
||||
22096,-100,4,2,1,60,0,0
|
||||
22985,-200,4,2,1,60,0,0
|
||||
23318,-100,4,2,1,60,0,0
|
||||
23429,-100,4,2,1,60,0,0
|
||||
23540,-100,4,2,1,60,0,0
|
||||
23651,-100,4,2,1,60,0,0
|
||||
23762,-100,4,2,1,60,0,0
|
||||
23874,-133.333333333333,4,2,1,60,0,0
|
||||
24208,-133.333333333333,4,2,1,5,0,0
|
||||
24318,-200,4,2,1,5,0,0
|
||||
24319,-200,4,2,1,60,0,0
|
||||
24540,-100,4,2,1,60,0,0
|
||||
24651,-66.6666666666667,4,2,1,60,0,0
|
||||
24874,-100,4,2,1,60,0,0
|
||||
25374,-100,4,2,1,5,0,0
|
||||
25429,-100,4,2,1,60,0,0
|
||||
27096,-100,4,2,1,60,0,0
|
||||
27596,-100,4,2,1,5,0,0
|
||||
27651,-100,4,2,1,60,0,0
|
||||
27818,-100,4,2,1,5,0,0
|
||||
27873,-133.333333333333,4,2,1,60,0,0
|
||||
28096,-100,4,2,1,60,0,0
|
||||
28206,-100,4,2,1,60,0,0
|
||||
28485,-100,4,2,1,5,0,0
|
||||
28540,-100,4,2,1,60,0,0
|
||||
28707,-100,4,2,1,5,0,0
|
||||
28762,-100,4,2,1,60,0,0
|
||||
28929,-100,4,2,1,5,0,0
|
||||
28985,-66.6666666666667,4,2,1,60,0,0
|
||||
29151,-100,4,2,1,60,0,0
|
||||
29207,-100,4,2,1,60,0,0
|
||||
29651,-100,4,2,1,60,0,0
|
||||
30429,-100,4,2,1,60,0,0
|
||||
30540,-58.8235294117647,4,2,1,60,0,0
|
||||
30874,-58.8235294117647,4,2,1,5,0,0
|
||||
30985,-58.8235294117647,4,2,1,60,0,0
|
||||
31040,-100,4,2,1,5,0,0
|
||||
31429,-100,4,2,1,60,0,0
|
||||
32485,-100,4,2,1,60,0,0
|
||||
32540,-100,4,2,1,60,0,0
|
||||
32707,-100,4,2,1,60,0,0
|
||||
32762,-100,4,2,1,60,0,0
|
||||
32985,-100,4,2,1,60,0,0
|
||||
34318,-50,4,2,1,60,0,0
|
||||
34485,-100,4,2,1,5,0,0
|
||||
34540,-100,4,2,1,60,0,0
|
||||
35151,-100,4,2,1,5,0,0
|
||||
35207,-100,4,2,1,60,0,0
|
||||
35374,-100,4,2,1,5,0,0
|
||||
35430,-100,4,2,1,60,0,0
|
||||
35818,-100,4,2,1,5,0,0
|
||||
35874,-200,4,2,1,60,0,0
|
||||
36429,-100,4,2,1,60,0,0
|
||||
37818,-100,4,2,1,5,0,0
|
||||
37874,-100,4,2,1,60,0,0
|
||||
38040,-100,4,2,1,5,0,0
|
||||
38096,-50,4,2,1,60,0,0
|
||||
38151,-100,4,2,1,5,0,0
|
||||
38540,-100,4,2,1,60,0,0
|
||||
39596,-100,4,2,1,5,0,0
|
||||
39651,-100,4,2,1,60,0,0
|
||||
39818,-100,4,2,1,60,0,0
|
||||
39873,-100,4,2,1,60,0,0
|
||||
40096,-100,4,2,1,60,0,0
|
||||
41429,-50,4,2,1,60,0,0
|
||||
41596,-100,4,2,1,5,0,0
|
||||
41651,-100,4,2,1,60,0,0
|
||||
41818,-100,4,2,1,5,0,0
|
||||
41874,-100,4,2,1,60,0,0
|
||||
42040,-100,4,2,1,5,0,0
|
||||
42096,-100,4,2,1,60,0,0
|
||||
44318,-100,4,2,1,60,0,0
|
||||
44762,-83.3333333333333,4,2,1,60,0,0
|
||||
45207,-66.6666666666667,4,2,1,45,0,0
|
||||
45651,-133.333333333333,4,2,1,45,0,0
|
||||
51540,-133.333333333333,4,2,1,50,0,0
|
||||
51651,-133.333333333333,4,2,1,45,0,0
|
||||
52318,-133.333333333333,4,2,1,45,0,0
|
||||
58540,-76.9230769230769,4,2,1,45,0,0
|
||||
58818,-100,4,2,1,45,0,0
|
||||
58874,-111.111111111111,4,2,1,45,0,0
|
||||
59318,-111.111111111111,4,2,1,45,0,0
|
||||
59429,-83.3333333333333,4,2,1,60,0,0
|
||||
59540,-83.3333333333333,4,2,1,5,0,0
|
||||
59874,-100,4,2,1,60,0,0
|
||||
60096,-100,4,2,1,5,0,0
|
||||
60207,-100,4,2,1,60,0,0
|
||||
60707,-100,4,2,1,5,0,0
|
||||
60763,-100,4,2,1,60,0,0
|
||||
60818,-100,4,2,1,5,0,0
|
||||
60874,-100,4,2,1,60,0,0
|
||||
60929,-100,4,2,1,5,0,0
|
||||
60985,-100,4,2,1,60,0,0
|
||||
61040,-100,4,2,1,5,0,0
|
||||
61096,-100,4,2,1,60,0,0
|
||||
61151,-100,4,2,1,5,0,0
|
||||
61207,-100,4,2,1,60,0,0
|
||||
61596,-100,4,2,1,5,0,0
|
||||
61651,-100,4,2,1,60,0,0
|
||||
61762,-83.3333333333333,4,2,1,60,0,0
|
||||
61985,-100,4,2,1,5,0,0
|
||||
62096,-100,4,2,1,60,0,0
|
||||
62151,-100,4,2,1,5,0,0
|
||||
62207,-100,4,2,1,60,0,0
|
||||
62262,-100,4,2,1,5,0,0
|
||||
62318,-100,4,2,1,60,0,0
|
||||
62374,-100,4,2,1,5,0,0
|
||||
62430,-100,4,2,1,60,0,0
|
||||
62485,-100,4,2,1,5,0,0
|
||||
62540,-100,4,2,1,60,0,0
|
||||
62596,-100,4,2,1,5,0,0
|
||||
62651,-100,4,2,1,60,0,0
|
||||
62707,-100,4,2,1,5,0,0
|
||||
62762,-100,4,2,1,60,0,0
|
||||
62818,-100,4,2,1,5,0,0
|
||||
62874,-100,4,2,1,60,0,0
|
||||
62929,-100,4,2,1,60,0,0
|
||||
62930,-100,4,2,1,5,0,0
|
||||
62985,-100,4,2,1,60,0,0
|
||||
63707,-100,4,2,1,5,0,0
|
||||
63762,-100,4,2,1,60,0,0
|
||||
64262,-100,4,2,1,5,0,0
|
||||
64318,-100,4,2,1,60,0,0
|
||||
64485,-100,4,2,1,5,0,0
|
||||
64540,-100,4,2,1,60,0,0
|
||||
64596,-100,4,2,1,5,0,0
|
||||
64651,-100,4,2,1,60,0,0
|
||||
64707,-100,4,2,1,5,0,0
|
||||
64762,-71.4285714285714,4,2,1,60,0,0
|
||||
64929,-71.4285714285714,4,2,1,5,0,0
|
||||
64984,-133.333333333333,4,2,1,60,0,0
|
||||
65151,-133.333333333333,4,2,1,5,0,0
|
||||
65206,-71.4285714285714,4,2,1,60,0,0
|
||||
65374,-71.4285714285714,4,2,1,5,0,0
|
||||
65429,-133.333333333333,4,2,1,60,0,0
|
||||
65596,-133.333333333333,4,2,1,5,0,0
|
||||
65651,-100,4,2,1,60,0,0
|
||||
66540,-66.6666666666667,4,2,1,60,0,0
|
||||
66596,-66.6666666666667,4,2,1,5,0,0
|
||||
66929,-100,4,2,1,5,0,0
|
||||
66985,-200,4,2,1,60,0,0
|
||||
67207,-200,4,2,1,5,0,0
|
||||
67318,-100,4,2,1,60,0,0
|
||||
67818,-100,4,2,1,5,0,0
|
||||
67874,-100,4,2,1,60,0,0
|
||||
67929,-100,4,2,1,5,0,0
|
||||
67985,-100,4,2,1,60,0,0
|
||||
68040,-100,4,2,1,5,0,0
|
||||
68096,-100,4,2,1,60,0,0
|
||||
68151,-100,4,2,1,5,0,0
|
||||
68207,-100,4,2,1,60,0,0
|
||||
68262,-100,4,2,1,5,0,0
|
||||
68318,-100,4,2,1,60,0,0
|
||||
68874,-83.3333333333333,4,2,1,60,0,0
|
||||
69096,-100,4,2,1,60,0,0
|
||||
69097,-100,4,2,1,5,0,0
|
||||
69207,-100,4,2,1,60,0,0
|
||||
69263,-100,4,2,1,5,0,0
|
||||
69319,-100,4,2,1,60,0,0
|
||||
69374,-100,4,2,1,5,0,0
|
||||
69430,-100,4,2,1,60,0,0
|
||||
69486,-100,4,2,1,5,0,0
|
||||
69542,-100,4,2,1,60,0,0
|
||||
69597,-100,4,2,1,5,0,0
|
||||
69651,-100,4,2,1,60,0,0
|
||||
69707,-100,4,2,1,5,0,0
|
||||
69762,-100,4,2,1,60,0,0
|
||||
69818,-100,4,2,1,5,0,0
|
||||
69874,-100,4,2,1,60,0,0
|
||||
69929,-100,4,2,1,5,0,0
|
||||
69985,-100,4,2,1,60,0,0
|
||||
70040,-100,4,2,1,60,0,0
|
||||
70041,-100,4,2,1,5,0,0
|
||||
70096,-100,4,2,1,60,0,0
|
||||
70818,-100,4,2,1,5,0,0
|
||||
70873,-100,4,2,1,60,0,0
|
||||
71207,-71.4285714285714,4,2,1,60,0,0
|
||||
71429,-100,4,2,1,60,0,0
|
||||
71874,-71.4285714285714,4,2,1,60,0,0
|
||||
72041,-71.4285714285714,4,2,1,5,0,0
|
||||
72096,-133.333333333333,4,2,1,60,0,0
|
||||
72263,-133.333333333333,4,2,1,5,0,0
|
||||
72318,-71.4285714285714,4,2,1,60,0,0
|
||||
72485,-71.4285714285714,4,2,1,5,0,0
|
||||
72540,-133.333333333333,4,2,1,60,0,0
|
||||
72985,-66.6666666666667,4,2,1,60,0,0
|
||||
73207,-100,4,2,1,60,0,0
|
||||
73651,-133.333333333333,4,2,1,45,0,0
|
||||
75318,-133.333333333333,4,2,1,5,0,0
|
||||
75429,-133.333333333333,4,2,1,45,0,0
|
||||
76762,-100,4,2,1,45,0,0
|
||||
77096,-100,4,2,1,5,0,0
|
||||
77207,-100,4,2,1,70,0,1
|
||||
77818,-100,4,2,1,5,0,1
|
||||
77874,-100,4,2,1,70,0,1
|
||||
78262,-100,4,2,1,5,0,1
|
||||
78318,-100,4,2,1,70,0,1
|
||||
78540,-83.3333333333333,4,2,1,70,0,1
|
||||
78985,-100,4,2,1,70,0,1
|
||||
79596,-100,4,2,1,5,0,1
|
||||
79651,-100,4,2,1,70,0,1
|
||||
80040,-100,4,2,1,5,0,1
|
||||
80096,-100,4,2,1,70,0,1
|
||||
80318,-83.3333333333333,4,2,1,70,0,1
|
||||
84318,-100,4,2,1,70,0,1
|
||||
84929,-100,4,2,1,5,0,1
|
||||
84985,-100,4,2,1,70,0,1
|
||||
85207,-100,4,2,1,70,0,1
|
||||
85374,-100,4,2,1,5,0,1
|
||||
85429,-100,4,2,1,70,0,1
|
||||
85651,-83.3333333333333,4,2,1,70,0,1
|
||||
86096,-100,4,2,1,70,0,1
|
||||
86707,-100,4,2,1,5,0,1
|
||||
86762,-100,4,2,1,70,0,1
|
||||
88818,-100,4,2,1,5,0,1
|
||||
88874,-100,4,2,1,70,0,1
|
||||
88929,-100,4,2,1,5,0,1
|
||||
88985,-100,4,2,1,70,0,1
|
||||
89040,-100,4,2,1,5,0,1
|
||||
89096,-100,4,2,1,70,0,1
|
||||
92040,-100,4,2,1,5,0,1
|
||||
92096,-100,4,2,1,70,0,1
|
||||
92485,-100,4,2,1,5,0,1
|
||||
92540,-100,4,2,1,70,0,1
|
||||
97651,-200,4,2,1,70,0,1
|
||||
97818,-200,4,2,1,5,0,1
|
||||
97874,-66.6666666666667,4,2,1,70,0,1
|
||||
97985,-66.6666666666667,4,2,1,70,0,1
|
||||
98040,-66.6666666666667,4,2,1,5,0,1
|
||||
98096,-133.333333333333,4,2,1,70,0,1
|
||||
98262,-133.333333333333,4,2,1,5,0,1
|
||||
98318,-66.6666666666667,4,2,1,70,0,1
|
||||
98540,-100,4,2,1,70,0,1
|
||||
99151,-100,4,2,1,5,0,1
|
||||
99207,-100,4,2,1,70,0,1
|
||||
99596,-100,4,2,1,5,0,1
|
||||
99651,-100,4,2,1,70,0,1
|
||||
103040,-100,4,2,1,5,0,1
|
||||
103096,-100,4,2,1,70,0,1
|
||||
103151,-100,4,2,1,5,0,1
|
||||
103207,-100,4,2,1,70,0,1
|
||||
103262,-100,4,2,1,5,0,1
|
||||
103318,-100,4,2,1,70,0,1
|
||||
105207,-83.3333333333333,4,2,1,70,0,1
|
||||
105540,-83.3333333333333,4,2,1,70,0,1
|
||||
105651,-133.333333333333,4,2,1,60,0,0
|
||||
105985,-133.333333333333,4,2,1,5,0,0
|
||||
106096,-200,4,2,1,60,0,0
|
||||
106985,-66.6666666666667,4,2,1,60,0,0
|
||||
107151,-66.6666666666667,4,2,1,5,0,0
|
||||
107207,-66.6666666666667,4,2,1,60,0,0
|
||||
107429,-100,4,2,1,60,0,0
|
||||
107763,-100,4,2,1,5,0,0
|
||||
107874,-100,4,2,1,60,0,0
|
||||
108874,-100,4,2,1,60,0,0
|
||||
109374,-100,4,2,1,5,0,0
|
||||
109429,-100,4,2,1,60,0,0
|
||||
109596,-100,4,2,1,5,0,0
|
||||
109651,-200,4,2,1,60,0,0
|
||||
109929,-100,4,2,1,60,0,0
|
||||
109984,-100,4,2,1,60,0,0
|
||||
110262,-100,4,2,1,5,0,0
|
||||
110318,-100,4,2,1,60,0,0
|
||||
110485,-100,4,2,1,5,0,0
|
||||
110540,-100,4,2,1,60,0,0
|
||||
110707,-100,4,2,1,5,0,0
|
||||
110762,-66.6666666666667,4,2,1,60,0,0
|
||||
110929,-100,4,2,1,60,0,0
|
||||
110985,-133.333333333333,4,2,1,60,0,0
|
||||
111429,-133.333333333333,4,2,1,60,0,0
|
||||
111596,-133.333333333333,4,2,1,60,0,0
|
||||
111651,-133.333333333333,4,2,1,60,0,0
|
||||
111818,-133.333333333333,4,2,1,60,0,0
|
||||
111874,-100,4,2,1,60,0,1
|
||||
112318,-83.3333333333333,4,2,1,60,0,1
|
||||
112429,-100,4,2,1,5,0,0
|
||||
|
||||
|
||||
[Colours]
|
||||
Combo1 : 112,75,180
|
||||
Combo2 : 0,255,255
|
||||
Combo3 : 255,15,117
|
||||
Combo4 : 255,135,15
|
||||
|
||||
[HitObjects]
|
||||
309,230,763,37,0,3:0:0:0:
|
||||
485,146,985,2,0,L|406:167,1,67.4999968671799,8|0,3:0|0:0,0:0:0:0:
|
||||
374,249,1207,2,0,L|299:227,1,67.4999968671799,8|0,3:0|0:0,0:0:0:0:
|
||||
196,91,1429,2,0,L|191:44,3,33.7499984335899,0|0|0|0,3:0|3:0|3:0|3:0,0:0:0:0:
|
||||
124,173,1651,2,0,L|131:222,2,44.9999979114532,0|0|0,3:0|3:0|3:0,0:0:0:0:
|
||||
221,284,1874,2,0,L|213:208,1,67.4999968671799,0|0,3:0|3:0,0:0:0:0:
|
||||
292,86,2096,38,0,L|310:234,1,146.249990980625,12|0,3:0|0:0,0:0:0:0:
|
||||
314,328,2540,38,0,B|280:359|280:359|230:320|252:242|313:230,1,209.999990253448,0|0,3:0|0:0,0:0:0:0:
|
||||
421,300,2874,1,0,0:0:0:0:
|
||||
421,300,2985,2,0,P|461:288|491:253,1,74.999998807907,8|0,3:0|0:0,0:0:0:0:
|
||||
309,231,3207,2,0,P|297:190|305:153,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||
394,22,3429,5,0,3:0:0:0:
|
||||
461,72,3540,2,0,B|477:103|477:103|461:148,1,74.999998807907,0|4,0:0|0:0,0:0:0:0:
|
||||
378,183,3762,2,0,L|206:157,1,149.999997615814,0|0,0:0|0:0,0:0:0:0:
|
||||
229,161,4096,2,0,P|227:202|211:250,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||
61,384,4318,38,0,P|101:359|134:322,1,74.999998807907,0|0,3:0|0:0,0:0:0:0:
|
||||
317,310,4540,2,0,P|267:305|226:288,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||
141,110,4762,2,0,B|121:175|152:226|152:226|152:202|161:183,1,149.999997615814,8|4,3:0|0:0,0:0:0:0:
|
||||
155,196,5096,6,0,P|67:211|79:286,1,179.999991645813,0|0,0:0|0:0,0:0:0:0:
|
||||
212,366,5429,38,0,P|207:335|174:281,1,56.2500012516975,4|0,0:0|0:0,0:0:0:0:
|
||||
206,286,5651,2,0,P|236:297|299:295,1,56.2500012516975,8|0,3:0|0:0,0:0:0:0:
|
||||
281,321,5874,2,0,P|257:340|227:396,1,56.2500012516975,4|0,0:0|0:0,0:0:0:0:
|
||||
124,246,6096,6,0,P|198:198|277:232,1,149.999997615814,0|0,3:0|0:0,0:0:0:0:
|
||||
253,211,6429,1,0,0:0:0:0:
|
||||
276,99,6540,2,0,P|335:139|369:215,1,149.999997615814,8|4,3:0|0:0,0:0:0:0:
|
||||
368,208,6874,1,0,0:0:0:0:
|
||||
430,96,6985,37,0,3:0:0:0:
|
||||
497,147,7096,2,0,P|507:189|488:244,1,74.999998807907,0|4,0:0|0:0,0:0:0:0:
|
||||
414,379,7318,2,0,B|383:322|421:267|421:267|421:308,1,149.999997615814,0|0,0:0|0:0,0:0:0:0:
|
||||
421,298,7651,2,0,P|378:312|336:304,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||
270,170,7874,6,0,P|275:228|236:278,1,74.999998807907,0|0,3:0|0:0,0:0:0:0:
|
||||
94,300,8096,2,0,P|133:263|208:274,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||
261,374,8318,2,0,L|176:365,1,74.999998807907,8|0,3:0|0:0,0:0:0:0:
|
||||
38,377,8540,2,0,L|55:197,1,168.750003755093,4|0,0:0|0:0,0:0:0:0:
|
||||
123,25,8985,38,0,L|132:110,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||
217,242,9207,2,0,L|237:168,1,74.999998807907,8|0,3:0|0:0,0:0:0:0:
|
||||
48,92,9429,5,4,0:0:0:0:
|
||||
63,176,9540,1,0,0:0:0:0:
|
||||
83,259,9651,38,0,P|167:223|231:255,1,149.999997615814,0|0,3:0|0:0,0:0:0:0:
|
||||
274,312,9985,1,0,0:0:0:0:
|
||||
274,312,10096,2,0,L|354:292,1,74.999998807907,8|0,3:0|0:0,0:0:0:0:
|
||||
459,225,10318,2,0,L|375:204,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||
269,107,10540,1,0,3:0:0:0:
|
||||
276,54,10651,1,0,0:0:0:0:
|
||||
313,17,10762,1,4,0:0:0:0:
|
||||
363,9,10874,1,0,0:0:0:0:
|
||||
363,9,11096,5,0,0:0:0:0:
|
||||
432,68,11207,2,0,P|444:107|425:154,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||
309,252,11429,38,0,P|297:195|321:158,1,74.999998807907,0|0,3:0|0:0,0:0:0:0:
|
||||
450,316,11651,2,0,L|361:312,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||
160,341,11874,2,0,B|187:380|187:380|233:309|177:235,1,187.499997019767,8|4,3:0|0:0,0:0:0:0:
|
||||
116,200,12207,6,0,P|52:224|122:264,1,168.750003755093,0|4,0:0|0:0,0:0:0:0:
|
||||
297,91,12762,37,8,3:0:0:0:
|
||||
276,44,12874,1,0,0:0:0:0:
|
||||
226,27,12985,1,4,0:0:0:0:
|
||||
187,63,13096,1,0,0:0:0:0:
|
||||
196,115,13207,1,0,0:0:0:0:
|
||||
376,144,13429,2,0,L|378:121,2,16.6666664017571,0|0|0,0:0|0:0|0:0,0:0:0:0:
|
||||
436,220,13651,6,0,B|395:211|373:164|373:164|332:208|264:185,1,179.999991645813,8|4,3:0|0:0,0:0:0:0:
|
||||
276,44,13985,1,0,0:0:0:0:
|
||||
196,115,14096,38,0,L|139:124,4,37.4999994039535,0|0|0|0|4,3:0|0:0|0:0|0:0|0:0,0:0:0:0:
|
||||
82,69,14429,1,0,0:0:0:0:
|
||||
106,190,14540,2,0,L|126:276,1,74.999998807907,8|0,3:0|0:0,0:0:0:0:
|
||||
218,383,14762,2,0,L|234:309,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||
26,231,14985,5,0,3:0:0:0:
|
||||
253,202,15207,37,0,0:0:0:0:
|
||||
331,271,15318,1,0,0:0:0:0:
|
||||
233,309,15429,1,8,3:0:0:0:
|
||||
389,73,15651,6,0,P|410:22|447:112,1,224.999996423721,4|0,3:0|0:0,0:0:0:0:
|
||||
391,165,16096,1,0,0:0:0:0:
|
||||
377,177,16207,1,0,0:0:0:0:
|
||||
365,187,16318,38,0,B|253:261|221:119|94:192,1,269.999987468719,0|0,0:0|0:0,0:0:0:0:
|
||||
73,319,16762,22,0,P|133:336|116:236,1,168.750003755093,4|0,3:0|0:0,0:0:0:0:
|
||||
139,258,17207,6,0,P|138:315|69:283,1,112.500002503395,8|0,3:0|0:0,0:0:0:0:
|
||||
92,323,17762,37,0,0:0:0:0:
|
||||
43,245,17874,1,4,0:0:0:0:
|
||||
4,322,17985,1,0,0:0:0:0:
|
||||
133,245,18096,1,0,3:0:0:0:
|
||||
29,105,18318,6,0,L|38:40,3,56.2500012516975,4|0|0|0,3:0|0:0|0:0|0:0,0:0:0:0:
|
||||
50,30,18540,38,0,P|111:56|193:25,1,149.999997615814,0|0,3:0|0:0,0:0:0:0:
|
||||
240,120,18985,2,0,P|328:91|394:125,1,149.999997615814,8|4,3:0|0:0,0:0:0:0:
|
||||
409,213,19318,2,0,B|377:226|377:226|243:200,1,149.999997615814,0|0,0:0|0:0,0:0:0:0:
|
||||
119,187,19651,2,0,L|127:286,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||
179,338,19874,1,8,3:0:0:0:
|
||||
45,307,19985,6,0,L|3:297,2,37.4999994039535,0|0|4,0:0|0:0|0:0,0:0:0:0:
|
||||
103,380,20207,1,0,3:0:0:0:
|
||||
212,257,20318,38,0,P|233:218|231:171,1,74.999998807907,0|0,3:0|0:0,0:0:0:0:
|
||||
111,118,20540,1,4,0:0:0:0:
|
||||
111,118,20762,6,0,L|197:109,1,74.999998807907,8|4,3:0|0:0,0:0:0:0:
|
||||
256,18,21096,37,0,0:0:0:0:
|
||||
337,121,21207,2,0,P|350:60|403:16,1,112.49999821186,0|0,3:0|0:0,0:0:0:0:
|
||||
384,26,21429,2,0,P|406:86|465:122,1,112.49999821186,0|0,0:0|0:0,0:0:0:0:
|
||||
443,114,21651,2,0,P|377:105|327:131,1,112.49999821186,8|0,3:0|0:0,0:0:0:0:
|
||||
352,223,21874,6,0,B|369:230|369:230|391:228|391:228|416:239|416:239|440:235|440:235|462:244|462:244|489:249,1,112.500002503395,4|0,0:0|0:0,0:0:0:0:
|
||||
322,343,22096,37,0,3:0:0:0:
|
||||
259,270,22207,2,0,P|223:276|182:263,2,74.999998807907,0|4|0,0:0|0:0|0:0,0:0:0:0:
|
||||
86,360,22540,5,8,3:0:0:0:
|
||||
15,295,22651,2,0,L|0:201,2,74.999998807907,0|4|0,0:0|0:0|0:0,0:0:0:0:
|
||||
94,384,22985,38,0,P|118:328|112:277,1,112.49999821186,0|0,3:0|0:0,0:0:0:0:
|
||||
0,211,23429,22,0,L|76:196,1,74.999998807907,12|0,3:0|0:0,0:0:0:0:
|
||||
215,134,23651,2,0,L|114:110,1,74.999998807907,12|0,3:0|0:0,0:0:0:0:
|
||||
33,124,23874,22,0,L|43:2,1,112.49999821186,0|0,3:0|0:0,0:0:0:0:
|
||||
150,269,24318,2,0,L|162:194,1,74.999998807907,0|4,3:0|0:0,0:0:0:0:
|
||||
229,134,24651,6,0,L|386:164,1,112.500002503395,12|0,3:0|0:0,0:0:0:0:
|
||||
486,268,24874,37,0,0:0:0:0:
|
||||
410,119,24985,1,4,0:0:0:0:
|
||||
381,213,25096,1,0,0:0:0:0:
|
||||
512,120,25207,1,0,3:0:0:0:
|
||||
247,36,25429,6,0,L|191:25,3,37.4999994039535,4|0|0|0,3:0|0:0|0:0|0:0,0:0:0:0:
|
||||
185,24,25651,2,0,B|145:72|145:72|174:164,1,149.999997615814,0|0,3:0|0:0,0:0:0:0:
|
||||
253,219,26096,2,0,B|281:311|281:311|228:382,1,149.999997615814,8|4,3:0|0:0,0:0:0:0:
|
||||
100,363,26429,38,0,L|259:354,1,149.999997615814,0|0,0:0|0:0,0:0:0:0:
|
||||
404,262,26762,1,4,0:0:0:0:
|
||||
390,352,26874,1,0,0:0:0:0:
|
||||
314,295,26985,1,8,3:0:0:0:
|
||||
425,256,27096,6,0,L|492:246,2,37.4999994039535,0|0|4,0:0|0:0|0:0,0:0:0:0:
|
||||
329,216,27318,1,0,3:0:0:0:
|
||||
193,177,27429,38,0,L|266:161,1,74.999998807907,0|0,3:0|0:0,0:0:0:0:
|
||||
322,107,27651,1,4,0:0:0:0:
|
||||
322,107,27874,2,0,L|310:238,1,112.500002503395,8|4,3:0|0:0,0:0:0:0:
|
||||
110,299,28207,5,0,0:0:0:0:
|
||||
164,231,28318,2,0,B|168:303|168:303|121:338,1,112.49999821186,0|0,3:0|0:0,0:0:0:0:
|
||||
30,284,28540,2,0,B|90:244|90:244|144:267,1,112.49999821186,0|0,0:0|0:0,0:0:0:0:
|
||||
148,371,28762,2,0,B|83:338|83:338|76:280,1,112.49999821186,8|0,3:0|0:0,0:0:0:0:
|
||||
194,201,28985,38,0,B|207:210|207:210|227:210|227:210|243:217|243:217|265:218|265:218|282:227|282:227|305:225|305:225|325:238,1,112.500002503395,4|0,0:0|0:0,0:0:0:0:
|
||||
492,114,29207,6,0,P|445:136|410:138,1,74.999998807907,0|0,3:0|0:0,0:0:0:0:
|
||||
324,102,29429,2,0,P|291:68|280:29,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||
418,17,29651,1,8,3:0:0:0:
|
||||
495,201,29874,1,4,3:2:0:0:
|
||||
221,136,30096,37,0,3:0:0:0:
|
||||
299,188,30207,2,0,B|316:251|316:251|271:352,1,149.999997615814,4|0,3:0|0:0,0:0:0:0:
|
||||
115,334,30540,6,0,P|11:252|167:266,1,382.500001215934,0|0,0:0|0:0,0:0:0:0:
|
||||
216,326,30985,38,0,L|304:331,1,63.7500002026557,4|0,3:0|0:0,0:0:0:0:
|
||||
280,330,31429,6,0,L|293:241,1,74.999998807907,8|0,3:0|0:0,0:0:0:0:
|
||||
426,252,31651,2,0,L|439:163,1,74.999998807907,0|0,0:0|0:0,0:0:0:0:
|
||||
253,158,31874,37,0,3:0:0:0:
|
||||
258,132,31985,1,0,0:0:0:0:
|
||||
337,111,32096,5,4,0:0:0:0:
|
||||
341,85,32207,1,0,0:0:0:0:
|
||||
271,30,32318,38,0,B|212:42|212:42|141:19,1,112.49999821186,8|0,3:0|0:0,0:0:0:0:
|
||||
163,26,32540,2,0,L|144:181,1,149.999997615814,4|0,0:0|3:0,0:0:0:0:
|
||||
445,343,32985,22,0,B|439:234|439:234|384:269,1,149.999997615814,4|8,0:0|3:0,0:0:0:0:
|
||||
240,257,33429,2,0,B|263:148|263:148|291:205,1,149.999997615814,4|0,0:0|3:0,0:0:0:0:
|
||||
68,333,33874,2,0,B|83:233|83:233|41:256,1,149.999997615814,4|8,0:0|3:0,0:0:0:0:
|
||||
344,347,34318,22,0,B|368:372|368:372|455:355|455:355|472:308,1,149.999997615814,4|0,0:0|0:0,0:0:0:0:
|
||||
452,255,34540,2,0,B|389:212|389:212|332:273,1,149.999997615814,0|4,3:0|0:0,0:0:0:0:
|
||||
256,220,34874,5,0,0:0:0:0:
|
||||
256,220,34985,2,0,B|256:128,1,74.999998807907,8|0,3:0|0:0,0:0:0:0:
|
||||
256,70,35207,2,0,B|256:162,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||
112,312,35429,37,0,3:0:0:0:
|
||||
60,255,35540,2,0,B|123:212|123:212|180:273,1,149.999997615814,0|0,0:0|0:0,0:0:0:0:
|
||||
169,350,35874,6,0,B|144:375|144:375|57:358|57:358|40:311,1,149.999997615814,8|0,3:0|3:0,0:0:0:0:
|
||||
62,169,36429,6,0,L|76:267,2,74.999998807907,0|4|0,0:0|0:0|0:0,0:0:0:0:
|
||||
134,61,36762,1,8,3:0:0:0:
|
||||
201,113,36874,2,0,L|215:211,2,74.999998807907,0|4|0,0:0|0:0|0:0,0:0:0:0:
|
||||
298,272,37207,6,0,L|315:184,1,74.999998807907,0|0,3:0|0:0,0:0:0:0:
|
||||
330,114,37429,1,4,0:0:0:0:
|
||||
446,176,37540,2,0,B|404:214|404:214|307:197,1,149.999997615814,4|0,3:0|0:0,0:0:0:0:
|
||||
231,240,37874,2,0,P|223:199|231:162,1,74.999998807907,4|0,3:0|0:0,0:0:0:0:
|
||||
325,285,38096,6,0,L|154:300,1,149.999997615814,4|0,3:0|0:0,0:0:0:0:
|
||||
175,298,38540,6,0,L|163:396,1,74.999998807907,8|0,3:0|0:0,0:0:0:0:
|
||||
75,208,38762,2,0,L|63:306,1,74.999998807907,0|0,0:0|0:0,0:0:0:0:
|
||||
233,74,38985,37,0,3:0:0:0:
|
||||
231,98,39096,1,0,0:0:0:0:
|
||||
156,139,39207,5,4,0:0:0:0:
|
||||
155,165,39318,1,0,0:0:0:0:
|
||||
227,215,39429,38,0,P|282:209|352:230,1,112.49999821186,8|0,3:0|0:0,0:0:0:0:
|
||||
336,222,39651,2,0,L|366:67,1,149.999997615814,4|0,0:0|3:0,0:0:0:0:
|
||||
81,35,40096,22,0,B|82:105|82:105|118:136|118:136|132:89,1,149.999997615814,4|8,0:0|3:0,0:0:0:0:
|
||||
272,158,40540,2,0,B|270:228|270:228|234:259|234:259|220:212,1,149.999997615814,4|0,0:0|3:0,0:0:0:0:
|
||||
423,36,40985,2,0,B|400:102|400:102|423:143|423:143|453:104,1,149.999997615814,4|8,0:0|3:0,0:0:0:0:
|
||||
512,278,41429,6,0,P|415:258|361:293,1,149.999997615814,4|0,0:0|0:0,0:0:0:0:
|
||||
359,302,41651,6,0,B|320:264|320:264|310:187,1,112.49999821186,0|0,3:0|0:0,0:0:0:0:
|
||||
322,190,41874,2,0,L|449:171,1,112.49999821186,4|0,0:0|0:0,0:0:0:0:
|
||||
443,159,42096,1,8,3:0:0:0:
|
||||
240,52,42318,6,0,B|255:79|255:79|241:135,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||
177,166,42540,1,0,3:0:0:0:
|
||||
163,151,42651,2,0,B|161:207|161:207|192:240|192:240|189:299,1,149.999997615814,0|0,0:0|0:0,0:0:0:0:
|
||||
131,365,42985,2,0,P|198:322|280:345,1,149.999997615814,8|4,3:0|0:0,0:0:0:0:
|
||||
335,377,43318,1,0,0:0:0:0:
|
||||
442,239,43429,38,0,B|456:178|456:178|422:136|422:136|427:68|427:68|449:112,1,224.999996423721,0|0,3:0|0:0,0:0:0:0:
|
||||
444,103,43874,2,0,P|402:118|356:120,1,74.999998807907,0|0,0:0|0:0,0:0:0:0:
|
||||
249,28,44096,2,0,P|295:35|324:48,1,74.999998807907,0|0,0:0|0:0,0:0:0:0:
|
||||
364,201,44318,5,0,0:0:0:0:
|
||||
332,195,44429,1,0,0:0:0:0:
|
||||
251,135,44540,37,0,0:0:0:0:
|
||||
281,123,44651,1,0,0:0:0:0:
|
||||
332,195,44762,6,0,B|356:269|324:333|324:333|303:293,1,179.999991645813,4|0,0:3|0:0,0:0:0:0:
|
||||
61,25,45207,38,0,L|88:158,1,112.500002503395,0|0,3:0|0:0,0:0:0:0:
|
||||
84,136,45651,1,8,3:0:0:0:
|
||||
84,136,46096,1,0,3:0:0:0:
|
||||
176,33,46207,2,0,L|164:103,1,56.2500012516975,0|0,0:0|0:0,0:0:0:0:
|
||||
219,207,46429,2,0,L|232:152,1,56.2500012516975,0|8,0:0|3:0,0:0:0:0:
|
||||
312,65,46651,1,0,0:0:0:0:
|
||||
312,65,46762,2,0,L|398:94,1,56.2500012516975,0|0,0:0|0:0,0:0:0:0:
|
||||
512,176,46985,5,0,3:0:0:0:
|
||||
421,192,47096,1,0,0:0:0:0:
|
||||
421,192,47429,1,8,3:0:0:0:
|
||||
402,357,47651,37,0,0:0:0:0:
|
||||
394,277,47762,1,0,0:0:0:0:
|
||||
328,324,47874,1,0,3:0:0:0:
|
||||
328,324,48318,1,8,3:0:0:0:
|
||||
110,357,48540,5,0,0:0:0:0:
|
||||
118,277,48651,1,0,0:0:0:0:
|
||||
184,324,48763,1,0,3:0:0:0:
|
||||
110,357,48874,1,0,0:0:0:0:
|
||||
110,357,49207,1,8,3:0:0:0:
|
||||
110,357,49651,1,0,3:0:0:0:
|
||||
0,283,49762,38,0,P|41:301|97:295,1,56.2500012516975,0|0,0:0|0:0,0:0:0:0:
|
||||
188,219,49985,2,0,P|168:236|137:246,1,56.2500012516975,0|8,0:0|3:0,0:0:0:0:
|
||||
49,137,50207,1,0,0:0:0:0:
|
||||
49,137,50318,2,0,P|65:184|93:205,1,56.2500012516975,0|0,0:0|0:0,0:0:0:0:
|
||||
107,67,50540,5,0,3:0:0:0:
|
||||
32,15,50651,1,0,0:0:0:0:
|
||||
32,15,50985,1,8,3:0:0:0:
|
||||
265,114,51207,37,0,0:0:0:0:
|
||||
254,196,51318,1,0,0:0:0:0:
|
||||
241,279,51429,1,0,3:0:0:0:
|
||||
241,279,51651,1,0,0:0:0:0:
|
||||
336,207,51762,6,0,P|397:191|371:274,1,168.750003755093,0|0,0:0|0:0,0:0:0:0:
|
||||
83,206,52318,5,0,3:0:0:0:
|
||||
83,206,52429,2,0,L|101:260,1,56.2500012516975,0|0,0:0|0:0,0:0:0:0:
|
||||
40,383,52651,2,0,P|70:355|90:324,1,56.2500012516975,0|8,0:0|3:0,0:0:0:0:
|
||||
214,334,52874,1,0,0:0:0:0:
|
||||
214,334,52985,2,0,P|171:322|140:304,1,56.2500012516975,0|0,0:0|0:0,0:0:0:0:
|
||||
151,160,53207,5,0,3:0:0:0:
|
||||
188,135,53318,1,0,0:0:0:0:
|
||||
232,129,53429,1,0,0:0:0:0:
|
||||
273,146,53540,1,0,0:0:0:0:
|
||||
339,198,53651,37,8,3:0:0:0:
|
||||
383,199,53762,1,0,0:0:0:0:
|
||||
426,185,53874,1,0,0:0:0:0:
|
||||
450,147,53985,1,0,0:0:0:0:
|
||||
444,61,54096,6,0,P|414:28|377:15,1,56.2500012516975,0|0,3:0|0:0,0:0:0:0:
|
||||
301,28,54318,2,0,P|268:48|255:77,1,56.2500012516975,0|0,0:0|0:0,0:0:0:0:
|
||||
189,271,54540,38,0,P|209:222|204:198,1,56.2500012516975,8|0,3:0|0:0,0:0:0:0:
|
||||
186,114,54762,2,0,P|152:74|124:68,1,56.2500012516975,0|0,0:0|0:0,0:0:0:0:
|
||||
27,137,54985,5,0,3:0:0:0:
|
||||
34,167,55096,1,0,0:0:0:0:
|
||||
122,204,55207,37,0,0:0:0:0:
|
||||
116,178,55318,1,0,0:0:0:0:
|
||||
48,249,55429,5,8,3:0:0:0:
|
||||
54,274,55540,1,0,0:0:0:0:
|
||||
124,329,55651,38,0,P|157:326|200:310,1,56.2500012516975,0|0,0:0|0:0,0:0:0:0:
|
||||
320,185,55874,5,0,3:0:0:0:
|
||||
287,175,55985,1,0,0:0:0:0:
|
||||
254,181,56096,2,0,P|258:221|264:241,1,56.2500012516975,0|0,0:0|0:0,0:0:0:0:
|
||||
337,347,56318,2,0,P|348:321|350:293,1,56.2500012516975,8|0,3:0|0:0,0:0:0:0:
|
||||
418,197,56540,37,0,0:0:0:0:
|
||||
418,197,56651,2,0,L|492:180,1,56.2500012516975,0|0,0:0|3:0,0:0:0:0:
|
||||
329,114,56874,2,0,L|262:94,1,56.2500012516975,0|0,0:0|0:0,0:0:0:0:
|
||||
436,59,57096,6,0,L|413:126,1,56.2500012516975,0|8,0:0|3:0,0:0:0:0:
|
||||
332,194,57318,2,0,L|353:259,2,56.2500012516975,0|0|0,0:0|0:0|0:0,0:0:0:0:
|
||||
202,194,57651,37,0,3:0:0:0:
|
||||
224,233,57762,1,0,0:0:0:0:
|
||||
222,279,57874,1,0,0:0:0:0:
|
||||
193,314,57985,1,0,0:0:0:0:
|
||||
144,244,58096,5,0,0:0:0:0:
|
||||
127,214,58207,1,0,0:0:0:0:
|
||||
126,180,58318,1,0,0:0:0:0:
|
||||
139,149,58429,1,0,0:0:0:0:
|
||||
224,113,58540,38,0,B|262:88|235:70|189:83|189:83|224:138|194:193,1,194.999987974167
|
||||
299,319,58874,1,0,0:0:0:0:
|
||||
299,319,58985,2,0,B|316:283|314:237|314:237|278:226|278:226|320:243|359:227,1,202.49999060154,4|0,0:0|0:0,0:0:0:0:
|
||||
428,181,59429,22,0,P|454:129|399:4,1,179.999991645813,0|0,3:0|0:0,0:0:0:0:
|
||||
418,18,59874,2,0,L|373:15,6,24.9999996026357,8|0|0|0|0|0|4,3:0|0:0|0:0|0:0|0:0|0:0|0:0,0:0:0:0:
|
||||
428,181,60207,5,0,0:0:0:0:
|
||||
352,209,60318,1,0,3:0:0:0:
|
||||
278,177,60429,1,0,0:0:0:0:
|
||||
208,225,60540,2,0,L|222:267,2,37.4999994039535,4|0|0,0:0|0:0|0:0,0:0:0:0:
|
||||
71,144,60762,38,0,L|65:109,3,24.9999996026357,8|0|0|0,3:0|0:0|0:0|0:0,0:0:0:0:
|
||||
145,86,60985,1,4,0:0:0:0:
|
||||
163,127,61096,1,0,0:0:0:0:
|
||||
161,171,61207,1,0,3:0:0:0:
|
||||
136,208,61318,1,0,0:0:0:0:
|
||||
99,231,61429,2,0,B|91:279|91:279|117:314,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||
177,378,61651,5,8,3:0:0:0:
|
||||
177,378,61762,2,0,B|231:371|231:371|272:326|272:326|345:319,1,179.999991645813
|
||||
417,293,62096,1,0,3:0:0:0:
|
||||
438,263,62207,1,0,0:0:0:0:
|
||||
436,225,62318,1,4,0:0:0:0:
|
||||
412,196,62429,1,0,0:0:0:0:
|
||||
320,172,62540,6,0,P|307:192|291:204,1,37.4999994039535,8|0,3:0|0:0,0:0:0:0:
|
||||
291,147,62651,2,0,P|274:156|245:153,1,37.4999994039535,0|0,0:0|0:0,0:0:0:0:
|
||||
276,114,62762,2,0,P|250:107|234:94,1,37.4999994039535,4|0,0:0|0:0,0:0:0:0:
|
||||
283,81,62874,2,0,P|265:61|260:45,1,37.4999994039535,0|0,0:0|0:0,0:0:0:0:
|
||||
365,31,62985,38,0,P|398:44|442:49,1,74.999998807907,0|0,3:0|0:0,0:0:0:0:
|
||||
512,169,63207,2,0,P|466:163|421:176,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||
350,107,63429,1,8,3:0:0:0:
|
||||
293,237,63540,38,0,L|276:158,1,74.999998807907,0|0,0:0|0:0,0:0:0:0:
|
||||
428,269,63762,2,0,B|373:275|373:275|338:249|338:249|267:255,1,149.999997615814,0|0,0:0|0:0,0:0:0:0:
|
||||
191,318,64096,2,0,B|182:355|182:355|212:395,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||
192,186,64318,5,8,3:0:0:0:
|
||||
135,253,64429,2,0,L|56:270,2,74.999998807907,0|4|0,0:0|0:0|0:0,0:0:0:0:
|
||||
24,136,64762,38,0,P|69:76|158:75,1,157.499992690086,0|0,3:0|0:0,0:0:0:0:
|
||||
160,80,64985,6,0,P|193:102|255:102,1,84.3750018775463,4|0,0:0|0:0,0:0:0:0:
|
||||
276,34,65207,38,0,L|290:212,1,157.499992690086,8|0,3:0|0:0,0:0:0:0:
|
||||
291,219,65429,6,0,L|311:132,1,84.3750018775463,4|0,0:0|0:0,0:0:0:0:
|
||||
381,111,65651,38,0,B|418:126|418:126|460:126,1,74.999998807907,0|0,3:0|0:0,0:0:0:0:
|
||||
221,163,65874,2,0,B|186:143|186:143|139:153,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||
41,231,66096,1,8,3:0:0:0:
|
||||
49,267,66207,1,0,0:0:0:0:
|
||||
56,303,66318,1,4,0:0:0:0:
|
||||
67,288,66429,1,4,0:0:0:0:
|
||||
77,270,66540,6,0,P|171:255|72:350,1,337.500007510185,0|0,0:0|0:0,0:0:0:0:
|
||||
95,356,66985,38,0,L|185:343,1,74.999998807907,8|4,3:0|0:0,0:0:0:0:
|
||||
274,286,67318,6,0,B|289:324|289:324|268:378,1,74.999998807907,0|0,0:0|3:0,0:0:0:0:
|
||||
191,227,67540,1,0,0:0:0:0:
|
||||
255,168,67651,2,0,L|264:116,2,37.4999994039535,4|0|0,0:0|0:0|0:0,0:0:0:0:
|
||||
147,83,67874,2,0,L|154:108,3,24.9999996026357,8|0|0|0,3:0|0:0|0:0|0:0,0:0:0:0:
|
||||
80,148,68096,38,0,L|98:224,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||
125,356,68318,1,0,3:0:0:0:
|
||||
0,319,68429,1,0,0:0:0:0:
|
||||
0,319,68540,2,0,L|76:294,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||
277,219,68762,5,8,3:0:0:0:
|
||||
277,219,68874,2,0,B|327:199|327:199|293:138|197:173,1,179.999991645813,0|0,0:0|0:0,0:0:0:0:
|
||||
157,273,69207,37,0,3:0:0:0:
|
||||
175,316,69318,1,0,0:0:0:0:
|
||||
212,334,69429,1,4,0:0:0:0:
|
||||
254,333,69540,1,0,0:0:0:0:
|
||||
332,268,69651,38,0,P|333:237|343:213,1,37.4999994039535,8|0,3:0|0:0,0:0:0:0:
|
||||
373,265,69762,2,0,P|386:239|404:232,1,37.4999994039535,0|0,0:0|0:0,0:0:0:0:
|
||||
413,284,69874,2,0,P|430:269|454:269,1,37.4999994039535,4|0,0:0|0:0,0:0:0:0:
|
||||
433,318,69985,2,0,P|452:320|474:337,1,37.4999994039535,4|0,0:0|0:0,0:0:0:0:
|
||||
401,384,70096,6,0,P|353:378|319:346,1,74.999998807907,0|0,3:0|0:0,0:0:0:0:
|
||||
251,251,70318,2,0,P|240:196|260:154,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||
401,18,70540,1,8,3:0:0:0:
|
||||
401,18,70651,2,0,P|409:54|398:90,1,74.999998807907,0|0,0:0|0:0,0:0:0:0:
|
||||
327,193,70874,2,0,L|304:45,1,149.999997615814,0|0,0:0|0:0,0:0:0:0:
|
||||
290,26,71207,6,0,L|308:144,1,104.999995126724,0|0,0:0|0:0,0:0:0:0:
|
||||
272,302,71429,2,0,L|187:288,1,74.999998807907,8|0,3:0|0:0,0:0:0:0:
|
||||
33,217,71651,37,4,0:0:0:0:
|
||||
27,187,71762,1,4,0:0:0:0:
|
||||
20,157,71874,2,0,B|103:140|103:140|162:58,1,157.499992690086,0|0,3:0|0:0,0:0:0:0:
|
||||
145,82,72096,6,0,L|218:75,1,56.2500012516975,0|0,0:0|0:0,0:0:0:0:
|
||||
336,136,72318,38,0,P|331:213|231:208,1,157.499992690086
|
||||
263,232,72540,6,0,L|278:300,1,56.2500012516975,0|0,0:0|0:0,0:0:0:0:
|
||||
183,384,72762,2,0,L|172:307,1,56.2500012516975,0|0,0:0|0:0,0:0:0:0:
|
||||
37,140,72985,38,0,B|10:168|10:168|17:204|17:204|54:220|54:220|89:196|89:196|87:157|87:157|57:138,1,225.00000500679
|
||||
275,372,73651,6,0,P|320:352|387:369,1,112.500002503395
|
||||
380,364,74096,2,0,L|436:358,1,56.2500012516975,0|0,0:0|0:0,0:0:0:0:
|
||||
495,271,74318,2,0,L|424:282,1,56.2500012516975,0|0,0:0|0:0,0:0:0:0:
|
||||
339,270,74540,1,0,0:0:0:0:
|
||||
339,270,74651,1,0,0:0:0:0:
|
||||
339,270,74762,2,0,L|329:196,1,56.2500012516975,0|0,0:0|0:0,0:0:0:0:
|
||||
408,46,74985,38,0,L|392:120,1,56.2500012516975
|
||||
220,230,75207,2,0,L|209:156,1,56.2500012516975,0|0,0:0|0:0,0:0:0:0:
|
||||
282,7,75429,37,0,0:0:0:0:
|
||||
300,98,75540,1,0,0:0:0:0:
|
||||
197,25,75651,5,0,0:0:0:0:
|
||||
222,103,75762,1,0,0:0:0:0:
|
||||
126,69,75874,5,0,0:0:0:0:
|
||||
153,134,75985,1,0,0:0:0:0:
|
||||
76,145,76096,5,0,0:0:0:0:
|
||||
116,179,76207,1,0,0:0:0:0:
|
||||
70,222,76318,5,0,0:0:0:0:
|
||||
111,222,76429,1,0,0:0:0:0:
|
||||
134,253,76540,6,0,P|135:298|126:314,1,56.2500012516975,0|0,0:0|0:0,0:0:0:0:
|
||||
21,384,76762,2,0,P|124:354|260:391,1,224.999996423721,0|0,0:0|0:0,0:0:0:0:
|
||||
384,366,77207,22,0,L|394:268,1,74.999998807907,0|0,3:0|0:0,0:0:0:0:
|
||||
499,62,77429,2,0,L|486:135,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||
507,237,77651,2,0,P|450:231|388:184,1,112.49999821186,8|0,3:0|0:0,0:0:0:0:
|
||||
404,203,77874,2,0,L|313:217,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||
113,212,78096,6,0,P|128:267|111:328,1,112.49999821186,0|0,3:0|0:0,0:0:0:0:
|
||||
115,319,78318,2,0,L|213:340,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||
274,371,78540,38,0,L|257:186,1,179.999991645813,8|0,3:0|0:0,0:0:0:0:
|
||||
128,139,78874,1,0,0:0:0:0:
|
||||
128,139,78985,6,0,L|230:128,1,74.999998807907,0|0,3:0|0:0,0:0:0:0:
|
||||
365,34,79207,37,4,0:0:0:0:
|
||||
430,114,79318,1,0,0:0:0:0:
|
||||
361,184,79429,2,0,P|304:170|277:110,1,112.49999821186,8|0,3:0|0:0,0:0:0:0:
|
||||
278,126,79651,2,0,L|189:133,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||
64,263,79874,6,0,B|37:230|37:230|50:143,1,112.49999821186,0|0,3:0|0:0,0:0:0:0:
|
||||
66,119,80096,2,0,L|80:210,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||
71,361,80318,38,0,B|135:350|135:350|182:305|182:305|243:297,1,179.999991645813,8|0,3:0|0:0,0:0:0:0:
|
||||
302,247,80651,1,0,0:0:0:0:
|
||||
222,211,80762,1,0,3:0:0:0:
|
||||
478,344,80985,5,4,0:0:0:0:
|
||||
491,309,81096,5,0,0:0:0:0:
|
||||
498,265,81207,5,8,3:0:0:0:
|
||||
485,223,81318,5,0,0:0:0:0:
|
||||
458,179,81429,5,4,0:0:0:0:
|
||||
418,147,81540,5,0,0:0:0:0:
|
||||
352,126,81651,5,0,3:0:0:0:
|
||||
281,149,81762,5,0,0:0:0:0:
|
||||
239,221,81874,5,4,0:0:0:0:
|
||||
159,262,81985,5,0,0:0:0:0:
|
||||
66,234,82096,5,8,3:0:0:0:
|
||||
11,145,82207,5,0,0:0:0:0:
|
||||
55,33,82318,5,4,0:0:0:0:
|
||||
273,44,82540,37,0,3:0:0:0:
|
||||
320,103,82651,1,0,0:0:0:0:
|
||||
394,118,82762,1,4,0:0:0:0:
|
||||
468,100,82874,1,0,0:0:0:0:
|
||||
507,36,82985,1,8,3:0:0:0:
|
||||
495,19,83207,5,4,0:0:0:0:
|
||||
335,83,83318,1,0,0:0:0:0:
|
||||
453,81,83429,1,0,3:0:0:0:
|
||||
283,24,83540,2,0,P|196:37|141:120,1,149.999997615814,0|0,0:0|0:0,0:0:0:0:
|
||||
60,238,83874,1,8,3:0:0:0:
|
||||
21,164,83985,2,0,P|59:149|175:193,1,149.999997615814,0|8,0:0|3:0,0:0:0:0:
|
||||
252,206,84318,38,0,P|271:160|264:125,1,74.999998807907,0|0,3:0|0:0,0:0:0:0:
|
||||
139,257,84540,2,0,P|131:302|149:340,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||
240,379,84762,2,0,B|330:360|330:360|298:344,1,112.49999821186,8|0,3:0|0:0,0:0:0:0:
|
||||
312,351,84985,2,0,P|279:321|270:287,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||
359,165,85207,6,0,B|389:202|389:202|368:282,1,112.49999821186,0|0,3:0|0:0,0:0:0:0:
|
||||
373,265,85429,2,0,L|454:282,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||
498,139,85651,38,0,P|446:120|396:0,1,179.999991645813,8|0,3:0|0:0,0:0:0:0:
|
||||
394,13,85985,1,0,0:0:0:0:
|
||||
301,92,86096,6,0,L|214:83,1,74.999998807907,0|0,3:0|0:0,0:0:0:0:
|
||||
66,66,86318,1,4,0:0:0:0:
|
||||
13,136,86429,1,0,0:0:0:0:
|
||||
72,193,86540,2,0,P|120:210|190:178,1,112.49999821186,8|0,3:0|0:0,0:0:0:0:
|
||||
176,192,86762,2,0,P|154:237|160:288,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||
309,370,86985,37,0,3:0:0:0:
|
||||
359,310,87096,1,0,0:0:0:0:
|
||||
283,297,87207,2,0,L|203:318,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||
4,203,87429,2,0,B|55:211|55:211|82:255|82:255|134:266,1,149.999997615814,8|0,3:0|0:0,0:0:0:0:
|
||||
238,217,87762,1,0,0:0:0:0:
|
||||
183,120,87874,6,0,L|89:111,1,74.999998807907,0|0,3:0|0:0,0:0:0:0:
|
||||
98,33,88096,2,0,L|23:26,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||
306,182,88318,38,0,L|400:173,1,74.999998807907,8|0,3:0|0:0,0:0:0:0:
|
||||
391,95,88540,2,0,L|465:88,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||
232,28,88762,2,0,L|220:92,1,37.4999994039535,0|0,3:0|0:0,0:0:0:0:
|
||||
243,39,88874,2,0,L|231:103,1,37.4999994039535,0|0,0:0|0:0,0:0:0:0:
|
||||
256,50,88985,2,0,L|251:87,1,37.4999994039535,4|0,0:0|0:0,0:0:0:0:
|
||||
485,87,89207,6,0,L|493:51,3,37.4999994039535,8|0|0|0,3:0|0:0|0:0|0:0,0:0:0:0:
|
||||
396,120,89429,2,0,L|411:197,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||
471,317,89651,38,0,P|411:299|320:336,1,149.999997615814,0|4,3:0|0:0,0:0:0:0:
|
||||
61,239,90096,2,0,P|121:221|212:258,1,149.999997615814,8|4,3:0|0:0,0:0:0:0:
|
||||
367,21,90540,6,0,P|336:57|328:104,1,74.999998807907,0|0,3:0|0:0,0:0:0:0:
|
||||
163,96,90762,2,0,P|194:132|202:179,1,74.999998807907,0|0,0:0|0:0,0:0:0:0:
|
||||
190,346,90985,37,8,3:0:0:0:
|
||||
328,272,91096,1,0,0:0:0:0:
|
||||
154,272,91207,5,8,3:0:0:0:
|
||||
365,338,91318,1,0,0:0:0:0:
|
||||
257,382,91429,38,0,B|290:333|224:286|269:219,1,149.999997615814,4|4,3:0|0:0,0:0:0:0:
|
||||
325,196,91762,1,0,0:0:0:0:
|
||||
325,196,91874,2,0,P|365:210|436:184,1,112.49999821186,8|0,3:0|0:0,0:0:0:0:
|
||||
430,190,92096,2,0,B|418:110,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||
313,19,92318,2,0,L|190:36,1,112.49999821186,0|0,3:0|0:0,0:0:0:0:
|
||||
201,34,92540,2,0,B|214:117,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||
209,252,92762,5,8,3:0:0:0:
|
||||
156,261,92874,1,0,0:0:0:0:
|
||||
112,231,92985,1,4,0:0:0:0:
|
||||
60,222,93096,1,0,0:0:0:0:
|
||||
13,247,93207,38,0,P|4:288|19:328,1,74.999998807907,0|0,3:0|0:0,0:0:0:0:
|
||||
173,186,93429,1,4,0:0:0:0:
|
||||
215,120,93540,1,0,0:0:0:0:
|
||||
162,49,93651,2,0,P|125:39|76:61,1,74.999998807907,8|0,3:0|0:0,0:0:0:0:
|
||||
234,138,93874,2,0,P|273:157|313:148,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||
385,39,94096,5,0,3:0:0:0:
|
||||
337,286,94318,2,0,L|322:373,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||
409,327,94540,2,0,P|418:277|280:230,1,224.999996423721,8|0,3:0|0:0,0:0:0:0:
|
||||
239,319,94985,2,0,P|218:357|173:373,1,74.999998807907,0|0,3:0|0:0,0:0:0:0:
|
||||
34,344,95207,37,4,0:0:0:0:
|
||||
21,309,95318,5,0,0:0:0:0:
|
||||
14,265,95429,5,8,3:0:0:0:
|
||||
27,223,95540,5,0,0:0:0:0:
|
||||
54,179,95651,5,4,0:0:0:0:
|
||||
94,147,95762,5,0,0:0:0:0:
|
||||
160,126,95873,5,0,3:0:0:0:
|
||||
231,149,95984,5,0,0:0:0:0:
|
||||
273,221,96096,5,4,0:0:0:0:
|
||||
353,262,96207,5,0,0:0:0:0:
|
||||
446,234,96318,5,8,3:0:0:0:
|
||||
501,145,96429,5,0,0:0:0:0:
|
||||
450,36,96540,5,4,0:0:0:0:
|
||||
239,44,96762,5,0,3:0:0:0:
|
||||
192,103,96873,1,0,0:0:0:0:
|
||||
118,118,96984,1,4,0:0:0:0:
|
||||
44,100,97096,1,0,0:0:0:0:
|
||||
5,36,97207,1,8,3:0:0:0:
|
||||
17,19,97429,37,4,0:0:0:0:
|
||||
146,51,97540,1,0,0:0:0:0:
|
||||
29,122,97651,2,0,L|39:193,1,56.2499991059302,0|0,3:0|0:0,0:0:0:0:
|
||||
44,197,97874,6,0,P|100:231|176:201,1,112.500002503395,4|0,0:0|0:0,0:0:0:0:
|
||||
301,160,98096,38,0,P|329:140|382:137,1,84.3750018775463,8|0,3:0|0:0,0:0:0:0:
|
||||
398,147,98318,6,0,B|431:187|431:187|415:279,1,112.500002503395,4|0,0:0|0:0,0:0:0:0:
|
||||
265,371,98540,38,0,L|180:361,1,74.999998807907,0|0,3:0|0:0,0:0:0:0:
|
||||
127,202,98762,2,0,L|141:113,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||
193,260,98985,2,0,P|144:291|68:278,1,112.49999821186,8|0,3:0|0:0,0:0:0:0:
|
||||
91,290,99207,2,0,L|79:373,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||
20,184,99429,6,0,B|4:141|4:141|27:66,1,112.49999821186,0|0,3:0|0:0,0:0:0:0:
|
||||
23,78,99651,2,0,L|109:91,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||
271,74,99874,2,0,P|254:31|222:12,1,74.999998807907,8|0,3:0|0:0,0:0:0:0:
|
||||
186,180,100096,2,0,P|232:175|260:147,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||
132,63,100318,37,0,3:0:0:0:
|
||||
253,157,100540,1,4,0:0:0:0:
|
||||
285,167,100651,1,0,0:0:0:0:
|
||||
357,129,100762,5,8,3:0:0:0:
|
||||
389,139,100873,1,0,0:0:0:0:
|
||||
422,148,100985,2,0,P|407:200|416:233,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||
459,377,101207,38,0,P|472:333|459:295,1,74.999998807907,0|0,3:0|0:0,0:0:0:0:
|
||||
398,242,101429,2,0,L|314:257,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||
165,354,101651,2,0,P|116:332|211:264,1,224.999996423721,8|0,3:0|0:0,0:0:0:0:
|
||||
302,165,102096,6,0,L|292:89,1,74.999998807907,0|0,3:0|0:0,0:0:0:0:
|
||||
392,91,102318,2,0,L|382:14,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||
192,229,102540,38,0,L|212:136,1,74.999998807907,8|0,3:0|0:0,0:0:0:0:
|
||||
107,172,102762,2,0,L|127:79,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||
314,332,102985,6,0,L|305:278,1,37.4999994039535,0|0,3:0|0:0,0:0:0:0:
|
||||
343,345,103096,2,0,L|334:291,1,37.4999994039535,0|0,0:0|0:0,0:0:0:0:
|
||||
370,358,103207,2,0,L|361:304,1,37.4999994039535,4|0,0:0|0:0,0:0:0:0:
|
||||
380,117,103429,38,0,L|374:75,3,37.4999994039535,8|0|0|0,3:0|0:0|0:0|0:0,0:0:0:0:
|
||||
444,166,103651,2,0,P|417:188|346:191,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||
392,2,103874,2,0,P|424:14|462:74,1,74.999998807907,4|0,3:0|0:0,0:0:0:0:
|
||||
271,129,104096,2,0,P|265:94|298:31,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||
505,113,104318,5,8,3:0:0:0:
|
||||
269,217,104540,38,0,L|216:216,3,37.4999994039535,0|0|0|0,3:0|3:0|3:0|3:0,0:0:0:0:
|
||||
360,220,104762,1,0,3:0:0:0:
|
||||
296,384,104874,1,4,3:0:0:0:
|
||||
102,307,105096,5,0,0:0:0:0:
|
||||
102,307,105207,2,0,B|206:381|258:244|374:330,1,269.999987468719,12|0,3:0|0:0,0:0:0:0:
|
||||
439,319,105651,6,0,P|379:336|396:236,1,168.750003755093,0|0,3:0|0:0,0:0:0:0:
|
||||
373,258,106096,6,0,P|374:315|443:283,1,112.500002503395,8|0,3:0|0:0,0:0:0:0:
|
||||
420,323,106651,37,0,0:0:0:0:
|
||||
469,245,106763,1,4,0:0:0:0:
|
||||
508,322,106874,1,0,0:0:0:0:
|
||||
379,245,106985,1,8,3:0:0:0:
|
||||
483,105,107207,6,0,L|474:40,3,56.2500012516975,4|0|0|0,3:0|0:0|0:0|0:0,0:0:0:0:
|
||||
462,30,107429,38,0,P|401:56|319:25,1,149.999997615814,0|0,3:0|0:0,0:0:0:0:
|
||||
272,120,107874,2,0,P|184:91|118:125,1,149.999997615814,8|4,3:0|0:0,0:0:0:0:
|
||||
103,213,108207,2,0,B|128:232|128:232|269:200,1,149.999997615814,0|0,0:0|0:0,0:0:0:0:
|
||||
393,187,108540,2,0,L|385:286,1,74.999998807907,4|0,0:0|0:0,0:0:0:0:
|
||||
333,338,108763,1,8,3:0:0:0:
|
||||
467,307,108874,6,0,L|509:297,2,37.4999994039535,0|0|4,0:0|0:0|0:0,0:0:0:0:
|
||||
409,380,109096,1,0,0:0:0:0:
|
||||
300,257,109207,38,0,P|279:218|281:171,1,74.999998807907,0|0,3:0|0:0,0:0:0:0:
|
||||
401,118,109429,1,4,0:0:0:0:
|
||||
401,118,109651,6,0,L|315:109,1,74.999998807907,8|4,3:0|0:0,0:0:0:0:
|
||||
256,15,109985,37,0,0:0:0:0:
|
||||
175,121,110096,2,0,P|162:60|109:16,1,112.49999821186,0|0,3:0|0:0,0:0:0:0:
|
||||
128,26,110318,2,0,P|106:86|47:122,1,112.49999821186,0|0,0:0|0:0,0:0:0:0:
|
||||
69,114,110540,2,0,P|135:105|185:131,1,112.49999821186,8|0,3:0|0:0,0:0:0:0:
|
||||
160,223,110762,6,0,B|142:230|142:230|120:228|120:228|95:239|95:239|71:235|71:235|49:244|49:244|22:249,1,112.500002503395,4|0,0:0|0:0,0:0:0:0:
|
||||
193,334,110985,38,0,P|216:310|242:301,1,56.2500012516975,0|0,3:0|0:0,0:0:0:0:
|
||||
335,325,111207,2,0,P|366:353|378:379,1,56.2500012516975,0|0,0:0|0:0,0:0:0:0:
|
||||
273,383,111429,2,0,L|304:213,1,168.750003755093,0|0,0:0|0:0,0:0:0:0:
|
||||
383,255,111874,22,0,B|422:273|422:273|476:273,1,74.999998807907,8|0,3:0|3:0,0:0:0:0:
|
||||
209,219,112096,2,0,B|169:221|169:221|131:206,1,74.999998807907,0|0,0:0|0:0,0:0:0:0:
|
||||
403,147,112318,2,0,B|352:114|352:114|337:43|337:43|295:109|295:109|234:115,1,269.999987468719,8|0,3:0|0:0,0:0:0:0:
|
||||
@@ -4,7 +4,6 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using NUnit.Framework;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.IO;
|
||||
@@ -19,23 +18,9 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
public class StackingTest
|
||||
{
|
||||
[Test]
|
||||
public void TestStacking()
|
||||
public void TestStackingEdgeCaseOne()
|
||||
{
|
||||
using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(beatmap_data)))
|
||||
using (var reader = new LineBufferedReader(stream))
|
||||
{
|
||||
var beatmap = Decoder.GetDecoder<Beatmap>(reader).Decode(reader);
|
||||
var converted = new TestWorkingBeatmap(beatmap).GetPlayableBeatmap(new OsuRuleset().RulesetInfo, Array.Empty<Mod>());
|
||||
|
||||
var objects = converted.HitObjects.ToList();
|
||||
|
||||
// The last hitobject triggers the stacking
|
||||
for (int i = 0; i < objects.Count - 1; i++)
|
||||
Assert.AreEqual(0, ((OsuHitObject)objects[i]).StackHeight);
|
||||
}
|
||||
}
|
||||
|
||||
private const string beatmap_data = @"
|
||||
using (var stream = new MemoryStream(@"
|
||||
osu file format v14
|
||||
|
||||
[General]
|
||||
@@ -62,6 +47,65 @@ SliderTickRate:0.5
|
||||
311,185,218471,2,0,L|325:209,1,25
|
||||
311,185,218671,2,0,L|304:212,1,25
|
||||
311,185,240271,5,0,0:0:0:0:
|
||||
";
|
||||
"u8.ToArray()))
|
||||
using (var reader = new LineBufferedReader(stream))
|
||||
{
|
||||
var beatmap = Decoder.GetDecoder<Beatmap>(reader).Decode(reader);
|
||||
var converted = new TestWorkingBeatmap(beatmap).GetPlayableBeatmap(new OsuRuleset().RulesetInfo, Array.Empty<Mod>());
|
||||
|
||||
var objects = converted.HitObjects.ToList();
|
||||
|
||||
// The last hitobject triggers the stacking
|
||||
for (int i = 0; i < objects.Count - 1; i++)
|
||||
Assert.AreEqual(0, ((OsuHitObject)objects[i]).StackHeight);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestStackingEdgeCaseTwo()
|
||||
{
|
||||
using (var stream = new MemoryStream(@"
|
||||
osu file format v14
|
||||
// extracted from https://osu.ppy.sh/beatmapsets/365006#osu/801165
|
||||
|
||||
[General]
|
||||
StackLeniency: 0.2
|
||||
|
||||
[Difficulty]
|
||||
HPDrainRate:6
|
||||
CircleSize:4
|
||||
OverallDifficulty:8
|
||||
ApproachRate:9.3
|
||||
SliderMultiplier:2
|
||||
SliderTickRate:1
|
||||
|
||||
[TimingPoints]
|
||||
5338,444.444444444444,4,2,0,50,1,0
|
||||
82893,-76.9230769230769,4,2,8,50,0,0
|
||||
85115,-76.9230769230769,4,2,0,50,0,0
|
||||
85337,-100,4,2,8,60,0,0
|
||||
85893,-100,4,2,7,60,0,0
|
||||
86226,-100,4,2,8,60,0,0
|
||||
88893,-58.8235294117647,4,1,8,70,0,1
|
||||
|
||||
[HitObjects]
|
||||
427,124,84226,1,0,3:0:0:0:
|
||||
427,124,84337,1,0,3:0:0:0:
|
||||
427,124,84449,1,8,0:0:0:0:
|
||||
"u8.ToArray()))
|
||||
using (var reader = new LineBufferedReader(stream))
|
||||
{
|
||||
var beatmap = Decoder.GetDecoder<Beatmap>(reader).Decode(reader);
|
||||
var converted = new TestWorkingBeatmap(beatmap).GetPlayableBeatmap(new OsuRuleset().RulesetInfo, Array.Empty<Mod>());
|
||||
|
||||
var objects = converted.HitObjects.ToList();
|
||||
|
||||
Assert.That(objects, Has.Count.EqualTo(3));
|
||||
|
||||
// The last hitobject triggers the stacking
|
||||
for (int i = 0; i < objects.Count - 1; i++)
|
||||
Assert.AreEqual(0, ((OsuHitObject)objects[i]).StackHeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
// 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.Framework.Allocation;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Skinning;
|
||||
using osu.Game.Tests.Visual;
|
||||
using osuTK.Input;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Tests
|
||||
{
|
||||
public partial class TestSceneGameplayCursorSizeChange : PlayerTestScene
|
||||
{
|
||||
private const float initial_cursor_size = 1f;
|
||||
protected override Ruleset CreatePlayerRuleset() => new OsuRuleset();
|
||||
|
||||
[Resolved]
|
||||
private SkinManager? skins { get; set; }
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
if (skins != null) skins.CurrentSkinInfo.Value = skins.DefaultClassicSkin.SkinInfo;
|
||||
}
|
||||
|
||||
[SetUpSteps]
|
||||
public override void SetUpSteps()
|
||||
{
|
||||
base.SetUpSteps();
|
||||
|
||||
AddStep("Set gameplay cursor size: 1", () => LocalConfig.SetValue(OsuSetting.GameplayCursorSize, initial_cursor_size));
|
||||
AddStep("resume player", () => Player.GameplayClockContainer.Start());
|
||||
AddUntilStep("clock running", () => Player.GameplayClockContainer.IsRunning);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestPausedChangeCursorSize()
|
||||
{
|
||||
AddStep("move cursor to center", () => InputManager.MoveMouseTo(Player.ScreenSpaceDrawQuad.Centre));
|
||||
AddStep("move cursor to top left", () => InputManager.MoveMouseTo(Player.ScreenSpaceDrawQuad.TopLeft));
|
||||
AddStep("move cursor to center", () => InputManager.MoveMouseTo(Player.ScreenSpaceDrawQuad.Centre));
|
||||
AddStep("move cursor to top right", () => InputManager.MoveMouseTo(Player.ScreenSpaceDrawQuad.TopRight));
|
||||
AddStep("press escape", () => InputManager.Key(Key.Escape));
|
||||
|
||||
AddSliderStep("cursor size", 0.1f, 2f, 1f, v => LocalConfig.SetValue(OsuSetting.GameplayCursorSize, v));
|
||||
}
|
||||
|
||||
protected override TestPlayer CreatePlayer(Ruleset ruleset) => new TestPlayer(true, false);
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Input.Events;
|
||||
@@ -10,6 +11,7 @@ using osu.Framework.Input.States;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Framework.Testing.Input;
|
||||
using osu.Game.Rulesets.Osu.UI;
|
||||
using osu.Game.Skinning;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Tests
|
||||
@@ -58,7 +60,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
||||
|
||||
foreach (var smokeContainer in smokeContainers)
|
||||
{
|
||||
if (smokeContainer.Children.Count != 0)
|
||||
if (smokeContainer.Children.OfType<SkinnableDrawable>().Any())
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -91,7 +91,7 @@ namespace osu.Game.Rulesets.Osu.Beatmaps
|
||||
continue;
|
||||
|
||||
double endTime = stackBaseObject.GetEndTime();
|
||||
double stackThreshold = objectN.TimePreempt * beatmap.StackLeniency;
|
||||
float stackThreshold = calculateStackThreshold(beatmap, objectN);
|
||||
|
||||
if (objectN.StartTime - endTime > stackThreshold)
|
||||
// We are no longer within stacking range of the next object.
|
||||
@@ -136,7 +136,7 @@ namespace osu.Game.Rulesets.Osu.Beatmaps
|
||||
OsuHitObject objectI = hitObjects[i];
|
||||
if (objectI.StackHeight != 0 || objectI is Spinner) continue;
|
||||
|
||||
double stackThreshold = objectI.TimePreempt * beatmap.StackLeniency;
|
||||
float stackThreshold = calculateStackThreshold(beatmap, objectI);
|
||||
|
||||
/* If this object is a hitcircle, then we enter this "special" case.
|
||||
* It either ends with a stack of hitcircles only, or a stack of hitcircles that are underneath a slider.
|
||||
@@ -151,7 +151,10 @@ namespace osu.Game.Rulesets.Osu.Beatmaps
|
||||
|
||||
double endTime = objectN.GetEndTime();
|
||||
|
||||
if (objectI.StartTime - endTime > stackThreshold)
|
||||
// truncation to integer is required to match stable
|
||||
// compare https://github.com/peppy/osu-stable-reference/blob/08e3dafd525934cf48880b08e91c24ce4ad8b761/osu!/GameplayElements/HitObjectManager.cs#L1725
|
||||
// - both quantities being subtracted there are integers
|
||||
if ((int)objectI.StartTime - (int)endTime > stackThreshold)
|
||||
// We are no longer within stacking range of the previous object.
|
||||
break;
|
||||
|
||||
@@ -232,7 +235,7 @@ namespace osu.Game.Rulesets.Osu.Beatmaps
|
||||
|
||||
for (int j = i + 1; j < hitObjects.Count; j++)
|
||||
{
|
||||
double stackThreshold = hitObjects[i].TimePreempt * beatmap.StackLeniency;
|
||||
float stackThreshold = calculateStackThreshold(beatmap, hitObjects[i]);
|
||||
|
||||
if (hitObjects[j].StartTime - stackThreshold > startTime)
|
||||
break;
|
||||
@@ -264,5 +267,17 @@ namespace osu.Game.Rulesets.Osu.Beatmaps
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <remarks>
|
||||
/// Truncation of <see cref="OsuHitObject.TimePreempt"/> to <see cref="int"/>, as well as keeping the result as <see cref="float"/>, are both done
|
||||
/// <a href="https://github.com/peppy/osu-stable-reference/blob/08e3dafd525934cf48880b08e91c24ce4ad8b761/osu!/GameplayElements/HitObjectManager.cs#L1652">
|
||||
/// for the purposes of stable compatibility
|
||||
/// </a>.
|
||||
/// Note that for top-level objects <see cref="OsuHitObject.TimePreempt"/> is supposed to be integral anyway;
|
||||
/// see <see cref="OsuHitObject.ApplyDefaultsToSelf"/> using <see cref="IBeatmapDifficultyInfo.DifficultyRangeInt"/> when calculating it.
|
||||
/// Slider ticks and end circles are the exception to that, but they do not matter for stacking.
|
||||
/// </remarks>
|
||||
private static float calculateStackThreshold(IBeatmap beatmap, OsuHitObject hitObject)
|
||||
=> (int)hitObject.TimePreempt * beatmap.StackLeniency;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty
|
||||
{
|
||||
private const double star_rating_multiplier = 0.0265;
|
||||
|
||||
public override int Version => 20250306;
|
||||
public override int Version => 20251020;
|
||||
|
||||
public OsuDifficultyCalculator(IRulesetInfo ruleset, IWorkingBeatmap beatmap)
|
||||
: base(ruleset, beatmap)
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints
|
||||
{
|
||||
this.gridToolboxGroup = gridToolboxGroup;
|
||||
originalOrigin = gridToolboxGroup.StartPosition.Value;
|
||||
originalSpacing = gridToolboxGroup.Spacing.Value;
|
||||
originalSpacing = gridToolboxGroup.GridLineSpacing.Value;
|
||||
originalRotation = gridToolboxGroup.GridLinesRotation.Value;
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints
|
||||
{
|
||||
// Reset the grid to the default values.
|
||||
gridToolboxGroup.StartPosition.Value = gridToolboxGroup.StartPosition.Default;
|
||||
gridToolboxGroup.Spacing.Value = gridToolboxGroup.Spacing.Default;
|
||||
gridToolboxGroup.GridLineSpacing.Value = gridToolboxGroup.GridLineSpacing.Default;
|
||||
if (!gridToolboxGroup.GridLinesRotation.Disabled)
|
||||
gridToolboxGroup.GridLinesRotation.Value = gridToolboxGroup.GridLinesRotation.Default;
|
||||
EndPlacement(true);
|
||||
@@ -112,7 +112,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints
|
||||
// Default to the original spacing and rotation if the distance is too small.
|
||||
if (Vector2.Distance(gridToolboxGroup.StartPosition.Value, pos) < 2)
|
||||
{
|
||||
gridToolboxGroup.Spacing.Value = originalSpacing;
|
||||
gridToolboxGroup.GridLineSpacing.Value = originalSpacing;
|
||||
if (!gridToolboxGroup.GridLinesRotation.Disabled)
|
||||
gridToolboxGroup.GridLinesRotation.Value = originalRotation;
|
||||
}
|
||||
@@ -134,7 +134,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints
|
||||
private void resetGridState()
|
||||
{
|
||||
gridToolboxGroup.StartPosition.Value = originalOrigin;
|
||||
gridToolboxGroup.Spacing.Value = originalSpacing;
|
||||
gridToolboxGroup.GridLineSpacing.Value = originalSpacing;
|
||||
if (!gridToolboxGroup.GridLinesRotation.Disabled)
|
||||
gridToolboxGroup.GridLinesRotation.Value = originalRotation;
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ namespace osu.Game.Rulesets.Osu.Edit.Blueprints.Sliders
|
||||
|
||||
private readonly IncrementalBSplineBuilder bSplineBuilder = new IncrementalBSplineBuilder { Degree = 4 };
|
||||
|
||||
protected override bool IsValidForPlacement => HitObject.Path.HasValidLengthForPlacement;
|
||||
protected override bool IsValidForPlacement => base.IsValidForPlacement && (PlacementActive == PlacementState.Waiting || HitObject.Path.HasValidLengthForPlacement);
|
||||
|
||||
public SliderPlacementBlueprint()
|
||||
: base(new Slider())
|
||||
|
||||
@@ -5,8 +5,10 @@ using System;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Game.Graphics.Containers;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Rulesets.Edit;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.Edit
|
||||
{
|
||||
@@ -42,25 +44,31 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
private readonly BindableInt displayTolerance = new BindableInt(90)
|
||||
{
|
||||
MinValue = 5,
|
||||
MaxValue = 100
|
||||
MaxValue = 100,
|
||||
Precision = 1,
|
||||
};
|
||||
|
||||
private readonly BindableInt displayCornerThreshold = new BindableInt(40)
|
||||
{
|
||||
MinValue = 5,
|
||||
MaxValue = 100
|
||||
MaxValue = 100,
|
||||
Precision = 1,
|
||||
};
|
||||
|
||||
private readonly BindableInt displayCircleThreshold = new BindableInt(30)
|
||||
{
|
||||
MinValue = 0,
|
||||
MaxValue = 100
|
||||
MaxValue = 100,
|
||||
Precision = 1,
|
||||
};
|
||||
|
||||
private ExpandableSlider<int> toleranceSlider = null!;
|
||||
private ExpandableSlider<int> cornerThresholdSlider = null!;
|
||||
private ExpandableSlider<int> circleThresholdSlider = null!;
|
||||
|
||||
[Resolved]
|
||||
private IExpandingContainer? expandingContainer { get; set; }
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
@@ -68,15 +76,18 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
{
|
||||
toleranceSlider = new ExpandableSlider<int>
|
||||
{
|
||||
Current = displayTolerance
|
||||
Current = displayTolerance,
|
||||
ExpandedLabelText = "Control point spacing",
|
||||
},
|
||||
cornerThresholdSlider = new ExpandableSlider<int>
|
||||
{
|
||||
Current = displayCornerThreshold
|
||||
Current = displayCornerThreshold,
|
||||
ExpandedLabelText = "Corner bias",
|
||||
},
|
||||
circleThresholdSlider = new ExpandableSlider<int>
|
||||
{
|
||||
Current = displayCircleThreshold
|
||||
Current = displayCircleThreshold,
|
||||
ExpandedLabelText = "Perfect curve bias"
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -88,24 +99,18 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
displayTolerance.BindValueChanged(tolerance =>
|
||||
{
|
||||
toleranceSlider.ContractedLabelText = $"C. P. S.: {tolerance.NewValue:N0}";
|
||||
toleranceSlider.ExpandedLabelText = $"Control Point Spacing: {tolerance.NewValue:N0}";
|
||||
|
||||
Tolerance.Value = displayToInternalTolerance(tolerance.NewValue);
|
||||
}, true);
|
||||
|
||||
displayCornerThreshold.BindValueChanged(threshold =>
|
||||
{
|
||||
cornerThresholdSlider.ContractedLabelText = $"C. T.: {threshold.NewValue:N0}";
|
||||
cornerThresholdSlider.ExpandedLabelText = $"Corner Threshold: {threshold.NewValue:N0}";
|
||||
|
||||
cornerThresholdSlider.ContractedLabelText = $"C. B.: {threshold.NewValue:N0}";
|
||||
CornerThreshold.Value = displayToInternalCornerThreshold(threshold.NewValue);
|
||||
}, true);
|
||||
|
||||
displayCircleThreshold.BindValueChanged(threshold =>
|
||||
{
|
||||
circleThresholdSlider.ContractedLabelText = $"P. C. T.: {threshold.NewValue:N0}";
|
||||
circleThresholdSlider.ExpandedLabelText = $"Perfect Curve Threshold: {threshold.NewValue:N0}";
|
||||
|
||||
circleThresholdSlider.ContractedLabelText = $"P. C. B.: {threshold.NewValue:N0}";
|
||||
CircleThreshold.Value = displayToInternalCircleThreshold(threshold.NewValue);
|
||||
}, true);
|
||||
|
||||
@@ -119,6 +124,11 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
displayCircleThreshold.Value = internalToDisplayCircleThreshold(threshold.NewValue)
|
||||
);
|
||||
|
||||
expandingContainer?.Expanded.BindValueChanged(v =>
|
||||
{
|
||||
Spacing = v.NewValue ? new Vector2(5) : new Vector2(15);
|
||||
}, true);
|
||||
|
||||
float displayToInternalTolerance(float v) => v / 50f;
|
||||
int internalToDisplayTolerance(float v) => (int)Math.Round(v * 50f);
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
{
|
||||
MinValue = 0f,
|
||||
MaxValue = OsuPlayfield.BASE_SIZE.X,
|
||||
Precision = 0.01f,
|
||||
Precision = 0.1f,
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
@@ -48,17 +48,17 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
{
|
||||
MinValue = 0f,
|
||||
MaxValue = OsuPlayfield.BASE_SIZE.Y,
|
||||
Precision = 0.01f,
|
||||
Precision = 0.1f,
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// The spacing between grid lines.
|
||||
/// </summary>
|
||||
public BindableFloat Spacing { get; } = new BindableFloat(4f)
|
||||
public BindableFloat GridLineSpacing { get; } = new BindableFloat(4f)
|
||||
{
|
||||
MinValue = 4f,
|
||||
MaxValue = 256f,
|
||||
Precision = 0.01f,
|
||||
Precision = 0.1f,
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
@@ -68,7 +68,7 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
{
|
||||
MinValue = -180f,
|
||||
MaxValue = 180f,
|
||||
Precision = 0.01f,
|
||||
Precision = 0.1f,
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
@@ -115,7 +115,7 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
float dist = Vector2.Distance(point1, point2);
|
||||
while (dist >= max_automatic_spacing)
|
||||
dist /= 2;
|
||||
Spacing.Value = dist;
|
||||
GridLineSpacing.Value = dist;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
@@ -127,21 +127,25 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
{
|
||||
Current = StartPositionX,
|
||||
KeyboardStep = 1,
|
||||
ExpandedLabelText = "X offset",
|
||||
},
|
||||
startPositionYSlider = new ExpandableSlider<float>
|
||||
{
|
||||
Current = StartPositionY,
|
||||
KeyboardStep = 1,
|
||||
ExpandedLabelText = "Y offset",
|
||||
},
|
||||
spacingSlider = new ExpandableSlider<float>
|
||||
{
|
||||
Current = Spacing,
|
||||
Current = GridLineSpacing,
|
||||
KeyboardStep = 1,
|
||||
ExpandedLabelText = "Spacing",
|
||||
},
|
||||
gridLinesRotationSlider = new ExpandableSlider<float>
|
||||
{
|
||||
Current = GridLinesRotation,
|
||||
KeyboardStep = 1,
|
||||
ExpandedLabelText = "Rotation",
|
||||
},
|
||||
new FillFlowContainer
|
||||
{
|
||||
@@ -170,7 +174,7 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
},
|
||||
};
|
||||
|
||||
Spacing.Value = editorBeatmap.GridSize;
|
||||
GridLineSpacing.Value = editorBeatmap.GridSize;
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
@@ -182,14 +186,12 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
StartPositionX.BindValueChanged(x =>
|
||||
{
|
||||
startPositionXSlider.ContractedLabelText = $"X: {x.NewValue:#,0.##}";
|
||||
startPositionXSlider.ExpandedLabelText = $"X Offset: {x.NewValue:#,0.##}";
|
||||
StartPosition.Value = new Vector2(x.NewValue, StartPosition.Value.Y);
|
||||
}, true);
|
||||
|
||||
StartPositionY.BindValueChanged(y =>
|
||||
{
|
||||
startPositionYSlider.ContractedLabelText = $"Y: {y.NewValue:#,0.##}";
|
||||
startPositionYSlider.ExpandedLabelText = $"Y Offset: {y.NewValue:#,0.##}";
|
||||
StartPosition.Value = new Vector2(StartPosition.Value.X, y.NewValue);
|
||||
}, true);
|
||||
|
||||
@@ -199,10 +201,9 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
StartPositionY.Value = pos.NewValue.Y;
|
||||
});
|
||||
|
||||
Spacing.BindValueChanged(spacing =>
|
||||
GridLineSpacing.BindValueChanged(spacing =>
|
||||
{
|
||||
spacingSlider.ContractedLabelText = $"S: {spacing.NewValue:#,0.##}";
|
||||
spacingSlider.ExpandedLabelText = $"Spacing: {spacing.NewValue:#,0.##}";
|
||||
SpacingVector.Value = new Vector2(spacing.NewValue);
|
||||
editorBeatmap.GridSize = (int)spacing.NewValue;
|
||||
}, true);
|
||||
@@ -210,7 +211,6 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
GridLinesRotation.BindValueChanged(rotation =>
|
||||
{
|
||||
gridLinesRotationSlider.ContractedLabelText = $"R: {rotation.NewValue:#,0.##}";
|
||||
gridLinesRotationSlider.ExpandedLabelText = $"Rotation: {rotation.NewValue:#,0.##}";
|
||||
}, true);
|
||||
|
||||
GridType.BindValueChanged(v =>
|
||||
@@ -239,6 +239,8 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
{
|
||||
gridTypeButtons.FadeTo(v.NewValue ? 1f : 0f, 500, Easing.OutQuint);
|
||||
gridTypeButtons.BypassAutoSizeAxes = !v.NewValue ? Axes.Y : Axes.None;
|
||||
|
||||
Spacing = v.NewValue ? new Vector2(5) : new Vector2(15);
|
||||
}, true);
|
||||
}
|
||||
|
||||
@@ -252,7 +254,7 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
switch (e.Action)
|
||||
{
|
||||
case GlobalAction.EditorCycleGridSpacing:
|
||||
Spacing.Value = Spacing.Value * 2 >= max_automatic_spacing ? Spacing.Value / 8 : Spacing.Value * 2;
|
||||
GridLineSpacing.Value = GridLineSpacing.Value * 2 >= max_automatic_spacing ? GridLineSpacing.Value / 8 : GridLineSpacing.Value * 2;
|
||||
return true;
|
||||
|
||||
case GlobalAction.EditorCycleGridType:
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using JetBrains.Annotations;
|
||||
@@ -142,7 +143,7 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
case PositionSnapGridType.Triangle:
|
||||
var triangularPositionSnapGrid = new TriangularPositionSnapGrid();
|
||||
|
||||
triangularPositionSnapGrid.Spacing.BindTo(OsuGridToolboxGroup.Spacing);
|
||||
triangularPositionSnapGrid.Spacing.BindTo(OsuGridToolboxGroup.GridLineSpacing);
|
||||
triangularPositionSnapGrid.GridLineRotation.BindTo(OsuGridToolboxGroup.GridLinesRotation);
|
||||
|
||||
positionSnapGrid = triangularPositionSnapGrid;
|
||||
@@ -151,7 +152,7 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
case PositionSnapGridType.Circle:
|
||||
var circularPositionSnapGrid = new CircularPositionSnapGrid();
|
||||
|
||||
circularPositionSnapGrid.Spacing.BindTo(OsuGridToolboxGroup.Spacing);
|
||||
circularPositionSnapGrid.Spacing.BindTo(OsuGridToolboxGroup.GridLineSpacing);
|
||||
|
||||
positionSnapGrid = circularPositionSnapGrid;
|
||||
break;
|
||||
@@ -171,7 +172,8 @@ namespace osu.Game.Rulesets.Osu.Edit
|
||||
=> new OsuBlueprintContainer(this);
|
||||
|
||||
public override string ConvertSelectionToString()
|
||||
=> string.Join(',', selectedHitObjects.Cast<OsuHitObject>().OrderBy(h => h.StartTime).Select(h => (h.IndexInCurrentCombo + 1).ToString()));
|
||||
=> string.Join(',', selectedHitObjects.Cast<OsuHitObject>().OrderBy(h => h.StartTime)
|
||||
.Select(h => (h.IndexInCurrentCombo + 1).ToString(CultureInfo.InvariantCulture)));
|
||||
|
||||
// 1,2,3,4 ...
|
||||
private static readonly Regex selection_regex = new Regex(@"^\d+(,\d+)*$", RegexOptions.Compiled);
|
||||
|
||||
@@ -67,6 +67,9 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
{
|
||||
if (LastAcceptedAction != null && nonGameplayPeriods.IsInAny(gameplayClock.CurrentTime))
|
||||
LastAcceptedAction = null;
|
||||
|
||||
if (LastAcceptedAction != null && gameplayClock.IsRewinding)
|
||||
LastAcceptedAction = null;
|
||||
}
|
||||
|
||||
protected abstract bool CheckValidNewAction(OsuAction action);
|
||||
|
||||
@@ -16,6 +16,7 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
public override LocalisableString Description => @"Don't use the same key twice in a row!";
|
||||
public override IconUsage? Icon => OsuIcon.ModAlternate;
|
||||
public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(OsuModSingleTap) }).ToArray();
|
||||
public override bool Ranked => true;
|
||||
|
||||
protected override bool CheckValidNewAction(OsuAction action) => LastAcceptedAction != action;
|
||||
}
|
||||
|
||||
@@ -51,7 +51,8 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
|
||||
return string.Empty;
|
||||
|
||||
string format(string acronym, DifficultyBindable bindable) => $"{acronym}{bindable.Value!.Value.ToStandardFormattedString(1)}";
|
||||
string format(string acronym, DifficultyBindable bindable)
|
||||
=> $"{acronym}{bindable.Value!.Value.ToStandardFormattedString(1)}";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ namespace osu.Game.Rulesets.Osu.Mods
|
||||
public override IconUsage? Icon => OsuIcon.ModSingleTap;
|
||||
public override LocalisableString Description => @"You must only use one key!";
|
||||
public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(OsuModAlternate) }).ToArray();
|
||||
public override bool Ranked => true;
|
||||
|
||||
protected override bool CheckValidNewAction(OsuAction action) => LastAcceptedAction == null || LastAcceptedAction == action;
|
||||
}
|
||||
|
||||
@@ -171,7 +171,7 @@ namespace osu.Game.Rulesets.Osu.Objects
|
||||
{
|
||||
base.ApplyDefaultsToSelf(controlPointInfo, difficulty);
|
||||
|
||||
TimePreempt = (float)IBeatmapDifficultyInfo.DifficultyRange(difficulty.ApproachRate, PREEMPT_RANGE);
|
||||
TimePreempt = IBeatmapDifficultyInfo.DifficultyRangeInt(difficulty.ApproachRate, PREEMPT_RANGE);
|
||||
|
||||
// Preempt time can go below 450ms. Normally, this is achieved via the DT mod which uniformly speeds up all animations game wide regardless of AR.
|
||||
// This uniform speedup is hard to match 1:1, however we can at least make AR>10 (via mods) feel good by extending the upper linear function above.
|
||||
|
||||
@@ -412,7 +412,8 @@ namespace osu.Game.Rulesets.Osu
|
||||
Description = "Affects how early objects appear on screen relative to their hit time.",
|
||||
AdditionalMetrics =
|
||||
[
|
||||
new RulesetBeatmapAttribute.AdditionalMetric("Approach time", LocalisableString.Interpolate($@"{IBeatmapDifficultyInfo.DifficultyRange(effectiveDifficulty.ApproachRate, OsuHitObject.PREEMPT_RANGE):#,0.##} ms"))
|
||||
new RulesetBeatmapAttribute.AdditionalMetric("Approach time",
|
||||
LocalisableString.Interpolate($@"{IBeatmapDifficultyInfo.DifficultyRangeInt(effectiveDifficulty.ApproachRate, OsuHitObject.PREEMPT_RANGE):#,0.##} ms"))
|
||||
]
|
||||
};
|
||||
|
||||
|
||||
@@ -103,6 +103,9 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy
|
||||
leaderboard.Origin = Anchor.BottomLeft;
|
||||
leaderboard.Position = pos;
|
||||
}
|
||||
|
||||
foreach (var d in container.OfType<ISerialisableDrawable>())
|
||||
d.UsesFixedAnchor = true;
|
||||
})
|
||||
{
|
||||
Children = new Drawable[]
|
||||
|
||||
@@ -77,9 +77,14 @@ namespace osu.Game.Rulesets.Osu.Skinning
|
||||
base.LoadComplete();
|
||||
|
||||
RelativeSizeAxes = Axes.Both;
|
||||
}
|
||||
|
||||
LifetimeStart = smokeStartTime = Time.Current;
|
||||
|
||||
public void StartDrawing(double time)
|
||||
{
|
||||
LifetimeStart = smokeStartTime = time;
|
||||
LifetimeEnd = smokeEndTime = double.MaxValue;
|
||||
SmokePoints.Clear();
|
||||
lastPosition = null;
|
||||
totalDistance = pointInterval;
|
||||
}
|
||||
|
||||
|
||||
@@ -49,6 +49,18 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
||||
/// </summary>
|
||||
protected bool AllowPartRotation { get; set; }
|
||||
|
||||
private Vector2 cursorScale = Vector2.One;
|
||||
|
||||
public Vector2 CursorScale
|
||||
{
|
||||
get => cursorScale;
|
||||
set
|
||||
{
|
||||
cursorScale = value;
|
||||
Invalidate(Invalidation.DrawNode);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The trail part texture origin.
|
||||
/// </summary>
|
||||
@@ -186,7 +198,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
||||
float distance = diff.Length;
|
||||
Vector2 direction = diff / distance;
|
||||
|
||||
float interval = Texture.DisplayWidth / 2.5f * IntervalMultiplier;
|
||||
float interval = Texture.DisplayWidth * CursorScale.X / 2.5f * IntervalMultiplier;
|
||||
float stopAt = distance - (AvoidDrawingNearCursor ? interval : 0);
|
||||
|
||||
for (float d = interval; d < stopAt; d += interval)
|
||||
@@ -233,6 +245,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
||||
private float time;
|
||||
private float fadeExponent;
|
||||
private float angle;
|
||||
private Vector2 cursorScale;
|
||||
|
||||
private readonly TrailPart[] parts = new TrailPart[max_sprites];
|
||||
private Vector2 originPosition;
|
||||
@@ -253,6 +266,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
||||
time = Source.time;
|
||||
fadeExponent = Source.FadeExponent;
|
||||
angle = Source.AllowPartRotation ? float.DegreesToRadians(Source.PartRotation) : 0;
|
||||
cursorScale = Source.cursorScale;
|
||||
|
||||
originPosition = Vector2.Zero;
|
||||
|
||||
@@ -307,7 +321,9 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
||||
vertexBatch.Add(new TexturedTrailVertex
|
||||
{
|
||||
Position = rotateAround(
|
||||
new Vector2(part.Position.X - texture.DisplayWidth * originPosition.X * part.Scale.X, part.Position.Y + texture.DisplayHeight * (1 - originPosition.Y) * part.Scale.Y),
|
||||
new Vector2(
|
||||
part.Position.X - texture.DisplayWidth * originPosition.X * part.Scale.X * cursorScale.X,
|
||||
part.Position.Y + texture.DisplayHeight * (1 - originPosition.Y) * part.Scale.Y * cursorScale.Y),
|
||||
part.Position, sin, cos),
|
||||
TexturePosition = textureRect.BottomLeft,
|
||||
TextureRect = new Vector4(0, 0, 1, 1),
|
||||
@@ -318,8 +334,10 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
||||
vertexBatch.Add(new TexturedTrailVertex
|
||||
{
|
||||
Position = rotateAround(
|
||||
new Vector2(part.Position.X + texture.DisplayWidth * (1 - originPosition.X) * part.Scale.X,
|
||||
part.Position.Y + texture.DisplayHeight * (1 - originPosition.Y) * part.Scale.Y), part.Position, sin, cos),
|
||||
new Vector2(
|
||||
part.Position.X + texture.DisplayWidth * (1 - originPosition.X) * part.Scale.X * cursorScale.X,
|
||||
part.Position.Y + texture.DisplayHeight * (1 - originPosition.Y) * part.Scale.Y * cursorScale.Y),
|
||||
part.Position, sin, cos),
|
||||
TexturePosition = textureRect.BottomRight,
|
||||
TextureRect = new Vector4(0, 0, 1, 1),
|
||||
Colour = DrawColourInfo.Colour.BottomRight.Linear,
|
||||
@@ -329,7 +347,9 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
||||
vertexBatch.Add(new TexturedTrailVertex
|
||||
{
|
||||
Position = rotateAround(
|
||||
new Vector2(part.Position.X + texture.DisplayWidth * (1 - originPosition.X) * part.Scale.X, part.Position.Y - texture.DisplayHeight * originPosition.Y * part.Scale.Y),
|
||||
new Vector2(
|
||||
part.Position.X + texture.DisplayWidth * (1 - originPosition.X) * part.Scale.X * cursorScale.X,
|
||||
part.Position.Y - texture.DisplayHeight * originPosition.Y * part.Scale.Y * cursorScale.Y),
|
||||
part.Position, sin, cos),
|
||||
TexturePosition = textureRect.TopRight,
|
||||
TextureRect = new Vector4(0, 0, 1, 1),
|
||||
@@ -340,7 +360,9 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
||||
vertexBatch.Add(new TexturedTrailVertex
|
||||
{
|
||||
Position = rotateAround(
|
||||
new Vector2(part.Position.X - texture.DisplayWidth * originPosition.X * part.Scale.X, part.Position.Y - texture.DisplayHeight * originPosition.Y * part.Scale.Y),
|
||||
new Vector2(
|
||||
part.Position.X - texture.DisplayWidth * originPosition.X * part.Scale.X * cursorScale.X,
|
||||
part.Position.Y - texture.DisplayHeight * originPosition.Y * part.Scale.Y * cursorScale.Y),
|
||||
part.Position, sin, cos),
|
||||
TexturePosition = textureRect.TopLeft,
|
||||
TextureRect = new Vector4(0, 0, 1, 1),
|
||||
|
||||
@@ -64,8 +64,14 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
||||
var newScale = new Vector2(e.NewValue);
|
||||
|
||||
rippleVisualiser.CursorScale = newScale;
|
||||
cursorTrail.Scale = newScale;
|
||||
updateTrailScale();
|
||||
}, true);
|
||||
cursorTrail.OnSkinChanged += updateTrailScale;
|
||||
}
|
||||
|
||||
private void updateTrailScale()
|
||||
{
|
||||
if (cursorTrail.Drawable is CursorTrail trail) trail.CursorScale = new Vector2(ActiveCursor.CursorScale.Value);
|
||||
}
|
||||
|
||||
private int downCount;
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Extensions.Color4Extensions;
|
||||
using osu.Framework.Graphics.Lines;
|
||||
using osu.Framework.Graphics.Performance;
|
||||
using osu.Game.Graphics;
|
||||
@@ -12,7 +11,7 @@ using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Osu.UI.ReplayAnalysis
|
||||
{
|
||||
public partial class CursorPathContainer : Path
|
||||
public partial class CursorPathContainer : SmoothPath
|
||||
{
|
||||
private readonly LifetimeEntryManager lifetimeManager = new LifetimeEntryManager();
|
||||
private readonly SortedSet<AnalysisFrameEntry> aliveEntries = new SortedSet<AnalysisFrameEntry>(new AimLinePointComparator());
|
||||
@@ -22,14 +21,13 @@ namespace osu.Game.Rulesets.Osu.UI.ReplayAnalysis
|
||||
lifetimeManager.EntryBecameAlive += entryBecameAlive;
|
||||
lifetimeManager.EntryBecameDead += entryBecameDead;
|
||||
|
||||
PathRadius = 0.5f;
|
||||
PathRadius = 1f;
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
Colour = colours.Pink2;
|
||||
BackgroundColour = colours.Pink2.Opacity(0);
|
||||
}
|
||||
|
||||
protected override void Update()
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Localisation;
|
||||
using osu.Game.Rulesets.Osu.Configuration;
|
||||
using osu.Game.Screens.Play.PlayerSettings;
|
||||
|
||||
@@ -13,19 +14,19 @@ namespace osu.Game.Rulesets.Osu.UI
|
||||
{
|
||||
private readonly OsuRulesetConfigManager config;
|
||||
|
||||
[SettingSource("Show click markers", SettingControlType = typeof(PlayerCheckbox))]
|
||||
[SettingSource(typeof(PlayerSettingsOverlayStrings), nameof(PlayerSettingsOverlayStrings.ShowClickMarkers), SettingControlType = typeof(PlayerCheckbox))]
|
||||
public BindableBool ShowClickMarkers { get; } = new BindableBool();
|
||||
|
||||
[SettingSource("Show frame markers", SettingControlType = typeof(PlayerCheckbox))]
|
||||
[SettingSource(typeof(PlayerSettingsOverlayStrings), nameof(PlayerSettingsOverlayStrings.ShowFrameMarkers), SettingControlType = typeof(PlayerCheckbox))]
|
||||
public BindableBool ShowAimMarkers { get; } = new BindableBool();
|
||||
|
||||
[SettingSource("Show cursor path", SettingControlType = typeof(PlayerCheckbox))]
|
||||
[SettingSource(typeof(PlayerSettingsOverlayStrings), nameof(PlayerSettingsOverlayStrings.ShowCursorPath), SettingControlType = typeof(PlayerCheckbox))]
|
||||
public BindableBool ShowCursorPath { get; } = new BindableBool();
|
||||
|
||||
[SettingSource("Hide gameplay cursor", SettingControlType = typeof(PlayerCheckbox))]
|
||||
[SettingSource(typeof(PlayerSettingsOverlayStrings), nameof(PlayerSettingsOverlayStrings.HideGameplayCursor), SettingControlType = typeof(PlayerCheckbox))]
|
||||
public BindableBool HideSkinCursor { get; } = new BindableBool();
|
||||
|
||||
[SettingSource("Display length", SettingControlType = typeof(PlayerSliderBar<int>))]
|
||||
[SettingSource(typeof(PlayerSettingsOverlayStrings), nameof(PlayerSettingsOverlayStrings.DisplayLength), SettingControlType = typeof(PlayerSliderBar<int>))]
|
||||
public BindableInt DisplayLength { get; } = new BindableInt
|
||||
{
|
||||
MinValue = 200,
|
||||
@@ -35,7 +36,7 @@ namespace osu.Game.Rulesets.Osu.UI
|
||||
};
|
||||
|
||||
public ReplayAnalysisSettings(OsuRulesetConfigManager config)
|
||||
: base("Analysis Settings")
|
||||
: base(PlayerSettingsOverlayStrings.AnalysisSettingsTitle)
|
||||
{
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
// 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.Graphics;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Pooling;
|
||||
using osu.Framework.Input;
|
||||
using osu.Framework.Input.Bindings;
|
||||
using osu.Framework.Input.Events;
|
||||
@@ -19,17 +19,24 @@ namespace osu.Game.Rulesets.Osu.UI
|
||||
/// </summary>
|
||||
public partial class SmokeContainer : Container, IRequireHighFrequencyMousePosition, IKeyBindingHandler<OsuAction>
|
||||
{
|
||||
private DrawablePool<SmokeSkinnableDrawable> segmentPool = null!;
|
||||
private SmokeSkinnableDrawable? currentSegmentSkinnable;
|
||||
|
||||
private Vector2 lastMousePosition;
|
||||
|
||||
public override bool ReceivePositionalInputAt(Vector2 _) => true;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
AddInternal(segmentPool = new DrawablePool<SmokeSkinnableDrawable>(10));
|
||||
}
|
||||
|
||||
public bool OnPressed(KeyBindingPressEvent<OsuAction> e)
|
||||
{
|
||||
if (e.Action == OsuAction.Smoke)
|
||||
{
|
||||
AddInternal(currentSegmentSkinnable = new SmokeSkinnableDrawable(new OsuSkinComponentLookup(OsuSkinComponents.CursorSmoke), _ => new DefaultSmokeSegment()));
|
||||
AddInternal(currentSegmentSkinnable = segmentPool.Get(segment => segment.Segment?.StartDrawing(Time.Current)));
|
||||
|
||||
// Add initial position immediately.
|
||||
addPosition();
|
||||
@@ -59,17 +66,19 @@ namespace osu.Game.Rulesets.Osu.UI
|
||||
return base.OnMouseMove(e);
|
||||
}
|
||||
|
||||
private void addPosition() => (currentSegmentSkinnable?.Drawable as SmokeSegment)?.AddPosition(lastMousePosition, Time.Current);
|
||||
private void addPosition() => currentSegmentSkinnable?.Segment?.AddPosition(lastMousePosition, Time.Current);
|
||||
|
||||
private partial class SmokeSkinnableDrawable : SkinnableDrawable
|
||||
{
|
||||
public SmokeSegment? Segment => Drawable as SmokeSegment;
|
||||
|
||||
public override bool RemoveWhenNotAlive => true;
|
||||
|
||||
public override double LifetimeStart => Drawable.LifetimeStart;
|
||||
public override double LifetimeEnd => Drawable.LifetimeEnd;
|
||||
|
||||
public SmokeSkinnableDrawable(ISkinComponentLookup lookup, Func<ISkinComponentLookup, Drawable>? defaultImplementation = null, ConfineMode confineMode = ConfineMode.NoScaling)
|
||||
: base(lookup, defaultImplementation, confineMode)
|
||||
public SmokeSkinnableDrawable()
|
||||
: base(new OsuSkinComponentLookup(OsuSkinComponents.CursorSmoke), _ => new DefaultSmokeSegment())
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty
|
||||
private bool isRelax;
|
||||
private bool isConvert;
|
||||
|
||||
public override int Version => 20250306;
|
||||
public override int Version => 20251020;
|
||||
|
||||
public TaikoDifficultyCalculator(IRulesetInfo ruleset, IWorkingBeatmap beatmap)
|
||||
: base(ruleset, beatmap)
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace osu.Game.Rulesets.Taiko.Edit.Blueprints
|
||||
[Resolved]
|
||||
private TaikoHitObjectComposer? composer { get; set; }
|
||||
|
||||
protected override bool IsValidForPlacement => Precision.DefinitelyBigger(spanPlacementObject.Duration, 0);
|
||||
protected override bool IsValidForPlacement => base.IsValidForPlacement && (PlacementActive == PlacementState.Waiting || Precision.DefinitelyBigger(spanPlacementObject.Duration, 0));
|
||||
|
||||
public TaikoSpanPlacementBlueprint(HitObject hitObject)
|
||||
: base(hitObject)
|
||||
|
||||
@@ -13,9 +13,9 @@ namespace osu.Game.Rulesets.Taiko.Edit.Checks
|
||||
protected override IEnumerable<(DifficultyRating rating, double thresholdMs, string name)> GetThresholds()
|
||||
{
|
||||
// See lowest difficulty requirements in https://osu.ppy.sh/wiki/en/Ranking_criteria/osu%21taiko#general
|
||||
yield return (DifficultyRating.Hard, new TimeSpan(0, 3, 30).TotalMilliseconds, "Muzukashii");
|
||||
yield return (DifficultyRating.Insane, new TimeSpan(0, 4, 15).TotalMilliseconds, "Oni");
|
||||
yield return (DifficultyRating.Expert, new TimeSpan(0, 5, 0).TotalMilliseconds, "Inner Oni");
|
||||
yield return (DifficultyRating.Hard, new TimeSpan(0, 2, 30).TotalMilliseconds, "Muzukashii");
|
||||
yield return (DifficultyRating.Insane, new TimeSpan(0, 3, 15).TotalMilliseconds, "Oni");
|
||||
yield return (DifficultyRating.Expert, new TimeSpan(0, 4, 0).TotalMilliseconds, "Inner Oni");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,8 @@ namespace osu.Game.Rulesets.Taiko.Mods
|
||||
|
||||
return string.Empty;
|
||||
|
||||
string format(string acronym, DifficultyBindable bindable, int digits) => $"{acronym}{bindable.Value!.Value.ToStandardFormattedString(digits)}";
|
||||
string format(string acronym, DifficultyBindable bindable, int digits)
|
||||
=> $"{acronym}{bindable.Value!.Value.ToStandardFormattedString(digits)}";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ namespace osu.Game.Rulesets.Taiko.Mods
|
||||
public override IconUsage? Icon => OsuIcon.ModSingleTap;
|
||||
public override LocalisableString Description => @"One key for dons, one key for kats.";
|
||||
|
||||
public override bool Ranked => true;
|
||||
public override double ScoreMultiplier => 1.0;
|
||||
public override Type[] IncompatibleMods => new[] { typeof(ModAutoplay), typeof(ModRelax), typeof(TaikoModCinema) };
|
||||
public override ModType Type => ModType.Conversion;
|
||||
|
||||
@@ -22,6 +22,7 @@ namespace osu.Game.Rulesets.Taiko.Mods
|
||||
public override ModType Type => ModType.Conversion;
|
||||
public override double ScoreMultiplier => 1;
|
||||
public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(ModRandom)).ToArray();
|
||||
public override bool Ranked => true;
|
||||
|
||||
public void ApplyToBeatmap(IBeatmap beatmap)
|
||||
{
|
||||
|
||||
@@ -40,6 +40,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
|
||||
private int rollingHits;
|
||||
|
||||
private readonly Container tickContainer;
|
||||
private SkinnableDrawable headPiece;
|
||||
|
||||
private Color4 colourIdle;
|
||||
private Color4 colourEngaged;
|
||||
@@ -59,7 +60,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
|
||||
Content.Add(tickContainer = new Container
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Depth = float.MinValue
|
||||
Depth = -1,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -79,7 +80,13 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
|
||||
|
||||
protected override void RecreatePieces()
|
||||
{
|
||||
if (headPiece != null)
|
||||
Content.Remove(headPiece, true);
|
||||
|
||||
base.RecreatePieces();
|
||||
|
||||
Content.Add(headPiece = createHeadPiece());
|
||||
|
||||
updateColour();
|
||||
Height = HitObject.IsStrong ? TaikoStrongableHitObject.DEFAULT_STRONG_SIZE : TaikoHitObject.DEFAULT_SIZE;
|
||||
}
|
||||
@@ -122,6 +129,12 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
|
||||
protected override SkinnableDrawable CreateMainPiece() => new SkinnableDrawable(new TaikoSkinComponentLookup(TaikoSkinComponents.DrumRollBody),
|
||||
_ => new ElongatedCirclePiece());
|
||||
|
||||
private SkinnableDrawable createHeadPiece() => new SkinnableDrawable(new TaikoSkinComponentLookup(TaikoSkinComponents.DrumRollHead), _ => Empty())
|
||||
{
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
Depth = -2,
|
||||
};
|
||||
|
||||
public override bool OnPressed(KeyBindingPressEvent<TaikoAction> e) => false;
|
||||
|
||||
private void onNewResult(DrawableHitObject obj, JudgementResult result)
|
||||
@@ -174,7 +187,23 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
|
||||
private void updateColour(double fadeDuration = 0)
|
||||
{
|
||||
Color4 newColour = Interpolation.ValueAt((float)rollingHits / rolling_hits_for_engaged_colour, colourIdle, colourEngaged, 0, 1);
|
||||
(MainPiece.Drawable as IHasAccentColour)?.FadeAccent(newColour, fadeDuration);
|
||||
|
||||
if (fadeDuration == 0)
|
||||
{
|
||||
// fade duration is 0 when calling via `RecreatePieces()`.
|
||||
// in this case we want to apply the colour *without* using transforms.
|
||||
// using transforms may result in the application of colour being undone via `DrawableHitObject.UpdateState()` clearing transforms.
|
||||
if (MainPiece.Drawable is IHasAccentColour mainPieceWithAccentColour)
|
||||
mainPieceWithAccentColour.AccentColour = newColour;
|
||||
|
||||
if (headPiece.Drawable is IHasAccentColour headPieceWithAccentColour)
|
||||
headPieceWithAccentColour.AccentColour = newColour;
|
||||
}
|
||||
else
|
||||
{
|
||||
(MainPiece.Drawable as IHasAccentColour)?.FadeAccent(newColour, fadeDuration);
|
||||
(headPiece.Drawable as IHasAccentColour)?.FadeAccent(newColour, fadeDuration);
|
||||
}
|
||||
}
|
||||
|
||||
public partial class StrongNestedHit : DrawableStrongNestedHit
|
||||
|
||||
@@ -51,6 +51,9 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Argon
|
||||
spectatorList.Anchor = Anchor.BottomLeft;
|
||||
spectatorList.Origin = Anchor.TopLeft;
|
||||
}
|
||||
|
||||
foreach (var d in container.OfType<ISerialisableDrawable>())
|
||||
d.UsesFixedAnchor = true;
|
||||
})
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
|
||||
@@ -13,7 +13,8 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Argon
|
||||
public const int SAMPLE_VOLUME_THRESHOLD_MEDIUM = 60;
|
||||
|
||||
public VolumeAwareHitSampleInfo(HitSampleInfo sampleInfo, bool isStrong = false)
|
||||
: base(sampleInfo.Name, isStrong ? BANK_STRONG : getBank(sampleInfo.Bank, sampleInfo.Name, sampleInfo.Volume), sampleInfo.Suffix, sampleInfo.Volume)
|
||||
: base(sampleInfo.Name, isStrong ? BANK_STRONG : getBank(sampleInfo.Bank, sampleInfo.Name, sampleInfo.Volume), sampleInfo.Suffix, sampleInfo.Volume,
|
||||
sampleInfo.EditorAutoBank, sampleInfo.UseBeatmapSamples)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -51,6 +51,9 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Default
|
||||
spectatorList.Origin = Anchor.TopLeft;
|
||||
spectatorList.Position = new Vector2(320, -280);
|
||||
}
|
||||
|
||||
foreach (var d in container.OfType<ISerialisableDrawable>())
|
||||
d.UsesFixedAnchor = true;
|
||||
})
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
// 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.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
@@ -21,14 +20,10 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy
|
||||
{
|
||||
get
|
||||
{
|
||||
// the reason why this calculation is so involved is that the head & tail sprites have different sizes/radii.
|
||||
// therefore naively taking the SSDQs of them and making a quad out of them results in a trapezoid shape and not a box.
|
||||
var headCentre = headCircle.ScreenSpaceDrawQuad.Centre;
|
||||
var headCentre = (body.ScreenSpaceDrawQuad.TopLeft + body.ScreenSpaceDrawQuad.BottomLeft) / 2;
|
||||
var tailCentre = (tailCircle.ScreenSpaceDrawQuad.TopLeft + tailCircle.ScreenSpaceDrawQuad.BottomLeft) / 2;
|
||||
|
||||
float headRadius = headCircle.ScreenSpaceDrawQuad.Height / 2;
|
||||
float tailRadius = tailCircle.ScreenSpaceDrawQuad.Height / 2;
|
||||
float radius = Math.Max(headRadius, tailRadius);
|
||||
float radius = body.ScreenSpaceDrawQuad.Height / 2;
|
||||
|
||||
var rectangle = new RectangleF(headCentre.X, headCentre.Y, tailCentre.X - headCentre.X, 0).Inflate(radius);
|
||||
return new Quad(rectangle.TopLeft, rectangle.TopRight, rectangle.BottomLeft, rectangle.BottomRight);
|
||||
@@ -37,8 +32,6 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy
|
||||
|
||||
public override bool ReceivePositionalInputAt(Vector2 screenSpacePos) => ScreenSpaceDrawQuad.Contains(screenSpacePos);
|
||||
|
||||
private LegacyCirclePiece headCircle = null!;
|
||||
|
||||
private Sprite body = null!;
|
||||
|
||||
private Sprite tailCircle = null!;
|
||||
@@ -66,10 +59,6 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Texture = skin.GetTexture("taiko-roll-middle", WrapMode.ClampToEdge, WrapMode.ClampToEdge),
|
||||
},
|
||||
headCircle = new LegacyCirclePiece
|
||||
{
|
||||
RelativeSizeAxes = Axes.Y,
|
||||
},
|
||||
};
|
||||
|
||||
AccentColour = colours.YellowDark;
|
||||
@@ -101,7 +90,6 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy
|
||||
{
|
||||
var colour = LegacyColourCompatibility.DisallowZeroAlpha(accentColour);
|
||||
|
||||
headCircle.AccentColour = colour;
|
||||
body.Colour = colour;
|
||||
tailCircle.Colour = colour;
|
||||
}
|
||||
|
||||
@@ -79,6 +79,9 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy
|
||||
spectatorList.Origin = Anchor.TopLeft;
|
||||
spectatorList.Position = pos;
|
||||
}
|
||||
|
||||
foreach (var d in container.OfType<ISerialisableDrawable>())
|
||||
d.UsesFixedAnchor = true;
|
||||
})
|
||||
{
|
||||
new LegacyDefaultComboCounter(),
|
||||
@@ -103,6 +106,12 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy
|
||||
{
|
||||
switch (taikoComponent.Component)
|
||||
{
|
||||
case TaikoSkinComponents.DrumRollHead:
|
||||
if (GetTexture("taiko-roll-middle") != null)
|
||||
return new LegacyCirclePiece();
|
||||
|
||||
return null;
|
||||
|
||||
case TaikoSkinComponents.DrumRollBody:
|
||||
if (GetTexture("taiko-roll-middle") != null)
|
||||
return new LegacyDrumRoll();
|
||||
@@ -240,7 +249,7 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy
|
||||
private class LegacyTaikoSampleInfo : HitSampleInfo
|
||||
{
|
||||
public LegacyTaikoSampleInfo(HitSampleInfo sampleInfo)
|
||||
: base(sampleInfo.Name, sampleInfo.Bank, sampleInfo.Suffix, sampleInfo.Volume)
|
||||
: base(sampleInfo.Name, sampleInfo.Bank, sampleInfo.Suffix, sampleInfo.Volume, sampleInfo.EditorAutoBank, sampleInfo.UseBeatmapSamples)
|
||||
|
||||
{
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ namespace osu.Game.Rulesets.Taiko
|
||||
InputDrum,
|
||||
CentreHit,
|
||||
RimHit,
|
||||
DrumRollHead,
|
||||
DrumRollBody,
|
||||
DrumRollTick,
|
||||
Swell,
|
||||
|
||||
@@ -11,6 +11,7 @@ using NUnit.Framework;
|
||||
using osu.Framework.Audio.Track;
|
||||
using osu.Framework.Graphics.Textures;
|
||||
using osu.Framework.IO.Stores;
|
||||
using osu.Game.Audio;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Beatmaps.Formats;
|
||||
@@ -236,6 +237,31 @@ namespace osu.Game.Tests.Beatmaps.Formats
|
||||
Is.EquivalentTo(originalSlider.Path.ControlPoints.Select(p => p.Position)));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestEncodeCustomSampleBanks()
|
||||
{
|
||||
var beatmap = new Beatmap
|
||||
{
|
||||
HitObjects =
|
||||
{
|
||||
new HitCircle { StartTime = 100, Samples = [new HitSampleInfo(HitSampleInfo.HIT_NORMAL)] },
|
||||
new HitCircle { StartTime = 200, Samples = [new HitSampleInfo(HitSampleInfo.HIT_NORMAL, useBeatmapSamples: true)] },
|
||||
new HitCircle { StartTime = 300, Samples = [new HitSampleInfo(HitSampleInfo.HIT_NORMAL, suffix: "3", useBeatmapSamples: true)] },
|
||||
}
|
||||
};
|
||||
|
||||
var decodedAfterEncode = decodeFromLegacy(encodeToLegacy((beatmap, new TestLegacySkin(beatmaps_resource_store, string.Empty))), string.Empty);
|
||||
|
||||
Assert.That(decodedAfterEncode.beatmap.HitObjects[0].Samples[0].Suffix, Is.Null);
|
||||
Assert.That(decodedAfterEncode.beatmap.HitObjects[0].Samples[0].UseBeatmapSamples, Is.False);
|
||||
|
||||
Assert.That(decodedAfterEncode.beatmap.HitObjects[1].Samples[0].Suffix, Is.Null);
|
||||
Assert.That(decodedAfterEncode.beatmap.HitObjects[1].Samples[0].UseBeatmapSamples, Is.True);
|
||||
|
||||
Assert.That(decodedAfterEncode.beatmap.HitObjects[2].Samples[0].Suffix, Is.EqualTo("3"));
|
||||
Assert.That(decodedAfterEncode.beatmap.HitObjects[2].Samples[0].UseBeatmapSamples, Is.True);
|
||||
}
|
||||
|
||||
private bool areComboColoursEqual(IHasComboColours a, IHasComboColours b)
|
||||
{
|
||||
// equal to null, no need to SequenceEqual
|
||||
|
||||
@@ -59,7 +59,15 @@ namespace osu.Game.Tests.Beatmaps.IO
|
||||
|
||||
// Ensure importer encoding is correct
|
||||
AddStep("import beatmap", () => beatmap = importBeatmapFromArchives(@"fractional-coordinates.olz"));
|
||||
AddAssert("hit object has fractional position", () => ((IHasYPosition)beatmap.Beatmap.HitObjects[1]).Y, () => Is.EqualTo(383.99997).Within(0.00001));
|
||||
AddAssert("second slider has fractional position",
|
||||
() => ((IHasXPosition)beatmap.Beatmap.HitObjects[1]).X,
|
||||
() => Is.EqualTo(-3.0517578E-05).Within(0.00001));
|
||||
AddAssert("second slider path has fractional coordinates",
|
||||
() => ((IHasPath)beatmap.Beatmap.HitObjects[1]).Path.ControlPoints[1].Position.X,
|
||||
() => Is.EqualTo(191.999939).Within(0.00001));
|
||||
AddAssert("second hit circle has fractional position",
|
||||
() => ((IHasYPosition)beatmap.Beatmap.HitObjects[3]).Y,
|
||||
() => Is.EqualTo(383.99997).Within(0.00001));
|
||||
|
||||
// Ensure exporter legacy conversion is correct
|
||||
AddStep("export", () =>
|
||||
@@ -71,7 +79,15 @@ namespace osu.Game.Tests.Beatmaps.IO
|
||||
});
|
||||
|
||||
AddStep("import beatmap again", () => beatmap = importBeatmapFromStream(outStream));
|
||||
AddAssert("hit object is snapped", () => ((IHasYPosition)beatmap.Beatmap.HitObjects[1]).Y, () => Is.EqualTo(384).Within(0.00001));
|
||||
AddAssert("second slider is snapped",
|
||||
() => ((IHasXPosition)beatmap.Beatmap.HitObjects[1]).X,
|
||||
() => Is.EqualTo(0).Within(0.00001));
|
||||
AddAssert("second slider path is snapped",
|
||||
() => ((IHasPath)beatmap.Beatmap.HitObjects[1]).Path.ControlPoints[1].Position.X,
|
||||
() => Is.EqualTo(192).Within(0.00001));
|
||||
AddAssert("second hit circle is snapped",
|
||||
() => ((IHasYPosition)beatmap.Beatmap.HitObjects[3]).Y,
|
||||
() => Is.EqualTo(384).Within(0.00001));
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
||||
@@ -42,6 +42,7 @@ namespace osu.Game.Tests.Chat
|
||||
sentMessages = new List<Message>();
|
||||
silencedUserIds = new List<int>();
|
||||
|
||||
((DummyAPIAccess)API).LocalUserState.Blocks.Clear();
|
||||
((DummyAPIAccess)API).HandleRequest = req =>
|
||||
{
|
||||
switch (req)
|
||||
@@ -63,6 +64,10 @@ namespace osu.Game.Tests.Chat
|
||||
silencedUserIds.Clear();
|
||||
return true;
|
||||
|
||||
case GetMessagesRequest getMessages:
|
||||
getMessages.TriggerSuccess(sentMessages);
|
||||
return true;
|
||||
|
||||
case GetUpdatesRequest updatesRequest:
|
||||
updatesRequest.TriggerSuccess(new GetUpdatesResponse
|
||||
{
|
||||
@@ -161,6 +166,85 @@ namespace osu.Game.Tests.Chat
|
||||
AddUntilStep("/help command received", () => channel.Messages.Last().Content.Contains("Supported commands"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestBlockedUserMessagesAreDeletedFromInitialMessageBatch()
|
||||
{
|
||||
Channel channel = null;
|
||||
|
||||
AddStep("create channel", () => channel = createChannel(1, ChannelType.Public));
|
||||
AddStep("post a message from blocked user", () => sentMessages.Add(new Message
|
||||
{
|
||||
ChannelId = channel.Id,
|
||||
Content = "i am blocked",
|
||||
SenderId = 1234
|
||||
}));
|
||||
AddStep("mark user as blocked", () => ((DummyAPIAccess)API).LocalUserState.Blocks.Add(new APIRelation
|
||||
{
|
||||
TargetUser = new APIUser { Username = "blocked", Id = 1234 },
|
||||
TargetID = 1234,
|
||||
}));
|
||||
|
||||
AddStep("join channel and select it", () =>
|
||||
{
|
||||
channelManager.JoinChannel(channel);
|
||||
channelManager.CurrentChannel.Value = channel;
|
||||
});
|
||||
AddAssert("channel has no messages", () => channel.Messages, () => Is.Empty);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestBlockedUserMessagesAreDeletedImmediatelyOnBlock()
|
||||
{
|
||||
Channel channel = null;
|
||||
|
||||
AddStep("create channel", () => channel = createChannel(1, ChannelType.Public));
|
||||
|
||||
AddStep("join channel and select it", () =>
|
||||
{
|
||||
channelManager.JoinChannel(channel);
|
||||
channelManager.CurrentChannel.Value = channel;
|
||||
});
|
||||
AddStep("post a message from blocked user", () => sentMessages.Add(new Message
|
||||
{
|
||||
ChannelId = channel.Id,
|
||||
Content = "i am blocked",
|
||||
SenderId = 1234
|
||||
}));
|
||||
AddUntilStep("channel has message", () => channel.Messages, () => Is.Not.Empty);
|
||||
|
||||
AddStep("block user", () => ((DummyAPIAccess)API).LocalUserState.Blocks.Add(new APIRelation
|
||||
{
|
||||
TargetUser = new APIUser { Username = "blocked", Id = 1234 },
|
||||
TargetID = 1234,
|
||||
}));
|
||||
AddAssert("channel has no messages", () => channel.Messages, () => Is.Empty);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestPrivateChannelsPurgedOnUserChange()
|
||||
{
|
||||
var pmChannel = createChannel(1002, ChannelType.PM);
|
||||
AddStep("join a few private channels", () =>
|
||||
{
|
||||
channelManager.JoinChannel(createChannel(1001, ChannelType.PM));
|
||||
channelManager.JoinChannel(createChannel(1003, ChannelType.Team));
|
||||
channelManager.JoinChannel(pmChannel);
|
||||
});
|
||||
AddStep("close a PM channel", () => channelManager.LeaveChannel(pmChannel));
|
||||
|
||||
AddStep("switch user", () =>
|
||||
{
|
||||
((DummyAPIAccess.DummyLocalUserState)API.LocalUserState).User.Value = new APIUser
|
||||
{
|
||||
Id = 9009,
|
||||
Username = "someone_else"
|
||||
};
|
||||
});
|
||||
|
||||
AddAssert("not joined to private channels of previous user",
|
||||
() => !channelManager.JoinedChannels.Select(ch => ch.Id).Any(id => id >= 1001 && id <= 1003));
|
||||
}
|
||||
|
||||
private void handlePostMessageRequest(PostMessageRequest request)
|
||||
{
|
||||
var message = new Message(++currentMessageId)
|
||||
@@ -191,7 +275,7 @@ namespace osu.Game.Tests.Chat
|
||||
}
|
||||
}
|
||||
|
||||
private Channel createChannel(int id, ChannelType type) => new Channel(new APIUser())
|
||||
private Channel createChannel(int id, ChannelType type) => new Channel(new APIUser { Id = id })
|
||||
{
|
||||
Id = id,
|
||||
Name = $"Channel {id}",
|
||||
|
||||
@@ -17,6 +17,7 @@ namespace osu.Game.Tests.Extensions
|
||||
[TestCase(0, true, 0, ExpectedResult = "0%")]
|
||||
[TestCase(1, true, 0, ExpectedResult = "1%")]
|
||||
[TestCase(50, true, 0, ExpectedResult = "50%")]
|
||||
[SetCulture("")] // invariant culture
|
||||
public string TestInteger(int input, bool percent, int decimalDigits)
|
||||
{
|
||||
return input.ToStandardFormattedString(decimalDigits, percent);
|
||||
@@ -39,6 +40,7 @@ namespace osu.Game.Tests.Extensions
|
||||
[TestCase(0.48333, true, 2, ExpectedResult = "48%")]
|
||||
[TestCase(0.48333, true, 4, ExpectedResult = "48.33%")]
|
||||
[TestCase(1, true, 0, ExpectedResult = "100%")]
|
||||
[SetCulture("")] // invariant culture
|
||||
public string TestDouble(double input, bool percent, int decimalDigits)
|
||||
{
|
||||
return input.ToStandardFormattedString(decimalDigits, percent);
|
||||
@@ -47,9 +49,9 @@ namespace osu.Game.Tests.Extensions
|
||||
[Test]
|
||||
[SetCulture("fr-FR")]
|
||||
[TestCase(0.4, true, 2, ExpectedResult = "40%")]
|
||||
[TestCase(1e-6, false, 6, ExpectedResult = "0.000001")]
|
||||
[TestCase(0.48333, true, 4, ExpectedResult = "48.33%")]
|
||||
public string TestCultureInsensitivity(double input, bool percent, int decimalDigits)
|
||||
[TestCase(1e-6, false, 6, ExpectedResult = "0,000001")]
|
||||
[TestCase(0.48333, true, 4, ExpectedResult = "48,33%")]
|
||||
public string TestCultureSensitivity(double input, bool percent, int decimalDigits)
|
||||
{
|
||||
return input.ToStandardFormattedString(decimalDigits, percent);
|
||||
}
|
||||
|
||||
@@ -126,6 +126,22 @@ namespace osu.Game.Tests.Gameplay
|
||||
AssertBeatmapLookup(expected_sample);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests that a hitobject which specifies a specific sample file which doesn't exist (or isn't allowed to be looked up)
|
||||
/// falls back to a normal sample.
|
||||
/// </summary>
|
||||
[Test]
|
||||
public void TestFileSampleFallsBackToNormal()
|
||||
{
|
||||
const string expected_sample = "normal-hitnormal";
|
||||
|
||||
SetupSkins(null, expected_sample);
|
||||
|
||||
CreateTestWithBeatmap("file-beatmap-sample.osu");
|
||||
|
||||
AssertUserLookup(expected_sample);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tests that a default hitobject and control point causes <see cref="TestDefaultSampleFromUserSkin"/>.
|
||||
/// </summary>
|
||||
|
||||
@@ -299,6 +299,23 @@ namespace osu.Game.Tests.NonVisual.Filtering
|
||||
Assert.AreEqual(filtered, carouselItem.Filtered.Value);
|
||||
}
|
||||
|
||||
[Test]
|
||||
[TestCase("artist")]
|
||||
[TestCase("unicode")]
|
||||
public void TestCriteriaNotMatchingArtist(string excludedTerm)
|
||||
{
|
||||
var beatmap = getExampleBeatmap();
|
||||
var criteria = new FilterCriteria
|
||||
{
|
||||
Artist = new FilterCriteria.OptionalTextFilter { SearchTerm = excludedTerm, ExcludeTerm = true }
|
||||
};
|
||||
|
||||
var carouselItem = new CarouselBeatmap(beatmap);
|
||||
carouselItem.Filter(criteria);
|
||||
|
||||
Assert.True(carouselItem.Filtered.Value);
|
||||
}
|
||||
|
||||
[TestCase("simple", false)]
|
||||
[TestCase("\"style/clean\"", false)]
|
||||
[TestCase("\"style/clean\"!", false)]
|
||||
@@ -350,6 +367,41 @@ namespace osu.Game.Tests.NonVisual.Filtering
|
||||
Assert.AreEqual(true, carouselItem.Filtered.Value);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestCriteriaMatchingTagExcluded()
|
||||
{
|
||||
var beatmap = getExampleBeatmap();
|
||||
var criteria = new FilterCriteria
|
||||
{
|
||||
UserTags =
|
||||
[
|
||||
new FilterCriteria.OptionalTextFilter { SearchTerm = "\"song representation/simple\"!", ExcludeTerm = true },
|
||||
]
|
||||
};
|
||||
var carouselItem = new CarouselBeatmap(beatmap);
|
||||
carouselItem.Filter(criteria);
|
||||
|
||||
Assert.AreEqual(true, carouselItem.Filtered.Value);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestCriteriaOneTagIncludedAndOneTagExcluded()
|
||||
{
|
||||
var beatmap = getExampleBeatmap();
|
||||
var criteria = new FilterCriteria
|
||||
{
|
||||
UserTags =
|
||||
[
|
||||
new FilterCriteria.OptionalTextFilter { SearchTerm = "\"song representation/simple\"!" },
|
||||
new FilterCriteria.OptionalTextFilter { SearchTerm = "\"style/clean\"!", ExcludeTerm = true }
|
||||
]
|
||||
};
|
||||
var carouselItem = new CarouselBeatmap(beatmap);
|
||||
carouselItem.Filter(criteria);
|
||||
|
||||
Assert.AreEqual(true, carouselItem.Filtered.Value);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestBeatmapMustHaveAtLeastOneTagIfUserTagFilterActive()
|
||||
{
|
||||
|
||||
@@ -738,6 +738,16 @@ namespace osu.Game.Tests.NonVisual.Filtering
|
||||
new object[] { "submitted=99999", false },
|
||||
new object[] { "submitted>=2012-03-05-04", false },
|
||||
new object[] { "submitted>=2012/03.05-04", false },
|
||||
|
||||
new object[] { "created<2012", true },
|
||||
new object[] { "created<2012.03", true },
|
||||
new object[] { "created<2012/03/05", true },
|
||||
new object[] { "created<2012-3-5", true },
|
||||
|
||||
new object[] { "created<0", false },
|
||||
new object[] { "created=99999", false },
|
||||
new object[] { "created>=2012-03-05-04", false },
|
||||
new object[] { "created>=2012/03.05-04", false },
|
||||
};
|
||||
|
||||
[Test]
|
||||
|
||||
@@ -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 System;
|
||||
using NUnit.Framework;
|
||||
using osu.Game.Online.API.Requests.Responses;
|
||||
using osu.Game.Online.Multiplayer.MatchTypes.Matchmaking;
|
||||
@@ -29,17 +30,17 @@ namespace osu.Game.Tests.Online.Matchmaking
|
||||
new SoloScoreInfo { UserID = 3, TotalScore = 750 },
|
||||
], placement_points);
|
||||
|
||||
Assert.AreEqual(8, state.Users[1].Points);
|
||||
Assert.AreEqual(1, state.Users[1].Placement);
|
||||
Assert.AreEqual(1, state.Users[1].Rounds[1].Placement);
|
||||
Assert.AreEqual(8, state.Users.GetOrAdd(1).Points);
|
||||
Assert.AreEqual(1, state.Users.GetOrAdd(1).Placement);
|
||||
Assert.AreEqual(1, state.Users.GetOrAdd(1).Rounds.GetOrAdd(1).Placement);
|
||||
|
||||
Assert.AreEqual(6, state.Users[2].Points);
|
||||
Assert.AreEqual(3, state.Users[2].Placement);
|
||||
Assert.AreEqual(3, state.Users[2].Rounds[1].Placement);
|
||||
Assert.AreEqual(6, state.Users.GetOrAdd(2).Points);
|
||||
Assert.AreEqual(3, state.Users.GetOrAdd(2).Placement);
|
||||
Assert.AreEqual(3, state.Users.GetOrAdd(2).Rounds.GetOrAdd(1).Placement);
|
||||
|
||||
Assert.AreEqual(7, state.Users[3].Points);
|
||||
Assert.AreEqual(2, state.Users[3].Placement);
|
||||
Assert.AreEqual(2, state.Users[3].Rounds[1].Placement);
|
||||
Assert.AreEqual(7, state.Users.GetOrAdd(3).Points);
|
||||
Assert.AreEqual(2, state.Users.GetOrAdd(3).Placement);
|
||||
Assert.AreEqual(2, state.Users.GetOrAdd(3).Rounds.GetOrAdd(1).Placement);
|
||||
|
||||
// 2 -> 1 -> 3
|
||||
|
||||
@@ -51,17 +52,17 @@ namespace osu.Game.Tests.Online.Matchmaking
|
||||
new SoloScoreInfo { UserID = 3, TotalScore = 500 },
|
||||
], placement_points);
|
||||
|
||||
Assert.AreEqual(15, state.Users[1].Points);
|
||||
Assert.AreEqual(1, state.Users[1].Placement);
|
||||
Assert.AreEqual(2, state.Users[1].Rounds[2].Placement);
|
||||
Assert.AreEqual(15, state.Users.GetOrAdd(1).Points);
|
||||
Assert.AreEqual(1, state.Users.GetOrAdd(1).Placement);
|
||||
Assert.AreEqual(2, state.Users.GetOrAdd(1).Rounds.GetOrAdd(2).Placement);
|
||||
|
||||
Assert.AreEqual(14, state.Users[2].Points);
|
||||
Assert.AreEqual(2, state.Users[2].Placement);
|
||||
Assert.AreEqual(1, state.Users[2].Rounds[2].Placement);
|
||||
Assert.AreEqual(14, state.Users.GetOrAdd(2).Points);
|
||||
Assert.AreEqual(2, state.Users.GetOrAdd(2).Placement);
|
||||
Assert.AreEqual(1, state.Users.GetOrAdd(2).Rounds.GetOrAdd(2).Placement);
|
||||
|
||||
Assert.AreEqual(13, state.Users[3].Points);
|
||||
Assert.AreEqual(3, state.Users[3].Placement);
|
||||
Assert.AreEqual(3, state.Users[3].Rounds[2].Placement);
|
||||
Assert.AreEqual(13, state.Users.GetOrAdd(3).Points);
|
||||
Assert.AreEqual(3, state.Users.GetOrAdd(3).Placement);
|
||||
Assert.AreEqual(3, state.Users.GetOrAdd(3).Rounds.GetOrAdd(2).Placement);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -80,21 +81,21 @@ namespace osu.Game.Tests.Online.Matchmaking
|
||||
new SoloScoreInfo { UserID = 4, TotalScore = 500 },
|
||||
], placement_points);
|
||||
|
||||
Assert.AreEqual(7, state.Users[1].Points);
|
||||
Assert.AreEqual(1, state.Users[1].Placement);
|
||||
Assert.AreEqual(2, state.Users[1].Rounds[1].Placement);
|
||||
Assert.AreEqual(7, state.Users.GetOrAdd(1).Points);
|
||||
Assert.AreEqual(1, state.Users.GetOrAdd(1).Placement);
|
||||
Assert.AreEqual(2, state.Users.GetOrAdd(1).Rounds.GetOrAdd(1).Placement);
|
||||
|
||||
Assert.AreEqual(7, state.Users[2].Points);
|
||||
Assert.AreEqual(2, state.Users[2].Placement);
|
||||
Assert.AreEqual(2, state.Users[2].Rounds[1].Placement);
|
||||
Assert.AreEqual(7, state.Users.GetOrAdd(2).Points);
|
||||
Assert.AreEqual(2, state.Users.GetOrAdd(2).Placement);
|
||||
Assert.AreEqual(2, state.Users.GetOrAdd(2).Rounds.GetOrAdd(1).Placement);
|
||||
|
||||
Assert.AreEqual(5, state.Users[3].Points);
|
||||
Assert.AreEqual(3, state.Users[3].Placement);
|
||||
Assert.AreEqual(4, state.Users[3].Rounds[1].Placement);
|
||||
Assert.AreEqual(5, state.Users.GetOrAdd(3).Points);
|
||||
Assert.AreEqual(3, state.Users.GetOrAdd(3).Placement);
|
||||
Assert.AreEqual(4, state.Users.GetOrAdd(3).Rounds.GetOrAdd(1).Placement);
|
||||
|
||||
Assert.AreEqual(5, state.Users[4].Points);
|
||||
Assert.AreEqual(4, state.Users[4].Placement);
|
||||
Assert.AreEqual(4, state.Users[4].Rounds[1].Placement);
|
||||
Assert.AreEqual(5, state.Users.GetOrAdd(4).Points);
|
||||
Assert.AreEqual(4, state.Users.GetOrAdd(4).Placement);
|
||||
Assert.AreEqual(4, state.Users.GetOrAdd(4).Rounds.GetOrAdd(1).Placement);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -120,8 +121,8 @@ namespace osu.Game.Tests.Online.Matchmaking
|
||||
new SoloScoreInfo { UserID = 2, TotalScore = 1000 },
|
||||
], placement_points);
|
||||
|
||||
Assert.AreEqual(1, state.Users[1].Placement);
|
||||
Assert.AreEqual(2, state.Users[2].Placement);
|
||||
Assert.AreEqual(1, state.Users.GetOrAdd(1).Placement);
|
||||
Assert.AreEqual(2, state.Users.GetOrAdd(2).Placement);
|
||||
}
|
||||
|
||||
[Test]
|
||||
@@ -142,12 +143,40 @@ namespace osu.Game.Tests.Online.Matchmaking
|
||||
new SoloScoreInfo { UserID = 5, TotalScore = 1000 },
|
||||
], placement_points);
|
||||
|
||||
Assert.AreEqual(1, state.Users[1].Placement);
|
||||
Assert.AreEqual(2, state.Users[2].Placement);
|
||||
Assert.AreEqual(3, state.Users[3].Placement);
|
||||
Assert.AreEqual(4, state.Users[4].Placement);
|
||||
Assert.AreEqual(5, state.Users[5].Placement);
|
||||
Assert.AreEqual(6, state.Users[6].Placement);
|
||||
Assert.AreEqual(1, state.Users.GetOrAdd(1).Placement);
|
||||
Assert.AreEqual(2, state.Users.GetOrAdd(2).Placement);
|
||||
Assert.AreEqual(3, state.Users.GetOrAdd(3).Placement);
|
||||
Assert.AreEqual(4, state.Users.GetOrAdd(4).Placement);
|
||||
Assert.AreEqual(5, state.Users.GetOrAdd(5).Placement);
|
||||
Assert.AreEqual(6, state.Users.GetOrAdd(6).Placement);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AbandonOrder()
|
||||
{
|
||||
var state = new MatchmakingRoomState();
|
||||
|
||||
state.AdvanceRound();
|
||||
state.RecordScores(
|
||||
[
|
||||
new SoloScoreInfo { UserID = 1, TotalScore = 1000 },
|
||||
new SoloScoreInfo { UserID = 2, TotalScore = 500 },
|
||||
], placement_points);
|
||||
|
||||
Assert.AreEqual(1, state.Users.GetOrAdd(1).Placement);
|
||||
Assert.AreEqual(2, state.Users.GetOrAdd(2).Placement);
|
||||
|
||||
state.Users.GetOrAdd(1).AbandonedAt = DateTimeOffset.Now;
|
||||
state.RecordScores([], placement_points);
|
||||
|
||||
Assert.AreEqual(2, state.Users.GetOrAdd(1).Placement);
|
||||
Assert.AreEqual(1, state.Users.GetOrAdd(2).Placement);
|
||||
|
||||
state.Users.GetOrAdd(2).AbandonedAt = DateTimeOffset.Now - TimeSpan.FromMinutes(1);
|
||||
state.RecordScores([], placement_points);
|
||||
|
||||
Assert.AreEqual(1, state.Users.GetOrAdd(1).Placement);
|
||||
Assert.AreEqual(2, state.Users.GetOrAdd(2).Placement);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,7 +44,13 @@ namespace osu.Game.Tests.Online
|
||||
availableBeatmap = importedSet.Beatmaps[0];
|
||||
unavailableBeatmap = importedSet.Beatmaps[1];
|
||||
|
||||
Realm.Write(r => r.Remove(r.Find<BeatmapInfo>(unavailableBeatmap.ID)!));
|
||||
Realm.Write(r =>
|
||||
{
|
||||
BeatmapInfo available = r.Find<BeatmapInfo>(availableBeatmap.ID)!;
|
||||
available.OnlineMD5Hash = available.MD5Hash;
|
||||
|
||||
r.Remove(r.Find<BeatmapInfo>(unavailableBeatmap.ID)!);
|
||||
});
|
||||
}
|
||||
|
||||
public override void SetUpSteps()
|
||||
|
||||
@@ -27,6 +27,7 @@ using osu.Game.Screens.OnlinePlay;
|
||||
using osu.Game.Screens.OnlinePlay.Playlists;
|
||||
using osu.Game.Tests.Resources;
|
||||
using osu.Game.Tests.Visual;
|
||||
using Realms;
|
||||
|
||||
namespace osu.Game.Tests.Online
|
||||
{
|
||||
@@ -229,6 +230,14 @@ namespace osu.Game.Tests.Online
|
||||
|
||||
return testBeatmapManager.CurrentImport = base.ImportModel(item, archive, parameters, cancellationToken);
|
||||
}
|
||||
|
||||
protected override void PostImport(BeatmapSetInfo model, Realm realm, ImportParameters parameters)
|
||||
{
|
||||
foreach (var beatmap in model.Beatmaps)
|
||||
beatmap.OnlineMD5Hash = beatmap.MD5Hash;
|
||||
|
||||
base.PostImport(model, realm, parameters);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 3.3 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 3.6 KiB |
|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 930 B |
|
After Width: | Height: | Size: 5.3 KiB |
|
After Width: | Height: | Size: 4.7 KiB |