├── osu.Game.Rulesets.PumpTrainer
├── Resources
│ └── Textures
│ │ ├── C.png
│ │ ├── DL.png
│ │ ├── UL.png
│ │ ├── C-gray.png
│ │ ├── DL-gray.png
│ │ └── UL-gray.png
├── Mods
│ ├── PumpTrainerModHalfTime.cs
│ ├── PumpTrainerModDoubleTime.cs
│ ├── ExcludeColumns
│ │ ├── PumpTrainerModExcludeP1C.cs
│ │ ├── PumpTrainerModExcludeP2C.cs
│ │ ├── PumpTrainerModExcludeP1DL.cs
│ │ ├── PumpTrainerModExcludeP1DR.cs
│ │ ├── PumpTrainerModExcludeP1UL.cs
│ │ ├── PumpTrainerModExcludeP1UR.cs
│ │ ├── PumpTrainerModExcludeP2DL.cs
│ │ ├── PumpTrainerModExcludeP2DR.cs
│ │ ├── PumpTrainerModExcludeP2UL.cs
│ │ ├── PumpTrainerModExcludeP2UR.cs
│ │ └── PumpTrainerModExcludeColumn.cs
│ ├── PumpTrainerModAutoplay.cs
│ ├── PumpTrainerModSeeded.cs
│ ├── PumpTrainerModDiagonalSkips.cs
│ ├── PumpTrainerModNoFarColumns.cs
│ ├── PumpTrainerModCornersOnSixteenths.cs
│ ├── PumpTrainerModHorizontalTriplesOnSixteenths.cs
│ └── PumpTrainerModHorizontalTwists.cs
├── osu.Game.Rulesets.PumpTrainer.csproj
├── Replays
│ ├── PumpTrainerReplayFrame.cs
│ ├── PumpTrainerFramedReplayInputHandler.cs
│ └── PumpTrainerAutoGenerator.cs
├── PumpTrainerInputManager.cs
├── Objects
│ ├── Drawables
│ │ ├── DrawableTopRowHitObject.cs
│ │ └── DrawablePumpTrainerHitObject.cs
│ └── PumpTrainerHitObject.cs
├── PumpTrainerDifficultyCalculator.cs
├── PumpTrainerKeybindConversions.cs
├── UI
│ ├── DrawablePumpTrainerRuleset.cs
│ └── PumpTrainerPlayfield.cs
├── Beatmaps
│ ├── PumpTrainerHitObjectGeneratorSettingsPerHitObject.cs
│ ├── PumpTrainerHitObjectGeneratorSettings.cs
│ ├── PumpTrainerBeatmapConverter.cs
│ └── PumpTrainerHitObjectGenerator.cs
└── PumpTrainerRuleset.cs
├── Directory.Build.props
├── osu.Game.Rulesets.PumpTrainer.Tests
├── TestSceneOsuPlayer.cs
├── VisualTestRunner.cs
├── TestSceneOsuGame.cs
├── .vscode
│ ├── launch.json
│ └── tasks.json
└── osu.Game.Rulesets.PumpTrainer.Tests.csproj
├── README.md
├── app.manifest
├── .gitattributes
├── osu.Game.Rulesets.PumpTrainer.sln
├── .gitignore
├── .editorconfig
└── osu.Game.Rulesets.PumpTrainer.sln.DotSettings
/osu.Game.Rulesets.PumpTrainer/Resources/Textures/C.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hwabis/pump-trainer/HEAD/osu.Game.Rulesets.PumpTrainer/Resources/Textures/C.png
--------------------------------------------------------------------------------
/osu.Game.Rulesets.PumpTrainer/Resources/Textures/DL.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hwabis/pump-trainer/HEAD/osu.Game.Rulesets.PumpTrainer/Resources/Textures/DL.png
--------------------------------------------------------------------------------
/osu.Game.Rulesets.PumpTrainer/Resources/Textures/UL.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hwabis/pump-trainer/HEAD/osu.Game.Rulesets.PumpTrainer/Resources/Textures/UL.png
--------------------------------------------------------------------------------
/osu.Game.Rulesets.PumpTrainer/Resources/Textures/C-gray.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hwabis/pump-trainer/HEAD/osu.Game.Rulesets.PumpTrainer/Resources/Textures/C-gray.png
--------------------------------------------------------------------------------
/osu.Game.Rulesets.PumpTrainer/Resources/Textures/DL-gray.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hwabis/pump-trainer/HEAD/osu.Game.Rulesets.PumpTrainer/Resources/Textures/DL-gray.png
--------------------------------------------------------------------------------
/osu.Game.Rulesets.PumpTrainer/Resources/Textures/UL-gray.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hwabis/pump-trainer/HEAD/osu.Game.Rulesets.PumpTrainer/Resources/Textures/UL-gray.png
--------------------------------------------------------------------------------
/osu.Game.Rulesets.PumpTrainer/Mods/PumpTrainerModHalfTime.cs:
--------------------------------------------------------------------------------
1 | using osu.Game.Rulesets.Mods;
2 |
3 | namespace osu.Game.Rulesets.PumpTrainer.Mods
4 | {
5 | public class PumpTrainerModHalfTime : ModHalfTime
6 | {
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/osu.Game.Rulesets.PumpTrainer/Mods/PumpTrainerModDoubleTime.cs:
--------------------------------------------------------------------------------
1 | using osu.Game.Rulesets.Mods;
2 |
3 | namespace osu.Game.Rulesets.PumpTrainer.Mods
4 | {
5 | public class PumpTrainerModDoubleTime : ModDoubleTime
6 | {
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/osu.Game.Rulesets.PumpTrainer/Mods/ExcludeColumns/PumpTrainerModExcludeP1C.cs:
--------------------------------------------------------------------------------
1 | using osu.Game.Rulesets.PumpTrainer.Objects;
2 |
3 | namespace osu.Game.Rulesets.PumpTrainer.Mods.ExcludeColumns
4 | {
5 | public class PumpTrainerModExcludeP1C : PumpTrainerModExcludeColumn
6 | {
7 | public override Column ExcludedColumn => Column.P1C;
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/osu.Game.Rulesets.PumpTrainer/Mods/ExcludeColumns/PumpTrainerModExcludeP2C.cs:
--------------------------------------------------------------------------------
1 | using osu.Game.Rulesets.PumpTrainer.Objects;
2 |
3 | namespace osu.Game.Rulesets.PumpTrainer.Mods.ExcludeColumns
4 | {
5 | public class PumpTrainerModExcludeP2C : PumpTrainerModExcludeColumn
6 | {
7 | public override Column ExcludedColumn => Column.P2C;
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/osu.Game.Rulesets.PumpTrainer/Mods/ExcludeColumns/PumpTrainerModExcludeP1DL.cs:
--------------------------------------------------------------------------------
1 | using osu.Game.Rulesets.PumpTrainer.Objects;
2 |
3 | namespace osu.Game.Rulesets.PumpTrainer.Mods.ExcludeColumns
4 | {
5 | public class PumpTrainerModExcludeP1DL : PumpTrainerModExcludeColumn
6 | {
7 | public override Column ExcludedColumn => Column.P1DL;
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/osu.Game.Rulesets.PumpTrainer/Mods/ExcludeColumns/PumpTrainerModExcludeP1DR.cs:
--------------------------------------------------------------------------------
1 | using osu.Game.Rulesets.PumpTrainer.Objects;
2 |
3 | namespace osu.Game.Rulesets.PumpTrainer.Mods.ExcludeColumns
4 | {
5 | public class PumpTrainerModExcludeP1DR : PumpTrainerModExcludeColumn
6 | {
7 | public override Column ExcludedColumn => Column.P1DR;
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/osu.Game.Rulesets.PumpTrainer/Mods/ExcludeColumns/PumpTrainerModExcludeP1UL.cs:
--------------------------------------------------------------------------------
1 | using osu.Game.Rulesets.PumpTrainer.Objects;
2 |
3 | namespace osu.Game.Rulesets.PumpTrainer.Mods.ExcludeColumns
4 | {
5 | public class PumpTrainerModExcludeP1UL : PumpTrainerModExcludeColumn
6 | {
7 | public override Column ExcludedColumn => Column.P1UL;
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/osu.Game.Rulesets.PumpTrainer/Mods/ExcludeColumns/PumpTrainerModExcludeP1UR.cs:
--------------------------------------------------------------------------------
1 | using osu.Game.Rulesets.PumpTrainer.Objects;
2 |
3 | namespace osu.Game.Rulesets.PumpTrainer.Mods.ExcludeColumns
4 | {
5 | public class PumpTrainerModExcludeP1UR : PumpTrainerModExcludeColumn
6 | {
7 | public override Column ExcludedColumn => Column.P1UR;
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/osu.Game.Rulesets.PumpTrainer/Mods/ExcludeColumns/PumpTrainerModExcludeP2DL.cs:
--------------------------------------------------------------------------------
1 | using osu.Game.Rulesets.PumpTrainer.Objects;
2 |
3 | namespace osu.Game.Rulesets.PumpTrainer.Mods.ExcludeColumns
4 | {
5 | public class PumpTrainerModExcludeP2DL : PumpTrainerModExcludeColumn
6 | {
7 | public override Column ExcludedColumn => Column.P2DL;
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/osu.Game.Rulesets.PumpTrainer/Mods/ExcludeColumns/PumpTrainerModExcludeP2DR.cs:
--------------------------------------------------------------------------------
1 | using osu.Game.Rulesets.PumpTrainer.Objects;
2 |
3 | namespace osu.Game.Rulesets.PumpTrainer.Mods.ExcludeColumns
4 | {
5 | public class PumpTrainerModExcludeP2DR : PumpTrainerModExcludeColumn
6 | {
7 | public override Column ExcludedColumn => Column.P2DR;
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/osu.Game.Rulesets.PumpTrainer/Mods/ExcludeColumns/PumpTrainerModExcludeP2UL.cs:
--------------------------------------------------------------------------------
1 | using osu.Game.Rulesets.PumpTrainer.Objects;
2 |
3 | namespace osu.Game.Rulesets.PumpTrainer.Mods.ExcludeColumns
4 | {
5 | public class PumpTrainerModExcludeP2UL : PumpTrainerModExcludeColumn
6 | {
7 | public override Column ExcludedColumn => Column.P2UL;
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/osu.Game.Rulesets.PumpTrainer/Mods/ExcludeColumns/PumpTrainerModExcludeP2UR.cs:
--------------------------------------------------------------------------------
1 | using osu.Game.Rulesets.PumpTrainer.Objects;
2 |
3 | namespace osu.Game.Rulesets.PumpTrainer.Mods.ExcludeColumns
4 | {
5 | public class PumpTrainerModExcludeP2UR : PumpTrainerModExcludeColumn
6 | {
7 | public override Column ExcludedColumn => Column.P2UR;
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/Directory.Build.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | $(MSBuildThisFileDirectory)app.manifest
5 |
6 |
7 | true
8 | $(NoWarn);CS1591
9 |
10 |
11 |
--------------------------------------------------------------------------------
/osu.Game.Rulesets.PumpTrainer.Tests/TestSceneOsuPlayer.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
2 | // See the LICENCE file in the repository root for full licence text.
3 |
4 | using NUnit.Framework;
5 | using osu.Game.Tests.Visual;
6 |
7 | namespace osu.Game.Rulesets.PumpTrainer.Tests
8 | {
9 | [TestFixture]
10 | public partial class TestSceneOsuPlayer : PlayerTestScene
11 | {
12 | protected override Ruleset CreatePlayerRuleset() => new PumpTrainerRuleset();
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/osu.Game.Rulesets.PumpTrainer/osu.Game.Rulesets.PumpTrainer.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | net8.0
4 | osu.Game.Rulesets.PumpTrainer
5 | Library
6 | AnyCPU
7 | osu.Game.Rulesets.PumpTrainer
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/osu.Game.Rulesets.PumpTrainer/Replays/PumpTrainerReplayFrame.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
2 | // See the LICENCE file in the repository root for full licence text.
3 |
4 | using System.Collections.Generic;
5 | using osu.Game.Rulesets.Replays;
6 |
7 | namespace osu.Game.Rulesets.PumpTrainer.Replays
8 | {
9 | public class PumpTrainerReplayFrame : ReplayFrame
10 | {
11 | public List Actions = new List();
12 |
13 | public PumpTrainerReplayFrame(PumpTrainerAction? button = null)
14 | {
15 | if (button.HasValue)
16 | Actions.Add(button.Value);
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/osu.Game.Rulesets.PumpTrainer/Mods/PumpTrainerModAutoplay.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
2 | // See the LICENCE file in the repository root for full licence text.
3 |
4 | using System.Collections.Generic;
5 | using osu.Game.Beatmaps;
6 | using osu.Game.Rulesets.PumpTrainer.Replays;
7 | using osu.Game.Rulesets.Mods;
8 |
9 | namespace osu.Game.Rulesets.PumpTrainer.Mods
10 | {
11 | public class PumpTrainerModAutoplay : ModAutoplay
12 | {
13 | public override ModReplayData CreateReplayData(IBeatmap beatmap, IReadOnlyList mods)
14 | => new ModReplayData(new PumpTrainerAutoGenerator(beatmap).Generate(), new ModCreatedUser { Username = "sample" });
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/osu.Game.Rulesets.PumpTrainer.Tests/VisualTestRunner.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
2 | // See the LICENCE file in the repository root for full licence text.
3 |
4 | using System;
5 | using osu.Framework;
6 | using osu.Framework.Platform;
7 | using osu.Game.Tests;
8 |
9 | namespace osu.Game.Rulesets.PumpTrainer.Tests
10 | {
11 | public static class VisualTestRunner
12 | {
13 | [STAThread]
14 | public static int Main(string[] args)
15 | {
16 | using (DesktopGameHost host = Host.GetSuitableDesktopHost(@"osu"))
17 | {
18 | host.Run(new OsuTestBrowser());
19 | return 0;
20 | }
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/osu.Game.Rulesets.PumpTrainer/PumpTrainerInputManager.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
2 | // See the LICENCE file in the repository root for full licence text.
3 |
4 | using osu.Framework.Input.Bindings;
5 | using osu.Game.Rulesets.UI;
6 |
7 | namespace osu.Game.Rulesets.PumpTrainer
8 | {
9 | public partial class PumpTrainerInputManager : RulesetInputManager
10 | {
11 | public PumpTrainerInputManager(RulesetInfo ruleset)
12 | : base(ruleset, 0, SimultaneousBindingMode.Unique)
13 | {
14 | }
15 | }
16 |
17 | public enum PumpTrainerAction
18 | {
19 | P1DL,
20 | P1UL,
21 | P1C,
22 | P1UR,
23 | P1DR,
24 | P2DL,
25 | P2UL,
26 | P2C,
27 | P2UR,
28 | P2DR,
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/osu.Game.Rulesets.PumpTrainer.Tests/TestSceneOsuGame.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
2 | // See the LICENCE file in the repository root for full licence text.
3 |
4 | using osu.Framework.Allocation;
5 | using osu.Framework.Graphics;
6 | using osu.Framework.Graphics.Shapes;
7 | using osu.Game.Tests.Visual;
8 | using osuTK.Graphics;
9 |
10 | namespace osu.Game.Rulesets.PumpTrainer.Tests
11 | {
12 | public partial class TestSceneOsuGame : OsuTestScene
13 | {
14 | [BackgroundDependencyLoader]
15 | private void load()
16 | {
17 | Children = new Drawable[]
18 | {
19 | new Box
20 | {
21 | RelativeSizeAxes = Axes.Both,
22 | Colour = Color4.Black,
23 | },
24 | };
25 |
26 | AddGame(new OsuGame());
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/osu.Game.Rulesets.PumpTrainer.Tests/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "0.2.0",
3 | "configurations": [
4 | {
5 | "name": "VisualTests (Debug)",
6 | "type": "coreclr",
7 | "request": "launch",
8 | "program": "dotnet",
9 | "args": [
10 | "${workspaceRoot}/bin/Debug/net8.0/osu.Game.Rulesets.PumpTrainer.Tests.dll"
11 | ],
12 | "cwd": "${workspaceRoot}",
13 | "preLaunchTask": "Build (Debug)",
14 | "env": {},
15 | "console": "internalConsole"
16 | },
17 | {
18 | "name": "VisualTests (Release)",
19 | "type": "coreclr",
20 | "request": "launch",
21 | "program": "dotnet",
22 | "args": [
23 | "${workspaceRoot}/bin/Release/net8.0/osu.Game.Rulesets.PumpTrainer.Tests.dll"
24 | ],
25 | "cwd": "${workspaceRoot}",
26 | "preLaunchTask": "Build (Release)",
27 | "env": {},
28 | "console": "internalConsole"
29 | }
30 | ]
31 | }
--------------------------------------------------------------------------------
/osu.Game.Rulesets.PumpTrainer/Objects/Drawables/DrawableTopRowHitObject.cs:
--------------------------------------------------------------------------------
1 | using osu.Framework.Allocation;
2 | using osu.Framework.Graphics;
3 | using osu.Framework.Graphics.Containers;
4 | using osu.Framework.Graphics.Textures;
5 | using osuTK;
6 | using osuTK.Graphics;
7 |
8 | namespace osu.Game.Rulesets.PumpTrainer.Objects.Drawables
9 | {
10 | public partial class DrawableTopRowHitObject : CompositeDrawable
11 | {
12 | private PumpTrainerHitObject hitObject;
13 |
14 | public DrawableTopRowHitObject(PumpTrainerHitObject hitObject)
15 | : base()
16 | {
17 | this.hitObject = hitObject;
18 | Size = new Vector2(DrawablePumpTrainerHitObject.WIDTH);
19 |
20 | Colour = Color4.Gray;
21 | }
22 |
23 | [BackgroundDependencyLoader]
24 | private void load(TextureStore textures)
25 | {
26 | AddInternal(hitObject.GetAssociatedSprite(textures, true));
27 | }
28 |
29 | public void FlashOnHit()
30 | {
31 | this.FlashColour(Color4.White, 250, Easing.In);
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/osu.Game.Rulesets.PumpTrainer.Tests/osu.Game.Rulesets.PumpTrainer.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 | osu.Game.Rulesets.PumpTrainer.Tests.VisualTestRunner
4 |
5 |
6 |
7 |
8 |
9 | false
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | WinExe
21 | net8.0
22 | osu.Game.Rulesets.PumpTrainer.Tests
23 |
24 |
25 |
--------------------------------------------------------------------------------
/osu.Game.Rulesets.PumpTrainer/Replays/PumpTrainerFramedReplayInputHandler.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
2 | // See the LICENCE file in the repository root for full licence text.
3 |
4 | using System.Collections.Generic;
5 | using System.Linq;
6 | using osu.Framework.Input.StateChanges;
7 | using osu.Game.Replays;
8 | using osu.Game.Rulesets.Replays;
9 |
10 | namespace osu.Game.Rulesets.PumpTrainer.Replays
11 | {
12 | public class PumpTrainerFramedReplayInputHandler : FramedReplayInputHandler
13 | {
14 | public PumpTrainerFramedReplayInputHandler(Replay replay)
15 | : base(replay)
16 | {
17 | }
18 |
19 | protected override bool IsImportant(PumpTrainerReplayFrame frame) => frame.Actions.Any();
20 |
21 | protected override void CollectReplayInputs(List inputs)
22 | {
23 | inputs.Add(new ReplayState
24 | {
25 | PressedActions = CurrentFrame?.Actions ?? new List(),
26 | });
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/osu.Game.Rulesets.PumpTrainer/Mods/ExcludeColumns/PumpTrainerModExcludeColumn.cs:
--------------------------------------------------------------------------------
1 | using osu.Framework.Localisation;
2 | using osu.Game.Beatmaps;
3 | using osu.Game.Rulesets.Mods;
4 | using osu.Game.Rulesets.PumpTrainer.Beatmaps;
5 | using osu.Game.Rulesets.PumpTrainer.Objects;
6 |
7 | namespace osu.Game.Rulesets.PumpTrainer.Mods.ExcludeColumns
8 | {
9 | public abstract class PumpTrainerModExcludeColumn : Mod, IApplicableToBeatmapConverter
10 | {
11 | public override string Name => "Exclude " + ExcludedColumn.ToString();
12 | public override string Acronym => ExcludedColumn.ToString().Substring(1);
13 | public override LocalisableString Description => "Excludes the column " + ExcludedColumn + ".";
14 | public override double ScoreMultiplier => 1;
15 | public override ModType Type => ModType.Conversion;
16 |
17 | public abstract Column ExcludedColumn { get; }
18 |
19 | public void ApplyToBeatmapConverter(IBeatmapConverter beatmapConverter)
20 | {
21 | var pumpBeatmapConverter = (PumpTrainerBeatmapConverter)beatmapConverter;
22 |
23 | pumpBeatmapConverter.HitObjectGenerator.Settings.AllowedColumns.Remove(ExcludedColumn);
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/osu.Game.Rulesets.PumpTrainer/Mods/PumpTrainerModSeeded.cs:
--------------------------------------------------------------------------------
1 | using osu.Framework.Bindables;
2 | using osu.Framework.Localisation;
3 | using osu.Game.Beatmaps;
4 | using osu.Game.Configuration;
5 | using osu.Game.Rulesets.Mods;
6 | using osu.Game.Rulesets.PumpTrainer.Beatmaps;
7 |
8 | namespace osu.Game.Rulesets.PumpTrainer.Mods
9 | {
10 | public class PumpTrainerModSeeded : Mod, IApplicableToBeatmapConverter
11 | {
12 | [SettingSource("Seed")]
13 | public Bindable Seed { get; } = new BindableInt(0)
14 | {
15 | MinValue = 0,
16 | MaxValue = 100,
17 | };
18 |
19 | public override string Name => "Seeded";
20 | public override string Acronym => "SD";
21 | public override LocalisableString Description => "Play consistently generated charts.";
22 | public override double ScoreMultiplier => 1;
23 | public override ModType Type => ModType.Automation;
24 |
25 | public void ApplyToBeatmapConverter(IBeatmapConverter beatmapConverter)
26 | {
27 | var pumpBeatmapConverter = (PumpTrainerBeatmapConverter)beatmapConverter;
28 |
29 | pumpBeatmapConverter.HitObjectGenerator.Seed = Seed.Value;
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/osu.Game.Rulesets.PumpTrainer/Replays/PumpTrainerAutoGenerator.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
2 | // See the LICENCE file in the repository root for full licence text.
3 |
4 | using osu.Game.Beatmaps;
5 | using osu.Game.Rulesets.PumpTrainer.Objects;
6 | using osu.Game.Rulesets.Replays;
7 |
8 | namespace osu.Game.Rulesets.PumpTrainer.Replays
9 | {
10 | public class PumpTrainerAutoGenerator : AutoGenerator
11 | {
12 | public new Beatmap Beatmap => (Beatmap)base.Beatmap;
13 |
14 | public PumpTrainerAutoGenerator(IBeatmap beatmap)
15 | : base(beatmap)
16 | {
17 | }
18 |
19 | protected override void GenerateFrames()
20 | {
21 | Frames.Add(new PumpTrainerReplayFrame());
22 |
23 | foreach (PumpTrainerHitObject hitObject in Beatmap.HitObjects)
24 | {
25 | Frames.Add(new PumpTrainerReplayFrame
26 | {
27 | Time = hitObject.StartTime,
28 | Actions = [PumpTrainerKeybindConversions.COLUMN_TO_ACTION[hitObject.Column]],
29 | });
30 | }
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/osu.Game.Rulesets.PumpTrainer/PumpTrainerDifficultyCalculator.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
2 | // See the LICENCE file in the repository root for full licence text.
3 |
4 | using System;
5 | using System.Collections.Generic;
6 | using System.Linq;
7 | using osu.Game.Beatmaps;
8 | using osu.Game.Rulesets.Difficulty;
9 | using osu.Game.Rulesets.Difficulty.Preprocessing;
10 | using osu.Game.Rulesets.Difficulty.Skills;
11 | using osu.Game.Rulesets.Mods;
12 |
13 | namespace osu.Game.Rulesets.PumpTrainer
14 | {
15 | public class PumpTrainerDifficultyCalculator : DifficultyCalculator
16 | {
17 | public PumpTrainerDifficultyCalculator(IRulesetInfo ruleset, IWorkingBeatmap beatmap)
18 | : base(ruleset, beatmap)
19 | {
20 | }
21 |
22 | protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate)
23 | {
24 | return new DifficultyAttributes(mods, 0);
25 | }
26 |
27 | protected override IEnumerable CreateDifficultyHitObjects(IBeatmap beatmap, double clockRate) => Enumerable.Empty();
28 |
29 | protected override Skill[] CreateSkills(IBeatmap beatmap, Mod[] mods, double clockRate) => Array.Empty();
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/osu.Game.Rulesets.PumpTrainer/PumpTrainerKeybindConversions.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Collections.Immutable;
3 | using osu.Game.Rulesets.PumpTrainer.Objects;
4 |
5 | namespace osu.Game.Rulesets.PumpTrainer
6 | {
7 | public static class PumpTrainerKeybindConversions
8 | {
9 | public static readonly ImmutableDictionary ACTION_TO_COLUMN = new Dictionary()
10 | {
11 | { PumpTrainerAction.P1DL, Column.P1DL },
12 | { PumpTrainerAction.P1UL, Column.P1UL },
13 | { PumpTrainerAction.P1C, Column.P1C },
14 | { PumpTrainerAction.P1UR, Column.P1UR },
15 | { PumpTrainerAction.P1DR, Column.P1DR },
16 | { PumpTrainerAction.P2DL, Column.P2DL },
17 | { PumpTrainerAction.P2UL, Column.P2UL },
18 | { PumpTrainerAction.P2C, Column.P2C },
19 | { PumpTrainerAction.P2UR, Column.P2UR },
20 | { PumpTrainerAction.P2DR, Column.P2DR },
21 | }.ToImmutableDictionary();
22 |
23 | public static readonly ImmutableDictionary COLUMN_TO_ACTION;
24 |
25 | static PumpTrainerKeybindConversions()
26 | {
27 | COLUMN_TO_ACTION = ACTION_TO_COLUMN.ToImmutableDictionary(i => i.Value, i => i.Key);
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/osu.Game.Rulesets.PumpTrainer.Tests/.vscode/tasks.json:
--------------------------------------------------------------------------------
1 | {
2 | // See https://go.microsoft.com/fwlink/?LinkId=733558
3 | // for the documentation about the tasks.json format
4 | "version": "2.0.0",
5 | "tasks": [
6 | {
7 | "label": "Build (Debug)",
8 | "type": "shell",
9 | "command": "dotnet",
10 | "args": [
11 | "build",
12 | "--no-restore",
13 | "osu.Game.Rulesets.PumpTrainer.Tests.csproj",
14 | "-p:GenerateFullPaths=true",
15 | "-m",
16 | "-verbosity:m"
17 | ],
18 | "group": "build",
19 | "problemMatcher": "$msCompile"
20 | },
21 | {
22 | "label": "Build (Release)",
23 | "type": "shell",
24 | "command": "dotnet",
25 | "args": [
26 | "build",
27 | "--no-restore",
28 | "osu.Game.Rulesets.PumpTrainer.Tests.csproj",
29 | "-p:Configuration=Release",
30 | "-p:GenerateFullPaths=true",
31 | "-m",
32 | "-verbosity:m"
33 | ],
34 | "group": "build",
35 | "problemMatcher": "$msCompile"
36 | },
37 | {
38 | "label": "Restore",
39 | "type": "shell",
40 | "command": "dotnet",
41 | "args": [
42 | "restore"
43 | ],
44 | "problemMatcher": []
45 | }
46 | ]
47 | }
--------------------------------------------------------------------------------
/osu.Game.Rulesets.PumpTrainer/Mods/PumpTrainerModDiagonalSkips.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using osu.Framework.Bindables;
3 | using osu.Framework.Localisation;
4 | using osu.Game.Beatmaps;
5 | using osu.Game.Configuration;
6 | using osu.Game.Rulesets.Mods;
7 | using osu.Game.Rulesets.PumpTrainer.Beatmaps;
8 | using osu.Game.Rulesets.PumpTrainer.Mods.ExcludeColumns;
9 |
10 | namespace osu.Game.Rulesets.PumpTrainer.Mods
11 | {
12 | public class PumpTrainerModDiagonalSkips : Mod, IApplicableToBeatmapConverter
13 | {
14 | [SettingSource("Frequency")]
15 | public Bindable DiagonalSkipFrequency { get; } = new BindableDouble(0.8)
16 | {
17 | MinValue = 0.1,
18 | MaxValue = 1.0,
19 | Default = 0.8,
20 | Precision = 0.1,
21 | };
22 |
23 | public override string Name => "[P1Single+] Diagonal Skips";
24 | public override string Acronym => "DD";
25 | public override LocalisableString Description => "Twists across a single pad that skip over the center panel.\n";
26 | public override double ScoreMultiplier => 1;
27 | public override ModType Type => ModType.DifficultyIncrease;
28 | public override Type[] IncompatibleMods => new Type[]
29 | {
30 | typeof(PumpTrainerModExcludeP1DL),
31 | typeof(PumpTrainerModExcludeP1UL),
32 | typeof(PumpTrainerModExcludeP1C),
33 | typeof(PumpTrainerModExcludeP1UR),
34 | typeof(PumpTrainerModExcludeP1DR),
35 | };
36 |
37 | public void ApplyToBeatmapConverter(IBeatmapConverter beatmapConverter)
38 | {
39 | var pumpBeatmapConverter = (PumpTrainerBeatmapConverter)beatmapConverter;
40 |
41 | pumpBeatmapConverter.HitObjectGenerator.Settings.DiagonalSkipFrequency = DiagonalSkipFrequency.Value;
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/osu.Game.Rulesets.PumpTrainer/UI/DrawablePumpTrainerRuleset.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
2 | // See the LICENCE file in the repository root for full licence text.
3 |
4 | using System.Collections.Generic;
5 | using osu.Framework.Allocation;
6 | using osu.Framework.Input;
7 | using osu.Game.Beatmaps;
8 | using osu.Game.Input.Handlers;
9 | using osu.Game.Replays;
10 | using osu.Game.Rulesets.Mods;
11 | using osu.Game.Rulesets.Objects.Drawables;
12 | using osu.Game.Rulesets.PumpTrainer.Objects;
13 | using osu.Game.Rulesets.PumpTrainer.Objects.Drawables;
14 | using osu.Game.Rulesets.PumpTrainer.Replays;
15 | using osu.Game.Rulesets.UI;
16 | using osu.Game.Rulesets.UI.Scrolling;
17 |
18 | namespace osu.Game.Rulesets.PumpTrainer.UI
19 | {
20 | [Cached]
21 | public partial class DrawablePumpTrainerRuleset : DrawableScrollingRuleset
22 | {
23 | public DrawablePumpTrainerRuleset(PumpTrainerRuleset ruleset, IBeatmap beatmap, IReadOnlyList mods = null)
24 | : base(ruleset, beatmap, mods)
25 | {
26 | Direction.Value = ScrollingDirection.Up;
27 | TimeRange.Value = 5000;
28 | // still have no idea what this number means. but apparently you can use F3 and F4 to adjust scroll speed
29 | }
30 |
31 | protected override Playfield CreatePlayfield() => new PumpTrainerPlayfield();
32 |
33 | protected override ReplayInputHandler CreateReplayInputHandler(Replay replay) => new PumpTrainerFramedReplayInputHandler(replay);
34 |
35 | public override DrawableHitObject CreateDrawableRepresentation(PumpTrainerHitObject h) =>
36 | new DrawablePumpTrainerHitObject(h, (PumpTrainerPlayfield)Playfield);
37 |
38 | protected override PassThroughInputManager CreateInputManager() => new PumpTrainerInputManager(Ruleset?.RulesetInfo);
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/osu.Game.Rulesets.PumpTrainer/Beatmaps/PumpTrainerHitObjectGeneratorSettingsPerHitObject.cs:
--------------------------------------------------------------------------------
1 | namespace osu.Game.Rulesets.PumpTrainer.Beatmaps
2 | {
3 | ///
4 | /// By default, all the fields in this class are set to maximize the frequency of each pattern.
5 | ///
6 | public class PumpTrainerHitObjectGeneratorSettingsPerHitObject
7 | {
8 | ///
9 | /// 0 to 1 determining how frequently to generate a corner pattern. Higher means more likely.
10 | /// Corner patterns include 90 degree patterns and V shape patterns (see examples below).
11 | /// (Corner patterns are usually banned on sixteenth rhythms.)
12 | /// Examples:
13 | /// Starting left: UL, UR, DR (and 7 other variations per singles panel) - 90 degrees across a single panel.
14 | /// Starting left: UL, DR, UR (and 7 other variations per singles panel) - V shape across a single panel.
15 | ///
16 | public double CornersFrequency = 1;
17 |
18 | ///
19 | /// 0 to 1 determining how frequently to generate 3 horizontally adjacent notes that go in one direction (i.e. only left, or only right),
20 | /// and are not all on the same single pad. Higher means more likely.
21 | /// Example: P1C --> P1DR --> P2UL
22 | /// NON-example: P1C --> P2UL --> P2DL (because the notes do not go in one direction)
23 | /// NON-example: P1C --> P2UL --> P1DR (because the notes do not go in one direction)
24 | /// NON-example: P1UL --> P1C --> P1UR (because the notes only span a single pad)
25 | /// NON-example: P1C --> P1UR --> P2C (because the notes are not horizontally adjacent. This case is actually always banned, no matter what mods are on.)
26 | ///
27 | public double HorizontalTripleFrequency = 1;
28 |
29 | public PumpTrainerHitObjectGeneratorSettingsPerHitObject()
30 | {
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/osu.Game.Rulesets.PumpTrainer/Mods/PumpTrainerModNoFarColumns.cs:
--------------------------------------------------------------------------------
1 | using osu.Framework.Bindables;
2 | using osu.Framework.Localisation;
3 | using osu.Game.Beatmaps;
4 | using osu.Game.Configuration;
5 | using osu.Game.Rulesets.Mods;
6 | using osu.Game.Rulesets.PumpTrainer.Beatmaps;
7 | using osu.Game.Rulesets.PumpTrainer.Mods.ExcludeColumns;
8 | using System;
9 |
10 | namespace osu.Game.Rulesets.PumpTrainer.Mods
11 | {
12 | public class PumpTrainerModNoFarColumns : Mod, IApplicableToBeatmapConverter
13 | {
14 | [SettingSource("Frequency")]
15 | public Bindable FarColumnsFrequency { get; } = new BindableDouble(0.5)
16 | {
17 | MinValue = 0,
18 | MaxValue = 0.9,
19 | Default = 0.5,
20 | Precision = 0.1,
21 | };
22 |
23 | public override string Name => "[Half-Dbl+] No Far Columns";
24 | public override string Acronym => "D";
25 | public override LocalisableString Description =>
26 | "Reduces the frequency of two physically non-adjacent consecutive notes in the half-doubles region.";
27 | public override double ScoreMultiplier => 1;
28 | public override ModType Type => ModType.DifficultyReduction;
29 | public override Type[] IncompatibleMods => new Type[]
30 | {
31 | typeof(PumpTrainerModExcludeP1C),
32 | typeof(PumpTrainerModExcludeP1UR),
33 | typeof(PumpTrainerModExcludeP1DR),
34 | typeof(PumpTrainerModExcludeP2DL),
35 | typeof(PumpTrainerModExcludeP2UL),
36 | typeof(PumpTrainerModExcludeP2C),
37 | };
38 |
39 | public void ApplyToBeatmapConverter(IBeatmapConverter beatmapConverter)
40 | {
41 | var pumpBeatmapConverter = (PumpTrainerBeatmapConverter)beatmapConverter;
42 |
43 | pumpBeatmapConverter.HitObjectGenerator.Settings.FarColumnsFrequency = FarColumnsFrequency.Value;
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/osu.Game.Rulesets.PumpTrainer/Mods/PumpTrainerModCornersOnSixteenths.cs:
--------------------------------------------------------------------------------
1 | using osu.Framework.Bindables;
2 | using osu.Framework.Localisation;
3 | using System;
4 | using osu.Game.Beatmaps;
5 | using osu.Game.Configuration;
6 | using osu.Game.Rulesets.Mods;
7 | using osu.Game.Rulesets.PumpTrainer.Beatmaps;
8 | using osu.Game.Rulesets.PumpTrainer.Mods.ExcludeColumns;
9 |
10 | namespace osu.Game.Rulesets.PumpTrainer.Mods
11 | {
12 | public class PumpTrainerModCornersOnSixteenths : Mod, IApplicableToBeatmapConverter
13 | {
14 | [SettingSource("Frequency")]
15 | public Bindable CornersOnSixteenthsFrequency { get; } = new BindableDouble(0.8)
16 | {
17 | MinValue = 0.1,
18 | MaxValue = 1.0,
19 | Default = 0.8,
20 | Precision = 0.1,
21 | };
22 |
23 | public override string Name => "[P1Single+] Corners on 1/4s";
24 | public override string Acronym => "CO";
25 | public override LocalisableString Description =>
26 | "90-degree and V-twists across a single pad.\n" +
27 | "These are normally banned for rhythms 1/4 and faster.";
28 | public override double ScoreMultiplier => 1;
29 | public override ModType Type => ModType.DifficultyIncrease;
30 | public override Type[] IncompatibleMods => new Type[]
31 | {
32 | typeof(PumpTrainerModExcludeP1DL),
33 | typeof(PumpTrainerModExcludeP1UL),
34 | typeof(PumpTrainerModExcludeP1C),
35 | typeof(PumpTrainerModExcludeP1UR),
36 | typeof(PumpTrainerModExcludeP1DR),
37 | };
38 |
39 | public void ApplyToBeatmapConverter(IBeatmapConverter beatmapConverter)
40 | {
41 | var pumpBeatmapConverter = (PumpTrainerBeatmapConverter)beatmapConverter;
42 |
43 | pumpBeatmapConverter.GeneratorSettingsForSixteenthRhythms.CornersFrequency = CornersOnSixteenthsFrequency.Value;
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/osu.Game.Rulesets.PumpTrainer/Mods/PumpTrainerModHorizontalTriplesOnSixteenths.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using osu.Framework.Bindables;
3 | using osu.Framework.Localisation;
4 | using osu.Game.Beatmaps;
5 | using osu.Game.Configuration;
6 | using osu.Game.Rulesets.Mods;
7 | using osu.Game.Rulesets.PumpTrainer.Beatmaps;
8 | using osu.Game.Rulesets.PumpTrainer.Mods.ExcludeColumns;
9 |
10 | namespace osu.Game.Rulesets.PumpTrainer.Mods
11 | {
12 | public class PumpTrainerModHorizontalTriplesOnSixteenths : Mod, IApplicableToBeatmapConverter
13 | {
14 | [SettingSource("Frequency")]
15 | public Bindable HorizontalTripleFrequency { get; } = new BindableDouble(0.8)
16 | {
17 | MinValue = 0.1,
18 | MaxValue = 1.0,
19 | Default = 0.8,
20 | Precision = 0.1,
21 | };
22 |
23 | public override string Name => "[Half-Dbl+] Horiz-3's on 1/4s";
24 | public override string Acronym => "3H";
25 | public override LocalisableString Description =>
26 | "Three consecutive notes in horizontally adjacent columns in a single direction.\n" +
27 | "These are normally banned for rhythms 1/4 and faster.";
28 | public override double ScoreMultiplier => 1;
29 | public override ModType Type => ModType.DifficultyIncrease;
30 | public override Type[] IncompatibleMods => new Type[]
31 | {
32 | typeof(PumpTrainerModExcludeP1C),
33 | typeof(PumpTrainerModExcludeP1UR),
34 | typeof(PumpTrainerModExcludeP1DR),
35 | typeof(PumpTrainerModExcludeP2DL),
36 | typeof(PumpTrainerModExcludeP2UL),
37 | typeof(PumpTrainerModExcludeP2C),
38 | };
39 |
40 | public void ApplyToBeatmapConverter(IBeatmapConverter beatmapConverter)
41 | {
42 | var pumpBeatmapConverter = (PumpTrainerBeatmapConverter)beatmapConverter;
43 |
44 | pumpBeatmapConverter.GeneratorSettingsForSixteenthRhythms.HorizontalTripleFrequency = HorizontalTripleFrequency.Value;
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## What is this?
2 |
3 | This is a ruleset for [osu!](https://github.com/ppy/osu). It generates Pump It Up charts that are playable with two feet, from osu! beatmaps.
4 |
5 | The current the formula generates charts with:
6 | - No double-steps
7 | - No spins
8 | - No splits (consecutive notes have at most 1 panel horizontally between them)
9 | - No large horizontal travels (e.g. P2DL --> P1UR --> P1UL)
10 | - osu! slider rhythm simplification: 1/6 and 1/8 buzz sliders are treated as 1/4's, and long sliders are rounded down to the nearest 1/2 (e.g. 3/4 sliders are treated as 1/2)
11 | - For rhythms 1/4 and faster (overridable through mods):
12 | - No 90 degree twists (e.g. DL --> DR --> UR)
13 | - No horizontal travels (e.g. P1C --> P1UR --> P2DL)
14 | - Adjustable through mods:
15 | - Regular twists (e.g. C --> UL)
16 | - Large twists (e.g. P2DL --> P1C)
17 | - Diagonal twists (e.g. DL --> C --> UR)
18 | - Diagonal skips (e.g. UR --> DL)
19 |
20 | All examples above start with the left foot. See [this page](https://www.piucenter.com/skill) for more background.
21 | (The terminology I'm using here and in the code don't match exactly to that page.)
22 |
23 | ## How to install
24 |
25 | https://rulesets.info/install/rulesets
26 |
27 | The ruleset file is provided here: https://github.com/hwabis/pump-trainer/releases
28 |
29 | ## Tips
30 |
31 | - Keybinds:
32 | ```
33 | Q E R Y
34 | S G
35 | Z C V N
36 | ```
37 | - However, I believe playing with your feet with Autoplay mod is more fun.
38 | - f3 and f4 in-game to change scroll speed. This is a keybind in osu! itself, not a ruleset keybind.
39 |
40 | ## Example converted beatmaps
41 |
42 | Converted map: https://osu.ppy.sh/beatmapsets/2010589#osu/4183614
43 |
44 | ### Single
45 |
46 | https://github.com/user-attachments/assets/443fd2df-9c3f-4c19-bf72-c9ba25ae3e57
47 |
48 | ### Half-double
49 |
50 | https://github.com/user-attachments/assets/87712408-7cc8-42e1-b919-8e6acae75598
51 |
52 | ### Double with regular twists
53 |
54 | Converted map: https://osu.ppy.sh/beatmapsets/600303#osu/1310291
55 |
56 | https://github.com/user-attachments/assets/30c1f1d2-d591-476f-acda-669ef21f94d8
57 |
--------------------------------------------------------------------------------
/app.manifest:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 | true
32 |
33 |
34 |
35 |
36 |
44 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/osu.Game.Rulesets.PumpTrainer/UI/PumpTrainerPlayfield.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
2 | // See the LICENCE file in the repository root for full licence text.
3 |
4 | using System.Collections.Generic;
5 | using osu.Framework.Allocation;
6 | using osu.Framework.Graphics;
7 | using osu.Framework.Graphics.Containers;
8 | using osu.Framework.Graphics.Textures;
9 | using osu.Game.Rulesets.PumpTrainer.Objects;
10 | using osu.Game.Rulesets.PumpTrainer.Objects.Drawables;
11 | using osu.Game.Rulesets.UI.Scrolling;
12 |
13 | namespace osu.Game.Rulesets.PumpTrainer.UI
14 | {
15 | [Cached]
16 | public partial class PumpTrainerPlayfield : ScrollingPlayfield
17 | {
18 | public IReadOnlyList TopRowHitObjects;
19 |
20 | [BackgroundDependencyLoader]
21 | private void load(TextureStore textures)
22 | {
23 | Margin = new()
24 | {
25 | Top = 50,
26 | };
27 |
28 | AddRangeInternal(new Drawable[]
29 | {
30 | new FillFlowContainer()
31 | {
32 | Direction = FillDirection.Horizontal,
33 | Anchor = Anchor.TopCentre,
34 | Origin = Anchor.TopCentre,
35 | AutoSizeAxes = Axes.Both,
36 | Children = TopRowHitObjects =
37 | [
38 | new DrawableTopRowHitObject(new(Column.P1DL)),
39 | new DrawableTopRowHitObject(new(Column.P1UL)),
40 | new DrawableTopRowHitObject(new(Column.P1C)),
41 | new DrawableTopRowHitObject(new(Column.P1UR)),
42 | new DrawableTopRowHitObject(new(Column.P1DR)),
43 | new DrawableTopRowHitObject(new(Column.P2DL)),
44 | new DrawableTopRowHitObject(new(Column.P2UL)),
45 | new DrawableTopRowHitObject(new(Column.P2C)),
46 | new DrawableTopRowHitObject(new(Column.P2UR)),
47 | new DrawableTopRowHitObject(new(Column.P2DR)),
48 | ]
49 | },
50 | HitObjectContainer,
51 | });
52 | }
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/osu.Game.Rulesets.PumpTrainer/Mods/PumpTrainerModHorizontalTwists.cs:
--------------------------------------------------------------------------------
1 | using osu.Framework.Bindables;
2 | using osu.Framework.Localisation;
3 | using osu.Game.Beatmaps;
4 | using osu.Game.Configuration;
5 | using osu.Game.Rulesets.Mods;
6 | using osu.Game.Rulesets.PumpTrainer.Beatmaps;
7 |
8 | namespace osu.Game.Rulesets.PumpTrainer.Mods
9 | {
10 | public class PumpTrainerModHorizontalTwists : Mod, IApplicableToBeatmapConverter
11 | {
12 | [SettingSource("Twist Frequency")]
13 | public Bindable HorizontalTwistFrequency { get; } = new BindableDouble(0.8)
14 | {
15 | MinValue = 0.1,
16 | MaxValue = 1.0,
17 | Default = 0.8,
18 | Precision = 0.1,
19 | };
20 |
21 | [SettingSource("[Half-Dbl+] Large Twists")]
22 | public Bindable IncludeLargeTwists { get; } = new BindableBool(false)
23 | {
24 | Default = false,
25 | };
26 |
27 | [SettingSource("[P1Single+] Diagonal Twists")]
28 | public Bindable AllowDiagonalTwists { get; } = new BindableBool(false)
29 | {
30 | Default = false,
31 | };
32 |
33 | public override string Name => "Horizontal Twists";
34 | public override string Acronym => "TW";
35 | public override LocalisableString Description =>
36 | "Twists involving a center panel. Also enables other types of twists in mod customization.";
37 | public override double ScoreMultiplier => 1;
38 | public override ModType Type => ModType.DifficultyIncrease;
39 |
40 | public void ApplyToBeatmapConverter(IBeatmapConverter beatmapConverter)
41 | {
42 | var pumpBeatmapConverter = (PumpTrainerBeatmapConverter)beatmapConverter;
43 |
44 | pumpBeatmapConverter.HitObjectGenerator.Settings.HorizontalTwistFrequency = HorizontalTwistFrequency.Value;
45 |
46 | if (IncludeLargeTwists.Value)
47 | {
48 | pumpBeatmapConverter.HitObjectGenerator.Settings.LargeTwistFrequency = HorizontalTwistFrequency.Value;
49 | }
50 |
51 | if (AllowDiagonalTwists.Value)
52 | {
53 | pumpBeatmapConverter.HitObjectGenerator.Settings.AllowDiagonalTwists = true;
54 | }
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/osu.Game.Rulesets.PumpTrainer/Beatmaps/PumpTrainerHitObjectGeneratorSettings.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using osu.Game.Rulesets.PumpTrainer.Objects;
3 |
4 | namespace osu.Game.Rulesets.PumpTrainer.Beatmaps
5 | {
6 | public class PumpTrainerHitObjectGeneratorSettings
7 | {
8 | public List AllowedColumns =
9 | [Column.P1DL, Column.P1UL, Column.P1C, Column.P1UR, Column.P1DR, Column.P2DL, Column.P2UL, Column.P2C, Column.P2UR, Column.P2DR];
10 |
11 | ///
12 | /// 0 to 1 determining how frequently to generate two notes that are in adjacent columns on the physical dance pad.
13 | /// One of the notes must be a center panel (aka they do not span across a center panel, aka they must be in the half-doubles region).
14 | /// Higher means more likely.
15 | /// Example starting left foot: P1C --> P2UL
16 | /// Example starting right foot: P2DL --> P1C
17 | /// NON-example starting left foot: P1DL --> P1DR
18 | ///
19 | public double FarColumnsFrequency = 1;
20 |
21 | ///
22 | /// 0 to 1 determining how frequently to generate a horizontal twist. Higher means more likely.
23 | /// Example starting left foot: UL --> C --> UR
24 | ///
25 | public double HorizontalTwistFrequency = 0;
26 |
27 | ///
28 | /// Determines whether to allow generating diagonal twists.
29 | /// This requires horizontal twists to be on (greater than 0) to have any effect.
30 | /// Example starting left foot: DL --> C --> UR
31 | ///
32 | public bool AllowDiagonalTwists = false;
33 |
34 | ///
35 | /// 0 to 1 determining how frequently to generate a diagonal skip. Higher means more likely.
36 | /// Example starting left foot: DR --> UL
37 | ///
38 | public double DiagonalSkipFrequency = 0;
39 |
40 | ///
41 | /// 0 to 1 determining how frequently to generate a large horizontal twist. Higher means more likely.
42 | /// This kind of twist is very rare. Example charts are Uranium D24 and See D20 (those are actually the only charts I know of that have this pattern lol).
43 | /// Example starting right foot: P1C --> P2UL
44 | ///
45 | public double LargeTwistFrequency = 0;
46 |
47 | public PumpTrainerHitObjectGeneratorSettings()
48 | {
49 | }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/osu.Game.Rulesets.PumpTrainer/Objects/Drawables/DrawablePumpTrainerHitObject.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
2 | // See the LICENCE file in the repository root for full licence text.
3 |
4 | using osu.Framework.Allocation;
5 | using osu.Framework.Graphics;
6 | using osu.Framework.Graphics.Textures;
7 | using osu.Framework.Input.Bindings;
8 | using osu.Framework.Input.Events;
9 | using osu.Game.Rulesets.Objects.Drawables;
10 | using osu.Game.Rulesets.PumpTrainer.UI;
11 | using osu.Game.Rulesets.Scoring;
12 | using osuTK;
13 |
14 | namespace osu.Game.Rulesets.PumpTrainer.Objects.Drawables
15 | {
16 | public partial class DrawablePumpTrainerHitObject : DrawableHitObject, IKeyBindingHandler
17 | {
18 | public const int WIDTH = 80;
19 |
20 | private DrawableTopRowHitObject correspondingTopRowHitObject;
21 |
22 | public DrawablePumpTrainerHitObject(PumpTrainerHitObject hitObject, PumpTrainerPlayfield playfield)
23 | : base(hitObject)
24 | {
25 | Size = new Vector2(WIDTH);
26 | Origin = Anchor.TopCentre;
27 | Anchor = Anchor.TopCentre;
28 |
29 | // Indexes 0 to 9 so midpoint is 4.5
30 | X = (float)((int)HitObject.Column - 4.5) * WIDTH;
31 |
32 | correspondingTopRowHitObject = playfield.TopRowHitObjects[(int)HitObject.Column];
33 | }
34 |
35 | [BackgroundDependencyLoader]
36 | private void load(TextureStore textures)
37 | {
38 | AddInternal(HitObject.GetAssociatedSprite(textures, false));
39 | }
40 |
41 | protected override void CheckForResult(bool userTriggered, double timeOffset)
42 | {
43 | if (!userTriggered)
44 | {
45 | if (!HitObject.HitWindows.CanBeHit(timeOffset))
46 | {
47 | ApplyMinResult();
48 | }
49 |
50 | return;
51 | }
52 |
53 | var result = HitObject.HitWindows.ResultFor(timeOffset);
54 |
55 | if (result == HitResult.None)
56 | return;
57 |
58 | ApplyResult(result);
59 | correspondingTopRowHitObject.FlashOnHit();
60 | }
61 |
62 | protected override void UpdateHitStateTransforms(ArmedState state)
63 | {
64 | switch (state)
65 | {
66 | case ArmedState.Hit:
67 | this.FadeOut().Expire();
68 | break;
69 |
70 | case ArmedState.Miss:
71 | // todo ?
72 | break;
73 | }
74 | }
75 |
76 | public bool OnPressed(KeyBindingPressEvent e)
77 | {
78 | if (PumpTrainerKeybindConversions.ACTION_TO_COLUMN[e.Action] == HitObject.Column)
79 | {
80 | return UpdateResult(true);
81 | }
82 |
83 | return false;
84 | }
85 |
86 | public void OnReleased(KeyBindingReleaseEvent e)
87 | {
88 | }
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/osu.Game.Rulesets.PumpTrainer/Objects/PumpTrainerHitObject.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
2 | // See the LICENCE file in the repository root for full licence text.
3 |
4 | using System.Text;
5 | using osu.Framework.Graphics;
6 | using osu.Framework.Graphics.Sprites;
7 | using osu.Framework.Graphics.Textures;
8 | using osu.Game.Rulesets.Judgements;
9 | using osu.Game.Rulesets.Objects;
10 |
11 | namespace osu.Game.Rulesets.PumpTrainer.Objects
12 | {
13 | public class PumpTrainerHitObject : HitObject
14 | {
15 | public override Judgement CreateJudgement() => new Judgement();
16 |
17 | public Foot IntendedFoot;
18 | public Column Column;
19 |
20 | public PumpTrainerHitObject(Column column)
21 | : base()
22 | {
23 | Column = column;
24 | }
25 |
26 | // does this belong here?
27 | public Sprite GetAssociatedSprite(TextureStore textures, bool gray)
28 | {
29 | StringBuilder textureString = new();
30 |
31 | switch (Column)
32 | {
33 | case Column.P1DL:
34 | case Column.P1DR:
35 | case Column.P2DL:
36 | case Column.P2DR:
37 | textureString.Append("DL");
38 | break;
39 | case Column.P1UL:
40 | case Column.P1UR:
41 | case Column.P2UL:
42 | case Column.P2UR:
43 | textureString.Append("UL");
44 | break;
45 | default:
46 | textureString.Append("C");
47 | break;
48 | }
49 |
50 | if (gray)
51 | {
52 | textureString.Append("-gray");
53 | }
54 |
55 | Sprite sprite = new()
56 | {
57 | RelativeSizeAxes = Axes.Both,
58 | Origin = Anchor.TopCentre,
59 | Anchor = Anchor.TopCentre,
60 | Texture = textures.Get(textureString.ToString()),
61 | // In PIU, there is a slight overlap between hitobjects that are directly next to each other
62 | // so bloat the sprite by a little
63 | Scale = new(1.08f),
64 | };
65 |
66 |
67 | switch (Column)
68 | {
69 | case Column.P1UR:
70 | case Column.P1DR:
71 | case Column.P2UR:
72 | case Column.P2DR:
73 | sprite.Scale = new(-sprite.Scale.X, sprite.Scale.Y);
74 | break;
75 | }
76 |
77 | return sprite;
78 | }
79 | }
80 |
81 | public enum Column
82 | {
83 | P1DL,
84 | P1UL,
85 | P1C,
86 | P1UR,
87 | P1DR,
88 | P2DL,
89 | P2UL,
90 | P2C,
91 | P2UR,
92 | P2DR,
93 | }
94 |
95 | public enum Foot
96 | {
97 | Left,
98 | Right,
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/osu.Game.Rulesets.PumpTrainer.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.29123.88
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "osu.Game.Rulesets.PumpTrainer", "osu.Game.Rulesets.PumpTrainer\osu.Game.Rulesets.PumpTrainer.csproj", "{5AE1F0F1-DAFA-46E7-959C-DA233B7C87E9}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.PumpTrainer.Tests", "osu.Game.Rulesets.PumpTrainer.Tests\osu.Game.Rulesets.PumpTrainer.Tests.csproj", "{B4577C85-CB83-462A-BCE3-22FFEB16311D}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|Any CPU = Debug|Any CPU
13 | Release|Any CPU = Release|Any CPU
14 | VisualTests|Any CPU = VisualTests|Any CPU
15 | EndGlobalSection
16 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
17 | {5AE1F0F1-DAFA-46E7-959C-DA233B7C87E9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
18 | {5AE1F0F1-DAFA-46E7-959C-DA233B7C87E9}.Debug|Any CPU.Build.0 = Debug|Any CPU
19 | {5AE1F0F1-DAFA-46E7-959C-DA233B7C87E9}.Release|Any CPU.ActiveCfg = Release|Any CPU
20 | {5AE1F0F1-DAFA-46E7-959C-DA233B7C87E9}.Release|Any CPU.Build.0 = Release|Any CPU
21 | {5AE1F0F1-DAFA-46E7-959C-DA233B7C87E9}.VisualTests|Any CPU.ActiveCfg = Release|Any CPU
22 | {5AE1F0F1-DAFA-46E7-959C-DA233B7C87E9}.VisualTests|Any CPU.Build.0 = Release|Any CPU
23 | {B4577C85-CB83-462A-BCE3-22FFEB16311D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
24 | {B4577C85-CB83-462A-BCE3-22FFEB16311D}.Debug|Any CPU.Build.0 = Debug|Any CPU
25 | {B4577C85-CB83-462A-BCE3-22FFEB16311D}.Release|Any CPU.ActiveCfg = Release|Any CPU
26 | {B4577C85-CB83-462A-BCE3-22FFEB16311D}.Release|Any CPU.Build.0 = Release|Any CPU
27 | {B4577C85-CB83-462A-BCE3-22FFEB16311D}.VisualTests|Any CPU.ActiveCfg = Debug|Any CPU
28 | {B4577C85-CB83-462A-BCE3-22FFEB16311D}.VisualTests|Any CPU.Build.0 = Debug|Any CPU
29 | EndGlobalSection
30 | GlobalSection(SolutionProperties) = preSolution
31 | HideSolutionNode = FALSE
32 | EndGlobalSection
33 | GlobalSection(NestedProjects) = preSolution
34 | EndGlobalSection
35 | GlobalSection(ExtensibilityGlobals) = postSolution
36 | SolutionGuid = {671B0BEC-2403-45B0-9357-2C97CC517668}
37 | EndGlobalSection
38 | GlobalSection(MonoDevelopProperties) = preSolution
39 | Policies = $0
40 | $0.TextStylePolicy = $1
41 | $1.EolMarker = Windows
42 | $1.inheritsSet = VisualStudio
43 | $1.inheritsScope = text/plain
44 | $1.scope = text/x-csharp
45 | $0.CSharpFormattingPolicy = $2
46 | $2.IndentSwitchSection = True
47 | $2.NewLinesForBracesInProperties = True
48 | $2.NewLinesForBracesInAccessors = True
49 | $2.NewLinesForBracesInAnonymousMethods = True
50 | $2.NewLinesForBracesInControlBlocks = True
51 | $2.NewLinesForBracesInAnonymousTypes = True
52 | $2.NewLinesForBracesInObjectCollectionArrayInitializers = True
53 | $2.NewLinesForBracesInLambdaExpressionBody = True
54 | $2.NewLineForElse = True
55 | $2.NewLineForCatch = True
56 | $2.NewLineForFinally = True
57 | $2.NewLineForMembersInObjectInit = True
58 | $2.NewLineForMembersInAnonymousTypes = True
59 | $2.NewLineForClausesInQuery = True
60 | $2.SpacingAfterMethodDeclarationName = False
61 | $2.SpaceAfterMethodCallName = False
62 | $2.SpaceBeforeOpenSquareBracket = False
63 | $2.inheritsSet = Mono
64 | $2.inheritsScope = text/x-csharp
65 | $2.scope = text/x-csharp
66 | EndGlobalSection
67 | GlobalSection(MonoDevelopProperties) = preSolution
68 | Policies = $0
69 | $0.TextStylePolicy = $1
70 | $1.EolMarker = Windows
71 | $1.inheritsSet = VisualStudio
72 | $1.inheritsScope = text/plain
73 | $1.scope = text/x-csharp
74 | $0.CSharpFormattingPolicy = $2
75 | $2.IndentSwitchSection = True
76 | $2.NewLinesForBracesInProperties = True
77 | $2.NewLinesForBracesInAccessors = True
78 | $2.NewLinesForBracesInAnonymousMethods = True
79 | $2.NewLinesForBracesInControlBlocks = True
80 | $2.NewLinesForBracesInAnonymousTypes = True
81 | $2.NewLinesForBracesInObjectCollectionArrayInitializers = True
82 | $2.NewLinesForBracesInLambdaExpressionBody = True
83 | $2.NewLineForElse = True
84 | $2.NewLineForCatch = True
85 | $2.NewLineForFinally = True
86 | $2.NewLineForMembersInObjectInit = True
87 | $2.NewLineForMembersInAnonymousTypes = True
88 | $2.NewLineForClausesInQuery = True
89 | $2.SpacingAfterMethodDeclarationName = False
90 | $2.SpaceAfterMethodCallName = False
91 | $2.SpaceBeforeOpenSquareBracket = False
92 | $2.inheritsSet = Mono
93 | $2.inheritsScope = text/x-csharp
94 | $2.scope = text/x-csharp
95 | EndGlobalSection
96 | EndGlobal
97 |
--------------------------------------------------------------------------------
/osu.Game.Rulesets.PumpTrainer/PumpTrainerRuleset.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
2 | // See the LICENCE file in the repository root for full licence text.
3 |
4 | using System;
5 | using System.Collections.Generic;
6 | using osu.Framework.Graphics;
7 | using osu.Framework.Graphics.Sprites;
8 | using osu.Framework.Input.Bindings;
9 | using osu.Game.Beatmaps;
10 | using osu.Game.Graphics;
11 | using osu.Game.Rulesets.Difficulty;
12 | using osu.Game.Rulesets.Mods;
13 | using osu.Game.Rulesets.PumpTrainer.Beatmaps;
14 | using osu.Game.Rulesets.PumpTrainer.Mods;
15 | using osu.Game.Rulesets.PumpTrainer.Mods.ExcludeColumns;
16 | using osu.Game.Rulesets.PumpTrainer.UI;
17 | using osu.Game.Rulesets.UI;
18 |
19 | namespace osu.Game.Rulesets.PumpTrainer
20 | {
21 | public class PumpTrainerRuleset : Ruleset
22 | {
23 | public override string Description => "Pump It Up!";
24 |
25 | public override DrawableRuleset CreateDrawableRulesetWith(IBeatmap beatmap, IReadOnlyList mods = null) => new DrawablePumpTrainerRuleset(this, beatmap, mods);
26 |
27 | public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new PumpTrainerBeatmapConverter(beatmap, this);
28 |
29 | // todo yeah no this is impossible
30 | public override DifficultyCalculator CreateDifficultyCalculator(IWorkingBeatmap beatmap) => new PumpTrainerDifficultyCalculator(RulesetInfo, beatmap);
31 |
32 | public override IEnumerable GetModsFor(ModType type)
33 | {
34 | switch (type)
35 | {
36 | case ModType.DifficultyReduction:
37 | return new Mod[]
38 | {
39 | new PumpTrainerModNoFarColumns(),
40 | new PumpTrainerModHalfTime(),
41 | };
42 |
43 | case ModType.DifficultyIncrease:
44 | return new Mod[]
45 | {
46 | new PumpTrainerModHorizontalTwists(),
47 | new PumpTrainerModDiagonalSkips(),
48 | new PumpTrainerModCornersOnSixteenths(),
49 | new PumpTrainerModHorizontalTriplesOnSixteenths(),
50 | new PumpTrainerModDoubleTime(),
51 | };
52 |
53 | case ModType.Conversion:
54 | return new Mod[]
55 | {
56 | new PumpTrainerModExcludeP1DL(),
57 | new PumpTrainerModExcludeP1UL(),
58 | new PumpTrainerModExcludeP1C(),
59 | new PumpTrainerModExcludeP1UR(),
60 | new PumpTrainerModExcludeP1DR(),
61 | new PumpTrainerModExcludeP2DL(),
62 | new PumpTrainerModExcludeP2UL(),
63 | new PumpTrainerModExcludeP2C(),
64 | new PumpTrainerModExcludeP2UR(),
65 | new PumpTrainerModExcludeP2DR(),
66 | };
67 |
68 | case ModType.Automation:
69 | return new Mod[]
70 | {
71 | new PumpTrainerModAutoplay(),
72 | new PumpTrainerModSeeded(),
73 | };
74 |
75 | default:
76 | return Array.Empty();
77 | }
78 | }
79 |
80 | public override string ShortName => "pumptrainer";
81 |
82 | public override IEnumerable GetDefaultKeyBindings(int variant = 0) => new[]
83 | {
84 | new KeyBinding(InputKey.Z, PumpTrainerAction.P1DL),
85 | new KeyBinding(InputKey.Q, PumpTrainerAction.P1UL),
86 | new KeyBinding(InputKey.S, PumpTrainerAction.P1C),
87 | new KeyBinding(InputKey.E, PumpTrainerAction.P1UR),
88 | new KeyBinding(InputKey.C, PumpTrainerAction.P1DR),
89 | new KeyBinding(InputKey.V, PumpTrainerAction.P2DL),
90 | new KeyBinding(InputKey.R, PumpTrainerAction.P2UL),
91 | new KeyBinding(InputKey.G, PumpTrainerAction.P2C),
92 | new KeyBinding(InputKey.Y, PumpTrainerAction.P2UR),
93 | new KeyBinding(InputKey.N, PumpTrainerAction.P2DR),
94 | };
95 |
96 | // TODO make an actual icon like an arrow or something.
97 | // Apparently according to the tau developers, there's no good way to do the resource texture store stuff (???)
98 | // so that's my excuse for putting this off
99 | public override Drawable CreateIcon() => new SpriteText
100 | {
101 | Anchor = Anchor.Centre,
102 | Origin = Anchor.Centre,
103 | Text = ShortName[0].ToString(),
104 | Font = OsuFont.Default.With(size: 18),
105 | };
106 |
107 | // Leave this line intact. It will bake the correct version into the ruleset on each build/release.
108 | public override string RulesetAPIVersionSupported => CURRENT_RULESET_API_VERSION;
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/osu.Game.Rulesets.PumpTrainer/Beatmaps/PumpTrainerBeatmapConverter.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
2 | // See the LICENCE file in the repository root for full licence text.
3 |
4 | using System.Collections.Generic;
5 | using System.Threading;
6 | using osu.Game.Beatmaps;
7 | using osu.Game.Beatmaps.ControlPoints;
8 | using osu.Game.Rulesets.Objects;
9 | using osu.Game.Rulesets.Objects.Types;
10 | using osu.Game.Rulesets.PumpTrainer.Objects;
11 |
12 | namespace osu.Game.Rulesets.PumpTrainer.Beatmaps
13 | {
14 | public class PumpTrainerBeatmapConverter : BeatmapConverter
15 | {
16 | public PumpTrainerHitObjectGenerator HitObjectGenerator = new();
17 |
18 | // Initialized with values that minimize the per-(hit object) patterns
19 | public PumpTrainerHitObjectGeneratorSettingsPerHitObject GeneratorSettingsForSixteenthRhythms = new()
20 | {
21 | CornersFrequency = 0,
22 | HorizontalTripleFrequency = 0,
23 | };
24 |
25 | private double timeOfPreviousPumpHitObject = 0;
26 | private const double rounding_error = 5; // Use this rounding error "generously" for '<=' and '>=', and "not generously" for '<' and '>'
27 |
28 | public PumpTrainerBeatmapConverter(IBeatmap beatmap, Ruleset ruleset)
29 | : base(beatmap, ruleset)
30 | {
31 | }
32 |
33 | public override bool CanConvert() => true;
34 |
35 | protected override IEnumerable ConvertHitObject(HitObject original, IBeatmap beatmap, CancellationToken cancellationToken)
36 | {
37 | if (HitObjectGenerator.Settings.AllowedColumns.Count <= 1)
38 | {
39 | yield break;
40 | }
41 |
42 | yield return getNextHitObject(original.StartTime, beatmap);
43 |
44 | if (original is IHasRepeats hasRepeats)
45 | {
46 | // This is a slider. (Even a slider with no repeats is IHasRepeats)
47 |
48 | int hitObjectsToReturnAfterFirst = hasRepeats.RepeatCount + 1; // +1 for the last hit object
49 |
50 | double durationBetweenHitObjects = (hasRepeats.EndTime - original.StartTime) / hitObjectsToReturnAfterFirst;
51 |
52 | TimingControlPoint currentTimingPoint = beatmap.ControlPointInfo.TimingPointAt(original.StartTime);
53 |
54 | if (hitObjectsToReturnAfterFirst > 1)
55 | {
56 | // This is a slider with at least one repeat. Apply buzz slider protection:
57 | // If the duration between the points is shorter than 1/4 of a beat,
58 | // fill the duration with notes 1/4 apart instead of with the original rhythm.
59 |
60 | if (durationBetweenHitObjects < currentTimingPoint.BeatLength / 4)
61 | {
62 | durationBetweenHitObjects = currentTimingPoint.BeatLength / 4;
63 | }
64 |
65 | for (double newHitObjectTime = original.StartTime + durationBetweenHitObjects;
66 | newHitObjectTime <= hasRepeats.EndTime + rounding_error;
67 | newHitObjectTime += durationBetweenHitObjects)
68 | {
69 | yield return getNextHitObject(newHitObjectTime, beatmap);
70 | }
71 | }
72 | else if (durationBetweenHitObjects >= currentTimingPoint.BeatLength / 4 - rounding_error)
73 | {
74 | // This is a slider with no repeats, and lasts at least a 1/4 beat (same as buzz slider protection).
75 |
76 | double hitObjectTimeForSliderEnd = hasRepeats.EndTime;
77 |
78 | if (durationBetweenHitObjects > currentTimingPoint.BeatLength / 2 + rounding_error)
79 | {
80 | // The slider is longer than 1/2 a beat.
81 | // Round down to the nearest 1/4.
82 |
83 | double newEndTime = original.StartTime;
84 |
85 | while (newEndTime < hitObjectTimeForSliderEnd)
86 | {
87 | newEndTime += currentTimingPoint.BeatLength / 2;
88 | }
89 |
90 | hitObjectTimeForSliderEnd = newEndTime - currentTimingPoint.BeatLength / 2;
91 | }
92 | else if (durationBetweenHitObjects > currentTimingPoint.BeatLength / 4 + rounding_error
93 | && durationBetweenHitObjects < currentTimingPoint.BeatLength / 2 - rounding_error)
94 | {
95 | // The slider length is longer than 1/4 but shorter than 1/2, so it has to be 3/8 or something.
96 | // Round down to the nearest 1/4.
97 | // Good test map: https://osu.ppy.sh/beatmapsets/929924#osu/2073258
98 |
99 | double newEndTime = original.StartTime;
100 |
101 | while (newEndTime < hitObjectTimeForSliderEnd)
102 | {
103 | newEndTime += currentTimingPoint.BeatLength / 4;
104 | }
105 |
106 | hitObjectTimeForSliderEnd = newEndTime - currentTimingPoint.BeatLength / 4;
107 | }
108 |
109 | yield return getNextHitObject(hitObjectTimeForSliderEnd, beatmap);
110 | }
111 | }
112 | }
113 |
114 | private PumpTrainerHitObject getNextHitObject(double pumpHitObjectTime, IBeatmap beatmap)
115 | {
116 | double lengthOfSixteenthRhythm = beatmap.ControlPointInfo.TimingPointAt(pumpHitObjectTime).BeatLength / 4;
117 |
118 | PumpTrainerHitObjectGeneratorSettingsPerHitObject perHitObjectSettingsToUse =
119 | pumpHitObjectTime - timeOfPreviousPumpHitObject <= lengthOfSixteenthRhythm + rounding_error ?
120 | GeneratorSettingsForSixteenthRhythms : new();
121 |
122 | timeOfPreviousPumpHitObject = pumpHitObjectTime;
123 |
124 | return HitObjectGenerator.GetNextHitObject(pumpHitObjectTime, beatmap, perHitObjectSettingsToUse);
125 | }
126 | }
127 | }
128 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.userosscache
8 | *.sln.docstates
9 |
10 | # User-specific files (MonoDevelop/Xamarin Studio)
11 | *.userprefs
12 |
13 | # Build results
14 | [Dd]ebug/
15 | [Dd]ebugPublic/
16 | [Rr]elease/
17 | [Rr]eleases/
18 | bld/
19 | [Bb]in/
20 | [Oo]bj/
21 | [Ll]og/
22 |
23 | # Visual Studio 2015 cache/options directory
24 | .vs/
25 | # Uncomment if you have tasks that create the project's static files in wwwroot
26 | #wwwroot/
27 |
28 | # MSTest test Results
29 | [Tt]est[Rr]esult*/
30 | [Bb]uild[Ll]og.*
31 |
32 | # NUNIT
33 | *.VisualState.xml
34 | TestResult.xml
35 |
36 | # Build Results of an ATL Project
37 | [Dd]ebugPS/
38 | [Rr]eleasePS/
39 | dlldata.c
40 |
41 | # DNX
42 | project.lock.json
43 | project.fragment.lock.json
44 | artifacts/
45 |
46 | *_i.c
47 | *_p.c
48 | *_i.h
49 | *.ilk
50 | *.meta
51 | *.obj
52 | *.pch
53 | *.pdb
54 | *.pgc
55 | *.pgd
56 | *.rsp
57 | *.sbr
58 | *.tlb
59 | *.tli
60 | *.tlh
61 | *.tmp
62 | *.tmp_proj
63 | *.log
64 | *.vspscc
65 | *.vssscc
66 | .builds
67 | *.pidb
68 | *.svclog
69 | *.scc
70 |
71 | # Chutzpah Test files
72 | _Chutzpah*
73 |
74 | # Visual C++ cache files
75 | ipch/
76 | *.aps
77 | *.ncb
78 | *.opendb
79 | *.opensdf
80 | *.sdf
81 | *.cachefile
82 | *.VC.db
83 | *.VC.VC.opendb
84 |
85 | # Visual Studio profiler
86 | *.psess
87 | *.vsp
88 | *.vspx
89 | *.sap
90 |
91 | # TFS 2012 Local Workspace
92 | $tf/
93 |
94 | # Guidance Automation Toolkit
95 | *.gpState
96 |
97 | # ReSharper is a .NET coding add-in
98 | _ReSharper*/
99 | *.[Rr]e[Ss]harper
100 | *.DotSettings.user
101 |
102 | # JustCode is a .NET coding add-in
103 | .JustCode
104 |
105 | # TeamCity is a build add-in
106 | _TeamCity*
107 |
108 | # DotCover is a Code Coverage Tool
109 | *.dotCover
110 |
111 | # NCrunch
112 | _NCrunch_*
113 | .*crunch*.local.xml
114 | nCrunchTemp_*
115 |
116 | # MightyMoose
117 | *.mm.*
118 | AutoTest.Net/
119 |
120 | # Web workbench (sass)
121 | .sass-cache/
122 |
123 | # Installshield output folder
124 | [Ee]xpress/
125 |
126 | # DocProject is a documentation generator add-in
127 | DocProject/buildhelp/
128 | DocProject/Help/*.HxT
129 | DocProject/Help/*.HxC
130 | DocProject/Help/*.hhc
131 | DocProject/Help/*.hhk
132 | DocProject/Help/*.hhp
133 | DocProject/Help/Html2
134 | DocProject/Help/html
135 |
136 | # Click-Once directory
137 | publish/
138 |
139 | # Publish Web Output
140 | *.[Pp]ublish.xml
141 | *.azurePubxml
142 | # TODO: Comment the next line if you want to checkin your web deploy settings
143 | # but database connection strings (with potential passwords) will be unencrypted
144 | *.pubxml
145 | *.publishproj
146 |
147 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
148 | # checkin your Azure Web App publish settings, but sensitive information contained
149 | # in these scripts will be unencrypted
150 | PublishScripts/
151 |
152 | # NuGet Packages
153 | *.nupkg
154 | # The packages folder can be ignored because of Package Restore
155 | **/packages/*
156 | # except build/, which is used as an MSBuild target.
157 | !**/packages/build/
158 | # Uncomment if necessary however generally it will be regenerated when needed
159 | #!**/packages/repositories.config
160 | # NuGet v3's project.json files produces more ignoreable files
161 | *.nuget.props
162 | *.nuget.targets
163 |
164 | # Microsoft Azure Build Output
165 | csx/
166 | *.build.csdef
167 |
168 | # Microsoft Azure Emulator
169 | ecf/
170 | rcf/
171 |
172 | # Windows Store app package directories and files
173 | AppPackages/
174 | BundleArtifacts/
175 | Package.StoreAssociation.xml
176 | _pkginfo.txt
177 |
178 | # Visual Studio cache files
179 | # files ending in .cache can be ignored
180 | *.[Cc]ache
181 | # but keep track of directories ending in .cache
182 | !*.[Cc]ache/
183 |
184 | # Others
185 | ClientBin/
186 | ~$*
187 | *~
188 | *.dbmdl
189 | *.dbproj.schemaview
190 | *.pfx
191 | *.publishsettings
192 | node_modules/
193 | orleans.codegen.cs
194 | Resource.designer.cs
195 |
196 | # Since there are multiple workflows, uncomment next line to ignore bower_components
197 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
198 | #bower_components/
199 |
200 | # RIA/Silverlight projects
201 | Generated_Code/
202 |
203 | # Backup & report files from converting an old project file
204 | # to a newer Visual Studio version. Backup files are not needed,
205 | # because we have git ;-)
206 | _UpgradeReport_Files/
207 | Backup*/
208 | UpgradeLog*.XML
209 | UpgradeLog*.htm
210 |
211 | # SQL Server files
212 | *.mdf
213 | *.ldf
214 |
215 | # Business Intelligence projects
216 | *.rdl.data
217 | *.bim.layout
218 | *.bim_*.settings
219 |
220 | # Microsoft Fakes
221 | FakesAssemblies/
222 |
223 | # GhostDoc plugin setting file
224 | *.GhostDoc.xml
225 |
226 | # Node.js Tools for Visual Studio
227 | .ntvs_analysis.dat
228 |
229 | # Visual Studio 6 build log
230 | *.plg
231 |
232 | # Visual Studio 6 workspace options file
233 | *.opt
234 |
235 | # Visual Studio LightSwitch build output
236 | **/*.HTMLClient/GeneratedArtifacts
237 | **/*.DesktopClient/GeneratedArtifacts
238 | **/*.DesktopClient/ModelManifest.xml
239 | **/*.Server/GeneratedArtifacts
240 | **/*.Server/ModelManifest.xml
241 | _Pvt_Extensions
242 |
243 | # Paket dependency manager
244 | .paket/paket.exe
245 | paket-files/
246 |
247 | # FAKE - F# Make
248 | .fake/
249 |
250 | # Python Tools for Visual Studio (PTVS)
251 | __pycache__/
252 | *.pyc
253 |
254 | # Cake #
255 | /tools/**
256 | /build/tools/**
257 | /build/temp/**
258 |
259 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
260 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
261 |
262 | # User-specific stuff
263 | .idea/**/workspace.xml
264 | .idea/**/tasks.xml
265 | .idea/**/usage.statistics.xml
266 | .idea/**/dictionaries
267 | .idea/**/shelf
268 |
269 | # Generated files
270 | .idea/**/contentModel.xml
271 |
272 | # Sensitive or high-churn files
273 | .idea/**/dataSources/
274 | .idea/**/dataSources.ids
275 | .idea/**/dataSources.local.xml
276 | .idea/**/sqlDataSources.xml
277 | .idea/**/dynamic.xml
278 | .idea/**/uiDesigner.xml
279 | .idea/**/dbnavigator.xml
280 |
281 | # Gradle
282 | .idea/**/gradle.xml
283 | .idea/**/libraries
284 |
285 | # Gradle and Maven with auto-import
286 | # When using Gradle or Maven with auto-import, you should exclude module files,
287 | # since they will be recreated, and may cause churn. Uncomment if using
288 | # auto-import.
289 | .idea/modules.xml
290 | .idea/*.iml
291 | .idea/modules
292 | *.iml
293 | *.ipr
294 |
295 | # CMake
296 | cmake-build-*/
297 |
298 | # Mongo Explorer plugin
299 | .idea/**/mongoSettings.xml
300 |
301 | # File-based project format
302 | *.iws
303 |
304 | # IntelliJ
305 | out/
306 |
307 | # mpeltonen/sbt-idea plugin
308 | .idea_modules/
309 |
310 | # JIRA plugin
311 | atlassian-ide-plugin.xml
312 |
313 | # Cursive Clojure plugin
314 | .idea/replstate.xml
315 |
316 | # Crashlytics plugin (for Android Studio and IntelliJ)
317 | com_crashlytics_export_strings.xml
318 | crashlytics.properties
319 | crashlytics-build.properties
320 | fabric.properties
321 |
322 | # Editor-based Rest Client
323 | .idea/httpRequests
324 |
325 | # Android studio 3.1+ serialized cache file
326 | .idea/caches/build_file_checksums.ser
327 |
328 | # fastlane
329 | fastlane/report.xml
330 |
331 | # inspectcode
332 | inspectcodereport.xml
333 | inspectcode
334 |
335 | # BenchmarkDotNet
336 | /BenchmarkDotNet.Artifacts
337 |
338 | *.GeneratedMSBuildEditorConfig.editorconfig
339 |
340 | # Fody (pulled in by Realm) - schema file
341 | FodyWeavers.xsd
342 | **/FodyWeavers.xml
343 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig is awesome: http://editorconfig.org
2 | root = true
3 |
4 | [*.cs]
5 | end_of_line = crlf
6 | insert_final_newline = true
7 | indent_style = space
8 | indent_size = 4
9 | trim_trailing_whitespace = true
10 |
11 | #Roslyn naming styles
12 |
13 | #camelCase for private members
14 | dotnet_naming_style.camelcase.capitalization = camel_case
15 |
16 | dotnet_naming_symbols.private_members.applicable_accessibilities = private
17 | dotnet_naming_symbols.private_members.applicable_kinds = property,method,field,event
18 | dotnet_naming_rule.private_members_camelcase.severity = warning
19 | dotnet_naming_rule.private_members_camelcase.symbols = private_members
20 | dotnet_naming_rule.private_members_camelcase.style = camelcase
21 |
22 | dotnet_naming_symbols.local_function.applicable_kinds = local_function
23 | dotnet_naming_rule.local_function_camelcase.severity = warning
24 | dotnet_naming_rule.local_function_camelcase.symbols = local_function
25 | dotnet_naming_rule.local_function_camelcase.style = camelcase
26 |
27 | #all_lower for private and local constants/static readonlys
28 | dotnet_naming_style.all_lower.capitalization = all_lower
29 | dotnet_naming_style.all_lower.word_separator = _
30 |
31 | dotnet_naming_symbols.private_constants.applicable_accessibilities = private
32 | dotnet_naming_symbols.private_constants.required_modifiers = const
33 | dotnet_naming_symbols.private_constants.applicable_kinds = field
34 | dotnet_naming_rule.private_const_all_lower.severity = warning
35 | dotnet_naming_rule.private_const_all_lower.symbols = private_constants
36 | dotnet_naming_rule.private_const_all_lower.style = all_lower
37 |
38 | dotnet_naming_symbols.private_static_readonly.applicable_accessibilities = private
39 | dotnet_naming_symbols.private_static_readonly.required_modifiers = static,readonly
40 | dotnet_naming_symbols.private_static_readonly.applicable_kinds = field
41 | dotnet_naming_rule.private_static_readonly_all_lower.severity = warning
42 | dotnet_naming_rule.private_static_readonly_all_lower.symbols = private_static_readonly
43 | dotnet_naming_rule.private_static_readonly_all_lower.style = all_lower
44 |
45 | dotnet_naming_symbols.local_constants.applicable_kinds = local
46 | dotnet_naming_symbols.local_constants.required_modifiers = const
47 | dotnet_naming_rule.local_const_all_lower.severity = warning
48 | dotnet_naming_rule.local_const_all_lower.symbols = local_constants
49 | dotnet_naming_rule.local_const_all_lower.style = all_lower
50 |
51 | #ALL_UPPER for non private constants/static readonlys
52 | dotnet_naming_style.all_upper.capitalization = all_upper
53 | dotnet_naming_style.all_upper.word_separator = _
54 |
55 | dotnet_naming_symbols.public_constants.applicable_accessibilities = public,internal,protected,protected_internal,private_protected
56 | dotnet_naming_symbols.public_constants.required_modifiers = const
57 | dotnet_naming_symbols.public_constants.applicable_kinds = field
58 | dotnet_naming_rule.public_const_all_upper.severity = warning
59 | dotnet_naming_rule.public_const_all_upper.symbols = public_constants
60 | dotnet_naming_rule.public_const_all_upper.style = all_upper
61 |
62 | dotnet_naming_symbols.public_static_readonly.applicable_accessibilities = public,internal,protected,protected_internal,private_protected
63 | dotnet_naming_symbols.public_static_readonly.required_modifiers = static,readonly
64 | dotnet_naming_symbols.public_static_readonly.applicable_kinds = field
65 | dotnet_naming_rule.public_static_readonly_all_upper.severity = warning
66 | dotnet_naming_rule.public_static_readonly_all_upper.symbols = public_static_readonly
67 | dotnet_naming_rule.public_static_readonly_all_upper.style = all_upper
68 |
69 | #Roslyn formating options
70 |
71 | #Formatting - indentation options
72 | csharp_indent_case_contents = true
73 | csharp_indent_case_contents_when_block = false
74 | csharp_indent_labels = one_less_than_current
75 | csharp_indent_switch_labels = true
76 |
77 | #Formatting - new line options
78 | csharp_new_line_before_catch = true
79 | csharp_new_line_before_else = true
80 | csharp_new_line_before_finally = true
81 | csharp_new_line_before_open_brace = all
82 | #csharp_new_line_before_members_in_anonymous_types = true
83 | #csharp_new_line_before_members_in_object_initializers = true # Currently no effect in VS/dotnet format (16.4), and makes Rider confusing
84 | csharp_new_line_between_query_expression_clauses = true
85 |
86 | #Formatting - organize using options
87 | dotnet_sort_system_directives_first = true
88 |
89 | #Formatting - spacing options
90 | csharp_space_after_cast = false
91 | csharp_space_after_colon_in_inheritance_clause = true
92 | csharp_space_after_keywords_in_control_flow_statements = true
93 | csharp_space_before_colon_in_inheritance_clause = true
94 | csharp_space_between_method_call_empty_parameter_list_parentheses = false
95 | csharp_space_between_method_call_name_and_opening_parenthesis = false
96 | csharp_space_between_method_call_parameter_list_parentheses = false
97 | csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
98 | csharp_space_between_method_declaration_parameter_list_parentheses = false
99 |
100 | #Formatting - wrapping options
101 | csharp_preserve_single_line_blocks = true
102 | csharp_preserve_single_line_statements = true
103 |
104 | #Roslyn language styles
105 |
106 | #Style - this. qualification
107 | dotnet_style_qualification_for_field = false:warning
108 | dotnet_style_qualification_for_property = false:warning
109 | dotnet_style_qualification_for_method = false:warning
110 | dotnet_style_qualification_for_event = false:warning
111 |
112 | #Style - type names
113 | dotnet_style_predefined_type_for_locals_parameters_members = true:warning
114 | dotnet_style_predefined_type_for_member_access = true:warning
115 | csharp_style_var_when_type_is_apparent = true:none
116 | csharp_style_var_for_built_in_types = false:warning
117 | csharp_style_var_elsewhere = true:silent
118 |
119 | #Style - modifiers
120 | dotnet_style_require_accessibility_modifiers = for_non_interface_members:warning
121 | csharp_preferred_modifier_order = public,private,protected,internal,new,abstract,virtual,sealed,override,static,readonly,extern,unsafe,volatile,async:warning
122 |
123 | #Style - parentheses
124 | # Skipped because roslyn cannot separate +-*/ with << >>
125 |
126 | #Style - expression bodies
127 | csharp_style_expression_bodied_accessors = true:warning
128 | csharp_style_expression_bodied_constructors = false:none
129 | csharp_style_expression_bodied_indexers = true:warning
130 | csharp_style_expression_bodied_methods = false:silent
131 | csharp_style_expression_bodied_operators = true:warning
132 | csharp_style_expression_bodied_properties = true:warning
133 | csharp_style_expression_bodied_local_functions = true:silent
134 |
135 | #Style - expression preferences
136 | dotnet_style_object_initializer = true:warning
137 | dotnet_style_collection_initializer = true:warning
138 | dotnet_style_prefer_inferred_anonymous_type_member_names = true:warning
139 | dotnet_style_prefer_auto_properties = true:warning
140 | dotnet_style_prefer_conditional_expression_over_assignment = true:silent
141 | dotnet_style_prefer_conditional_expression_over_return = true:silent
142 | dotnet_style_prefer_compound_assignment = true:warning
143 |
144 | #Style - null/type checks
145 | dotnet_style_coalesce_expression = true:warning
146 | dotnet_style_null_propagation = true:warning
147 | csharp_style_pattern_matching_over_is_with_cast_check = true:warning
148 | csharp_style_pattern_matching_over_as_with_null_check = true:warning
149 | csharp_style_throw_expression = true:silent
150 | csharp_style_conditional_delegate_call = true:warning
151 |
152 | #Style - unused
153 | dotnet_style_readonly_field = true:silent
154 | dotnet_code_quality_unused_parameters = non_public:silent
155 | csharp_style_unused_value_expression_statement_preference = discard_variable:silent
156 | csharp_style_unused_value_assignment_preference = discard_variable:warning
157 |
158 | #Style - variable declaration
159 | csharp_style_inlined_variable_declaration = true:warning
160 | csharp_style_deconstructed_variable_declaration = false:silent
161 |
162 | #Style - other C# 7.x features
163 | dotnet_style_prefer_inferred_tuple_names = true:warning
164 | csharp_prefer_simple_default_expression = true:warning
165 | csharp_style_pattern_local_over_anonymous_function = true:warning
166 | dotnet_style_prefer_is_null_check_over_reference_equality_method = true:silent
167 |
168 | #Style - C# 8 features
169 | csharp_prefer_static_local_function = true:warning
170 | csharp_prefer_simple_using_statement = true:silent
171 | csharp_style_prefer_index_operator = false:silent
172 | csharp_style_prefer_range_operator = false:silent
173 | csharp_style_prefer_switch_expression = false:none
174 |
175 | #Supressing roslyn built-in analyzers
176 | # Suppress: EC112
177 |
178 | #Private method is unused
179 | dotnet_diagnostic.IDE0051.severity = silent
180 | #Private member is unused
181 | dotnet_diagnostic.IDE0052.severity = silent
182 |
183 | #Rules for disposable
184 | dotnet_diagnostic.IDE0067.severity = none
185 | dotnet_diagnostic.IDE0068.severity = none
186 | dotnet_diagnostic.IDE0069.severity = none
187 |
188 | #Disable operator overloads requiring alternate named methods
189 | dotnet_diagnostic.CA2225.severity = none
190 |
191 | # Banned APIs
192 | dotnet_diagnostic.RS0030.severity = error
193 |
--------------------------------------------------------------------------------
/osu.Game.Rulesets.PumpTrainer/Beatmaps/PumpTrainerHitObjectGenerator.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Collections.Immutable;
4 | using System.Linq;
5 | using osu.Game.Beatmaps;
6 | using osu.Game.Rulesets.PumpTrainer.Objects;
7 |
8 | namespace osu.Game.Rulesets.PumpTrainer.Beatmaps
9 | {
10 | public class PumpTrainerHitObjectGenerator
11 | {
12 | private Dictionary> nextColumnsPreviousFootLeft = new()
13 | {
14 | { Column.P1DL, [Column.P1UL, Column.P1C, Column.P1UR, Column.P1DR] },
15 | { Column.P1UL, [Column.P1DL, Column.P1C, Column.P1UR, Column.P1DR] },
16 | { Column.P1C, [Column.P1UR, Column.P1DR, Column.P2DL, Column.P2UL] },
17 | { Column.P1UR, [Column.P1DR, Column.P2DL, Column.P2UL, Column.P2C] },
18 | { Column.P1DR, [Column.P1UR, Column.P2DL, Column.P2UL, Column.P2C] },
19 | { Column.P2DL, [Column.P1UR, Column.P2UL, Column.P2C, Column.P2UR, Column.P2DR] },
20 | { Column.P2UL, [Column.P1DR, Column.P2DL, Column.P2C, Column.P2UR, Column.P2DR] },
21 | { Column.P2C, [Column.P2UR, Column.P2DR] },
22 | { Column.P2UR, [Column.P2DR] },
23 | { Column.P2DR, [Column.P2UR] },
24 | };
25 |
26 | private Dictionary> nextColumnsPreviousFootRight = [];
27 |
28 | private Dictionary> nextColumnsPreviousFootLeftHorizontalTwist = new()
29 | {
30 | { Column.P1C, [Column.P1DL, Column.P1UL] },
31 | { Column.P1UR, [Column.P1C] },
32 | { Column.P1DR, [Column.P1C] },
33 | { Column.P2C, [Column.P2DL, Column.P2UL] },
34 | { Column.P2UR, [Column.P2C] },
35 | { Column.P2DR, [Column.P2C] },
36 | };
37 |
38 | private Dictionary> nextColumnsPreviousFootRightHorizontalTwist = [];
39 |
40 | private Dictionary> nextColumnsPreviousFootLeftDiagonalSkip = new()
41 | {
42 | { Column.P1UR, [Column.P1DL] },
43 | { Column.P1DR, [Column.P1UL] },
44 | { Column.P2UR, [Column.P2DL] },
45 | { Column.P2DR, [Column.P2UL] },
46 | };
47 |
48 | private Dictionary> nextColumnsPreviousFootRightDiagonalSkip = [];
49 |
50 | private Dictionary> nextColumnsPreviousFootLeftLargeTwist = new()
51 | {
52 | { Column.P2DL, [Column.P1C] },
53 | { Column.P2UL, [Column.P1C] },
54 | { Column.P2C, [Column.P1UR, Column.P1DR] },
55 | };
56 |
57 | private Dictionary> nextColumnsPreviousFootRightLargeTwist = [];
58 |
59 | private Dictionary horizontalFlips = new()
60 | {
61 | { Column.P1DL, Column.P2DR },
62 | { Column.P1UL, Column.P2UR },
63 | { Column.P1C, Column.P2C },
64 | { Column.P1UR, Column.P2UL },
65 | { Column.P1DR, Column.P2DL },
66 | { Column.P2DL, Column.P1DR },
67 | { Column.P2UL, Column.P1UR },
68 | { Column.P2C, Column.P1C },
69 | { Column.P2UR, Column.P1UL },
70 | { Column.P2DR, Column.P1DL },
71 | };
72 |
73 | private ImmutableDictionary columnToPhysicalColumn = new Dictionary()
74 | {
75 | { Column.P1DL, 0 },
76 | { Column.P1UL, 0 },
77 | { Column.P1C, 1 },
78 | { Column.P1UR, 2 },
79 | { Column.P1DR, 2 },
80 | { Column.P2DL, 3 },
81 | { Column.P2UL, 3 },
82 | { Column.P2C, 4 },
83 | { Column.P2UR, 5 },
84 | { Column.P2DR, 5 },
85 | }.ToImmutableDictionary();
86 |
87 | public int Seed
88 | {
89 | set => random = new(value);
90 | }
91 | private Random random = new();
92 |
93 | private List hitObjectsSoFar = [];
94 |
95 | private Foot? previousFoot = null;
96 | private Column? previousColumn = null;
97 |
98 | public PumpTrainerHitObjectGeneratorSettings Settings = new();
99 |
100 | // Updated for every newly generated note
101 | private PumpTrainerHitObjectGeneratorSettingsPerHitObject perHitObjectsettings;
102 |
103 | private int fullDoublesEdgeStreak = 0;
104 | private int p1SinglesEdgeStreak = 0;
105 |
106 | public PumpTrainerHitObjectGenerator()
107 | {
108 | initializeFootRightDictionaries();
109 | }
110 |
111 | ///
112 | /// Generates a hitobject solely based off the settings of this class and previously generated hitobjects.
113 | /// Does NOT take into account any rhythms between the hitobject being generated and previously generated hitobjects.
114 | ///
115 | /// The start time of the next hitobject to generate.
116 | /// The source beatmap we're generating objects based off. Typically an osu! beatmap.
117 | /// The settings to apply for the generated hit object.
118 | ///
119 | public PumpTrainerHitObject GetNextHitObject(double startTime, IBeatmap beatmap, PumpTrainerHitObjectGeneratorSettingsPerHitObject perHitObjectsettings)
120 | {
121 | this.perHitObjectsettings = perHitObjectsettings;
122 |
123 | // Always start on the left foot as the first note (for now?)
124 | Foot nextFoot = previousFoot == null || previousFoot == Foot.Right ? Foot.Left : Foot.Right;
125 |
126 | Column nextColumn = previousColumn == null ? Settings.AllowedColumns[random.Next(Settings.AllowedColumns.Count())]
127 | : getNextColumn(nextFoot, (Column)previousColumn);
128 |
129 | PumpTrainerHitObject nextHitObject = new(nextColumn)
130 | {
131 | IntendedFoot = nextFoot,
132 | StartTime = startTime,
133 | };
134 |
135 | hitObjectsSoFar.Add(nextHitObject);
136 |
137 | previousFoot = nextFoot;
138 | previousColumn = nextColumn;
139 |
140 | return nextHitObject;
141 | }
142 |
143 | private Column getNextColumn(Foot nextFoot, Column previousColumn)
144 | {
145 | List candidateColumns = getCandidateColumns(nextFoot, previousColumn, false);
146 | includeOnlyAllowedColumns(candidateColumns);
147 | banColumnsCausingBannedPatterns(candidateColumns, nextFoot == Foot.Left ? Foot.Right : Foot.Left);
148 |
149 | if (candidateColumns.Count == 0)
150 | {
151 | // We messed up. Do the whole thing again but this time, allow all twists.
152 | // todo There are many combination of mods that can break beatmap generation
153 | // particularly when you have an "island" of included columns
154 |
155 | candidateColumns = getCandidateColumns(nextFoot, previousColumn, true);
156 | includeOnlyAllowedColumns(candidateColumns);
157 | banColumnsCausingBannedPatterns(candidateColumns, nextFoot == Foot.Left ? Foot.Right : Foot.Left);
158 | }
159 |
160 | return getRandomCandidateColumnWeighted(candidateColumns);
161 | }
162 |
163 | private List getCandidateColumns(Foot nextFoot, Column previousColumn, bool guaranteeTwistCandidates)
164 | {
165 | List candidateColumns = (nextFoot == Foot.Left ?
166 | nextColumnsPreviousFootRight[previousColumn] : nextColumnsPreviousFootLeft[previousColumn]).ToList();
167 |
168 | possiblyAddHorizontalTwistsToCandidates(candidateColumns, previousColumn, guaranteeTwistCandidates);
169 | possiblyAddDiagonalSkipsToCandidates(candidateColumns, previousColumn);
170 | possiblyAddLargeHorizontalTwistsToCandidates(candidateColumns, previousColumn);
171 |
172 | // Easy mod bans
173 | possiblyBanFarColumns(candidateColumns, previousColumn, guaranteeTwistCandidates);
174 |
175 | return candidateColumns;
176 | }
177 |
178 | private void possiblyAddHorizontalTwistsToCandidates(List candidates, Column previousColumn, bool alwaysAdd)
179 | {
180 | if (random.NextDouble() < Settings.HorizontalTwistFrequency || alwaysAdd)
181 | {
182 | List twistColumnsToAdd;
183 |
184 | if (previousFoot == Foot.Left)
185 | {
186 | if (nextColumnsPreviousFootLeftHorizontalTwist.ContainsKey(previousColumn))
187 | {
188 | twistColumnsToAdd = nextColumnsPreviousFootLeftHorizontalTwist[previousColumn];
189 | }
190 | else
191 | {
192 | return;
193 | }
194 | }
195 | else
196 | {
197 | if (nextColumnsPreviousFootRightHorizontalTwist.ContainsKey(previousColumn))
198 | {
199 | twistColumnsToAdd = nextColumnsPreviousFootRightHorizontalTwist[previousColumn];
200 | }
201 | else
202 | {
203 | return;
204 | }
205 | }
206 |
207 | candidates.AddRange(twistColumnsToAdd);
208 | }
209 | }
210 |
211 | private void possiblyAddDiagonalSkipsToCandidates(List candidates, Column previousColumn)
212 | {
213 | if (random.NextDouble() < Settings.DiagonalSkipFrequency)
214 | {
215 | List twistColumnsToAdd;
216 |
217 | if (previousFoot == Foot.Left)
218 | {
219 | if (nextColumnsPreviousFootLeftDiagonalSkip.ContainsKey(previousColumn))
220 | {
221 | twistColumnsToAdd = nextColumnsPreviousFootLeftDiagonalSkip[previousColumn];
222 | }
223 | else
224 | {
225 | return;
226 | }
227 | }
228 | else
229 | {
230 | if (nextColumnsPreviousFootRightDiagonalSkip.ContainsKey(previousColumn))
231 | {
232 | twistColumnsToAdd = nextColumnsPreviousFootRightDiagonalSkip[previousColumn];
233 | }
234 | else
235 | {
236 | return;
237 | }
238 | }
239 |
240 | candidates.AddRange(twistColumnsToAdd);
241 | }
242 | }
243 |
244 | private void possiblyAddLargeHorizontalTwistsToCandidates(List candidates, Column previousColumn)
245 | {
246 | if (random.NextDouble() < Settings.LargeTwistFrequency)
247 | {
248 | List twistColumnsToAdd;
249 |
250 | if (previousFoot == Foot.Left)
251 | {
252 | if (nextColumnsPreviousFootLeftLargeTwist.ContainsKey(previousColumn))
253 | {
254 | twistColumnsToAdd = nextColumnsPreviousFootLeftLargeTwist[previousColumn];
255 | }
256 | else
257 | {
258 | return;
259 | }
260 | }
261 | else
262 | {
263 | if (nextColumnsPreviousFootRightLargeTwist.ContainsKey(previousColumn))
264 | {
265 | twistColumnsToAdd = nextColumnsPreviousFootRightLargeTwist[previousColumn];
266 | }
267 | else
268 | {
269 | return;
270 | }
271 | }
272 |
273 | candidates.AddRange(twistColumnsToAdd);
274 | }
275 | }
276 |
277 | private void possiblyBanFarColumns(List candidates, Column previousColumn, bool neverBan)
278 | {
279 | if (neverBan)
280 | {
281 | return;
282 | }
283 |
284 | if (random.NextDouble() > Settings.FarColumnsFrequency)
285 | {
286 | List columnsToBan;
287 | int previousPhysicalColumn = columnToPhysicalColumn[previousColumn];
288 |
289 | if (previousColumn == Column.P1C || previousColumn == Column.P2C)
290 | {
291 | // Just ban everything that's two columns away
292 | columnsToBan =
293 | columnToPhysicalColumn
294 | .Where(entry => entry.Value == previousPhysicalColumn + 2 || entry.Value == previousPhysicalColumn - 2)
295 | .Select(entry => entry.Key)
296 | .ToList();
297 | }
298 | else
299 | {
300 | // Ban everything that's two columns away and that's also a center panel
301 | columnsToBan =
302 | columnToPhysicalColumn
303 | .Where(entry =>
304 | (entry.Value == previousPhysicalColumn + 2 || entry.Value == previousPhysicalColumn - 2)
305 | && (entry.Key == Column.P1C || entry.Key == Column.P2C))
306 | .Select(entry => entry.Key)
307 | .ToList();
308 | }
309 |
310 | candidates.RemoveAll(columnsToBan.Contains);
311 | }
312 | }
313 |
314 | private void includeOnlyAllowedColumns(List candidateColumns)
315 | {
316 | foreach (Column column in candidateColumns.ToList())
317 | {
318 | if (!Settings.AllowedColumns.Contains(column))
319 | {
320 | candidateColumns.Remove(column);
321 | }
322 | }
323 | }
324 |
325 | ///
326 | /// Bans columns the given list of candidates based on the columns two most recent hit objects in the generated beatmap.
327 | /// A pattern is a group of 3 notes (not 2).
328 | ///
329 | /// Candidate columns to ban from.
330 | /// Associated foot of the most recent hit object in the beatmap.
331 | private void banColumnsCausingBannedPatterns(List candidateColumns, Foot previousFoot)
332 | {
333 | // todo this function and maybe this whole class can be broken down into ban types and stuff
334 | // so we can just add the types of bans we want to a list instead of this hugh mungus method
335 |
336 | if (hitObjectsSoFar.Count <= 1)
337 | {
338 | // No possible bans if we're only on the first or second note
339 | return;
340 | }
341 |
342 | Column previousColumn = hitObjectsSoFar[^1].Column;
343 | Column previousPreviousColumn = hitObjectsSoFar[^2].Column;
344 |
345 | // Ban spins no matter what (this covers large twist spins as well)
346 | if (previousFoot == Foot.Left)
347 | {
348 | if (previousColumn == Column.P1C)
349 | {
350 | if (previousPreviousColumn == Column.P1DL)
351 | {
352 | candidateColumns.Remove(Column.P1UL);
353 | }
354 | else if (previousPreviousColumn == Column.P1UL)
355 | {
356 | candidateColumns.Remove(Column.P1DL);
357 | }
358 | }
359 | else if (previousColumn == Column.P2C)
360 | {
361 | if (previousPreviousColumn == Column.P2DL || previousPreviousColumn == Column.P1DR)
362 | {
363 | candidateColumns.Remove(Column.P2UL);
364 | candidateColumns.Remove(Column.P1UR);
365 | }
366 | else if (previousPreviousColumn == Column.P2UL || previousPreviousColumn == Column.P1UR)
367 | {
368 | candidateColumns.Remove(Column.P2DL);
369 | candidateColumns.Remove(Column.P1DR);
370 | }
371 | }
372 | }
373 | else if (previousFoot == Foot.Right)
374 | {
375 | if (previousColumn == Column.P1C)
376 | {
377 | if (previousPreviousColumn == Column.P1DR || previousPreviousColumn == Column.P2DL)
378 | {
379 | candidateColumns.Remove(Column.P1UR);
380 | candidateColumns.Remove(Column.P2UL);
381 | }
382 | else if (previousPreviousColumn == Column.P1UR || previousPreviousColumn == Column.P2UL)
383 | {
384 | candidateColumns.Remove(Column.P1DR);
385 | candidateColumns.Remove(Column.P2DL);
386 | }
387 | }
388 | else if (previousColumn == Column.P2C)
389 | {
390 | if (previousPreviousColumn == Column.P2DR)
391 | {
392 | candidateColumns.Remove(Column.P2UR);
393 | }
394 | else if (previousPreviousColumn == Column.P2UR)
395 | {
396 | candidateColumns.Remove(Column.P2DR);
397 | }
398 | }
399 | }
400 |
401 | // Ban large horizontal triples no matter what. This is where all three columns go in one direction, and they are not adjacent to each other.
402 | {
403 | int previousPhysicalColumn = columnToPhysicalColumn[previousColumn];
404 | int previousPreviousPhysicalColumn = columnToPhysicalColumn[previousPreviousColumn];
405 |
406 | List columnsToBan = [];
407 |
408 | // If the two previous columns are adjacent, then we have an extra column of leniency for the column of the next hit object
409 | // (so that we don't mistakenly ban a regular horizontal triple, where all the columns are adjacent).
410 | // If the two previous columns already have a gap between them, then we can't be lenient and we must ban everything going in that direction.
411 | int banColumnLeniency = Math.Abs(previousPhysicalColumn - previousPreviousPhysicalColumn) >= 2 ? 0 : 1;
412 |
413 | if (previousPhysicalColumn > previousPreviousPhysicalColumn)
414 | {
415 | // Going right! Ban everything to the right
416 | columnsToBan = columnToPhysicalColumn.Where(entry => entry.Value > previousPhysicalColumn + banColumnLeniency).Select(entry => entry.Key).ToList();
417 | }
418 | else if (previousPhysicalColumn < previousPreviousPhysicalColumn)
419 | {
420 | // Going left! Ban everything to the left
421 | columnsToBan = columnToPhysicalColumn.Where(entry => entry.Value < previousPhysicalColumn - banColumnLeniency).Select(entry => entry.Key).ToList();
422 | }
423 |
424 | candidateColumns.RemoveAll(columnsToBan.Contains);
425 | }
426 |
427 | // Ban diagonal twists (single pad)
428 | if (!Settings.AllowDiagonalTwists)
429 | {
430 | if (previousColumn == Column.P1C)
431 | {
432 | if (previousPreviousColumn == Column.P1DL)
433 | {
434 | candidateColumns.Remove(Column.P1UR);
435 | }
436 | else if (previousPreviousColumn == Column.P1UL)
437 | {
438 | candidateColumns.Remove(Column.P1DR);
439 | }
440 | else if (previousPreviousColumn == Column.P1DR)
441 | {
442 | candidateColumns.Remove(Column.P1UL);
443 | }
444 | else if (previousPreviousColumn == Column.P1UR)
445 | {
446 | candidateColumns.Remove(Column.P1DL);
447 | }
448 | }
449 | else if (previousColumn == Column.P2C)
450 | {
451 | if (previousPreviousColumn == Column.P2DR)
452 | {
453 | candidateColumns.Remove(Column.P2UL);
454 | }
455 | else if (previousPreviousColumn == Column.P2UR)
456 | {
457 | candidateColumns.Remove(Column.P2DL);
458 | }
459 | else if (previousPreviousColumn == Column.P2DL)
460 | {
461 | candidateColumns.Remove(Column.P2UR);
462 | }
463 | else if (previousPreviousColumn == Column.P2UL)
464 | {
465 | candidateColumns.Remove(Column.P2DR);
466 | }
467 | }
468 | }
469 |
470 | // Ban horizontal triples (horizontally adjacent to each other)
471 | if (random.NextDouble() > perHitObjectsettings.HorizontalTripleFrequency)
472 | {
473 | int previousPhysicalColumn = columnToPhysicalColumn[previousColumn];
474 | int previousPreviousPhysicalColumn = columnToPhysicalColumn[previousPreviousColumn];
475 |
476 | List columnsToBan = [];
477 |
478 | if (previousPhysicalColumn > previousPreviousPhysicalColumn)
479 | {
480 | // Going right! Ban everything to the right
481 | columnsToBan = columnToPhysicalColumn.Where(entry => entry.Value > previousPhysicalColumn).Select(entry => entry.Key).ToList();
482 | }
483 | else if (previousPhysicalColumn < previousPreviousPhysicalColumn)
484 | {
485 | // Going left! Ban everything to the left
486 | columnsToBan = columnToPhysicalColumn.Where(entry => entry.Value < previousPhysicalColumn).Select(entry => entry.Key).ToList();
487 | }
488 |
489 | // Don't ban columns where all three notes are on the same singles pad. This would interfere with horizontal twists.
490 | // Just manually check all four possibilities.
491 | if (previousPhysicalColumn == 1 && previousPreviousPhysicalColumn == 0)
492 | {
493 | columnsToBan.RemoveAll(column => columnToPhysicalColumn[column] == 2);
494 | }
495 | if (previousPhysicalColumn == 1 && previousPreviousPhysicalColumn == 2)
496 | {
497 | columnsToBan.RemoveAll(column => columnToPhysicalColumn[column] == 0);
498 | }
499 | if (previousPhysicalColumn == 4 && previousPreviousPhysicalColumn == 3)
500 | {
501 | columnsToBan.RemoveAll(column => columnToPhysicalColumn[column] == 5);
502 | }
503 | if (previousPhysicalColumn == 4 && previousPreviousPhysicalColumn == 5)
504 | {
505 | columnsToBan.RemoveAll(column => columnToPhysicalColumn[column] == 3);
506 | }
507 |
508 | candidateColumns.RemoveAll(columnsToBan.Contains);
509 | }
510 |
511 | // Ban corner patterns
512 | if (random.NextDouble() > perHitObjectsettings.CornersFrequency)
513 | {
514 | // Ban 90 degree patterns
515 | if (previousPreviousColumn == Column.P1UL && (previousColumn == Column.P1UR || previousColumn == Column.P1DL))
516 | {
517 | candidateColumns.Remove(Column.P1DR);
518 | }
519 | else if (previousPreviousColumn == Column.P1DL && (previousColumn == Column.P1DR || previousColumn == Column.P1UL))
520 | {
521 | candidateColumns.Remove(Column.P1UR);
522 | }
523 | else if (previousPreviousColumn == Column.P1UR && (previousColumn == Column.P1UL || previousColumn == Column.P1DR))
524 | {
525 | candidateColumns.Remove(Column.P1DL);
526 | }
527 | else if (previousPreviousColumn == Column.P1DR && (previousColumn == Column.P1DL || previousColumn == Column.P1UR))
528 | {
529 | candidateColumns.Remove(Column.P1UL);
530 | }
531 | else if (previousPreviousColumn == Column.P2UL && (previousColumn == Column.P2UR || previousColumn == Column.P2DL))
532 | {
533 | candidateColumns.Remove(Column.P2DR);
534 | }
535 | else if (previousPreviousColumn == Column.P2DL && (previousColumn == Column.P2DR || previousColumn == Column.P2UL))
536 | {
537 | candidateColumns.Remove(Column.P2UR);
538 | }
539 | else if (previousPreviousColumn == Column.P2UR && (previousColumn == Column.P2UL || previousColumn == Column.P2DR))
540 | {
541 | candidateColumns.Remove(Column.P2DL);
542 | }
543 | else if (previousPreviousColumn == Column.P2DR && (previousColumn == Column.P2DL || previousColumn == Column.P2UR))
544 | {
545 | candidateColumns.Remove(Column.P2UL);
546 | }
547 |
548 | // Ban V patterns
549 | if (previousPreviousColumn == Column.P1UL && (previousColumn == Column.P1DR || previousColumn == Column.P1DL))
550 | {
551 | candidateColumns.Remove(Column.P1UR);
552 | }
553 | else if (previousPreviousColumn == Column.P1DL && (previousColumn == Column.P1UR || previousColumn == Column.P1UL))
554 | {
555 | candidateColumns.Remove(Column.P1DR);
556 | }
557 | else if (previousPreviousColumn == Column.P1UR && (previousColumn == Column.P1DL || previousColumn == Column.P1DR))
558 | {
559 | candidateColumns.Remove(Column.P1UL);
560 | }
561 | else if (previousPreviousColumn == Column.P1DR && (previousColumn == Column.P1UL || previousColumn == Column.P1UR))
562 | {
563 | candidateColumns.Remove(Column.P1DL);
564 | }
565 | else if (previousPreviousColumn == Column.P2UL && (previousColumn == Column.P2DR || previousColumn == Column.P2DL))
566 | {
567 | candidateColumns.Remove(Column.P2UR);
568 | }
569 | else if (previousPreviousColumn == Column.P2DL && (previousColumn == Column.P2UR || previousColumn == Column.P2UL))
570 | {
571 | candidateColumns.Remove(Column.P2DR);
572 | }
573 | else if (previousPreviousColumn == Column.P2UR && (previousColumn == Column.P2DL || previousColumn == Column.P2DR))
574 | {
575 | candidateColumns.Remove(Column.P2UL);
576 | }
577 | else if (previousPreviousColumn == Column.P2DR && (previousColumn == Column.P2UL || previousColumn == Column.P2UR))
578 | {
579 | candidateColumns.Remove(Column.P2DL);
580 | }
581 | }
582 | }
583 |
584 | private Column getRandomCandidateColumnWeighted(List candidateColumns)
585 | {
586 | if (candidateColumns.Count == 0)
587 | {
588 | throw new Exception("There were no candidate columns :(");
589 | }
590 |
591 | if (hitObjectsSoFar.Count < 2)
592 | {
593 | return candidateColumns[random.Next(candidateColumns.Count)];
594 | }
595 |
596 | Column previousPreviousColumn = hitObjectsSoFar[^2].Column;
597 | List candidateColumnsWeighted = [];
598 |
599 | foreach (Column candidateColumn in candidateColumns)
600 | {
601 | candidateColumnsWeighted.Add(candidateColumn);
602 |
603 | // Reduce the likelihood of trills
604 | if (candidateColumn != previousPreviousColumn)
605 | {
606 | for (int i = 0; i < 4; i++)
607 | {
608 | candidateColumnsWeighted.Add(candidateColumn);
609 | }
610 | }
611 |
612 | // If full-doubles, decrease the likelihood of a panel on the same column as the previous if on the edge
613 | if (Settings.AllowedColumns.Count == 10 &&
614 | fullDoublesEdgeStreak > 0 &&
615 | previousColumn != null &&
616 | columnToPhysicalColumn[candidateColumn] != columnToPhysicalColumn[previousColumn.Value])
617 | {
618 | for (int i = 0; i < 4 * fullDoublesEdgeStreak; i++)
619 | {
620 | candidateColumnsWeighted.Add(candidateColumn);
621 | }
622 | }
623 |
624 | // Also apply for singles
625 | if (Settings.AllowedColumns.SequenceEqual([Column.P1DL, Column.P1UL, Column.P1C, Column.P1UR, Column.P1DR]) &&
626 | p1SinglesEdgeStreak > 0 &&
627 | previousColumn != null &&
628 | columnToPhysicalColumn[candidateColumn] != columnToPhysicalColumn[previousColumn.Value])
629 | {
630 | for (int i = 0; i < 4 * p1SinglesEdgeStreak; i++)
631 | {
632 | candidateColumnsWeighted.Add(candidateColumn);
633 | }
634 | }
635 | }
636 |
637 | Column selectedColumn = candidateColumnsWeighted[random.Next(candidateColumnsWeighted.Count)];
638 |
639 | fullDoublesEdgeStreak =
640 | columnToPhysicalColumn[selectedColumn] == 0 || columnToPhysicalColumn[selectedColumn] == 5 ?
641 | fullDoublesEdgeStreak + 1 : 0;
642 |
643 | p1SinglesEdgeStreak =
644 | columnToPhysicalColumn[selectedColumn] == 0 || columnToPhysicalColumn[selectedColumn] == 2 ?
645 | p1SinglesEdgeStreak + 1 : 0;
646 |
647 | return selectedColumn;
648 | }
649 |
650 | private void initializeFootRightDictionaries()
651 | {
652 | foreach (Column column in Enum.GetValues(typeof(Column)))
653 | {
654 | Column flippedColumn = horizontalFlips[column];
655 |
656 | if (nextColumnsPreviousFootLeft.ContainsKey(flippedColumn))
657 | {
658 | nextColumnsPreviousFootRight[column] = nextColumnsPreviousFootLeft[flippedColumn].Select(n => horizontalFlips[n]).ToList();
659 | }
660 |
661 | if (nextColumnsPreviousFootLeftHorizontalTwist.ContainsKey(flippedColumn))
662 | {
663 | nextColumnsPreviousFootRightHorizontalTwist[column] = nextColumnsPreviousFootLeftHorizontalTwist[flippedColumn].Select(n => horizontalFlips[n]).ToList();
664 | }
665 |
666 | if (nextColumnsPreviousFootLeftDiagonalSkip.ContainsKey(flippedColumn))
667 | {
668 | nextColumnsPreviousFootRightDiagonalSkip[column] = nextColumnsPreviousFootLeftDiagonalSkip[flippedColumn].Select(n => horizontalFlips[n]).ToList();
669 | }
670 |
671 | if (nextColumnsPreviousFootLeftLargeTwist.ContainsKey(flippedColumn))
672 | {
673 | nextColumnsPreviousFootRightLargeTwist[column] = nextColumnsPreviousFootLeftLargeTwist[flippedColumn].Select(n => horizontalFlips[n]).ToList();
674 | }
675 | }
676 | }
677 | }
678 | }
679 |
--------------------------------------------------------------------------------
/osu.Game.Rulesets.PumpTrainer.sln.DotSettings:
--------------------------------------------------------------------------------
1 |
2 | True
3 | True
4 | True
5 | True
6 | ExplicitlyExcluded
7 | ExplicitlyExcluded
8 | SOLUTION
9 | WARNING
10 | WARNING
11 | WARNING
12 | HINT
13 | HINT
14 | WARNING
15 | WARNING
16 | True
17 | WARNING
18 | WARNING
19 | HINT
20 | DO_NOT_SHOW
21 | WARNING
22 | WARNING
23 | HINT
24 | HINT
25 | WARNING
26 | WARNING
27 | WARNING
28 | WARNING
29 | WARNING
30 | WARNING
31 | WARNING
32 | WARNING
33 | WARNING
34 | WARNING
35 | WARNING
36 | WARNING
37 | WARNING
38 | WARNING
39 | WARNING
40 | WARNING
41 | WARNING
42 | WARNING
43 | WARNING
44 | WARNING
45 | WARNING
46 | WARNING
47 | WARNING
48 | WARNING
49 | WARNING
50 | WARNING
51 | WARNING
52 | WARNING
53 | WARNING
54 | HINT
55 | WARNING
56 | HINT
57 | SUGGESTION
58 | HINT
59 | HINT
60 | HINT
61 | WARNING
62 | WARNING
63 | WARNING
64 | WARNING
65 | WARNING
66 | WARNING
67 | WARNING
68 | WARNING
69 | WARNING
70 | WARNING
71 | WARNING
72 | WARNING
73 | WARNING
74 | HINT
75 | WARNING
76 | HINT
77 | DO_NOT_SHOW
78 | WARNING
79 | DO_NOT_SHOW
80 | WARNING
81 | WARNING
82 | WARNING
83 | WARNING
84 | WARNING
85 | WARNING
86 | WARNING
87 | WARNING
88 | HINT
89 | WARNING
90 | DO_NOT_SHOW
91 | WARNING
92 | HINT
93 | DO_NOT_SHOW
94 | HINT
95 | HINT
96 | ERROR
97 | WARNING
98 | HINT
99 | HINT
100 | HINT
101 | WARNING
102 | WARNING
103 | HINT
104 | DO_NOT_SHOW
105 | HINT
106 | HINT
107 | HINT
108 | HINT
109 | WARNING
110 | DO_NOT_SHOW
111 | DO_NOT_SHOW
112 | WARNING
113 | WARNING
114 | WARNING
115 | WARNING
116 | WARNING
117 | WARNING
118 | WARNING
119 | WARNING
120 | WARNING
121 | WARNING
122 | WARNING
123 | WARNING
124 | WARNING
125 | HINT
126 | HINT
127 | WARNING
128 | HINT
129 | HINT
130 | HINT
131 | DO_NOT_SHOW
132 | HINT
133 | HINT
134 | WARNING
135 | WARNING
136 | WARNING
137 | WARNING
138 | WARNING
139 | WARNING
140 | WARNING
141 | HINT
142 | DO_NOT_SHOW
143 | DO_NOT_SHOW
144 | DO_NOT_SHOW
145 | WARNING
146 | WARNING
147 | WARNING
148 | WARNING
149 | WARNING
150 | WARNING
151 | WARNING
152 | WARNING
153 | ERROR
154 | WARNING
155 | WARNING
156 | HINT
157 | WARNING
158 | WARNING
159 | WARNING
160 | WARNING
161 | WARNING
162 | WARNING
163 | WARNING
164 | WARNING
165 | WARNING
166 | WARNING
167 | WARNING
168 | WARNING
169 | WARNING
170 | WARNING
171 | WARNING
172 | WARNING
173 | WARNING
174 | WARNING
175 | WARNING
176 | WARNING
177 | WARNING
178 | WARNING
179 | WARNING
180 | WARNING
181 | WARNING
182 | WARNING
183 | WARNING
184 | WARNING
185 | WARNING
186 | WARNING
187 | WARNING
188 | WARNING
189 | WARNING
190 | WARNING
191 | WARNING
192 | WARNING
193 | WARNING
194 | WARNING
195 | WARNING
196 | WARNING
197 | WARNING
198 | WARNING
199 | WARNING
200 | WARNING
201 | WARNING
202 | WARNING
203 | WARNING
204 | WARNING
205 | WARNING
206 | WARNING
207 | WARNING
208 | HINT
209 | WARNING
210 | WARNING
211 | SUGGESTION
212 | DO_NOT_SHOW
213 |
214 | True
215 | DO_NOT_SHOW
216 | WARNING
217 | WARNING
218 | WARNING
219 | WARNING
220 | WARNING
221 | HINT
222 | WARNING
223 | HINT
224 | HINT
225 | HINT
226 | HINT
227 | HINT
228 | HINT
229 | HINT
230 | HINT
231 | HINT
232 | HINT
233 | DO_NOT_SHOW
234 | WARNING
235 | WARNING
236 | WARNING
237 | WARNING
238 | WARNING
239 | WARNING
240 | WARNING
241 |
242 | True
243 | WARNING
244 | WARNING
245 | WARNING
246 | WARNING
247 | WARNING
248 | HINT
249 | HINT
250 | WARNING
251 | WARNING
252 | <?xml version="1.0" encoding="utf-16"?><Profile name="Code Cleanup (peppy)"><CSArrangeThisQualifier>True</CSArrangeThisQualifier><CSUseVar><BehavourStyle>CAN_CHANGE_TO_EXPLICIT</BehavourStyle><LocalVariableStyle>ALWAYS_EXPLICIT</LocalVariableStyle><ForeachVariableStyle>ALWAYS_EXPLICIT</ForeachVariableStyle></CSUseVar><CSOptimizeUsings><OptimizeUsings>True</OptimizeUsings><EmbraceInRegion>False</EmbraceInRegion><RegionName></RegionName></CSOptimizeUsings><CSShortenReferences>True</CSShortenReferences><CSReformatCode>True</CSReformatCode><CSUpdateFileHeader>True</CSUpdateFileHeader><CSCodeStyleAttributes ArrangeTypeAccessModifier="False" ArrangeTypeMemberAccessModifier="False" SortModifiers="True" RemoveRedundantParentheses="True" AddMissingParentheses="False" ArrangeBraces="False" ArrangeAttributes="False" ArrangeArgumentsStyle="False" /><XAMLCollapseEmptyTags>False</XAMLCollapseEmptyTags><CSFixBuiltinTypeReferences>True</CSFixBuiltinTypeReferences><CSArrangeQualifiers>True</CSArrangeQualifiers></Profile>
253 | Code Cleanup (peppy)
254 | RequiredForMultiline
255 | RequiredForMultiline
256 | RequiredForMultiline
257 | RequiredForMultiline
258 | RequiredForMultiline
259 | RequiredForMultiline
260 | RequiredForMultiline
261 | RequiredForMultiline
262 | Explicit
263 | ExpressionBody
264 | BlockBody
265 | True
266 | NEXT_LINE
267 | True
268 | True
269 | True
270 | True
271 | True
272 | True
273 | True
274 | True
275 | NEXT_LINE
276 | 1
277 | 1
278 | NEXT_LINE
279 | MULTILINE
280 | True
281 | True
282 | True
283 | True
284 | NEXT_LINE
285 | 1
286 | 1
287 | True
288 | NEXT_LINE
289 | NEVER
290 | NEVER
291 | True
292 | False
293 | True
294 | NEVER
295 | False
296 | False
297 | True
298 | False
299 | False
300 | True
301 | True
302 | False
303 | False
304 | CHOP_IF_LONG
305 | True
306 | 200
307 | CHOP_IF_LONG
308 | UseExplicitType
309 | UseVarWhenEvident
310 | UseVarWhenEvident
311 | False
312 | False
313 | AABB
314 | API
315 | BPM
316 | EF
317 | FPS
318 | GC
319 | GL
320 | GLSL
321 | HID
322 | HSV
323 | HTML
324 | HUD
325 | ID
326 | IL
327 | IOS
328 | IP
329 | IPC
330 | JIT
331 | LTRB
332 | MD5
333 | NS
334 | OS
335 | PM
336 | RGB
337 | RNG
338 | SHA
339 | SRGB
340 | TK
341 | SS
342 | PP
343 | GMT
344 | QAT
345 | BNG
346 | UI
347 | False
348 | HINT
349 | <?xml version="1.0" encoding="utf-16"?>
350 | <Patterns xmlns="urn:schemas-jetbrains-com:member-reordering-patterns">
351 | <TypePattern DisplayName="COM interfaces or structs">
352 | <TypePattern.Match>
353 | <Or>
354 | <And>
355 | <Kind Is="Interface" />
356 | <Or>
357 | <HasAttribute Name="System.Runtime.InteropServices.InterfaceTypeAttribute" />
358 | <HasAttribute Name="System.Runtime.InteropServices.ComImport" />
359 | </Or>
360 | </And>
361 | <Kind Is="Struct" />
362 | </Or>
363 | </TypePattern.Match>
364 | </TypePattern>
365 | <TypePattern DisplayName="NUnit Test Fixtures" RemoveRegions="All">
366 | <TypePattern.Match>
367 | <And>
368 | <Kind Is="Class" />
369 | <HasAttribute Name="NUnit.Framework.TestFixtureAttribute" Inherited="True" />
370 | </And>
371 | </TypePattern.Match>
372 | <Entry DisplayName="Setup/Teardown Methods">
373 | <Entry.Match>
374 | <And>
375 | <Kind Is="Method" />
376 | <Or>
377 | <HasAttribute Name="NUnit.Framework.SetUpAttribute" Inherited="True" />
378 | <HasAttribute Name="NUnit.Framework.TearDownAttribute" Inherited="True" />
379 | <HasAttribute Name="NUnit.Framework.FixtureSetUpAttribute" Inherited="True" />
380 | <HasAttribute Name="NUnit.Framework.FixtureTearDownAttribute" Inherited="True" />
381 | </Or>
382 | </And>
383 | </Entry.Match>
384 | </Entry>
385 | <Entry DisplayName="All other members" />
386 | <Entry Priority="100" DisplayName="Test Methods">
387 | <Entry.Match>
388 | <And>
389 | <Kind Is="Method" />
390 | <HasAttribute Name="NUnit.Framework.TestAttribute" />
391 | </And>
392 | </Entry.Match>
393 | <Entry.SortBy>
394 | <Name />
395 | </Entry.SortBy>
396 | </Entry>
397 | </TypePattern>
398 | <TypePattern DisplayName="Default Pattern">
399 | <Group DisplayName="Fields/Properties">
400 | <Group DisplayName="Public Fields">
401 | <Entry DisplayName="Constant Fields">
402 | <Entry.Match>
403 | <And>
404 | <Access Is="Public" />
405 | <Or>
406 | <Kind Is="Constant" />
407 | <Readonly />
408 | <And>
409 | <Static />
410 | <Readonly />
411 | </And>
412 | </Or>
413 | </And>
414 | </Entry.Match>
415 | </Entry>
416 | <Entry DisplayName="Static Fields">
417 | <Entry.Match>
418 | <And>
419 | <Access Is="Public" />
420 | <Static />
421 | <Not>
422 | <Readonly />
423 | </Not>
424 | <Kind Is="Field" />
425 | </And>
426 | </Entry.Match>
427 | </Entry>
428 | <Entry DisplayName="Normal Fields">
429 | <Entry.Match>
430 | <And>
431 | <Access Is="Public" />
432 | <Not>
433 | <Or>
434 | <Static />
435 | <Readonly />
436 | </Or>
437 | </Not>
438 | <Kind Is="Field" />
439 | </And>
440 | </Entry.Match>
441 | </Entry>
442 | </Group>
443 | <Entry DisplayName="Public Properties">
444 | <Entry.Match>
445 | <And>
446 | <Access Is="Public" />
447 | <Kind Is="Property" />
448 | </And>
449 | </Entry.Match>
450 | </Entry>
451 | <Group DisplayName="Internal Fields">
452 | <Entry DisplayName="Constant Fields">
453 | <Entry.Match>
454 | <And>
455 | <Access Is="Internal" />
456 | <Or>
457 | <Kind Is="Constant" />
458 | <Readonly />
459 | <And>
460 | <Static />
461 | <Readonly />
462 | </And>
463 | </Or>
464 | </And>
465 | </Entry.Match>
466 | </Entry>
467 | <Entry DisplayName="Static Fields">
468 | <Entry.Match>
469 | <And>
470 | <Access Is="Internal" />
471 | <Static />
472 | <Not>
473 | <Readonly />
474 | </Not>
475 | <Kind Is="Field" />
476 | </And>
477 | </Entry.Match>
478 | </Entry>
479 | <Entry DisplayName="Normal Fields">
480 | <Entry.Match>
481 | <And>
482 | <Access Is="Internal" />
483 | <Not>
484 | <Or>
485 | <Static />
486 | <Readonly />
487 | </Or>
488 | </Not>
489 | <Kind Is="Field" />
490 | </And>
491 | </Entry.Match>
492 | </Entry>
493 | </Group>
494 | <Entry DisplayName="Internal Properties">
495 | <Entry.Match>
496 | <And>
497 | <Access Is="Internal" />
498 | <Kind Is="Property" />
499 | </And>
500 | </Entry.Match>
501 | </Entry>
502 | <Group DisplayName="Protected Fields">
503 | <Entry DisplayName="Constant Fields">
504 | <Entry.Match>
505 | <And>
506 | <Access Is="Protected" />
507 | <Or>
508 | <Kind Is="Constant" />
509 | <Readonly />
510 | <And>
511 | <Static />
512 | <Readonly />
513 | </And>
514 | </Or>
515 | </And>
516 | </Entry.Match>
517 | </Entry>
518 | <Entry DisplayName="Static Fields">
519 | <Entry.Match>
520 | <And>
521 | <Access Is="Protected" />
522 | <Static />
523 | <Not>
524 | <Readonly />
525 | </Not>
526 | <Kind Is="Field" />
527 | </And>
528 | </Entry.Match>
529 | </Entry>
530 | <Entry DisplayName="Normal Fields">
531 | <Entry.Match>
532 | <And>
533 | <Access Is="Protected" />
534 | <Not>
535 | <Or>
536 | <Static />
537 | <Readonly />
538 | </Or>
539 | </Not>
540 | <Kind Is="Field" />
541 | </And>
542 | </Entry.Match>
543 | </Entry>
544 | </Group>
545 | <Entry DisplayName="Protected Properties">
546 | <Entry.Match>
547 | <And>
548 | <Access Is="Protected" />
549 | <Kind Is="Property" />
550 | </And>
551 | </Entry.Match>
552 | </Entry>
553 | <Group DisplayName="Private Fields">
554 | <Entry DisplayName="Constant Fields">
555 | <Entry.Match>
556 | <And>
557 | <Access Is="Private" />
558 | <Or>
559 | <Kind Is="Constant" />
560 | <Readonly />
561 | <And>
562 | <Static />
563 | <Readonly />
564 | </And>
565 | </Or>
566 | </And>
567 | </Entry.Match>
568 | </Entry>
569 | <Entry DisplayName="Static Fields">
570 | <Entry.Match>
571 | <And>
572 | <Access Is="Private" />
573 | <Static />
574 | <Not>
575 | <Readonly />
576 | </Not>
577 | <Kind Is="Field" />
578 | </And>
579 | </Entry.Match>
580 | </Entry>
581 | <Entry DisplayName="Normal Fields">
582 | <Entry.Match>
583 | <And>
584 | <Access Is="Private" />
585 | <Not>
586 | <Or>
587 | <Static />
588 | <Readonly />
589 | </Or>
590 | </Not>
591 | <Kind Is="Field" />
592 | </And>
593 | </Entry.Match>
594 | </Entry>
595 | </Group>
596 | <Entry DisplayName="Private Properties">
597 | <Entry.Match>
598 | <And>
599 | <Access Is="Private" />
600 | <Kind Is="Property" />
601 | </And>
602 | </Entry.Match>
603 | </Entry>
604 | </Group>
605 | <Group DisplayName="Constructor/Destructor">
606 | <Entry DisplayName="Ctor">
607 | <Entry.Match>
608 | <Kind Is="Constructor" />
609 | </Entry.Match>
610 | </Entry>
611 | <Region Name="Disposal">
612 | <Entry DisplayName="Dtor">
613 | <Entry.Match>
614 | <Kind Is="Destructor" />
615 | </Entry.Match>
616 | </Entry>
617 | <Entry DisplayName="Dispose()">
618 | <Entry.Match>
619 | <And>
620 | <Access Is="Public" />
621 | <Kind Is="Method" />
622 | <Name Is="Dispose" />
623 | </And>
624 | </Entry.Match>
625 | </Entry>
626 | <Entry DisplayName="Dispose(true)">
627 | <Entry.Match>
628 | <And>
629 | <Access Is="Protected" />
630 | <Or>
631 | <Virtual />
632 | <Override />
633 | </Or>
634 | <Kind Is="Method" />
635 | <Name Is="Dispose" />
636 | </And>
637 | </Entry.Match>
638 | </Entry>
639 | </Region>
640 | </Group>
641 | <Group DisplayName="Methods">
642 | <Group DisplayName="Public">
643 | <Entry DisplayName="Static Methods">
644 | <Entry.Match>
645 | <And>
646 | <Access Is="Public" />
647 | <Static />
648 | <Kind Is="Method" />
649 | </And>
650 | </Entry.Match>
651 | </Entry>
652 | <Entry DisplayName="Methods">
653 | <Entry.Match>
654 | <And>
655 | <Access Is="Public" />
656 | <Not>
657 | <Static />
658 | </Not>
659 | <Kind Is="Method" />
660 | </And>
661 | </Entry.Match>
662 | </Entry>
663 | </Group>
664 | <Group DisplayName="Internal">
665 | <Entry DisplayName="Static Methods">
666 | <Entry.Match>
667 | <And>
668 | <Access Is="Internal" />
669 | <Static />
670 | <Kind Is="Method" />
671 | </And>
672 | </Entry.Match>
673 | </Entry>
674 | <Entry DisplayName="Methods">
675 | <Entry.Match>
676 | <And>
677 | <Access Is="Internal" />
678 | <Not>
679 | <Static />
680 | </Not>
681 | <Kind Is="Method" />
682 | </And>
683 | </Entry.Match>
684 | </Entry>
685 | </Group>
686 | <Group DisplayName="Protected">
687 | <Entry DisplayName="Static Methods">
688 | <Entry.Match>
689 | <And>
690 | <Access Is="Protected" />
691 | <Static />
692 | <Kind Is="Method" />
693 | </And>
694 | </Entry.Match>
695 | </Entry>
696 | <Entry DisplayName="Methods">
697 | <Entry.Match>
698 | <And>
699 | <Access Is="Protected" />
700 | <Not>
701 | <Static />
702 | </Not>
703 | <Kind Is="Method" />
704 | </And>
705 | </Entry.Match>
706 | </Entry>
707 | </Group>
708 | <Group DisplayName="Private">
709 | <Entry DisplayName="Static Methods">
710 | <Entry.Match>
711 | <And>
712 | <Access Is="Private" />
713 | <Static />
714 | <Kind Is="Method" />
715 | </And>
716 | </Entry.Match>
717 | </Entry>
718 | <Entry DisplayName="Methods">
719 | <Entry.Match>
720 | <And>
721 | <Access Is="Private" />
722 | <Not>
723 | <Static />
724 | </Not>
725 | <Kind Is="Method" />
726 | </And>
727 | </Entry.Match>
728 | </Entry>
729 | </Group>
730 | </Group>
731 | </TypePattern>
732 | </Patterns>
733 | <Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" />
734 | <Policy Inspect="False" Prefix="" Suffix="" Style="AaBb" />
735 | <Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" />
736 | <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" />
737 | <Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" />
738 | <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb"><ExtraRule Prefix="_" Suffix="" Style="aaBb" /></Policy>
739 | <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" />
740 | <Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" />
741 | <Policy Inspect="True" Prefix="" Suffix="" Style="AA_BB" />
742 | <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" />
743 | <Policy><Descriptor Staticness="Static, Instance" AccessRightKinds="Private" Description="private methods"><ElementKinds><Kind Name="ASYNC_METHOD" /><Kind Name="METHOD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></Policy>
744 | <Policy><Descriptor Staticness="Static, Instance" AccessRightKinds="Protected, ProtectedInternal, Internal, Public" Description="internal/protected/public methods"><ElementKinds><Kind Name="ASYNC_METHOD" /><Kind Name="METHOD" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></Policy>
745 | <Policy><Descriptor Staticness="Static, Instance" AccessRightKinds="Private" Description="private properties"><ElementKinds><Kind Name="PROPERTY" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" /></Policy>
746 | <Policy><Descriptor Staticness="Static, Instance" AccessRightKinds="Protected, ProtectedInternal, Internal, Public" Description="internal/protected/public properties"><ElementKinds><Kind Name="PROPERTY" /></ElementKinds></Descriptor><Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /></Policy>
747 | <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" />
748 | <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" />
749 | <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" />
750 | <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" />
751 | <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" />
752 | <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" />
753 | <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" />
754 | <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" />
755 | <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" />
756 | <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" />
757 | <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" />
758 | <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" />
759 | <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" />
760 | <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" />
761 | <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" />
762 | <Policy Inspect="True" Prefix="I" Suffix="" Style="AaBb" />
763 | <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" />
764 | <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" />
765 | <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" />
766 | <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" />
767 | <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" />
768 | <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" />
769 | <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" />
770 | <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" />
771 | <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" />
772 | <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" />
773 | <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" />
774 | <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" />
775 | <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" />
776 | <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" />
777 | <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" />
778 | <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" />
779 | <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" />
780 | <Policy Inspect="True" Prefix="T" Suffix="" Style="AaBb" />
781 | <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" />
782 | <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" />
783 | <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" />
784 | <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" />
785 | <Policy Inspect="True" Prefix="" Suffix="" Style="aaBb" />
786 | <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" />
787 | <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" />
788 |
789 | True
790 | True
791 | True
792 | True
793 | True
794 | True
795 | True
796 | True
797 | True
798 | True
799 | True
800 | TestFolder
801 | True
802 | True
803 | o!f – Object Initializer: Anchor&Origin
804 | True
805 | constant("Centre")
806 | 0
807 | True
808 | True
809 | 2.0
810 | InCSharpFile
811 | ofao
812 | True
813 | Anchor = Anchor.$anchor$,
814 | Origin = Anchor.$anchor$,
815 | True
816 | True
817 | o!f – InternalChildren = []
818 | True
819 | True
820 | 2.0
821 | InCSharpFile
822 | ofic
823 | True
824 | InternalChildren = new Drawable[]
825 | {
826 | $END$
827 | };
828 | True
829 | True
830 | o!f – new GridContainer { .. }
831 | True
832 | True
833 | 2.0
834 | InCSharpFile
835 | ofgc
836 | True
837 | new GridContainer
838 | {
839 | RelativeSizeAxes = Axes.Both,
840 | Content = new[]
841 | {
842 | new Drawable[] { $END$ },
843 | new Drawable[] { }
844 | }
845 | };
846 | True
847 | True
848 | o!f – new FillFlowContainer { .. }
849 | True
850 | True
851 | 2.0
852 | InCSharpFile
853 | offf
854 | True
855 | new FillFlowContainer
856 | {
857 | RelativeSizeAxes = Axes.Both,
858 | Direction = FillDirection.Vertical,
859 | Children = new Drawable[]
860 | {
861 | $END$
862 | }
863 | },
864 | True
865 | True
866 | o!f – new Container { .. }
867 | True
868 | True
869 | 2.0
870 | InCSharpFile
871 | ofcont
872 | True
873 | new Container
874 | {
875 | RelativeSizeAxes = Axes.Both,
876 | Children = new Drawable[]
877 | {
878 | $END$
879 | }
880 | },
881 | True
882 | True
883 | o!f – BackgroundDependencyLoader load()
884 | True
885 | True
886 | 2.0
887 | InCSharpFile
888 | ofbdl
889 | True
890 | [BackgroundDependencyLoader]
891 | private void load()
892 | {
893 | $END$
894 | }
895 | True
896 | True
897 | o!f – new Box { .. }
898 | True
899 | True
900 | 2.0
901 | InCSharpFile
902 | ofbox
903 | True
904 | new Box
905 | {
906 | Colour = Color4.Black,
907 | RelativeSizeAxes = Axes.Both,
908 | },
909 | True
910 | True
911 | o!f – Children = []
912 | True
913 | True
914 | 2.0
915 | InCSharpFile
916 | ofc
917 | True
918 | Children = new Drawable[]
919 | {
920 | $END$
921 | };
922 | True
923 | True
924 | True
925 | True
926 | True
927 | True
928 | True
929 | True
930 | True
931 | True
932 | True
933 | True
934 | True
935 | True
936 | True
937 | True
938 | True
939 | True
940 | True
941 | True
942 | True
943 | True
944 | True
945 | True
946 | True
947 | True
948 | True
949 | True
950 | True
951 | True
952 | True
953 | True
954 | True
955 | True
956 | True
957 | True
958 | True
959 | True
960 | True
961 | True
962 | True
963 | True
964 | True
965 | True
966 | True
967 | True
968 | True
969 | True
970 | True
971 | True
972 | True
973 | True
974 | True
975 | True
976 | True
977 | True
978 | True
979 | True
980 | True
981 | True
982 | True
983 | True
984 | True
985 | True
986 | True
987 | True
988 | True
989 | True
990 | True
991 | True
992 | True
993 | True
994 | True
995 | True
996 | True
997 | True
998 | True
999 | True
1000 | True
1001 |
--------------------------------------------------------------------------------