├── .editorconfig ├── .gitattributes ├── .github ├── dependabot.yml └── workflows │ ├── dotnet-core.yml │ └── release.yml ├── .gitignore ├── .vscode ├── launch.json └── tasks.json ├── Directory.Build.props ├── LICENSE ├── README.md ├── assets └── rush.png ├── osu.Game.Rulesets.Rush.Tests ├── Beatmaps │ ├── BeatmapConversionDecidingTest.cs │ └── CraftedBeatmapConversionTest.cs ├── Replay │ └── RushReplayFrameTest.cs ├── Visual │ ├── TestSceneFeverBar.cs │ ├── TestSceneGround.cs │ ├── TestSceneMiniBoss.cs │ ├── TestSceneOsuGame.cs │ ├── TestSceneRushAutoplay.cs │ ├── TestSceneRushPlayer.cs │ └── TestSceneTouchInputHandling.cs ├── VisualTestRunner.cs └── osu.Game.Rulesets.Rush.Tests.csproj ├── osu.Game.Rulesets.Rush.sln ├── osu.Game.Rulesets.Rush.sln.DotSettings └── osu.Game.Rulesets.Rush ├── Beatmaps ├── RushBeatmap.cs ├── RushBeatmapConverter.cs ├── RushCraftedBeatmapConverter.cs └── RushGeneratedBeatmapConverter.cs ├── Configuration ├── FeverActivationMode.cs └── RushRulesetConfigManager.cs ├── Input ├── IKeyBindingTouchHandler.cs ├── RushInputManager.cs ├── RushMouseEventManager.cs └── RushTouchEventManager.cs ├── Judgements ├── CollisionDamagingJudgement.cs ├── HeartJudgement.cs ├── RushFeverJudgement.cs ├── RushIgnoreJudgement.cs ├── RushJudgement.cs ├── RushJudgementResult.cs ├── RushTickJudgement.cs └── SawbladeJudgement.cs ├── Mods ├── RushModAutoplay.cs ├── RushModCinema.cs ├── RushModDaycore.cs ├── RushModDoubleTime.cs ├── RushModFlashlight.cs ├── RushModHalfTime.cs ├── RushModNightcore.cs ├── RushModNoFail.cs ├── RushModPerfect.cs └── RushModSuddenDeath.cs ├── Objects ├── Drawables │ ├── DrawableDualHit.cs │ ├── DrawableDualHitPart.cs │ ├── DrawableFeverBonus.cs │ ├── DrawableHeart.cs │ ├── DrawableLanedHit.cs │ ├── DrawableMiniBoss.cs │ ├── DrawableMiniBossTick.cs │ ├── DrawableMinion.cs │ ├── DrawableRushHitObject.cs │ ├── DrawableRushJudgement.cs │ ├── DrawableSawblade.cs │ ├── DrawableStarSheet.cs │ ├── DrawableStarSheetCap.cs │ ├── DrawableStarSheetHead.cs │ ├── DrawableStarSheetTail.cs │ ├── IDrawableLanedHit.cs │ └── Pieces │ │ ├── DualHitJoinPiece.cs │ │ ├── DualHitPartPiece.cs │ │ ├── HeartPiece.cs │ │ ├── MiniBossPiece.cs │ │ ├── MinionPiece.cs │ │ ├── SawbladePiece.cs │ │ ├── StarSheetBodyPiece.cs │ │ └── StarSheetCapStarPiece.cs ├── DualHit.cs ├── DualHitPart.cs ├── FeverBonus.cs ├── Heart.cs ├── LanedHit.cs ├── LanedHitLane.cs ├── MiniBoss.cs ├── MiniBossTick.cs ├── Minion.cs ├── RushHitObject.cs ├── Sawblade.cs ├── StarSheet.cs ├── StarSheetHead.cs └── StarSheetTail.cs ├── Replays ├── RushAutoGenerator.cs ├── RushFramedReplayInputHandler.cs └── RushReplayFrame.cs ├── Resources └── Textures │ ├── Effects │ └── explosion.png │ ├── MiniBoss │ ├── pippidon_boss_0.png │ ├── pippidon_boss_1.png │ ├── pippidon_boss_hurt_0.png │ ├── pippidon_boss_hurt_1.png │ └── pippidon_boss_hurt_2.png │ ├── Minion │ ├── pippidon_air_0.png │ ├── pippidon_air_1.png │ ├── pippidon_air_hit.png │ ├── pippidon_ground_0.png │ ├── pippidon_ground_1.png │ └── pippidon_ground_hit.png │ └── Player │ ├── Attack__000.png │ ├── Attack__001.png │ ├── Attack__002.png │ ├── Attack__003.png │ ├── Attack__004.png │ ├── Attack__005.png │ ├── Attack__006.png │ ├── Attack__007.png │ ├── Attack__008.png │ ├── Attack__009.png │ ├── Dead__000.png │ ├── Jump_Attack__000.png │ ├── Jump_Attack__001.png │ ├── Jump_Attack__002.png │ ├── Jump_Attack__003.png │ ├── Jump_Attack__004.png │ ├── Jump_Attack__005.png │ ├── Jump_Attack__006.png │ ├── Jump_Attack__007.png │ ├── Jump_Attack__008.png │ ├── Jump_Attack__009.png │ ├── Jump__000.png │ ├── Jump__001.png │ ├── Jump__002.png │ ├── Jump__003.png │ ├── Jump__004.png │ ├── Jump__005.png │ ├── Jump__006.png │ ├── Jump__007.png │ ├── Jump__008.png │ ├── Jump__009.png │ ├── Run__000.png │ ├── Run__001.png │ ├── Run__002.png │ ├── Run__003.png │ ├── Run__004.png │ ├── Run__005.png │ ├── Run__006.png │ ├── Run__007.png │ ├── Run__008.png │ ├── Run__009.png │ ├── Slide__000.png │ ├── Slide__001.png │ ├── Slide__002.png │ ├── Slide__003.png │ ├── Slide__004.png │ ├── Slide__005.png │ ├── Slide__006.png │ ├── Slide__007.png │ ├── Slide__008.png │ └── Slide__009.png ├── RushDifficultyCalculator.cs ├── RushRuleset.cs ├── RushSkinComponent.cs ├── RushSkinComponents.cs ├── Scoring ├── HeartHitWindows.cs ├── RushHealthProcessor.cs ├── RushHitWindows.cs ├── RushScoreProcessor.cs └── SawbladeHitWindows.cs ├── UI ├── ActionBeatSyncedContainer.cs ├── DefaultHitExplosion.cs ├── DrawableRushRuleset.cs ├── Fever │ ├── FeverProcessor.cs │ └── RushFeverBar.cs ├── Ground │ ├── DefaultGround.cs │ └── GroundDisplay.cs ├── HealthText.cs ├── HeartHitExplosion.cs ├── HitTarget.cs ├── LanePlayfield.cs ├── RushHitPolicy.cs ├── RushPlayerSprite.cs ├── RushPlayfield.cs ├── RushReplayRecorder.cs ├── RushSettingsSubsection.cs └── StarSheetHitExplosion.cs └── osu.Game.Rulesets.Rush.csproj /.gitattributes: -------------------------------------------------------------------------------- 1 | # Autodetect text files and ensure that we normalise their 2 | # line endings to lf internally. When checked out they may 3 | # use different line endings. 4 | * text=auto 5 | 6 | # Check out with crlf (Windows) line endings 7 | *.sln text eol=crlf 8 | *.csproj text eol=crlf 9 | *.cs text diff=csharp eol=crlf 10 | 11 | # Check out with lf (UNIX) line endings 12 | .gitignore text eol=lf 13 | .gitattributes text eol=lf 14 | *.sh text eol=lf 15 | *.md text eol=lf 16 | *.yml text eol=lf 17 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "nuget" 4 | directory: "/" 5 | schedule: 6 | interval: "daily" 7 | -------------------------------------------------------------------------------- /.github/workflows/dotnet-core.yml: -------------------------------------------------------------------------------- 1 | name: .NET Core 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - uses: actions/checkout@v2 15 | - name: Setup .NET Core 16 | uses: actions/setup-dotnet@v1 17 | - name: Install dependencies 18 | run: dotnet restore 19 | - name: Build 20 | run: dotnet build --configuration Development --no-restore 21 | - name: Test 22 | run: dotnet test --no-restore --verbosity normal 23 | - name: Upload Artifact 24 | uses: actions/upload-artifact@v4 25 | with: 26 | name: Rush (dev build) 27 | path: osu.Game.Rulesets.Rush/bin/Development/net8.0/osu.Game.Rulesets.Rush-dev.dll 28 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Tagged Release 2 | on: 3 | push: 4 | tags: ['*'] 5 | 6 | jobs: 7 | build: 8 | name: Build and Create Release 9 | runs-on: ubuntu-latest 10 | 11 | steps: 12 | - name: Checkout repository 13 | uses: actions/checkout@v2 14 | - name: Fetch all tags 15 | run: git fetch --depth=1 origin +refs/tags/*:refs/tags/* 16 | - name: Get current tag 17 | run: echo "CURRENT_TAG=$(git describe --abbrev=0 --tags $(git rev-list --tags --max-count=1))" >> $GITHUB_ENV 18 | - name: Install dependencies 19 | run: dotnet restore 20 | - name: Build 21 | run: dotnet build osu.Game.Rulesets.Rush --configuration Release -p:version=${{env.CURRENT_TAG}} --no-restore 22 | - name: Create Release 23 | id: create_release 24 | uses: actions/create-release@latest 25 | env: 26 | GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }} 27 | with: 28 | tag_name: ${{ github.ref }} 29 | release_name: ${{ github.ref }} 30 | body: | 31 | Tagged release ${{ github.ref }} 32 | draft: true 33 | prerelease: true 34 | - name: Upload Release Asset 35 | id: upload-release-asset 36 | uses: actions/upload-release-asset@master 37 | env: 38 | GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }} 39 | with: 40 | upload_url: ${{ steps.create_release.outputs.upload_url }} 41 | asset_path: ./osu.Game.Rulesets.Rush/bin/Release/net8.0/osu.Game.Rulesets.Rush.dll 42 | asset_name: osu.Game.Rulesets.Rush.dll 43 | asset_content_type: application/vnd.microsoft.portable-executable 44 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Rush for osu! (Tests, Debug)", 6 | "type": "coreclr", 7 | "request": "launch", 8 | "program": "dotnet", 9 | "args": [ 10 | "${workspaceRoot}/osu.Game.Rulesets.Rush.Tests/bin/Debug/net8.0/osu.Game.Rulesets.Rush.Tests.dll" 11 | ], 12 | "cwd": "${workspaceRoot}", 13 | "preLaunchTask": "Build tests (Debug)", 14 | "console": "internalConsole" 15 | }, 16 | { 17 | "name": "Rush for osu! (Tests, Release)", 18 | "type": "coreclr", 19 | "request": "launch", 20 | "program": "dotnet", 21 | "args": [ 22 | "${workspaceRoot}/osu.Game.Rulesets.Rush.Tests/bin/Release/net8.0/osu.Game.Rulesets.Rush.Tests.dll" 23 | ], 24 | "cwd": "${workspaceRoot}", 25 | "preLaunchTask": "Build tests (Release)", 26 | "console": "internalConsole" 27 | }, 28 | { 29 | "name": "Rush for osu! (Tests, Development)", 30 | "type": "coreclr", 31 | "request": "launch", 32 | "program": "dotnet", 33 | "args": [ 34 | "${workspaceRoot}/osu.Game.Rulesets.Rush.Tests/bin/Development/net8.0/osu.Game.Rulesets.Rush.Tests.dll" 35 | ], 36 | "cwd": "${workspaceRoot}", 37 | "preLaunchTask": "Build tests (Development)", 38 | "console": "internalConsole" 39 | }, 40 | ] 41 | } 42 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "2.0.0", 3 | "tasks": [ 4 | { 5 | "label": "Build tests (Debug)", 6 | "type": "shell", 7 | "command": "dotnet", 8 | "args": [ 9 | "build", 10 | "osu.Game.Rulesets.Rush.Tests", 11 | "/p:GenerateFullPaths=true", 12 | "/m", 13 | "/verbosity:m" 14 | ], 15 | "group": "build", 16 | "problemMatcher": "$msCompile" 17 | }, 18 | { 19 | "label": "Build tests (Release)", 20 | "type": "shell", 21 | "command": "dotnet", 22 | "args": [ 23 | "build", 24 | "osu.Game.Rulesets.Rush.Tests", 25 | "/p:Configuration=Release", 26 | "/p:GenerateFullPaths=true", 27 | "/m", 28 | "/verbosity:m" 29 | ], 30 | "group": "build", 31 | "problemMatcher": "$msCompile" 32 | }, 33 | { 34 | "label": "Build tests (Development)", 35 | "type": "shell", 36 | "command": "dotnet", 37 | "args": [ 38 | "build", 39 | "osu.Game.Rulesets.Rush.Tests", 40 | "/p:Configuration=Development", 41 | "/p:GenerateFullPaths=true", 42 | "/m", 43 | "/verbosity:m" 44 | ], 45 | "group": "build", 46 | "problemMatcher": "$msCompile" 47 | }, 48 | // Test Tasks 49 | { 50 | "label": "Run tests (Debug)", 51 | "type": "shell", 52 | "command": "dotnet", 53 | "args": [ 54 | "test", 55 | "/p:Configuration=Debug", 56 | ], 57 | "group": "test", 58 | "problemMatcher": "$msCompile" 59 | }, 60 | { 61 | "label": "Run tests (Release)", 62 | "type": "shell", 63 | "command": "dotnet", 64 | "args": [ 65 | "test", 66 | "/p:Configuration=Release", 67 | ], 68 | "group": "test", 69 | "problemMatcher": "$msCompile" 70 | } 71 | ] 72 | } 73 | -------------------------------------------------------------------------------- /Directory.Build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | 8.0 4 | true 5 | true 6 | true 7 | 8 | 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2020 Shane Woolcock 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Rush!](assets/rush.png) 2 | 3 | # Rush! 4 | Custom ruleset for osu!lazer, based loosely on Muse Dash. 5 | 6 | Demo: https://youtu.be/tLs1cqeLJ1U 7 | 8 | Discord: https://discord.gg/2P9E8MS 9 | 10 | ## Status 11 | WIP but playable. 12 | 13 | ## Installation 14 | 15 | Prebuilt binary releases are available if you are looking to test or play and do not wish to compile yourself. 16 | | [Releases Page](https://github.com/swoolcock/rush/releases/) | 17 | | -------------| 18 | 19 | **NOTE**: osu!lazer runs custom rulesets only on desktop platforms (Windows, macOS, Linux) for the time being. 20 | 21 | The ruleset consists of a single DLL file that you'll need to place in the `rulesets` subdirectory of your osu!lazer installation. 22 | 23 | ### Installation instructions 24 | 25 | 1. Navigate to the osu!lazer data directory. You can do so by opening the settings panel in osu!lazer and clicking on the "open osu! folder" button. Alternatively you can directly navigate to the `rulesets` directory via your OS directory explorer at the following locations: 26 | - `%AppData%/osu/rulesets` on Windows 27 | - `~/.local/share/osu/rulesets` on Linux / macOS 28 | 29 | **NOTE**: If you have relocated your osu! data directory to another directory, the `rulesets` directory will be there instead. 30 | 31 | 2. Drag and drop the ruleset's DLL file into the `rulesets` directory. 32 | 33 | 3. Have fun! 34 | If osu!lazer was running while installing the ruleset, you may need to restart the game in order for the ruleset to appear. 35 | 36 | **NOTE**: Custom Rulesets do not automatically update alongside osu!lazer but have a compatibility mechanism to continue using them on newer game versions. However, some changes made game-side may break that compatibility and require installing a newer version of the ruleset. 37 | Thus it is recommended that you periodically head over to the releases page and replace the ruleset DLL in the `rulesets` directory with the latest available version. 38 | 39 | ## TODO 40 | * Better player sprite 41 | * Boss sprite during kiai sections 42 | * Hammers and other minion variants 43 | * Custom avatars/abilities via mods? 44 | * Editor (waiting on updates in lazer) 45 | -------------------------------------------------------------------------------- /assets/rush.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Beamographic/rush/099eb77d51b7e491fd9259221472d351103ca4c8/assets/rush.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush.Tests/Beatmaps/BeatmapConversionDecidingTest.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. 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.Beatmaps; 6 | using osu.Game.Rulesets.Rush.Beatmaps; 7 | 8 | namespace osu.Game.Rulesets.Rush.Tests.Beatmaps 9 | { 10 | [TestFixture] 11 | public class BeatmapConversionDecidingTest 12 | { 13 | [Test] 14 | public void TestCraftedTagCreatesCrafter() 15 | => Assert.That(converterForTag("crafted") is RushCraftedBeatmapConverter, Is.True); 16 | 17 | [Test] 18 | public void TestWrongCasedCraftedTagCreatesCrafter() 19 | => Assert.That(converterForTag("cRafTeD") is RushCraftedBeatmapConverter, Is.True); 20 | 21 | [Test] 22 | public void TestWordContainingCraftedTagCreatesGenerator() 23 | => Assert.That(converterForTag("handcraftedison") is RushGeneratedBeatmapConverter, Is.True); 24 | 25 | [Test] 26 | public void TestRandomTagCreatesGenerator() 27 | => Assert.That(converterForTag("one two something") is RushGeneratedBeatmapConverter, Is.True); 28 | 29 | [Test] 30 | public void TestNullTagCreatesGenerator() 31 | => Assert.That(converterForTag(null) is RushGeneratedBeatmapConverter, Is.True); 32 | 33 | private IBeatmapConverter converterForTag(string tags) 34 | { 35 | var beatmap = new Beatmap { BeatmapInfo = { Metadata = { Tags = tags } } }; 36 | var wrapper = new RushBeatmapConverter(beatmap, new RushRuleset()); 37 | return wrapper.BackedConverter; 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush.Tests/Beatmaps/CraftedBeatmapConversionTest.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. 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 NUnit.Framework; 7 | using osu.Framework.Utils; 8 | using osu.Game.Rulesets.Objects; 9 | using osu.Game.Rulesets.Rush.Objects; 10 | using osu.Game.Tests.Beatmaps; 11 | 12 | namespace osu.Game.Rulesets.Rush.Tests.Beatmaps 13 | { 14 | [TestFixture] 15 | public class CraftedBeatmapConversionTest : BeatmapConversionTest 16 | { 17 | protected override string ResourceAssembly => typeof(RushRuleset).Namespace; 18 | 19 | // TODO: add tests for this 20 | //public void Test(string name) => base.Test(name); 21 | 22 | protected override IEnumerable CreateConvertValue(HitObject hitObject) 23 | { 24 | yield return new ConvertValue 25 | { 26 | StartTime = hitObject.StartTime, 27 | EndTime = hitObject.GetEndTime(), 28 | Lane = (hitObject as LanedHit)?.Lane, 29 | IsMinion = hitObject is Minion, 30 | IsStarSheet = hitObject is StarSheet, 31 | IsMiniBoss = hitObject is MiniBoss, 32 | IsSawblade = hitObject is Sawblade, 33 | HasHeart = hitObject is Heart /*|| (hitObject is LanedHit)?.HasHeart*/, 34 | IsHammer = false, // TODO 35 | IsNote = false, // TODO 36 | }; 37 | } 38 | 39 | protected override Ruleset CreateRuleset() => new RushRuleset(); 40 | } 41 | 42 | public struct ConvertValue : IEquatable 43 | { 44 | /// 45 | /// A sane value to account for osu!stable using ints everywhere. 46 | /// 47 | private const float conversion_lenience = 2; 48 | 49 | public double StartTime; 50 | public double EndTime; 51 | public LanedHitLane? Lane; 52 | public bool IsMinion; 53 | public bool IsStarSheet; 54 | public bool IsMiniBoss; 55 | public bool IsSawblade; 56 | public bool IsHammer; 57 | public bool HasHeart; 58 | public bool IsNote; 59 | 60 | public bool Equals(ConvertValue other) 61 | => Precision.AlmostEquals(StartTime, other.StartTime, conversion_lenience) 62 | && Precision.AlmostEquals(EndTime, other.EndTime, conversion_lenience) 63 | && Lane == other.Lane 64 | && IsMinion == other.IsMinion 65 | && IsStarSheet == other.IsStarSheet 66 | && IsSawblade == other.IsSawblade 67 | && IsHammer == other.IsHammer 68 | && HasHeart == other.HasHeart 69 | && IsNote == other.IsNote 70 | && IsMiniBoss == other.IsMiniBoss; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush.Tests/Replay/RushReplayFrameTest.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. 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.Beatmaps; 6 | using osu.Game.Rulesets.Rush.Input; 7 | using osu.Game.Rulesets.Rush.Replays; 8 | 9 | namespace osu.Game.Rulesets.Rush.Tests.Replay 10 | { 11 | [TestFixture] 12 | public class RushReplayFrameTest 13 | { 14 | [TestCase] 15 | [TestCase(RushAction.AirPrimary, RushAction.GroundPrimary)] 16 | [TestCase(RushAction.AirPrimary, RushAction.AirSecondary, RushAction.GroundQuaternary)] 17 | [TestCase(RushAction.GroundPrimary, RushAction.GroundSecondary)] 18 | [TestCase(RushAction.AirPrimary, RushAction.AirSecondary, RushAction.AirTertiary, RushAction.AirQuaternary, RushAction.GroundPrimary, RushAction.GroundSecondary, RushAction.GroundTertiary, RushAction.GroundTertiary)] 19 | public void TestParity(params RushAction[] actions) 20 | { 21 | var originalFrame = (RushReplayFrame)new RushRuleset().CreateConvertibleReplayFrame(); 22 | var resultFrame = (RushReplayFrame)new RushRuleset().CreateConvertibleReplayFrame(); 23 | 24 | resultFrame.FromLegacy(originalFrame.ToLegacy(new Beatmap()), new Beatmap()); 25 | 26 | Assert.That(resultFrame.Actions, Is.EquivalentTo(originalFrame.Actions)); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush.Tests/Visual/TestSceneFeverBar.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. 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.Game.Rulesets.Rush.UI.Fever; 7 | using osu.Game.Tests.Visual; 8 | 9 | namespace osu.Game.Rulesets.Rush.Tests.Visual 10 | { 11 | public partial class TestSceneFeverBar : OsuTestScene 12 | { 13 | [Cached] 14 | private readonly FeverProcessor feverProcessor = new FeverProcessor(); 15 | 16 | public TestSceneFeverBar() 17 | { 18 | Children = new Drawable[] 19 | { 20 | feverProcessor, 21 | new FeverBar() 22 | { 23 | Anchor = Anchor.Centre, 24 | Origin = Anchor.Centre, 25 | Y = 0, 26 | } 27 | }; 28 | 29 | AddSliderStep("Progress", 0, 1, 0, v => feverProcessor.FeverProgress.Value = v); 30 | AddToggleStep("Activated", v => feverProcessor.InFeverMode.Value = v); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush.Tests/Visual/TestSceneGround.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. Licensed under the MIT Licence. 2 | // See the LICENCE file in the repository root for full licence text. 3 | 4 | using osu.Framework.Graphics; 5 | using osu.Game.Rulesets.Rush.UI.Ground; 6 | using osu.Game.Tests.Visual; 7 | 8 | namespace osu.Game.Rulesets.Rush.Tests.Visual 9 | { 10 | public partial class TestSceneGround : OsuTestScene 11 | { 12 | public TestSceneGround() 13 | { 14 | Children = new Drawable[] 15 | { 16 | new GroundDisplay 17 | { 18 | RelativePositionAxes = Axes.Y, 19 | Y = 0.7f, 20 | }, 21 | }; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush.Tests/Visual/TestSceneMiniBoss.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. 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.Beatmaps; 6 | using osu.Game.Rulesets.Rush.Beatmaps; 7 | using osu.Game.Rulesets.Rush.Objects; 8 | using osu.Game.Rulesets.Rush.UI; 9 | using osuTK.Input; 10 | 11 | namespace osu.Game.Rulesets.Rush.Tests.Visual 12 | { 13 | public partial class TestSceneMiniBoss : TestSceneRushPlayer 14 | { 15 | private const float mini_boss_time = 600f; 16 | 17 | protected override IBeatmap CreateBeatmap(RulesetInfo ruleset) 18 | { 19 | var beatmap = new RushBeatmap(); 20 | 21 | for (int i = 0; i < mini_boss_time / 200f; i++) 22 | { 23 | beatmap.HitObjects.Add(new Minion 24 | { 25 | StartTime = i * 200, 26 | }); 27 | } 28 | 29 | beatmap.HitObjects.Add(new MiniBoss 30 | { 31 | StartTime = mini_boss_time, 32 | Duration = 1000f, 33 | }); 34 | 35 | return beatmap; 36 | } 37 | 38 | private PlayerTargetLane targetLane => ((DrawableRushRuleset)Player.DrawableRuleset).Playfield.PlayerSprite.Target; 39 | 40 | [Test] 41 | public void TestPlayerStateTransitionsAtCorrectTime() 42 | { 43 | AddStep("mash air actions", () => Scheduler.AddDelayed(() => 44 | { 45 | InputManager.Click(MouseButton.Left); 46 | }, 50f, true)); 47 | 48 | AddAssert("not in fight state", () => targetLane != PlayerTargetLane.MiniBoss); 49 | AddUntilStep("wait for fight state", () => targetLane == PlayerTargetLane.MiniBoss); 50 | AddAssert("time has reached mini-boss time", () => Player.GameplayClockContainer.CurrentTime >= mini_boss_time); 51 | 52 | AddStep("stop mashing", () => Scheduler.CancelDelayedTasks()); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush.Tests/Visual/TestSceneOsuGame.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. 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.Rush.Tests.Visual 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 | AddGame(new OsuGame()); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush.Tests/Visual/TestSceneRushAutoplay.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. Licensed under the MIT Licence. 2 | // See the LICENCE file in the repository root for full licence text. 3 | 4 | namespace osu.Game.Rulesets.Rush.Tests.Visual 5 | { 6 | public partial class TestSceneRushAutoplay : TestSceneRushPlayer 7 | { 8 | protected override bool Autoplay => true; 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush.Tests/Visual/TestSceneRushPlayer.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. 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.Framework.Allocation; 6 | using osu.Framework.Bindables; 7 | using osu.Framework.Graphics; 8 | using osu.Game.Graphics.UserInterface; 9 | using osu.Game.Tests.Visual; 10 | 11 | namespace osu.Game.Rulesets.Rush.Tests.Visual 12 | { 13 | [TestFixture] 14 | public partial class TestSceneRushPlayer : PlayerTestScene 15 | { 16 | private readonly BindableBool pausedBindable = new BindableBool(); 17 | 18 | protected new RushPlayer Player => (RushPlayer)base.Player; 19 | 20 | protected override TestPlayer CreatePlayer(Ruleset ruleset) => new RushPlayer(); 21 | 22 | protected override Ruleset CreatePlayerRuleset() => new RushRuleset(); 23 | 24 | [BackgroundDependencyLoader] 25 | private void load() 26 | { 27 | Add(new OsuCheckbox 28 | { 29 | LabelText = "Pause", 30 | RelativeSizeAxes = Axes.None, 31 | AutoSizeAxes = Axes.Y, 32 | Width = 100, 33 | Origin = Anchor.TopLeft, 34 | Anchor = Anchor.TopLeft, 35 | Margin = new MarginPadding { Top = 40f, Left = 10f }, 36 | Depth = float.NegativeInfinity, 37 | Current = { BindTarget = pausedBindable } 38 | }); 39 | 40 | pausedBindable.ValueChanged += e => Player?.SetGameplayClockPaused(e.NewValue); 41 | } 42 | 43 | protected partial class RushPlayer : TestPlayer 44 | { 45 | public void SetGameplayClockPaused(bool value) 46 | { 47 | if (GameplayClockContainer.IsPaused.Value && !value) 48 | GameplayClockContainer.Start(); 49 | else if (!GameplayClockContainer.IsPaused.Value && value) 50 | GameplayClockContainer.Stop(); 51 | } 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush.Tests/VisualTestRunner.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. 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.Rush.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.Rush.Tests/osu.Game.Rulesets.Rush.Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | osu.Game.Rulesets.Rush.Tests.VisualTestRunner 4 | Debug;Release;Development 5 | AnyCPU 6 | 7 | 8 | 9 | 10 | 11 | false 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | WinExe 20 | net8.0 21 | 22 | 23 | true 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush.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.Rush", "osu.Game.Rulesets.Rush\osu.Game.Rulesets.Rush.csproj", "{5AE1F0F1-DAFA-46E7-959C-DA233B7C87E9}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "osu.Game.Rulesets.Rush.Tests", "osu.Game.Rulesets.Rush.Tests\osu.Game.Rulesets.Rush.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 | Development|Any CPU = Development|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}.Development|Any CPU.ActiveCfg = Development|Any CPU 22 | {5AE1F0F1-DAFA-46E7-959C-DA233B7C87E9}.Development|Any CPU.Build.0 = Development|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}.Development|Any CPU.ActiveCfg = Development|Any CPU 28 | {B4577C85-CB83-462A-BCE3-22FFEB16311D}.Development|Any CPU.Build.0 = Development|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.Rush/Beatmaps/RushBeatmap.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. 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.Graphics; 7 | using osu.Framework.Graphics.Sprites; 8 | using osu.Game.Beatmaps; 9 | using osu.Game.Rulesets.Rush.Objects; 10 | using osuTK; 11 | 12 | namespace osu.Game.Rulesets.Rush.Beatmaps 13 | { 14 | public class RushBeatmap : Beatmap 15 | { 16 | public override IEnumerable GetStatistics() 17 | { 18 | int minions = HitObjects.Count(s => s is Minion); 19 | int starsheets = HitObjects.Count(s => s is StarSheet); 20 | int sawblades = HitObjects.Count(s => s is Sawblade); 21 | int dualhits = HitObjects.Count(s => s is DualHit); 22 | int minibosses = HitObjects.Count(s => s is MiniBoss); 23 | int hearts = HitObjects.Count(s => s is Heart); 24 | 25 | return new[] 26 | { 27 | new BeatmapStatistic 28 | { 29 | Name = @"Minion Count", 30 | Content = minions.ToString(), 31 | CreateIcon = () => createIcon(FontAwesome.Regular.Angry), 32 | }, 33 | new BeatmapStatistic 34 | { 35 | Name = @"Star Sheet Count", 36 | Content = starsheets.ToString(), 37 | CreateIcon = () => createIcon(FontAwesome.Regular.Star), 38 | }, 39 | new BeatmapStatistic 40 | { 41 | Name = @"Dual Hit Count", 42 | Content = dualhits.ToString(), 43 | CreateIcon = () => createIcon(FontAwesome.Solid.Cog), 44 | }, 45 | new BeatmapStatistic 46 | { 47 | Name = @"Sawblade Count", 48 | Content = sawblades.ToString(), 49 | CreateIcon = () => createIcon(FontAwesome.Solid.Sun), 50 | }, 51 | new BeatmapStatistic 52 | { 53 | Name = @"Miniboss Count", 54 | Content = minibosses.ToString(), 55 | CreateIcon = () => createIcon(FontAwesome.Solid.Mitten), 56 | }, 57 | new BeatmapStatistic 58 | { 59 | Name = @"Heart Count", 60 | Content = hearts.ToString(), 61 | CreateIcon = () => createIcon(FontAwesome.Solid.Heart), 62 | } 63 | }; 64 | } 65 | 66 | private static Drawable createIcon(IconUsage icon) => new SpriteIcon { Icon = icon, Scale = new Vector2(0.7f) }; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Beatmaps/RushBeatmapConverter.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. 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 System.Threading; 8 | using osu.Game.Beatmaps; 9 | using osu.Game.Rulesets.Objects; 10 | 11 | namespace osu.Game.Rulesets.Rush.Beatmaps 12 | { 13 | /// 14 | /// Wraps and depending 15 | /// on whether the original beatmap contains a given tag. Once the lazer editor has been fleshed out enough 16 | /// to explicitly choose rulesets, this will be unnecessary. 17 | /// 18 | public class RushBeatmapConverter : IBeatmapConverter 19 | { 20 | public readonly IBeatmapConverter BackedConverter; 21 | public const string CRAFTED_TAG = "crafted"; 22 | 23 | public RushBeatmapConverter(IBeatmap beatmap, Ruleset ruleset) 24 | { 25 | bool crafted = !string.IsNullOrEmpty(beatmap.Metadata.Tags) 26 | && beatmap.Metadata.Tags 27 | .Split(" ") 28 | .Any(tag => tag.Equals(CRAFTED_TAG, StringComparison.OrdinalIgnoreCase)); 29 | 30 | BackedConverter = crafted 31 | ? (IBeatmapConverter)new RushCraftedBeatmapConverter(beatmap, ruleset) 32 | : new RushGeneratedBeatmapConverter(beatmap, ruleset); 33 | } 34 | 35 | public event Action> ObjectConverted 36 | { 37 | add => BackedConverter.ObjectConverted += value; 38 | remove => BackedConverter.ObjectConverted -= value; 39 | } 40 | 41 | public bool CanConvert() => BackedConverter.CanConvert(); 42 | public IBeatmap Convert(CancellationToken cancellationToken = default) => BackedConverter.Convert(cancellationToken); 43 | 44 | public IBeatmap Beatmap => BackedConverter.Beatmap; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Configuration/FeverActivationMode.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. Licensed under the MIT Licence. 2 | // See the LICENCE file in the repository root for full licence text. 3 | 4 | namespace osu.Game.Rulesets.Rush.Configuration 5 | { 6 | /// 7 | /// The activation mode of fever for gaining bonus score on hits. 8 | /// 9 | public enum FeverActivationMode 10 | { 11 | /// 12 | /// Automatically once the fever progress fills up. 13 | /// 14 | Automatic, 15 | 16 | /// 17 | /// Manually using the action. 18 | /// 19 | Manual, 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Configuration/RushRulesetConfigManager.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. Licensed under the MIT Licence. 2 | // See the LICENCE file in the repository root for full licence text. 3 | 4 | using osu.Game.Configuration; 5 | using osu.Game.Rulesets.Configuration; 6 | 7 | namespace osu.Game.Rulesets.Rush.Configuration 8 | { 9 | public class RushRulesetConfigManager : RulesetConfigManager 10 | { 11 | public RushRulesetConfigManager(SettingsStore settings, RulesetInfo ruleset, int? variant = null) 12 | : base(settings, ruleset, variant) 13 | { 14 | } 15 | 16 | protected override void InitialiseDefaults() 17 | { 18 | base.InitialiseDefaults(); 19 | 20 | SetDefault(RushRulesetSettings.FeverActivationMode, FeverActivationMode.Automatic); 21 | } 22 | } 23 | 24 | public enum RushRulesetSettings 25 | { 26 | FeverActivationMode 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Input/IKeyBindingTouchHandler.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. Licensed under the MIT Licence. 2 | // See the LICENCE file in the repository root for full licence text. 3 | 4 | using osuTK; 5 | 6 | namespace osu.Game.Rulesets.Rush.Input 7 | { 8 | public interface IKeyBindingTouchHandler 9 | { 10 | RushActionTarget ActionTargetForTouchPosition(Vector2 screenSpaceTouchPos) => RushActionTarget.None; 11 | } 12 | 13 | public enum RushActionTarget 14 | { 15 | None, 16 | Ground, 17 | Air, 18 | Fever, 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Input/RushInputManager.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. 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.ComponentModel; 6 | using osu.Framework.Extensions.ListExtensions; 7 | using osu.Framework.Input; 8 | using osu.Framework.Input.Bindings; 9 | using osu.Framework.Lists; 10 | using osu.Game.Rulesets.Rush.Objects; 11 | using osu.Game.Rulesets.Rush.Replays; 12 | using osu.Game.Rulesets.UI; 13 | using osuTK.Input; 14 | 15 | namespace osu.Game.Rulesets.Rush.Input 16 | { 17 | public partial class RushInputManager : RulesetInputManager 18 | { 19 | protected override bool MapMouseToLatestTouch => false; 20 | public new RushFramedReplayInputHandler ReplayInputHandler => (RushFramedReplayInputHandler)base.ReplayInputHandler; 21 | 22 | /// 23 | /// Retrieves all actions in a currenty pressed states. 24 | /// 25 | public SlimReadOnlyListWrapper PressedActions => KeyBindingContainer.PressedActions; 26 | 27 | public RushInputManager(RulesetInfo ruleset) 28 | : base(ruleset, 0, SimultaneousBindingMode.Unique) 29 | { 30 | } 31 | 32 | protected override MouseButtonEventManager CreateButtonEventManagerFor(MouseButton button) 33 | => new RushMouseEventManager(button, this); 34 | 35 | protected override TouchEventManager CreateButtonEventManagerFor(TouchSource source) 36 | => new RushTouchEventManager(source, this); 37 | 38 | 39 | private readonly Dictionary touchActionMap = new Dictionary(); 40 | 41 | private readonly Dictionary actionsInUse = new Dictionary(); 42 | 43 | private void updateActionsCache() 44 | { 45 | for (RushAction action = RushAction.GroundPrimary; action <= RushAction.Fever; ++action) 46 | actionsInUse[action] = false; 47 | 48 | foreach (var pressedAction in PressedActions) 49 | actionsInUse[pressedAction] = true; 50 | } 51 | 52 | private RushAction? tryGetGroundAction() => tryGetActionInRange(RushAction.GroundPrimary, RushAction.AirPrimary); 53 | private RushAction? tryGetAirAction() => tryGetActionInRange(RushAction.AirPrimary, RushAction.Fever); 54 | private RushAction? tryGetFeverAction() 55 | { 56 | actionsInUse.TryGetValue(RushAction.Fever, out var inUse); 57 | 58 | if (!inUse) return RushAction.Fever; 59 | 60 | return null; 61 | } 62 | private RushAction? tryGetActionInRange(RushAction lowerBound, RushAction upperBound) 63 | { 64 | for (RushAction a = lowerBound; a < upperBound; ++a) 65 | { 66 | actionsInUse.TryGetValue(a, out var inUse); 67 | 68 | if (!inUse) return a; 69 | } 70 | 71 | return null; 72 | } 73 | 74 | public bool TryPressTouchAction(TouchSource source, RushActionTarget action) 75 | { 76 | updateActionsCache(); 77 | RushAction? convertedAction = action switch 78 | { 79 | RushActionTarget.Ground => tryGetGroundAction(), 80 | RushActionTarget.Air => tryGetAirAction(), 81 | RushActionTarget.Fever => tryGetFeverAction(), 82 | _ => null 83 | }; 84 | 85 | if (convertedAction is null) return false; 86 | 87 | touchActionMap[source] = convertedAction.Value; 88 | KeyBindingContainer.TriggerPressed(convertedAction.Value); 89 | 90 | return true; 91 | } 92 | 93 | public void ReleaseTouchAction(TouchSource source) 94 | { 95 | if (!touchActionMap.TryGetValue(source, out var action)) return; 96 | // The action has already been released, maybe due to the same keyboard key being released before the touch releases. 97 | if (!PressedActions.Contains(action)) return; 98 | 99 | KeyBindingContainer.TriggerReleased(action); 100 | } 101 | } 102 | 103 | public enum RushAction 104 | { 105 | [Description("Ground (Primary)")] 106 | GroundPrimary = 0, 107 | 108 | [Description("Ground (Secondary)")] 109 | GroundSecondary = 1, 110 | 111 | [Description("Ground (Tertiary)")] 112 | GroundTertiary = 2, 113 | 114 | [Description("Ground (Quaternary)")] 115 | GroundQuaternary = 3, 116 | 117 | [Description("Air (Primary)")] 118 | AirPrimary = 4, 119 | 120 | [Description("Air (Secondary)")] 121 | AirSecondary = 5, 122 | 123 | [Description("Air (Tertiary)")] 124 | AirTertiary = 6, 125 | 126 | [Description("Air (Quaternary)")] 127 | AirQuaternary = 7, 128 | 129 | [Description("Activate fever")] 130 | Fever = 8, 131 | } 132 | 133 | public static class RushActionExtensions 134 | { 135 | public static bool IsLaneAction(this RushAction action) => action < RushAction.Fever; 136 | 137 | public static LanedHitLane Lane(this RushAction action) => action switch 138 | { 139 | RushAction.GroundPrimary => LanedHitLane.Ground, 140 | RushAction.GroundSecondary => LanedHitLane.Ground, 141 | RushAction.GroundTertiary => LanedHitLane.Ground, 142 | RushAction.GroundQuaternary => LanedHitLane.Ground, 143 | RushAction.AirPrimary => LanedHitLane.Air, 144 | RushAction.AirSecondary => LanedHitLane.Air, 145 | RushAction.AirTertiary => LanedHitLane.Air, 146 | RushAction.AirQuaternary => LanedHitLane.Air, 147 | _ => LanedHitLane.Ground 148 | }; 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Input/RushMouseEventManager.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. 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.Graphics; 7 | using osu.Framework.Input; 8 | using osu.Framework.Input.States; 9 | using osuTK; 10 | using osuTK.Input; 11 | 12 | namespace osu.Game.Rulesets.Rush.Input 13 | { 14 | // Temporarily exists to be as a testing convenience, will remove be PR merge 15 | public class RushMouseEventManager : MouseButtonEventManager 16 | { 17 | public override bool EnableClick => true; 18 | public override bool EnableDrag => false; 19 | public override bool ChangeFocusOnClick => false; 20 | 21 | private readonly RushInputManager rushInputManager; 22 | 23 | public RushMouseEventManager(MouseButton source, RushInputManager inputManager) 24 | : base(source) 25 | { 26 | rushInputManager = inputManager; 27 | } 28 | 29 | private IKeyBindingTouchHandler touchHandler; 30 | 31 | protected override Drawable HandleButtonDown(InputState state, List targets) 32 | { 33 | var result = base.HandleButtonDown(state, targets); 34 | touchHandler = targets.FirstOrDefault(d => d is IKeyBindingTouchHandler) as IKeyBindingTouchHandler; 35 | 36 | if (touchHandler != null) 37 | rushInputManager.TryPressTouchAction((TouchSource)Button, touchHandler.ActionTargetForTouchPosition(MouseDownPosition ?? Vector2.Zero)); 38 | 39 | return result; 40 | } 41 | 42 | protected override void HandleButtonUp(InputState state, List targets) 43 | { 44 | if (touchHandler != null) 45 | rushInputManager.ReleaseTouchAction((TouchSource)Button); 46 | 47 | touchHandler = null; 48 | 49 | base.HandleButtonUp(state, targets); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Input/RushTouchEventManager.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. 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.Graphics; 7 | using osu.Framework.Input; 8 | using osu.Framework.Input.States; 9 | 10 | namespace osu.Game.Rulesets.Rush.Input 11 | { 12 | public class RushTouchEventManager : TouchEventManager 13 | { 14 | private readonly RushInputManager rushInputManager; 15 | 16 | public RushTouchEventManager(TouchSource source, RushInputManager inputManager) 17 | : base(source) 18 | { 19 | rushInputManager = inputManager; 20 | } 21 | 22 | private IKeyBindingTouchHandler touchHandler; 23 | 24 | protected override Drawable HandleButtonDown(InputState state, List targets) 25 | { 26 | // This must be done first to ensure TouchDownPosition is set 27 | var result = base.HandleButtonDown(state, targets); 28 | 29 | touchHandler = targets.FirstOrDefault(d => d is IKeyBindingTouchHandler) as IKeyBindingTouchHandler; 30 | 31 | if (touchHandler != null) 32 | rushInputManager.TryPressTouchAction(Button, touchHandler.ActionTargetForTouchPosition(TouchDownPosition.Value)); 33 | 34 | return result; 35 | } 36 | 37 | protected override void HandleButtonUp(InputState state, List targets) 38 | { 39 | if (touchHandler != null) 40 | rushInputManager.ReleaseTouchAction(Button); 41 | 42 | touchHandler = null; 43 | base.HandleButtonUp(state, targets); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Judgements/CollisionDamagingJudgement.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. Licensed under the MIT Licence. 2 | // See the LICENCE file in the repository root for full licence text. 3 | 4 | using osu.Game.Rulesets.Scoring; 5 | 6 | namespace osu.Game.Rulesets.Rush.Judgements 7 | { 8 | /// 9 | /// A judgement that decreases the player health points when 10 | /// the player collides with the hit object without hitting it. 11 | /// 12 | public class CollisionDamagingJudgement : RushJudgement 13 | { 14 | protected override double HealthPointIncreaseFor(HitResult result, bool playerCollided) => 15 | result == MinResult && playerCollided ? -10.0 : 0.0; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Judgements/HeartJudgement.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. Licensed under the MIT Licence. 2 | // See the LICENCE file in the repository root for full licence text. 3 | 4 | using osu.Game.Rulesets.Scoring; 5 | 6 | namespace osu.Game.Rulesets.Rush.Judgements 7 | { 8 | public class HeartJudgement : RushJudgement 9 | { 10 | public override HitResult MaxResult => HitResult.SmallBonus; 11 | 12 | protected override double HealthPointIncreaseFor(HitResult result, bool collided) => 13 | result == MinResult && !collided ? 0.0 : 50.0; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Judgements/RushFeverJudgement.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. Licensed under the MIT Licence. 2 | // See the LICENCE file in the repository root for full licence text. 3 | 4 | using osu.Game.Rulesets.Scoring; 5 | 6 | namespace osu.Game.Rulesets.Rush.Judgements 7 | { 8 | public class RushFeverJudgement : RushJudgement 9 | { 10 | public override HitResult MaxResult => HitResult.LargeBonus; 11 | 12 | protected override double HealthPointIncreaseFor(HitResult result, bool collided) => 0; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Judgements/RushIgnoreJudgement.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. Licensed under the MIT Licence. 2 | // See the LICENCE file in the repository root for full licence text. 3 | 4 | using osu.Game.Rulesets.Scoring; 5 | 6 | namespace osu.Game.Rulesets.Rush.Judgements 7 | { 8 | public class RushIgnoreJudgement : RushJudgement 9 | { 10 | public override HitResult MaxResult => HitResult.IgnoreHit; 11 | 12 | protected override double HealthPointIncreaseFor(HitResult result, bool playerCollided) => 0.0; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Judgements/RushJudgement.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. 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.Game.Rulesets.Judgements; 6 | using osu.Game.Rulesets.Scoring; 7 | 8 | namespace osu.Game.Rulesets.Rush.Judgements 9 | { 10 | public class RushJudgement : Judgement 11 | { 12 | public override HitResult MaxResult => HitResult.Great; 13 | 14 | /// 15 | /// Retrieves the numeric health point increase of a . 16 | /// 17 | /// The to find the numeric health points increase for. 18 | public double HealthPointIncreaseFor(RushJudgementResult result) => HealthPointIncreaseFor(result.Type, result.PlayerCollided); 19 | 20 | /// 21 | /// Retrieves the numeric health point increase of a and whether the player collided. 22 | /// 23 | /// The to find the numeric health points increase for. 24 | /// Whether the player collided with the corresponding hit object at the point of judgement. 25 | /// The numeric health points increase of and . 26 | protected virtual double HealthPointIncreaseFor(HitResult result, bool playerCollided) => 0.0; 27 | 28 | // Temporary measure to prevent crashes due to HealthDisplay using this method 29 | // No miss animation though. 30 | protected sealed override double HealthIncreaseFor(HitResult result) => 0.0; 31 | // protected sealed override double HealthIncreaseFor(HitResult result) => throw new NotSupportedException($"Use the Rush!-specific version: {nameof(HealthPointIncreaseFor)}"); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Judgements/RushJudgementResult.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. Licensed under the MIT Licence. 2 | // See the LICENCE file in the repository root for full licence text. 3 | 4 | using osu.Game.Rulesets.Judgements; 5 | using osu.Game.Rulesets.Rush.Objects; 6 | 7 | namespace osu.Game.Rulesets.Rush.Judgements 8 | { 9 | public class RushJudgementResult : JudgementResult 10 | { 11 | /// 12 | /// The that was judged. 13 | /// 14 | public new RushHitObject HitObject => (RushHitObject)base.HitObject; 15 | 16 | /// 17 | /// The judgement which this applies for. 18 | /// 19 | public new RushJudgement Judgement => (RushJudgement)base.Judgement; 20 | 21 | /// 22 | /// The gathered amount of fever prior to this occurring. 23 | /// 24 | public float FeverProgressAtJudgement { get; set; } 25 | 26 | /// 27 | /// Whether the player has collided with the corresponding hit object at the point of judgement. 28 | /// 29 | public bool PlayerCollided; 30 | 31 | public RushJudgementResult(RushHitObject hitObject, RushJudgement judgement) 32 | : base(hitObject, judgement) 33 | { 34 | } 35 | 36 | public override string ToString() => $"{Type} (HP:{Judgement.HealthPointIncreaseFor(this)} {Judgement})"; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Judgements/RushTickJudgement.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. Licensed under the MIT Licence. 2 | // See the LICENCE file in the repository root for full licence text. 3 | 4 | using osu.Game.Rulesets.Scoring; 5 | 6 | namespace osu.Game.Rulesets.Rush.Judgements 7 | { 8 | public class RushTickJudgement : RushJudgement 9 | { 10 | public override HitResult MaxResult => HitResult.SmallTickHit; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Judgements/SawbladeJudgement.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. Licensed under the MIT Licence. 2 | // See the LICENCE file in the repository root for full licence text. 3 | 4 | using osu.Game.Rulesets.Scoring; 5 | 6 | namespace osu.Game.Rulesets.Rush.Judgements 7 | { 8 | public class SawbladeJudgement : RushJudgement 9 | { 10 | protected override double HealthPointIncreaseFor(HitResult result, bool playerCollided) 11 | { 12 | if (playerCollided) 13 | return -20.0; 14 | 15 | return 0.0; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Mods/RushModAutoplay.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. 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.Mods; 7 | using osu.Game.Rulesets.Rush.Replays; 8 | 9 | namespace osu.Game.Rulesets.Rush.Mods 10 | { 11 | public class RushModAutoplay : ModAutoplay 12 | { 13 | public override ModReplayData CreateReplayData(IBeatmap beatmap, IReadOnlyList mods) 14 | { 15 | return new ModReplayData(new RushAutoGenerator(beatmap).Generate(), new ModCreatedUser { Username = "Autoplay" }); 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Mods/RushModCinema.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. 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.Mods; 7 | using osu.Game.Rulesets.Rush.Objects; 8 | using osu.Game.Rulesets.Rush.Replays; 9 | 10 | namespace osu.Game.Rulesets.Rush.Mods 11 | { 12 | public class RushModCinema : ModCinema 13 | { 14 | public override ModReplayData CreateReplayData(IBeatmap beatmap, IReadOnlyList mods) 15 | { 16 | return new ModReplayData(new RushAutoGenerator(beatmap).Generate(), new ModCreatedUser { Username = "Autoplay" }); 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Mods/RushModDaycore.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. Licensed under the MIT Licence. 2 | // See the LICENCE file in the repository root for full licence text. 3 | 4 | using osu.Game.Rulesets.Mods; 5 | 6 | namespace osu.Game.Rulesets.Rush.Mods 7 | { 8 | public class RushModDaycore : ModDaycore 9 | { 10 | public override double ScoreMultiplier => 0.3; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Mods/RushModDoubleTime.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. Licensed under the MIT Licence. 2 | // See the LICENCE file in the repository root for full licence text. 3 | 4 | using osu.Game.Rulesets.Mods; 5 | 6 | namespace osu.Game.Rulesets.Rush.Mods 7 | { 8 | public class RushModDoubleTime : ModDoubleTime 9 | { 10 | public override double ScoreMultiplier => 1.12; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Mods/RushModFlashlight.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. Licensed under the MIT Licence. 2 | // See the LICENCE file in the repository root for full licence text. 3 | 4 | using osu.Framework.Bindables; 5 | using osu.Framework.Graphics; 6 | using osu.Framework.Layout; 7 | using osu.Game.Configuration; 8 | using osu.Game.Rulesets.Mods; 9 | using osu.Game.Rulesets.Rush.Objects; 10 | using osu.Game.Rulesets.Rush.UI; 11 | using osu.Game.Rulesets.UI; 12 | using osuTK; 13 | 14 | namespace osu.Game.Rulesets.Rush.Mods 15 | { 16 | public partial class RushModFlashlight : ModFlashlight 17 | { 18 | public override double ScoreMultiplier => 1.12; 19 | 20 | public override float DefaultFlashlightSize => 330; 21 | 22 | [SettingSource("Flashlight size", "Multiplier applied to the default flashlight size.")] 23 | public override BindableFloat SizeMultiplier { get; } = new BindableFloat 24 | { 25 | MinValue = 0.5f, 26 | MaxValue = 1.5f, 27 | Default = 1f, 28 | Value = 1f, 29 | Precision = 0.1f 30 | }; 31 | 32 | [SettingSource("Change size based on combo", "Decrease the flashlight size as combo increases.")] 33 | public override BindableBool ComboBasedSize { get; } = new BindableBool 34 | { 35 | Default = true, 36 | Value = true 37 | }; 38 | 39 | protected override Flashlight CreateFlashlight() => new RushFlashlight(this, playfield); 40 | 41 | private RushPlayfield playfield; 42 | 43 | public override void ApplyToDrawableRuleset(DrawableRuleset drawableRuleset) 44 | { 45 | playfield = (RushPlayfield)drawableRuleset.Playfield; 46 | base.ApplyToDrawableRuleset(drawableRuleset); 47 | } 48 | 49 | private partial class RushFlashlight : Flashlight 50 | { 51 | private readonly LayoutValue flashlightProperties = new LayoutValue(Invalidation.DrawSize); 52 | 53 | private readonly RushPlayfield rushPlayfield; 54 | 55 | public RushFlashlight(ModFlashlight modFlashlight, RushPlayfield rushPlayfield) : base(modFlashlight) 56 | { 57 | this.rushPlayfield = rushPlayfield; 58 | FlashlightSize = new Vector2(0, GetSize()); 59 | 60 | AddLayout(flashlightProperties); 61 | } 62 | 63 | protected override void UpdateFlashlightSize(float size) 64 | { 65 | this.TransformTo(nameof(FlashlightSize), new Vector2(0, size), FLASHLIGHT_FADE_DURATION); 66 | } 67 | 68 | protected override string FragmentShader => "CircularFlashlight"; 69 | 70 | protected override void Update() 71 | { 72 | base.Update(); 73 | 74 | if (!flashlightProperties.IsValid) 75 | { 76 | var flashlightPosition = rushPlayfield.OverPlayerEffectsContainer.ToSpaceOfOtherDrawable(rushPlayfield.OverPlayerEffectsContainer.OriginPosition, this); 77 | flashlightPosition.X += RushPlayfield.HIT_TARGET_OFFSET; 78 | FlashlightPosition = flashlightPosition; 79 | flashlightProperties.Validate(); 80 | } 81 | } 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Mods/RushModHalfTime.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. Licensed under the MIT Licence. 2 | // See the LICENCE file in the repository root for full licence text. 3 | 4 | using osu.Game.Rulesets.Mods; 5 | 6 | namespace osu.Game.Rulesets.Rush.Mods 7 | { 8 | public class RushModHalfTime : ModHalfTime 9 | { 10 | public override double ScoreMultiplier => 0.3; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Mods/RushModNightcore.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. Licensed under the MIT Licence. 2 | // See the LICENCE file in the repository root for full licence text. 3 | 4 | using osu.Game.Rulesets.Mods; 5 | using osu.Game.Rulesets.Rush.Objects; 6 | 7 | namespace osu.Game.Rulesets.Rush.Mods 8 | { 9 | public class RushModNightcore : ModNightcore 10 | { 11 | public override double ScoreMultiplier => 1.12; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Mods/RushModNoFail.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. Licensed under the MIT Licence. 2 | // See the LICENCE file in the repository root for full licence text. 3 | 4 | using osu.Game.Rulesets.Mods; 5 | 6 | namespace osu.Game.Rulesets.Rush.Mods 7 | { 8 | public class RushModNoFail : ModNoFail 9 | { 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Mods/RushModPerfect.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. Licensed under the MIT Licence. 2 | // See the LICENCE file in the repository root for full licence text. 3 | 4 | using osu.Game.Rulesets.Mods; 5 | 6 | namespace osu.Game.Rulesets.Rush.Mods 7 | { 8 | public class RushModPerfect : ModPerfect 9 | { 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Mods/RushModSuddenDeath.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. Licensed under the MIT Licence. 2 | // See the LICENCE file in the repository root for full licence text. 3 | 4 | using osu.Game.Rulesets.Mods; 5 | 6 | namespace osu.Game.Rulesets.Rush.Mods 7 | { 8 | public class RushModSuddenDeath : ModSuddenDeath 9 | { 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Objects/Drawables/DrawableDualHit.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. Licensed under the MIT Licence. 2 | // See the LICENCE file in the repository root for full licence text. 3 | 4 | using osu.Framework.Graphics; 5 | using osu.Framework.Graphics.Containers; 6 | using osu.Framework.Input.Events; 7 | using osu.Game.Rulesets.Objects; 8 | using osu.Game.Rulesets.Objects.Drawables; 9 | using osu.Game.Rulesets.Rush.Input; 10 | using osu.Game.Rulesets.Rush.Objects.Drawables.Pieces; 11 | 12 | namespace osu.Game.Rulesets.Rush.Objects.Drawables 13 | { 14 | public partial class DrawableDualHit : DrawableRushHitObject 15 | { 16 | private readonly Container airHitContainer; 17 | private readonly Container groundHitContainer; 18 | private readonly DualHitJoinPiece skinnedJoin; 19 | 20 | public DrawableDualHitPart Air => airHitContainer.Child; 21 | public DrawableDualHitPart Ground => groundHitContainer.Child; 22 | 23 | public override bool DisplayResult => false; 24 | 25 | public DrawableDualHit() 26 | : this(null) 27 | { 28 | } 29 | 30 | public DrawableDualHit(DualHit hitObject) 31 | : base(hitObject) 32 | { 33 | RelativeSizeAxes = Axes.Y; 34 | Height = 1f; 35 | 36 | AddRangeInternal(new Drawable[] 37 | { 38 | skinnedJoin = new DualHitJoinPiece(), 39 | airHitContainer = new Container { Anchor = Anchor.TopCentre }, 40 | groundHitContainer = new Container { Anchor = Anchor.BottomCentre }, 41 | }); 42 | } 43 | 44 | protected override void AddNestedHitObject(DrawableHitObject hitObject) 45 | { 46 | base.AddNestedHitObject(hitObject); 47 | 48 | switch (hitObject) 49 | { 50 | case DrawableDualHitPart part: 51 | (part.HitObject.Lane == LanedHitLane.Air ? airHitContainer : groundHitContainer).Add(part); 52 | break; 53 | } 54 | } 55 | 56 | protected override void ClearNestedHitObjects() 57 | { 58 | base.ClearNestedHitObjects(); 59 | airHitContainer.Clear(false); 60 | groundHitContainer.Clear(false); 61 | } 62 | 63 | protected override DrawableHitObject CreateNestedHitObject(HitObject hitObject) 64 | { 65 | switch (hitObject) 66 | { 67 | case DualHitPart part: 68 | return new DrawableDualHitPart(part) { CheckHittable = CheckHittable }; 69 | } 70 | 71 | return base.CreateNestedHitObject(hitObject); 72 | } 73 | 74 | protected override void UpdateInitialTransforms() 75 | { 76 | base.UpdateInitialTransforms(); 77 | 78 | skinnedJoin.Show(); 79 | } 80 | 81 | // Input are handled by the DualHit parts, since they still act like normal minions 82 | public override bool OnPressed(KeyBindingPressEvent e) => false; 83 | 84 | protected override void CheckForResult(bool userTriggered, double timeOffset) 85 | { 86 | if (AllJudged) return; 87 | 88 | // We can judge this object the instant the nested objects are judged 89 | if (Air.AllJudged && Ground.AllJudged) 90 | ApplyResult((Air.IsHit && Ground.IsHit) ? Result.Judgement.MaxResult : Result.Judgement.MinResult); 91 | } 92 | 93 | protected override void UpdateHitStateTransforms(ArmedState state) 94 | { 95 | const float animation_time = 300f; 96 | 97 | switch (state) 98 | { 99 | case ArmedState.Miss: 100 | this.FadeOut(animation_time); 101 | break; 102 | 103 | case ArmedState.Hit: 104 | skinnedJoin.Hide(); 105 | this.FadeOut(animation_time); 106 | break; 107 | } 108 | } 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Objects/Drawables/DrawableDualHitPart.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. Licensed under the MIT Licence. 2 | // See the LICENCE file in the repository root for full licence text. 3 | 4 | using osu.Framework.Extensions.Color4Extensions; 5 | using osu.Framework.Graphics; 6 | using osu.Game.Rulesets.Objects.Drawables; 7 | using osu.Game.Rulesets.Rush.Objects.Drawables.Pieces; 8 | using osu.Game.Rulesets.Rush.UI; 9 | using osuTK; 10 | using osuTK.Graphics; 11 | 12 | namespace osu.Game.Rulesets.Rush.Objects.Drawables 13 | { 14 | public partial class DrawableDualHitPart : DrawableLanedHit 15 | { 16 | public override bool DisplayExplosion => true; 17 | 18 | public DrawableDualHitPart() 19 | : this(null) 20 | { 21 | } 22 | 23 | public DrawableDualHitPart(DualHitPart hitObject) 24 | : base(hitObject) 25 | { 26 | Size = new Vector2(RushPlayfield.HIT_TARGET_SIZE); 27 | 28 | AddInternal(new DualHitPartPiece()); 29 | } 30 | 31 | public new bool UpdateResult(bool userTriggered) => base.UpdateResult(userTriggered); 32 | 33 | protected override void UpdateHitStateTransforms(ArmedState state) 34 | { 35 | const float animation_time = 300f; 36 | 37 | switch (state) 38 | { 39 | case ArmedState.Miss: 40 | this.FadeColour(Color4.DarkGray.Darken(0.9f), 100); 41 | break; 42 | 43 | case ArmedState.Hit: 44 | float travelY = 400f * (HitObject.Lane == LanedHitLane.Air ? -1 : 1); 45 | 46 | this.MoveToY(travelY, animation_time, Easing.Out); 47 | this.FadeOut(animation_time); 48 | 49 | break; 50 | } 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Objects/Drawables/DrawableFeverBonus.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. 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.Game.Rulesets.Judgements; 6 | using osu.Game.Rulesets.Scoring; 7 | 8 | namespace osu.Game.Rulesets.Rush.Objects.Drawables 9 | { 10 | public partial class DrawableFeverBonus : DrawableRushHitObject 11 | { 12 | public override bool DisplayExplosion => false; 13 | public override bool DisplayResult => false; 14 | 15 | public DrawableFeverBonus() 16 | : this(null) 17 | { 18 | } 19 | 20 | public DrawableFeverBonus(FeverBonus hitObject) 21 | : base(hitObject) 22 | { 23 | } 24 | 25 | public new void ApplyResult(HitResult result) 26 | { 27 | if (!Result.HasResult) 28 | base.ApplyResult(result); 29 | } 30 | 31 | protected override void CheckForResult(bool userTriggered, double timeOffset) 32 | { 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Objects/Drawables/DrawableHeart.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. 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.Game.Rulesets.Rush.Objects.Drawables.Pieces; 7 | using osu.Game.Rulesets.Rush.UI; 8 | using osu.Game.Rulesets.Scoring; 9 | using osuTK; 10 | 11 | namespace osu.Game.Rulesets.Rush.Objects.Drawables 12 | { 13 | public partial class DrawableHeart : DrawableLanedHit 14 | { 15 | [Resolved] 16 | private RushPlayfield playfield { get; set; } 17 | 18 | public override bool DisplayResult => false; 19 | public override bool DisplayExplosion => true; 20 | protected override float LifetimeEndDelay => 0f; 21 | protected override bool ExpireOnHit => false; 22 | 23 | public DrawableHeart() 24 | : this(null) 25 | { 26 | } 27 | 28 | public DrawableHeart(Heart hitObject) 29 | : base(hitObject) 30 | { 31 | Size = new Vector2(RushPlayfield.HIT_TARGET_SIZE * 2f); 32 | 33 | AddInternal(new ActionBeatSyncedContainer 34 | { 35 | Origin = Anchor.Centre, 36 | Anchor = Anchor.Centre, 37 | RelativeSizeAxes = Axes.Both, 38 | Size = new Vector2(0.4f), 39 | NewBeat = (b, t, e, a) => this.ScaleTo(1.5f).Then().ScaleTo(1f, t.BeatLength, Easing.Out), 40 | Child = new HeartPiece 41 | { 42 | RelativeSizeAxes = Axes.Both, 43 | } 44 | }); 45 | } 46 | 47 | protected override void CheckForResult(bool userTriggered, double timeOffset) 48 | { 49 | if (AllJudged) 50 | return; 51 | 52 | var result = HitObject.HitWindows.ResultFor(timeOffset); 53 | 54 | if (userTriggered) 55 | { 56 | if (result != HitResult.None) 57 | ApplyResult(Result.Judgement.MaxResult); 58 | 59 | return; 60 | } 61 | 62 | // if we haven't passed the hitobject time, do nothing 63 | if (timeOffset < 0) 64 | return; 65 | 66 | // if we've passed the object and can longer hit it, miss 67 | if (result == HitResult.None) 68 | ApplyResult(Result.Judgement.MinResult); 69 | 70 | // else if we're still able to hit it, check if the player is in the correct lane 71 | else if (playfield.PlayerSprite.CollidesWith(HitObject)) 72 | ApplyResult(Result.Judgement.MaxResult); 73 | } 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Objects/Drawables/DrawableLanedHit.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. Licensed under the MIT Licence. 2 | // See the LICENCE file in the repository root for full licence text. 3 | 4 | using System.Diagnostics; 5 | using osu.Framework.Allocation; 6 | using osu.Framework.Bindables; 7 | using osu.Framework.Graphics; 8 | using osu.Framework.Input.Events; 9 | using osu.Game.Rulesets.Objects.Drawables; 10 | using osu.Game.Rulesets.Rush.Input; 11 | using osu.Game.Rulesets.Scoring; 12 | using osu.Game.Rulesets.UI.Scrolling; 13 | using osuTK.Graphics; 14 | 15 | namespace osu.Game.Rulesets.Rush.Objects.Drawables 16 | { 17 | [Cached(typeof(IDrawableLanedHit))] 18 | public partial class DrawableLanedHit : DrawableRushHitObject, IDrawableLanedHit 19 | where TLanedHit : LanedHit 20 | { 21 | public virtual Color4 LaneAccentColour => HitObject.Lane == LanedHitLane.Air ? AIR_ACCENT_COLOUR : GROUND_ACCENT_COLOUR; 22 | 23 | public Anchor LaneAnchor => Direction.Value == ScrollingDirection.Left ? Anchor.CentreLeft : Anchor.CentreRight; 24 | 25 | public Anchor LeadingAnchor => Direction.Value == ScrollingDirection.Left ? Anchor.CentreLeft : Anchor.CentreRight; 26 | 27 | public Anchor TrailingAnchor => Direction.Value == ScrollingDirection.Left ? Anchor.CentreRight : Anchor.CentreLeft; 28 | 29 | public LanedHitLane Lane { get; set; } 30 | 31 | public DrawableLanedHit() 32 | : base(null) 33 | { 34 | } 35 | 36 | public DrawableLanedHit(TLanedHit hitObject) 37 | : base(hitObject) 38 | { 39 | } 40 | 41 | protected override void OnApply() 42 | { 43 | base.OnApply(); 44 | 45 | Lane = HitObject.Lane; 46 | Anchor = LaneAnchor; 47 | AccentColour.Value = LaneAccentColour; 48 | } 49 | 50 | protected override void OnDirectionChanged(ValueChangedEvent e) 51 | { 52 | base.OnDirectionChanged(e); 53 | 54 | if (HitObject != null) 55 | Anchor = LaneAnchor; 56 | } 57 | 58 | public override bool OnPressed(KeyBindingPressEvent e) 59 | { 60 | if (!e.Action.IsLaneAction()) 61 | return false; 62 | 63 | if (!LaneMatchesAction(e.Action) || AllJudged) 64 | return false; 65 | 66 | if (!CheckHittable(this)) 67 | return false; 68 | 69 | return UpdateResult(true); 70 | } 71 | 72 | public virtual bool LaneMatchesAction(RushAction action) => action.Lane() == HitObject.Lane; 73 | 74 | protected override void CheckForResult(bool userTriggered, double timeOffset) 75 | { 76 | Debug.Assert(HitObject.HitWindows != null); 77 | 78 | if (!userTriggered) 79 | { 80 | if (!HitObject.HitWindows.CanBeHit(timeOffset)) 81 | ApplyResult(Result.Judgement.MinResult); 82 | return; 83 | } 84 | 85 | var result = HitObject.HitWindows.ResultFor(timeOffset); 86 | if (result == HitResult.None) 87 | return; 88 | 89 | ApplyResult(result); 90 | } 91 | 92 | protected override void UpdateHitStateTransforms(ArmedState state) 93 | { 94 | base.UpdateHitStateTransforms(state); 95 | 96 | switch (state) 97 | { 98 | case ArmedState.Miss: 99 | AccentColour.Value = Color4.Gray; 100 | break; 101 | } 102 | } 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Objects/Drawables/DrawableMiniBoss.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. 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.Linq; 6 | using osu.Framework.Graphics; 7 | using osu.Framework.Graphics.Containers; 8 | using osu.Framework.Input.Events; 9 | using osu.Game.Rulesets.Objects; 10 | using osu.Game.Rulesets.Objects.Drawables; 11 | using osu.Game.Rulesets.Rush.Input; 12 | using osu.Game.Rulesets.Rush.Objects.Drawables.Pieces; 13 | using osu.Game.Rulesets.Scoring; 14 | using osuTK; 15 | 16 | namespace osu.Game.Rulesets.Rush.Objects.Drawables 17 | { 18 | public partial class DrawableMiniBoss : DrawableRushHitObject 19 | { 20 | private const float base_sprite_scale = 1f; 21 | private const float target_sprite_scale = 1.1f; 22 | 23 | private readonly MiniBossPiece mainPiece; 24 | 25 | private readonly Container ticks; 26 | 27 | public event Action Attacked; 28 | 29 | public DrawableMiniBoss() 30 | : this(null) 31 | { 32 | } 33 | 34 | public DrawableMiniBoss(MiniBoss hitObject) 35 | : base(hitObject) 36 | { 37 | Origin = Anchor.Centre; 38 | 39 | AddRangeInternal(new Drawable[] 40 | { 41 | mainPiece = new MiniBossPiece() 42 | { 43 | Origin = Anchor.Centre, 44 | Anchor = Anchor.Centre 45 | }, 46 | ticks = new Container { RelativeSizeAxes = Axes.Both } 47 | }); 48 | } 49 | 50 | protected override void AddNestedHitObject(DrawableHitObject hitObject) 51 | { 52 | base.AddNestedHitObject(hitObject); 53 | 54 | switch (hitObject) 55 | { 56 | case DrawableMiniBossTick tick: 57 | ticks.Add(tick); 58 | break; 59 | } 60 | } 61 | 62 | protected override void ClearNestedHitObjects() 63 | { 64 | base.ClearNestedHitObjects(); 65 | ticks.Clear(false); 66 | } 67 | 68 | protected override DrawableHitObject CreateNestedHitObject(HitObject hitObject) 69 | { 70 | switch (hitObject) 71 | { 72 | case MiniBossTick tick: 73 | return new DrawableMiniBossTick(tick); 74 | } 75 | 76 | return base.CreateNestedHitObject(hitObject); 77 | } 78 | 79 | protected override void Update() 80 | { 81 | base.Update(); 82 | 83 | float fraction = (float)(HitObject.StartTime - Clock.CurrentTime) / 500f; 84 | mainPiece.Y = (float)(Math.Sin(fraction * 2 * Math.PI) * 5f); 85 | 86 | X = Math.Max(0, X); 87 | } 88 | 89 | protected override void UpdateInitialTransforms() 90 | { 91 | mainPiece.Scale = new Vector2(base_sprite_scale); 92 | } 93 | 94 | public override bool OnPressed(KeyBindingPressEvent e) => e.Action.IsLaneAction() && UpdateResult(true); 95 | 96 | protected override void CheckForResult(bool userTriggered, double timeOffset) 97 | { 98 | if (Time.Current < HitObject.StartTime || AllJudged) 99 | return; 100 | 101 | if (userTriggered && timeOffset < 0) 102 | { 103 | var nextTick = ticks.FirstOrDefault(t => !t.IsHit); 104 | nextTick?.TriggerResult(nextTick.Result.Judgement.MaxResult); 105 | 106 | var numHits = ticks.Count(r => r.IsHit); 107 | var completion = (float)numHits / HitObject.RequiredHits; 108 | 109 | mainPiece.ScaleTo(base_sprite_scale + Math.Min(target_sprite_scale - base_sprite_scale, (target_sprite_scale - base_sprite_scale) * completion), 260, Easing.OutQuint); 110 | 111 | OnAttacked(this, timeOffset); 112 | } 113 | else if (!userTriggered && timeOffset >= 0) 114 | { 115 | int numHits = 0; 116 | 117 | foreach (var tick in ticks) 118 | { 119 | if (tick.IsHit) 120 | { 121 | numHits++; 122 | continue; 123 | } 124 | 125 | tick.TriggerResult(tick.Result.Judgement.MinResult); 126 | } 127 | 128 | var hitResult = numHits == HitObject.RequiredHits 129 | ? HitResult.Great 130 | : numHits > HitObject.RequiredHits / 2 131 | ? HitResult.Good 132 | : HitResult.Miss; 133 | 134 | ApplyResult(hitResult); 135 | } 136 | } 137 | 138 | protected override void UpdateHitStateTransforms(ArmedState state) 139 | { 140 | switch (state) 141 | { 142 | case ArmedState.Miss: 143 | this.FadeOut(300); 144 | break; 145 | 146 | case ArmedState.Hit: 147 | const float gravity_time = 300; 148 | const float gravity_travel_height = 500f; 149 | 150 | using (BeginAbsoluteSequence(Time.Current, true)) 151 | { 152 | this.RotateTo(-180, gravity_time); 153 | this.MoveToY(-gravity_travel_height, gravity_time, Easing.Out); 154 | this.FadeOut(gravity_time); 155 | } 156 | 157 | break; 158 | } 159 | } 160 | 161 | protected virtual void OnAttacked(DrawableMiniBoss drawableMiniBoss, double timeOffset) => Attacked?.Invoke(drawableMiniBoss, timeOffset); 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Objects/Drawables/DrawableMiniBossTick.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. Licensed under the MIT Licence. 2 | // See the LICENCE file in the repository root for full licence text. 3 | 4 | using osu.Framework.Graphics; 5 | using osu.Framework.Input.Events; 6 | using osu.Game.Rulesets.Rush.Input; 7 | using osu.Game.Rulesets.Scoring; 8 | 9 | namespace osu.Game.Rulesets.Rush.Objects.Drawables 10 | { 11 | public partial class DrawableMiniBossTick : DrawableRushHitObject 12 | { 13 | public override bool DisplayResult => false; 14 | 15 | public DrawableMiniBossTick() 16 | : this(null) 17 | { 18 | } 19 | 20 | public DrawableMiniBossTick(MiniBossTick hitObject) 21 | : base(hitObject) 22 | { 23 | } 24 | 25 | protected override void UpdateInitialTransforms() => this.FadeOut(); 26 | 27 | public void TriggerResult(HitResult type) 28 | { 29 | HitObject.StartTime = Time.Current; 30 | ApplyResult(type); 31 | } 32 | 33 | protected override void CheckForResult(bool userTriggered, double timeOffset) 34 | { 35 | } 36 | 37 | public override bool OnPressed(KeyBindingPressEvent e) => false; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Objects/Drawables/DrawableMinion.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. 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.Allocation; 6 | using osu.Framework.Extensions.Color4Extensions; 7 | using osu.Framework.Graphics; 8 | using osu.Game.Rulesets.Objects.Drawables; 9 | using osu.Game.Rulesets.Rush.Objects.Drawables.Pieces; 10 | using osu.Game.Rulesets.Rush.UI; 11 | using osuTK; 12 | using osuTK.Graphics; 13 | 14 | namespace osu.Game.Rulesets.Rush.Objects.Drawables 15 | { 16 | public partial class DrawableMinion : DrawableLanedHit 17 | { 18 | protected virtual RushSkinComponents Component => RushSkinComponents.Minion; 19 | 20 | private readonly Drawable minionPiece; 21 | 22 | private readonly Random random = new Random(); 23 | 24 | [Resolved] 25 | private RushPlayfield playfield { get; set; } 26 | 27 | public override bool DisplayExplosion => true; 28 | 29 | public DrawableMinion() 30 | : this(null) 31 | { 32 | } 33 | 34 | public DrawableMinion(Minion hitObject = null) 35 | : base(hitObject) 36 | { 37 | Size = new Vector2(RushPlayfield.HIT_TARGET_SIZE); 38 | 39 | AddInternal(minionPiece = new MinionPiece() 40 | { 41 | RelativeSizeAxes = Axes.Both 42 | }); 43 | } 44 | 45 | protected override void Update() 46 | { 47 | base.Update(); 48 | 49 | float fraction = (float)(HitObject.StartTime - Clock.CurrentTime) / 500f; 50 | minionPiece.Y = (float)(Math.Sin(fraction * 2 * Math.PI) * (HitObject.Lane == LanedHitLane.Air ? 5f : 3f)); 51 | } 52 | 53 | protected override void UpdateHitStateTransforms(ArmedState state) 54 | { 55 | base.UpdateHitStateTransforms(state); 56 | 57 | switch (state) 58 | { 59 | case ArmedState.Miss: 60 | this.FadeColour(Color4.DarkGray.Darken(0.9f), 100); 61 | break; 62 | 63 | case ArmedState.Hit: 64 | const float gravity_time = 300; 65 | float randomness = -0.5f + (float)random.NextDouble(); 66 | float rotation = -180 + randomness * 50f; 67 | float gravityTravelHeight = randomness * 50f + (HitObject.Lane == LanedHitLane.Air ? 500f : 400f); 68 | 69 | this.RotateTo(rotation, gravity_time); 70 | this.MoveToY(-gravityTravelHeight, gravity_time, Easing.Out) 71 | .Then() 72 | .MoveToY(gravityTravelHeight * 2, gravity_time * 2, Easing.In); 73 | 74 | this.FadeOut(300); 75 | break; 76 | } 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Objects/Drawables/DrawableRushHitObject.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. Licensed under the MIT Licence. 2 | // See the LICENCE file in the repository root for full licence text. 3 | 4 | using System; 5 | using JetBrains.Annotations; 6 | using osu.Framework.Allocation; 7 | using osu.Framework.Bindables; 8 | using osu.Framework.Graphics; 9 | using osu.Framework.Graphics.Containers; 10 | using osu.Framework.Graphics.Primitives; 11 | using osu.Framework.Input.Bindings; 12 | using osu.Framework.Input.Events; 13 | using osu.Game.Rulesets.Judgements; 14 | using osu.Game.Rulesets.Objects; 15 | using osu.Game.Rulesets.Objects.Drawables; 16 | using osu.Game.Rulesets.Rush.Input; 17 | using osu.Game.Rulesets.Rush.Judgements; 18 | using osu.Game.Rulesets.Rush.UI; 19 | using osu.Game.Rulesets.Rush.UI.Fever; 20 | using osu.Game.Rulesets.Scoring; 21 | using osu.Game.Rulesets.UI.Scrolling; 22 | using osuTK.Graphics; 23 | 24 | namespace osu.Game.Rulesets.Rush.Objects.Drawables 25 | { 26 | public abstract partial class DrawableRushHitObject : DrawableHitObject, IKeyBindingHandler 27 | { 28 | public static readonly Color4 AIR_ACCENT_COLOUR = new Color4(0.35f, 0.75f, 1f, 1f); 29 | public static readonly Color4 GROUND_ACCENT_COLOUR = new Color4(1f, 0.4f, 1f, 1f); 30 | public static readonly float LIFETIME_END_DELAY = 500f; 31 | 32 | public Func CheckHittable; 33 | 34 | protected readonly IBindable Direction = new Bindable(); 35 | 36 | protected override bool ComputeIsMaskedAway(RectangleF maskingBounds) => false; 37 | 38 | protected RushInputManager ActionInputManager => (RushInputManager)GetContainingInputManager(); 39 | 40 | /// 41 | /// Whether to display an explosion when this hit object is hit. 42 | /// 43 | public virtual bool DisplayExplosion => false; 44 | 45 | protected virtual bool ExpireOnHit => true; 46 | protected virtual bool ExpireOnMiss => false; 47 | protected virtual float LifetimeEndDelay => LIFETIME_END_DELAY; 48 | 49 | [Resolved] 50 | private DrawableRushRuleset drawableRuleset { get; set; } 51 | 52 | [Resolved] 53 | private FeverProcessor feverProcessor { get; set; } 54 | 55 | private readonly Container feverBonusContainer; 56 | 57 | protected DrawableRushHitObject(RushHitObject hitObject) 58 | : base(hitObject) 59 | { 60 | AddInternal(feverBonusContainer = new Container()); 61 | } 62 | 63 | [BackgroundDependencyLoader(true)] 64 | private void load([NotNull] IScrollingInfo scrollingInfo) 65 | { 66 | Direction.BindTo(scrollingInfo.Direction); 67 | Direction.BindValueChanged(OnDirectionChanged, true); 68 | } 69 | 70 | protected virtual void OnDirectionChanged(ValueChangedEvent e) 71 | { 72 | Origin = Anchor.Centre; 73 | Anchor = e.NewValue == ScrollingDirection.Left ? Anchor.CentreLeft : Anchor.CentreRight; 74 | } 75 | 76 | protected override void CheckForResult(bool userTriggered, double timeOffset) 77 | { 78 | if (timeOffset >= 0) 79 | ApplyResult(Result.Judgement.MaxResult); 80 | } 81 | 82 | public virtual bool OnPressed(KeyBindingPressEvent e) => false; 83 | 84 | public virtual void OnReleased(KeyBindingReleaseEvent e) 85 | { 86 | } 87 | 88 | protected override void UpdateHitStateTransforms(ArmedState state) 89 | { 90 | switch (state) 91 | { 92 | case ArmedState.Miss: 93 | AccentColour.Value = Color4.Gray; 94 | 95 | if (!ExpireOnMiss) 96 | LifetimeEnd = HitObject.GetEndTime() + LifetimeEndDelay; 97 | 98 | break; 99 | 100 | case ArmedState.Hit: 101 | if (!ExpireOnHit) 102 | LifetimeEnd = HitObject.GetEndTime() + LifetimeEndDelay; 103 | 104 | break; 105 | } 106 | } 107 | 108 | protected override JudgementResult CreateResult(Judgement judgement) => new RushJudgementResult(HitObject, (RushJudgement)judgement); 109 | 110 | protected new void ApplyResult(HitResult result) 111 | { 112 | // This is the only point to correctly apply values to the judgement 113 | // result in correct time, check whether the player collided now. 114 | var r = (RushJudgementResult)Result; 115 | r.PlayerCollided = drawableRuleset.PlayerCollidesWith(r.HitObject); 116 | 117 | base.ApplyResult(result); 118 | 119 | foreach (var bonus in feverBonusContainer) 120 | { 121 | bool eligible = IsHit && feverProcessor.InFeverMode.Value; 122 | bonus.ApplyResult(eligible ? bonus.Result.Judgement.MaxResult : bonus.Result.Judgement.MinResult); 123 | } 124 | } 125 | 126 | protected override DrawableHitObject CreateNestedHitObject(HitObject hitObject) 127 | { 128 | if (hitObject is FeverBonus x) 129 | return new DrawableFeverBonus(x); 130 | 131 | return base.CreateNestedHitObject(hitObject); 132 | } 133 | 134 | protected override void AddNestedHitObject(DrawableHitObject hitObject) 135 | { 136 | if (hitObject is DrawableFeverBonus x) 137 | feverBonusContainer.Add(x); 138 | 139 | base.AddNestedHitObject(hitObject); 140 | } 141 | 142 | protected override void ClearNestedHitObjects() 143 | { 144 | feverBonusContainer.Clear(false); 145 | base.ClearNestedHitObjects(); 146 | } 147 | } 148 | 149 | public abstract partial class DrawableRushHitObject : DrawableRushHitObject 150 | where TObject : RushHitObject 151 | { 152 | public new TObject HitObject => (TObject)base.HitObject; 153 | 154 | protected DrawableRushHitObject(TObject hitObject) 155 | : base(hitObject) 156 | { 157 | } 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Objects/Drawables/DrawableRushJudgement.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. Licensed under the MIT Licence. 2 | // See the LICENCE file in the repository root for full licence text. 3 | 4 | using osu.Framework.Graphics; 5 | using osu.Game.Rulesets.Judgements; 6 | using osuTK; 7 | 8 | namespace osu.Game.Rulesets.Rush.Objects.Drawables 9 | { 10 | public partial class DrawableRushJudgement : DrawableJudgement 11 | { 12 | private const float judgement_time = 250f; 13 | private const float judgement_movement = 300; 14 | 15 | public DrawableRushJudgement() 16 | { 17 | Anchor = Anchor.Centre; 18 | Origin = Anchor.Centre; 19 | Position = new Vector2(0f, -80f); 20 | Scale = new Vector2(1.5f); 21 | } 22 | 23 | protected override void ApplyHitAnimations() => 24 | this.ScaleTo(1f, judgement_time) 25 | .Then() 26 | .MoveToOffset(new Vector2(-judgement_movement, 0f), judgement_time, Easing.In) 27 | .Expire(); 28 | 29 | protected override void ApplyMissAnimations() => 30 | this.ScaleTo(1f, judgement_time) 31 | .Then() 32 | .MoveToOffset(new Vector2(-judgement_movement, 0f), judgement_time, Easing.In) 33 | .Expire(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Objects/Drawables/DrawableSawblade.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. 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.Containers; 7 | using osu.Framework.Input.Events; 8 | using osu.Game.Rulesets.Rush.Input; 9 | using osu.Game.Rulesets.Rush.Objects.Drawables.Pieces; 10 | using osu.Game.Rulesets.Rush.UI; 11 | using osu.Game.Rulesets.Scoring; 12 | using osuTK; 13 | using osuTK.Graphics; 14 | 15 | namespace osu.Game.Rulesets.Rush.Objects.Drawables 16 | { 17 | public partial class DrawableSawblade : DrawableLanedHit 18 | { 19 | [Resolved] 20 | private RushPlayfield playfield { get; set; } 21 | 22 | // Sawblade uses the reverse lane colour to indicate which key the player should tap to avoid it 23 | public override Color4 LaneAccentColour => HitObject.Lane == LanedHitLane.Ground ? AIR_ACCENT_COLOUR : GROUND_ACCENT_COLOUR; 24 | 25 | protected override bool ExpireOnHit => false; 26 | protected override bool ExpireOnMiss => false; 27 | 28 | private readonly Container sawbladeContainer; 29 | private readonly Drawable sawblade; 30 | 31 | public DrawableSawblade() 32 | : this(null) 33 | { 34 | } 35 | 36 | public DrawableSawblade(Sawblade hitObject) 37 | : base(hitObject) 38 | { 39 | Size = new Vector2(RushPlayfield.HIT_TARGET_SIZE * 2f); 40 | 41 | AddRangeInternal(new[] 42 | { 43 | sawbladeContainer = new Container 44 | { 45 | Origin = Anchor.Centre, 46 | Anchor = Anchor.Centre, 47 | RelativeSizeAxes = Axes.Both, 48 | Size = new Vector2(0.8f), 49 | Child = sawblade = new SawbladePiece() 50 | { 51 | Origin = Anchor.Centre, 52 | RelativeSizeAxes = Axes.Both, 53 | Size = new Vector2(0.8f) 54 | } 55 | } 56 | }); 57 | } 58 | 59 | protected override void OnApply() 60 | { 61 | base.OnApply(); 62 | 63 | sawbladeContainer.Masking = HitObject.Lane == LanedHitLane.Ground; 64 | sawblade.Anchor = HitObject.Lane == LanedHitLane.Ground ? Anchor.BottomCentre : Anchor.TopCentre; 65 | } 66 | 67 | // Sawblade doesn't handle user presses at all. 68 | public override bool OnPressed(KeyBindingPressEvent e) => false; 69 | 70 | protected override void CheckForResult(bool userTriggered, double timeOffset) 71 | { 72 | // sawblades can't be user triggered, and will not hurt the player in the leading hit windows 73 | if (userTriggered || timeOffset < 0 || AllJudged) 74 | return; 75 | 76 | switch (HitObject.HitWindows.ResultFor(timeOffset)) 77 | { 78 | case HitResult.None: 79 | // if we've reached the trailing "none", we successfully dodged the sawblade 80 | ApplyResult(Result.Judgement.MaxResult); 81 | break; 82 | 83 | case HitResult.Miss: 84 | // sawblades only hurt the player if they collide within the trailing "miss" hit window 85 | if (playfield.PlayerSprite.CollidesWith(HitObject)) 86 | ApplyResult(Result.Judgement.MinResult); 87 | 88 | break; 89 | } 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Objects/Drawables/DrawableStarSheetCap.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. Licensed under the MIT Licence. 2 | // See the LICENCE file in the repository root for full licence text. 3 | 4 | using osu.Framework.Bindables; 5 | using osu.Framework.Graphics; 6 | using osu.Framework.Input.Events; 7 | using osu.Game.Rulesets.Objects.Drawables; 8 | using osu.Game.Rulesets.Rush.Input; 9 | using osu.Game.Rulesets.Rush.Objects.Drawables.Pieces; 10 | using osu.Game.Rulesets.UI.Scrolling; 11 | using osuTK; 12 | 13 | namespace osu.Game.Rulesets.Rush.Objects.Drawables 14 | { 15 | public abstract partial class DrawableStarSheetCap : DrawableLanedHit 16 | where TObject : LanedHit 17 | { 18 | protected abstract RushSkinComponents Component { get; } 19 | 20 | protected DrawableStarSheet StarSheet => (DrawableStarSheet)ParentHitObject; 21 | 22 | protected abstract Anchor CapAnchor { get; } 23 | 24 | public override bool DisplayExplosion => true; 25 | 26 | protected DrawableStarSheetCap(TObject hitObject) 27 | : base(hitObject) 28 | { 29 | Size = new Vector2(DrawableStarSheet.NOTE_SHEET_SIZE * 1.1f); 30 | Origin = Anchor.Centre; 31 | 32 | AddInternal(new StarSheetCapStarPiece() 33 | { 34 | Origin = Anchor.Centre, 35 | Anchor = Anchor.Centre, 36 | //RelativeSizeAxes = Axes.Both, 37 | }); 38 | } 39 | 40 | protected override void OnApply() 41 | { 42 | base.OnApply(); 43 | 44 | Anchor = CapAnchor; 45 | AccentColour.BindTo(StarSheet.AccentColour); 46 | } 47 | 48 | protected override void OnFree() 49 | { 50 | base.OnFree(); 51 | AccentColour.UnbindFrom(StarSheet.AccentColour); 52 | } 53 | 54 | protected override void UpdateStartTimeStateTransforms() 55 | { 56 | Scale = Vector2.One; 57 | Alpha = 1f; 58 | } 59 | 60 | protected override void UpdateHitStateTransforms(ArmedState state) 61 | { 62 | base.UpdateHitStateTransforms(state); 63 | 64 | if (state == ArmedState.Hit) 65 | Hide(); 66 | } 67 | 68 | public bool TriggerResult() => UpdateResult(true); 69 | 70 | protected override void OnDirectionChanged(ValueChangedEvent e) => Anchor = CapAnchor; 71 | 72 | public override bool OnPressed(KeyBindingPressEvent e) => false; // Handled by the star sheet object itself. 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Objects/Drawables/DrawableStarSheetHead.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. 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.Graphics; 6 | using osu.Game.Rulesets.Objects.Drawables; 7 | using osu.Game.Rulesets.Scoring; 8 | 9 | namespace osu.Game.Rulesets.Rush.Objects.Drawables 10 | { 11 | public partial class DrawableStarSheetHead : DrawableStarSheetCap 12 | { 13 | protected override RushSkinComponents Component => RushSkinComponents.StarSheetHead; 14 | 15 | protected override Anchor CapAnchor => LeadingAnchor; 16 | 17 | public DrawableStarSheetHead() 18 | : this(null) 19 | { 20 | } 21 | 22 | public DrawableStarSheetHead(StarSheetHead starSheetHead) 23 | : base(starSheetHead) 24 | { 25 | } 26 | 27 | protected override void CheckForResult(bool userTriggered, double timeOffset) 28 | { 29 | if (userTriggered) 30 | { 31 | var result = HitObject.HitWindows.ResultFor(timeOffset); 32 | if (result == HitResult.None) 33 | return; 34 | 35 | ApplyResult(result); 36 | } 37 | else if (!HitObject.HitWindows.CanBeHit(timeOffset)) 38 | { 39 | ApplyResult(Result.Judgement.MinResult); 40 | } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Objects/Drawables/DrawableStarSheetTail.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. Licensed under the MIT Licence. 2 | // See the LICENCE file in the repository root for full licence text. 3 | 4 | using osu.Framework.Graphics; 5 | using osu.Game.Rulesets.Scoring; 6 | 7 | namespace osu.Game.Rulesets.Rush.Objects.Drawables 8 | { 9 | public partial class DrawableStarSheetTail : DrawableStarSheetCap 10 | { 11 | protected override RushSkinComponents Component => RushSkinComponents.StarSheetTail; 12 | 13 | // FIXME: should logically be TrailingAnchor, not sure why it renders incorrectly 14 | protected override Anchor CapAnchor => LeadingAnchor; 15 | 16 | public DrawableStarSheetTail() 17 | : this(null) 18 | { 19 | } 20 | 21 | public DrawableStarSheetTail(StarSheetTail starSheetTail) 22 | : base(starSheetTail) 23 | { 24 | } 25 | 26 | protected override void CheckForResult(bool userTriggered, double timeOffset) 27 | { 28 | var overallMissed = StarSheet.Result.Type == StarSheet.Result.Judgement.MinResult; 29 | 30 | // Apply tail miss at its time when the entire star sheet has already been judged as missed. 31 | if (overallMissed && timeOffset >= 0) 32 | { 33 | ApplyResult(Result.Judgement.MinResult); 34 | return; 35 | } 36 | 37 | // for now let's give the player an automatic perfect if they hold the action (like in a certain other rhythm game) 38 | if (!userTriggered) 39 | { 40 | if (timeOffset >= 0) 41 | ApplyResult(Result.Judgement.MaxResult); 42 | return; 43 | } 44 | 45 | var result = HitObject.HitWindows.ResultFor(timeOffset); 46 | if (result == HitResult.None) 47 | return; 48 | 49 | // ...and an automatic perfect if they release within any "hit" judged period 50 | ApplyResult(Result.Judgement.MaxResult); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Objects/Drawables/IDrawableLanedHit.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. Licensed under the MIT Licence. 2 | // See the LICENCE file in the repository root for full licence text. 3 | 4 | using osu.Framework.Graphics; 5 | using osuTK.Graphics; 6 | 7 | namespace osu.Game.Rulesets.Rush.Objects.Drawables 8 | { 9 | public interface IDrawableLanedHit 10 | { 11 | LanedHitLane Lane { get; set; } 12 | Anchor LaneAnchor { get; } 13 | Color4 LaneAccentColour { get; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Objects/Drawables/Pieces/DualHitJoinPiece.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. Licensed under the MIT Licence. 2 | // See the LICENCE file in the repository root for full licence text. 3 | 4 | using osu.Framework.Graphics; 5 | using osu.Framework.Graphics.Colour; 6 | using osu.Framework.Graphics.Shapes; 7 | using osuTK; 8 | 9 | namespace osu.Game.Rulesets.Rush.Objects.Drawables.Pieces 10 | { 11 | public partial class DualHitJoinPiece : Box 12 | { 13 | public DualHitJoinPiece() 14 | { 15 | Anchor = Anchor.Centre; 16 | Origin = Anchor.Centre; 17 | RelativeSizeAxes = Axes.Y; 18 | Size = new Vector2(10f, 1f); 19 | Colour = ColourInfo.GradientVertical(DrawableRushHitObject.AIR_ACCENT_COLOUR, DrawableRushHitObject.GROUND_ACCENT_COLOUR); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Objects/Drawables/Pieces/DualHitPartPiece.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. Licensed under the MIT Licence. 2 | // See the LICENCE file in the repository root for full licence text. 3 | 4 | using JetBrains.Annotations; 5 | using osu.Framework.Allocation; 6 | using osu.Framework.Bindables; 7 | using osu.Framework.Extensions.Color4Extensions; 8 | using osu.Framework.Graphics; 9 | using osu.Framework.Graphics.Containers; 10 | using osu.Framework.Graphics.Shapes; 11 | using osu.Framework.Graphics.Sprites; 12 | using osu.Game.Graphics.Backgrounds; 13 | using osu.Game.Rulesets.Objects.Drawables; 14 | using osu.Game.Rulesets.Rush.UI; 15 | using osuTK; 16 | using osuTK.Graphics; 17 | 18 | namespace osu.Game.Rulesets.Rush.Objects.Drawables.Pieces 19 | { 20 | public partial class DualHitPartPiece : CompositeDrawable 21 | { 22 | private const double rotation_time = 1000; 23 | 24 | private readonly SpriteIcon gearSpriteIcon; 25 | private readonly Box background; 26 | private readonly Triangles triangles; 27 | 28 | public readonly Bindable AccentColour = new Bindable(); 29 | 30 | public DualHitPartPiece() 31 | { 32 | Size = new Vector2(RushPlayfield.HIT_TARGET_SIZE); 33 | 34 | AddRangeInternal(new Drawable[] 35 | { 36 | gearSpriteIcon = new SpriteIcon 37 | { 38 | Origin = Anchor.Centre, 39 | Anchor = Anchor.Centre, 40 | RelativeSizeAxes = Axes.Both, 41 | Icon = FontAwesome.Solid.Cog 42 | }, 43 | new CircularContainer 44 | { 45 | Origin = Anchor.Centre, 46 | Anchor = Anchor.Centre, 47 | RelativeSizeAxes = Axes.Both, 48 | Scale = new Vector2(0.7f), 49 | BorderThickness = RushPlayfield.HIT_TARGET_SIZE * 0.1f, 50 | BorderColour = Color4.White, 51 | Masking = true, 52 | Children = new Drawable[] 53 | { 54 | background = new Box { RelativeSizeAxes = Axes.Both }, 55 | triangles = new Triangles { RelativeSizeAxes = Axes.Both } 56 | } 57 | }, 58 | }); 59 | } 60 | 61 | [BackgroundDependencyLoader] 62 | private void load([CanBeNull] DrawableHitObject drawableHitObject) 63 | { 64 | if (drawableHitObject != null) 65 | AccentColour.BindTo(drawableHitObject.AccentColour); 66 | 67 | AccentColour.BindValueChanged(evt => 68 | { 69 | background.Colour = evt.NewValue.Darken(0.5f); 70 | triangles.Colour = evt.NewValue; 71 | triangles.Alpha = 0.8f; 72 | gearSpriteIcon.Colour = evt.NewValue.Lighten(0.5f); 73 | }); 74 | } 75 | 76 | protected override void Update() 77 | { 78 | base.Update(); 79 | 80 | gearSpriteIcon.Rotation = (float)(Time.Current % rotation_time / rotation_time) * 360f; 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Objects/Drawables/Pieces/HeartPiece.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. Licensed under the MIT Licence. 2 | // See the LICENCE file in the repository root for full licence text. 3 | 4 | using osu.Framework.Graphics; 5 | using osu.Framework.Graphics.Pooling; 6 | using osu.Framework.Graphics.Sprites; 7 | using osuTK; 8 | using osuTK.Graphics; 9 | 10 | namespace osu.Game.Rulesets.Rush.Objects.Drawables.Pieces 11 | { 12 | public partial class HeartPiece : PoolableDrawable 13 | { 14 | public HeartPiece() 15 | { 16 | Origin = Anchor.Centre; 17 | Anchor = Anchor.Centre; 18 | 19 | InternalChildren = new Drawable[] 20 | { 21 | new SpriteIcon 22 | { 23 | Origin = Anchor.Centre, 24 | Anchor = Anchor.Centre, 25 | RelativeSizeAxes = Axes.Both, 26 | FillMode = FillMode.Fit, 27 | Icon = FontAwesome.Solid.Heart, 28 | Colour = Color4.HotPink, 29 | }, 30 | new SpriteIcon 31 | { 32 | Origin = Anchor.Centre, 33 | Anchor = Anchor.Centre, 34 | RelativeSizeAxes = Axes.Both, 35 | FillMode = FillMode.Fit, 36 | Icon = FontAwesome.Solid.Heart, 37 | Size = new Vector2(0.8f), 38 | Colour = Color4.Red 39 | } 40 | }; 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Objects/Drawables/Pieces/MiniBossPiece.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. 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.Animations; 7 | using osu.Framework.Graphics.Containers; 8 | using osu.Framework.Graphics.Textures; 9 | 10 | namespace osu.Game.Rulesets.Rush.Objects.Drawables.Pieces 11 | { 12 | public partial class MiniBossPiece : CompositeDrawable 13 | { 14 | private readonly TextureAnimation normalAnimation; 15 | private readonly TextureAnimation hitAnimation; 16 | 17 | public MiniBossPiece() 18 | { 19 | Origin = Anchor.Centre; 20 | Anchor = Anchor.Centre; 21 | 22 | AddRangeInternal(new Drawable[] 23 | { 24 | normalAnimation = new TextureAnimation 25 | { 26 | Origin = Anchor.Centre, 27 | Anchor = Anchor.Centre, 28 | DefaultFrameLength = 250, 29 | }, 30 | hitAnimation = new TextureAnimation 31 | { 32 | Origin = Anchor.Centre, 33 | Anchor = Anchor.Centre, 34 | DefaultFrameLength = 250, 35 | Alpha = 0f 36 | }, 37 | }); 38 | } 39 | 40 | [BackgroundDependencyLoader] 41 | private void load(TextureStore store) 42 | { 43 | normalAnimation.AddFrames(new[] { store.Get("MiniBoss/pippidon_boss_0"), store.Get("MiniBoss/pippidon_boss_1") }); 44 | hitAnimation.AddFrames(new[] { store.Get("MiniBoss/pippidon_boss_hurt_0"), store.Get("MiniBoss/pippidon_boss_hurt_1"), store.Get("MiniBoss/pippidon_boss_hurt_2") }); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Objects/Drawables/Pieces/MinionPiece.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. 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.Animations; 7 | using osu.Framework.Graphics.Containers; 8 | using osu.Framework.Graphics.Textures; 9 | 10 | namespace osu.Game.Rulesets.Rush.Objects.Drawables.Pieces 11 | { 12 | public partial class MinionPiece : CompositeDrawable 13 | { 14 | private readonly TextureAnimation animation; 15 | 16 | public MinionPiece() 17 | { 18 | RelativeSizeAxes = Axes.Both; 19 | 20 | InternalChild = animation = new TextureAnimation 21 | { 22 | Origin = Anchor.Centre, 23 | Anchor = Anchor.Centre, 24 | FillMode = FillMode.Fit, 25 | RelativeSizeAxes = Axes.Both, 26 | DefaultFrameLength = 250, 27 | }; 28 | } 29 | 30 | [BackgroundDependencyLoader(true)] 31 | private void load(IDrawableLanedHit laned, TextureStore textures) 32 | { 33 | var laneStr = laned.Lane == LanedHitLane.Air ? "air" : "ground"; 34 | 35 | animation.AddFrames(new[] { textures.Get($"Minion/pippidon_{laneStr}_0"), textures.Get($"Minion/pippidon_{laneStr}_1") }); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Objects/Drawables/Pieces/SawbladePiece.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. Licensed under the MIT Licence. 2 | // See the LICENCE file in the repository root for full licence text. 3 | 4 | using JetBrains.Annotations; 5 | using osu.Framework.Allocation; 6 | using osu.Framework.Bindables; 7 | using osu.Framework.Extensions.Color4Extensions; 8 | using osu.Framework.Graphics; 9 | using osu.Framework.Graphics.Containers; 10 | using osu.Framework.Graphics.Shapes; 11 | using osu.Framework.Graphics.Sprites; 12 | using osu.Game.Graphics.Backgrounds; 13 | using osu.Game.Rulesets.Objects.Drawables; 14 | using osuTK; 15 | using osuTK.Graphics; 16 | 17 | namespace osu.Game.Rulesets.Rush.Objects.Drawables.Pieces 18 | { 19 | public partial class SawbladePiece : CompositeDrawable 20 | { 21 | private const double rotation_time = 1000; 22 | 23 | private readonly SpriteIcon outerSawIcon; 24 | private readonly SpriteIcon innerSawIcon; 25 | private readonly Box backgroundBox; 26 | private readonly Triangles triangles; 27 | 28 | public readonly Bindable AccentColour = new Bindable(); 29 | 30 | public SawbladePiece() 31 | { 32 | Origin = Anchor.Centre; 33 | Anchor = Anchor.Centre; 34 | RelativeSizeAxes = Axes.Both; 35 | 36 | InternalChildren = new Drawable[] 37 | { 38 | outerSawIcon = new SpriteIcon 39 | { 40 | Origin = Anchor.Centre, 41 | Anchor = Anchor.Centre, 42 | Icon = FontAwesome.Solid.Sun, 43 | Colour = Color4.White, 44 | RelativeSizeAxes = Axes.Both, 45 | Size = new Vector2(1.1f) 46 | }, 47 | innerSawIcon = new SpriteIcon 48 | { 49 | Origin = Anchor.Centre, 50 | Anchor = Anchor.Centre, 51 | Icon = FontAwesome.Solid.Sun, 52 | RelativeSizeAxes = Axes.Both, 53 | }, 54 | new CircularContainer 55 | { 56 | Anchor = Anchor.Centre, 57 | Origin = Anchor.Centre, 58 | RelativeSizeAxes = Axes.Both, 59 | BorderThickness = DrawableStarSheet.NOTE_SHEET_SIZE * 0.1f, 60 | BorderColour = Color4.White, 61 | Masking = true, 62 | Size = new Vector2(0.75f), 63 | Children = new Drawable[] 64 | { 65 | backgroundBox = new Box { RelativeSizeAxes = Axes.Both }, 66 | triangles = new Triangles { RelativeSizeAxes = Axes.Both } 67 | } 68 | } 69 | }; 70 | } 71 | 72 | [BackgroundDependencyLoader(true)] 73 | private void load([CanBeNull] DrawableHitObject drawableHitObject) 74 | { 75 | if (drawableHitObject != null) 76 | AccentColour.BindTo(drawableHitObject.AccentColour); 77 | 78 | AccentColour.BindValueChanged(evt => 79 | { 80 | backgroundBox.Colour = evt.NewValue.Darken(0.5f); 81 | triangles.Colour = evt.NewValue; 82 | triangles.Alpha = 0.8f; 83 | innerSawIcon.Colour = evt.NewValue.Lighten(0.5f); 84 | }, true); 85 | } 86 | 87 | protected override void Update() 88 | { 89 | base.Update(); 90 | 91 | innerSawIcon.Rotation = outerSawIcon.Rotation = (float)(Time.Current % rotation_time / rotation_time) * 360f; 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Objects/Drawables/Pieces/StarSheetBodyPiece.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. Licensed under the MIT Licence. 2 | // See the LICENCE file in the repository root for full licence text. 3 | 4 | using JetBrains.Annotations; 5 | using osu.Framework.Allocation; 6 | using osu.Framework.Bindables; 7 | using osu.Framework.Extensions.Color4Extensions; 8 | using osu.Framework.Graphics; 9 | using osu.Framework.Graphics.Containers; 10 | using osu.Framework.Graphics.Shapes; 11 | using osu.Game.Graphics.Backgrounds; 12 | using osu.Game.Rulesets.Objects.Drawables; 13 | using osuTK.Graphics; 14 | 15 | namespace osu.Game.Rulesets.Rush.Objects.Drawables.Pieces 16 | { 17 | public partial class StarSheetBodyPiece : CompositeDrawable 18 | { 19 | private const float border_size = 1f / 8f; 20 | 21 | private readonly Box backgroundBox, topBox, bottomBox; 22 | private readonly Triangles triangles; 23 | 24 | public readonly Bindable AccentColour = new Bindable(); 25 | 26 | public StarSheetBodyPiece() 27 | { 28 | RelativeSizeAxes = Axes.Y; 29 | 30 | InternalChildren = new Drawable[] 31 | { 32 | backgroundBox = new Box { RelativeSizeAxes = Axes.Both }, 33 | triangles = new Triangles { RelativeSizeAxes = Axes.Both }, 34 | topBox = new Box 35 | { 36 | RelativeSizeAxes = Axes.Both, 37 | Height = border_size, 38 | Origin = Anchor.TopCentre, 39 | Anchor = Anchor.TopCentre, 40 | }, 41 | bottomBox = new Box 42 | { 43 | RelativeSizeAxes = Axes.Both, 44 | Height = border_size, 45 | Origin = Anchor.BottomCentre, 46 | Anchor = Anchor.BottomCentre, 47 | } 48 | }; 49 | } 50 | 51 | [BackgroundDependencyLoader(true)] 52 | private void load([CanBeNull] DrawableHitObject drawableHitObject) 53 | { 54 | if (drawableHitObject != null) 55 | AccentColour.BindTo(drawableHitObject.AccentColour); 56 | 57 | AccentColour.BindValueChanged(c => 58 | { 59 | backgroundBox.Colour = c.NewValue.Darken(1f); 60 | topBox.Colour = bottomBox.Colour = c.NewValue; 61 | triangles.Colour = c.NewValue; 62 | triangles.Alpha = 0.8f; 63 | }, true); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Objects/Drawables/Pieces/StarSheetCapStarPiece.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. Licensed under the MIT Licence. 2 | // See the LICENCE file in the repository root for full licence text. 3 | 4 | using JetBrains.Annotations; 5 | using osu.Framework.Allocation; 6 | using osu.Framework.Bindables; 7 | using osu.Framework.Extensions.Color4Extensions; 8 | using osu.Framework.Graphics; 9 | using osu.Framework.Graphics.Containers; 10 | using osu.Framework.Graphics.Shapes; 11 | using osu.Framework.Graphics.Sprites; 12 | using osu.Game.Graphics; 13 | using osu.Game.Graphics.Backgrounds; 14 | using osu.Game.Rulesets.Objects.Drawables; 15 | using osuTK; 16 | using osuTK.Graphics; 17 | 18 | namespace osu.Game.Rulesets.Rush.Objects.Drawables.Pieces 19 | { 20 | public partial class StarSheetCapStarPiece : CompositeDrawable, IHasAccentColour 21 | { 22 | private const double rotation_time = 1000; 23 | 24 | private readonly SpriteIcon starIcon; 25 | private readonly Triangles triangles; 26 | private readonly Box backgroundBox; 27 | 28 | public readonly Bindable AccentColour = new Bindable(); 29 | 30 | Color4 IHasAccentColour.AccentColour 31 | { 32 | get => AccentColour.Value; 33 | set => AccentColour.Value = value; 34 | } 35 | 36 | public StarSheetCapStarPiece() 37 | { 38 | Origin = Anchor.Centre; 39 | Anchor = Anchor.Centre; 40 | Size = new Vector2(DrawableStarSheet.NOTE_SHEET_SIZE); 41 | 42 | AddRangeInternal(new Drawable[] 43 | { 44 | starIcon = new SpriteIcon 45 | { 46 | Anchor = Anchor.Centre, 47 | Scale = new Vector2(1.5f), 48 | RelativeSizeAxes = Axes.Both, 49 | Icon = FontAwesome.Solid.Star, 50 | }, 51 | new CircularContainer 52 | { 53 | Anchor = Anchor.Centre, 54 | Origin = Anchor.Centre, 55 | RelativeSizeAxes = Axes.Both, 56 | BorderThickness = DrawableStarSheet.NOTE_SHEET_SIZE * 0.1f, 57 | BorderColour = Color4.White, 58 | Masking = true, 59 | Children = new Drawable[] 60 | { 61 | backgroundBox = new Box { RelativeSizeAxes = Axes.Both }, 62 | triangles = new Triangles { RelativeSizeAxes = Axes.Both } 63 | } 64 | } 65 | }); 66 | } 67 | 68 | [BackgroundDependencyLoader(true)] 69 | private void load([CanBeNull] DrawableHitObject drawableHitObject) 70 | { 71 | if (drawableHitObject != null) 72 | AccentColour.BindTo(drawableHitObject.AccentColour); 73 | 74 | AccentColour.BindValueChanged(c => 75 | { 76 | starIcon.Colour = c.NewValue.Lighten(0.5f); 77 | backgroundBox.Colour = c.NewValue.Darken(0.5f); 78 | triangles.Colour = c.NewValue; 79 | triangles.Alpha = 0.8f; 80 | }, true); 81 | } 82 | 83 | protected override void Update() 84 | { 85 | base.Update(); 86 | 87 | starIcon.OriginPosition = new Vector2(DrawWidth * 0.5f, DrawHeight * 0.54f); 88 | starIcon.Rotation = (float)(Time.Current % rotation_time / rotation_time) * 360f; 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Objects/DualHit.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. Licensed under the MIT Licence. 2 | // See the LICENCE file in the repository root for full licence text. 3 | 4 | using System.Threading; 5 | using osu.Game.Rulesets.Judgements; 6 | using osu.Game.Rulesets.Rush.Judgements; 7 | using osu.Game.Rulesets.Scoring; 8 | 9 | namespace osu.Game.Rulesets.Rush.Objects 10 | { 11 | public class DualHit : RushHitObject 12 | { 13 | public override double StartTime 14 | { 15 | get => base.StartTime; 16 | set 17 | { 18 | base.StartTime = value; 19 | Air.StartTime = Ground.StartTime = value; 20 | } 21 | } 22 | 23 | public readonly DualHitPart Air = new DualHitPart { Lane = LanedHitLane.Air }; 24 | public readonly DualHitPart Ground = new DualHitPart { Lane = LanedHitLane.Ground }; 25 | 26 | public override Judgement CreateJudgement() => new RushIgnoreJudgement(); 27 | 28 | protected override HitWindows CreateHitWindows() => HitWindows.Empty; 29 | 30 | protected override bool HasFeverBonus => false; 31 | 32 | protected override void CreateNestedHitObjects(CancellationToken cancellationToken) 33 | { 34 | base.CreateNestedHitObjects(cancellationToken); 35 | 36 | AddNested(Air); 37 | AddNested(Ground); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Objects/DualHitPart.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. Licensed under the MIT Licence. 2 | // See the LICENCE file in the repository root for full licence text. 3 | 4 | using osu.Game.Rulesets.Judgements; 5 | using osu.Game.Rulesets.Rush.Judgements; 6 | 7 | namespace osu.Game.Rulesets.Rush.Objects 8 | { 9 | public class DualHitPart : LanedHit 10 | { 11 | public override Judgement CreateJudgement() => new CollisionDamagingJudgement(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Objects/FeverBonus.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. Licensed under the MIT Licence. 2 | // See the LICENCE file in the repository root for full licence text. 3 | 4 | using osu.Game.Rulesets.Judgements; 5 | using osu.Game.Rulesets.Rush.Judgements; 6 | using osu.Game.Rulesets.Scoring; 7 | 8 | namespace osu.Game.Rulesets.Rush.Objects 9 | { 10 | public class FeverBonus : RushHitObject 11 | { 12 | public override Judgement CreateJudgement() => new RushFeverJudgement(); 13 | 14 | protected override HitWindows CreateHitWindows() => HitWindows.Empty; 15 | 16 | protected override bool HasFeverBonus => false; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Objects/Heart.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. Licensed under the MIT Licence. 2 | // See the LICENCE file in the repository root for full licence text. 3 | 4 | using osu.Game.Rulesets.Judgements; 5 | using osu.Game.Rulesets.Rush.Judgements; 6 | using osu.Game.Rulesets.Rush.Scoring; 7 | using osu.Game.Rulesets.Scoring; 8 | 9 | namespace osu.Game.Rulesets.Rush.Objects 10 | { 11 | public class Heart : LanedHit 12 | { 13 | public override Judgement CreateJudgement() => new HeartJudgement(); 14 | 15 | protected override HitWindows CreateHitWindows() => new HeartHitWindows(); 16 | 17 | protected override bool HasFeverBonus => false; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Objects/LanedHit.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. Licensed under the MIT Licence. 2 | // See the LICENCE file in the repository root for full licence text. 3 | 4 | using osu.Framework.Bindables; 5 | using osu.Game.Rulesets.Judgements; 6 | using osu.Game.Rulesets.Rush.Judgements; 7 | 8 | namespace osu.Game.Rulesets.Rush.Objects 9 | { 10 | public class LanedHit : RushHitObject 11 | { 12 | public readonly Bindable LaneBindable = new Bindable(); 13 | 14 | public virtual LanedHitLane Lane 15 | { 16 | get => LaneBindable.Value; 17 | set => LaneBindable.Value = value; 18 | } 19 | 20 | public override Judgement CreateJudgement() => new RushJudgement(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Objects/LanedHitLane.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. Licensed under the MIT Licence. 2 | // See the LICENCE file in the repository root for full licence text. 3 | 4 | namespace osu.Game.Rulesets.Rush.Objects 5 | { 6 | public enum LanedHitLane 7 | { 8 | /// 9 | /// Must press the air attack key. 10 | /// 11 | Air, 12 | 13 | /// 14 | /// Must press the ground attack key. 15 | /// 16 | Ground, 17 | } 18 | 19 | public static class LanedHitLaneExtensions 20 | { 21 | public static LanedHitLane Opposite(this LanedHitLane lane) => lane == LanedHitLane.Air ? LanedHitLane.Ground : LanedHitLane.Air; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Objects/MiniBoss.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. 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.Threading; 6 | using osu.Game.Rulesets.Judgements; 7 | using osu.Game.Rulesets.Objects.Types; 8 | using osu.Game.Rulesets.Rush.Judgements; 9 | using osu.Game.Rulesets.Scoring; 10 | 11 | namespace osu.Game.Rulesets.Rush.Objects 12 | { 13 | public class MiniBoss : RushHitObject, IHasDuration 14 | { 15 | public static readonly int DEFAULT_REQUIRED_HITS_PER_SECOND = 3; 16 | 17 | public double EndTime 18 | { 19 | get => StartTime + Duration; 20 | set => Duration = value - StartTime; 21 | } 22 | 23 | public double Duration { get; set; } 24 | 25 | public int RequiredHitsPerSecond => DEFAULT_REQUIRED_HITS_PER_SECOND; 26 | 27 | public int RequiredHits => (int)(Math.Ceiling(Duration / 500f) * RequiredHitsPerSecond * 0.5f); 28 | 29 | protected override void CreateNestedHitObjects(CancellationToken cancellationToken) 30 | { 31 | base.CreateNestedHitObjects(cancellationToken); 32 | 33 | for (int i = 0; i < RequiredHits; i++) 34 | AddNested(new MiniBossTick()); 35 | } 36 | 37 | public override Judgement CreateJudgement() => new RushJudgement(); 38 | 39 | protected override HitWindows CreateHitWindows() => HitWindows.Empty; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Objects/MiniBossTick.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. Licensed under the MIT Licence. 2 | // See the LICENCE file in the repository root for full licence text. 3 | 4 | using osu.Game.Rulesets.Judgements; 5 | using osu.Game.Rulesets.Rush.Judgements; 6 | using osu.Game.Rulesets.Scoring; 7 | 8 | namespace osu.Game.Rulesets.Rush.Objects 9 | { 10 | public class MiniBossTick : RushHitObject 11 | { 12 | public override Judgement CreateJudgement() => new RushTickJudgement(); 13 | 14 | protected override HitWindows CreateHitWindows() => HitWindows.Empty; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Objects/Minion.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. Licensed under the MIT Licence. 2 | // See the LICENCE file in the repository root for full licence text. 3 | 4 | using osu.Game.Rulesets.Judgements; 5 | using osu.Game.Rulesets.Rush.Judgements; 6 | 7 | namespace osu.Game.Rulesets.Rush.Objects 8 | { 9 | /// 10 | /// Uses a sprite based on the beatmap environment and note hitsound. 11 | /// 12 | public class Minion : LanedHit 13 | { 14 | public override Judgement CreateJudgement() => new CollisionDamagingJudgement(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Objects/RushHitObject.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. Licensed under the MIT Licence. 2 | // See the LICENCE file in the repository root for full licence text. 3 | 4 | using System.Threading; 5 | using osu.Game.Rulesets.Judgements; 6 | using osu.Game.Rulesets.Objects; 7 | using osu.Game.Rulesets.Rush.Judgements; 8 | using osu.Game.Rulesets.Rush.Scoring; 9 | using osu.Game.Rulesets.Scoring; 10 | 11 | namespace osu.Game.Rulesets.Rush.Objects 12 | { 13 | public class RushHitObject : HitObject 14 | { 15 | public override Judgement CreateJudgement() => new RushJudgement(); 16 | 17 | protected override HitWindows CreateHitWindows() => new RushHitWindows(); 18 | 19 | protected virtual bool HasFeverBonus => true; 20 | 21 | protected override void CreateNestedHitObjects(CancellationToken cancellationToken) 22 | { 23 | base.CreateNestedHitObjects(cancellationToken); 24 | 25 | if (HasFeverBonus) 26 | AddNested(new FeverBonus() { StartTime = this.GetEndTime() }); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Objects/Sawblade.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. Licensed under the MIT Licence. 2 | // See the LICENCE file in the repository root for full licence text. 3 | 4 | using osu.Game.Rulesets.Judgements; 5 | using osu.Game.Rulesets.Rush.Judgements; 6 | using osu.Game.Rulesets.Rush.Scoring; 7 | using osu.Game.Rulesets.Scoring; 8 | 9 | namespace osu.Game.Rulesets.Rush.Objects 10 | { 11 | public class Sawblade : LanedHit 12 | { 13 | public override Judgement CreateJudgement() => new SawbladeJudgement(); 14 | 15 | protected override HitWindows CreateHitWindows() => new SawbladeHitWindows(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Objects/StarSheet.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. 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 System.Threading; 7 | using osu.Game.Audio; 8 | using osu.Game.Rulesets.Judgements; 9 | using osu.Game.Rulesets.Objects.Types; 10 | using osu.Game.Rulesets.Rush.Judgements; 11 | using osu.Game.Rulesets.Scoring; 12 | 13 | namespace osu.Game.Rulesets.Rush.Objects 14 | { 15 | public class StarSheet : LanedHit, IHasDuration 16 | { 17 | public IList> NodeSamples; 18 | 19 | public double EndTime 20 | { 21 | get => StartTime + Duration; 22 | set => Duration = value - StartTime; 23 | } 24 | 25 | private double duration; 26 | 27 | public double Duration 28 | { 29 | get => duration; 30 | set 31 | { 32 | duration = value; 33 | Tail.StartTime = EndTime; 34 | } 35 | } 36 | 37 | public override double StartTime 38 | { 39 | get => base.StartTime; 40 | set 41 | { 42 | base.StartTime = value; 43 | Head.StartTime = value; 44 | Tail.StartTime = EndTime; 45 | } 46 | } 47 | 48 | public override LanedHitLane Lane 49 | { 50 | get => base.Lane; 51 | set 52 | { 53 | base.Lane = value; 54 | Head.Lane = value; 55 | Tail.Lane = value; 56 | } 57 | } 58 | 59 | public readonly StarSheetHead Head = new StarSheetHead(); 60 | 61 | public readonly StarSheetTail Tail = new StarSheetTail(); 62 | 63 | protected override void CreateNestedHitObjects(CancellationToken cancellationToken) 64 | { 65 | base.CreateNestedHitObjects(cancellationToken); 66 | 67 | AddNested(Head); 68 | AddNested(Tail); 69 | 70 | updateNestedSamples(); 71 | } 72 | 73 | private void updateNestedSamples() 74 | { 75 | if (NodeSamples.Count == 0) 76 | return; 77 | 78 | Head.Samples = NodeSamples.First(); 79 | Tail.Samples = NodeSamples.Last(); 80 | } 81 | 82 | public override Judgement CreateJudgement() => new RushIgnoreJudgement(); 83 | 84 | protected override HitWindows CreateHitWindows() => HitWindows.Empty; 85 | 86 | protected override bool HasFeverBonus => false; 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Objects/StarSheetHead.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. Licensed under the MIT Licence. 2 | // See the LICENCE file in the repository root for full licence text. 3 | 4 | using osu.Game.Rulesets.Judgements; 5 | using osu.Game.Rulesets.Rush.Judgements; 6 | 7 | namespace osu.Game.Rulesets.Rush.Objects 8 | { 9 | public class StarSheetHead : LanedHit 10 | { 11 | public override Judgement CreateJudgement() => new RushJudgement(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Objects/StarSheetTail.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. Licensed under the MIT Licence. 2 | // See the LICENCE file in the repository root for full licence text. 3 | 4 | using osu.Game.Rulesets.Judgements; 5 | using osu.Game.Rulesets.Rush.Judgements; 6 | 7 | namespace osu.Game.Rulesets.Rush.Objects 8 | { 9 | public class StarSheetTail : LanedHit 10 | { 11 | public override Judgement CreateJudgement() => new RushJudgement(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Replays/RushFramedReplayInputHandler.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. 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 | using osu.Game.Rulesets.Rush.Configuration; 10 | using osu.Game.Rulesets.Rush.Input; 11 | 12 | namespace osu.Game.Rulesets.Rush.Replays 13 | { 14 | public class RushFramedReplayInputHandler : FramedReplayInputHandler 15 | { 16 | public RushFramedReplayInputHandler(Replay replay) 17 | : base(replay) 18 | { 19 | } 20 | 21 | protected override bool IsImportant(RushReplayFrame frame) => frame.Actions.Any(); 22 | 23 | /// 24 | /// The current fever activation mode determined by the replay's current frame. 25 | /// 26 | public FeverActivationMode? FeverActivationMode => CurrentFrame?.FeverActivationMode; 27 | 28 | protected override void CollectReplayInputs(List inputs) => 29 | inputs.Add(new ReplayState { PressedActions = CurrentFrame?.Actions ?? new List() }); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Replays/RushReplayFrame.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. 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.Diagnostics; 6 | using osu.Framework.Extensions.EnumExtensions; 7 | using osu.Game.Beatmaps; 8 | using osu.Game.Replays.Legacy; 9 | using osu.Game.Rulesets.Replays; 10 | using osu.Game.Rulesets.Replays.Types; 11 | using osu.Game.Rulesets.Rush.Configuration; 12 | using osu.Game.Rulesets.Rush.Input; 13 | 14 | namespace osu.Game.Rulesets.Rush.Replays 15 | { 16 | public class RushReplayFrame : ReplayFrame, IConvertibleReplayFrame 17 | { 18 | public List Actions = new List(); 19 | 20 | /// 21 | /// The fever activation mode at this frame. 22 | /// 23 | public FeverActivationMode FeverActivationMode; 24 | 25 | public RushReplayFrame() 26 | { 27 | } 28 | 29 | public RushReplayFrame(double time, RushAction? button = null) 30 | : base(time) 31 | { 32 | if (button.HasValue) 33 | Actions.Add(button.Value); 34 | } 35 | 36 | public RushReplayFrame(double time, IEnumerable buttons) 37 | : base(time) 38 | { 39 | Actions.AddRange(buttons); 40 | } 41 | 42 | public void FromLegacy(LegacyReplayFrame currentFrame, IBeatmap beatmap, ReplayFrame lastFrame = null) 43 | { 44 | Debug.Assert(currentFrame.MouseX != null); 45 | 46 | uint flags = (uint)currentFrame.MouseX; 47 | 48 | int currentBit = 0; 49 | 50 | while (flags > 0) 51 | { 52 | if ((flags & 1) > 0) 53 | Actions.Add((RushAction)currentBit); 54 | 55 | ++currentBit; 56 | flags >>= 1; 57 | } 58 | 59 | // We are repurposing ReplayButtonState.Smoke in order to store the AutoFever setting used at the time of recording. 60 | // This will serve as an interim solution until non-legacy replays are supported in osu. 61 | FeverActivationMode = getFeverActivationMode(currentFrame.ButtonState); 62 | } 63 | 64 | public LegacyReplayFrame ToLegacy(IBeatmap beatmap) 65 | { 66 | uint flags = 0; 67 | foreach (var action in Actions) 68 | flags |= 1u << (int)action; 69 | 70 | return new LegacyReplayFrame(Time, flags, 0f, getFeverActivationButtonState(FeverActivationMode)); 71 | } 72 | 73 | private static FeverActivationMode getFeverActivationMode(ReplayButtonState buttonState) => buttonState.HasFlag(ReplayButtonState.Smoke) switch 74 | { 75 | true => FeverActivationMode.Automatic, 76 | false => FeverActivationMode.Manual 77 | }; 78 | 79 | private static ReplayButtonState getFeverActivationButtonState(FeverActivationMode mode) => mode switch 80 | { 81 | FeverActivationMode.Automatic => ReplayButtonState.Smoke, 82 | _ => ReplayButtonState.None, 83 | }; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Resources/Textures/Effects/explosion.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Beamographic/rush/099eb77d51b7e491fd9259221472d351103ca4c8/osu.Game.Rulesets.Rush/Resources/Textures/Effects/explosion.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Resources/Textures/MiniBoss/pippidon_boss_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Beamographic/rush/099eb77d51b7e491fd9259221472d351103ca4c8/osu.Game.Rulesets.Rush/Resources/Textures/MiniBoss/pippidon_boss_0.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Resources/Textures/MiniBoss/pippidon_boss_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Beamographic/rush/099eb77d51b7e491fd9259221472d351103ca4c8/osu.Game.Rulesets.Rush/Resources/Textures/MiniBoss/pippidon_boss_1.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Resources/Textures/MiniBoss/pippidon_boss_hurt_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Beamographic/rush/099eb77d51b7e491fd9259221472d351103ca4c8/osu.Game.Rulesets.Rush/Resources/Textures/MiniBoss/pippidon_boss_hurt_0.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Resources/Textures/MiniBoss/pippidon_boss_hurt_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Beamographic/rush/099eb77d51b7e491fd9259221472d351103ca4c8/osu.Game.Rulesets.Rush/Resources/Textures/MiniBoss/pippidon_boss_hurt_1.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Resources/Textures/MiniBoss/pippidon_boss_hurt_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Beamographic/rush/099eb77d51b7e491fd9259221472d351103ca4c8/osu.Game.Rulesets.Rush/Resources/Textures/MiniBoss/pippidon_boss_hurt_2.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Resources/Textures/Minion/pippidon_air_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Beamographic/rush/099eb77d51b7e491fd9259221472d351103ca4c8/osu.Game.Rulesets.Rush/Resources/Textures/Minion/pippidon_air_0.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Resources/Textures/Minion/pippidon_air_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Beamographic/rush/099eb77d51b7e491fd9259221472d351103ca4c8/osu.Game.Rulesets.Rush/Resources/Textures/Minion/pippidon_air_1.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Resources/Textures/Minion/pippidon_air_hit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Beamographic/rush/099eb77d51b7e491fd9259221472d351103ca4c8/osu.Game.Rulesets.Rush/Resources/Textures/Minion/pippidon_air_hit.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Resources/Textures/Minion/pippidon_ground_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Beamographic/rush/099eb77d51b7e491fd9259221472d351103ca4c8/osu.Game.Rulesets.Rush/Resources/Textures/Minion/pippidon_ground_0.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Resources/Textures/Minion/pippidon_ground_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Beamographic/rush/099eb77d51b7e491fd9259221472d351103ca4c8/osu.Game.Rulesets.Rush/Resources/Textures/Minion/pippidon_ground_1.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Resources/Textures/Minion/pippidon_ground_hit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Beamographic/rush/099eb77d51b7e491fd9259221472d351103ca4c8/osu.Game.Rulesets.Rush/Resources/Textures/Minion/pippidon_ground_hit.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Resources/Textures/Player/Attack__000.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Beamographic/rush/099eb77d51b7e491fd9259221472d351103ca4c8/osu.Game.Rulesets.Rush/Resources/Textures/Player/Attack__000.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Resources/Textures/Player/Attack__001.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Beamographic/rush/099eb77d51b7e491fd9259221472d351103ca4c8/osu.Game.Rulesets.Rush/Resources/Textures/Player/Attack__001.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Resources/Textures/Player/Attack__002.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Beamographic/rush/099eb77d51b7e491fd9259221472d351103ca4c8/osu.Game.Rulesets.Rush/Resources/Textures/Player/Attack__002.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Resources/Textures/Player/Attack__003.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Beamographic/rush/099eb77d51b7e491fd9259221472d351103ca4c8/osu.Game.Rulesets.Rush/Resources/Textures/Player/Attack__003.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Resources/Textures/Player/Attack__004.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Beamographic/rush/099eb77d51b7e491fd9259221472d351103ca4c8/osu.Game.Rulesets.Rush/Resources/Textures/Player/Attack__004.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Resources/Textures/Player/Attack__005.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Beamographic/rush/099eb77d51b7e491fd9259221472d351103ca4c8/osu.Game.Rulesets.Rush/Resources/Textures/Player/Attack__005.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Resources/Textures/Player/Attack__006.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Beamographic/rush/099eb77d51b7e491fd9259221472d351103ca4c8/osu.Game.Rulesets.Rush/Resources/Textures/Player/Attack__006.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Resources/Textures/Player/Attack__007.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Beamographic/rush/099eb77d51b7e491fd9259221472d351103ca4c8/osu.Game.Rulesets.Rush/Resources/Textures/Player/Attack__007.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Resources/Textures/Player/Attack__008.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Beamographic/rush/099eb77d51b7e491fd9259221472d351103ca4c8/osu.Game.Rulesets.Rush/Resources/Textures/Player/Attack__008.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Resources/Textures/Player/Attack__009.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Beamographic/rush/099eb77d51b7e491fd9259221472d351103ca4c8/osu.Game.Rulesets.Rush/Resources/Textures/Player/Attack__009.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Resources/Textures/Player/Dead__000.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Beamographic/rush/099eb77d51b7e491fd9259221472d351103ca4c8/osu.Game.Rulesets.Rush/Resources/Textures/Player/Dead__000.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Resources/Textures/Player/Jump_Attack__000.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Beamographic/rush/099eb77d51b7e491fd9259221472d351103ca4c8/osu.Game.Rulesets.Rush/Resources/Textures/Player/Jump_Attack__000.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Resources/Textures/Player/Jump_Attack__001.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Beamographic/rush/099eb77d51b7e491fd9259221472d351103ca4c8/osu.Game.Rulesets.Rush/Resources/Textures/Player/Jump_Attack__001.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Resources/Textures/Player/Jump_Attack__002.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Beamographic/rush/099eb77d51b7e491fd9259221472d351103ca4c8/osu.Game.Rulesets.Rush/Resources/Textures/Player/Jump_Attack__002.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Resources/Textures/Player/Jump_Attack__003.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Beamographic/rush/099eb77d51b7e491fd9259221472d351103ca4c8/osu.Game.Rulesets.Rush/Resources/Textures/Player/Jump_Attack__003.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Resources/Textures/Player/Jump_Attack__004.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Beamographic/rush/099eb77d51b7e491fd9259221472d351103ca4c8/osu.Game.Rulesets.Rush/Resources/Textures/Player/Jump_Attack__004.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Resources/Textures/Player/Jump_Attack__005.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Beamographic/rush/099eb77d51b7e491fd9259221472d351103ca4c8/osu.Game.Rulesets.Rush/Resources/Textures/Player/Jump_Attack__005.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Resources/Textures/Player/Jump_Attack__006.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Beamographic/rush/099eb77d51b7e491fd9259221472d351103ca4c8/osu.Game.Rulesets.Rush/Resources/Textures/Player/Jump_Attack__006.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Resources/Textures/Player/Jump_Attack__007.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Beamographic/rush/099eb77d51b7e491fd9259221472d351103ca4c8/osu.Game.Rulesets.Rush/Resources/Textures/Player/Jump_Attack__007.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Resources/Textures/Player/Jump_Attack__008.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Beamographic/rush/099eb77d51b7e491fd9259221472d351103ca4c8/osu.Game.Rulesets.Rush/Resources/Textures/Player/Jump_Attack__008.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Resources/Textures/Player/Jump_Attack__009.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Beamographic/rush/099eb77d51b7e491fd9259221472d351103ca4c8/osu.Game.Rulesets.Rush/Resources/Textures/Player/Jump_Attack__009.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Resources/Textures/Player/Jump__000.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Beamographic/rush/099eb77d51b7e491fd9259221472d351103ca4c8/osu.Game.Rulesets.Rush/Resources/Textures/Player/Jump__000.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Resources/Textures/Player/Jump__001.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Beamographic/rush/099eb77d51b7e491fd9259221472d351103ca4c8/osu.Game.Rulesets.Rush/Resources/Textures/Player/Jump__001.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Resources/Textures/Player/Jump__002.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Beamographic/rush/099eb77d51b7e491fd9259221472d351103ca4c8/osu.Game.Rulesets.Rush/Resources/Textures/Player/Jump__002.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Resources/Textures/Player/Jump__003.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Beamographic/rush/099eb77d51b7e491fd9259221472d351103ca4c8/osu.Game.Rulesets.Rush/Resources/Textures/Player/Jump__003.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Resources/Textures/Player/Jump__004.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Beamographic/rush/099eb77d51b7e491fd9259221472d351103ca4c8/osu.Game.Rulesets.Rush/Resources/Textures/Player/Jump__004.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Resources/Textures/Player/Jump__005.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Beamographic/rush/099eb77d51b7e491fd9259221472d351103ca4c8/osu.Game.Rulesets.Rush/Resources/Textures/Player/Jump__005.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Resources/Textures/Player/Jump__006.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Beamographic/rush/099eb77d51b7e491fd9259221472d351103ca4c8/osu.Game.Rulesets.Rush/Resources/Textures/Player/Jump__006.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Resources/Textures/Player/Jump__007.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Beamographic/rush/099eb77d51b7e491fd9259221472d351103ca4c8/osu.Game.Rulesets.Rush/Resources/Textures/Player/Jump__007.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Resources/Textures/Player/Jump__008.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Beamographic/rush/099eb77d51b7e491fd9259221472d351103ca4c8/osu.Game.Rulesets.Rush/Resources/Textures/Player/Jump__008.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Resources/Textures/Player/Jump__009.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Beamographic/rush/099eb77d51b7e491fd9259221472d351103ca4c8/osu.Game.Rulesets.Rush/Resources/Textures/Player/Jump__009.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Resources/Textures/Player/Run__000.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Beamographic/rush/099eb77d51b7e491fd9259221472d351103ca4c8/osu.Game.Rulesets.Rush/Resources/Textures/Player/Run__000.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Resources/Textures/Player/Run__001.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Beamographic/rush/099eb77d51b7e491fd9259221472d351103ca4c8/osu.Game.Rulesets.Rush/Resources/Textures/Player/Run__001.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Resources/Textures/Player/Run__002.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Beamographic/rush/099eb77d51b7e491fd9259221472d351103ca4c8/osu.Game.Rulesets.Rush/Resources/Textures/Player/Run__002.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Resources/Textures/Player/Run__003.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Beamographic/rush/099eb77d51b7e491fd9259221472d351103ca4c8/osu.Game.Rulesets.Rush/Resources/Textures/Player/Run__003.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Resources/Textures/Player/Run__004.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Beamographic/rush/099eb77d51b7e491fd9259221472d351103ca4c8/osu.Game.Rulesets.Rush/Resources/Textures/Player/Run__004.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Resources/Textures/Player/Run__005.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Beamographic/rush/099eb77d51b7e491fd9259221472d351103ca4c8/osu.Game.Rulesets.Rush/Resources/Textures/Player/Run__005.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Resources/Textures/Player/Run__006.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Beamographic/rush/099eb77d51b7e491fd9259221472d351103ca4c8/osu.Game.Rulesets.Rush/Resources/Textures/Player/Run__006.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Resources/Textures/Player/Run__007.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Beamographic/rush/099eb77d51b7e491fd9259221472d351103ca4c8/osu.Game.Rulesets.Rush/Resources/Textures/Player/Run__007.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Resources/Textures/Player/Run__008.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Beamographic/rush/099eb77d51b7e491fd9259221472d351103ca4c8/osu.Game.Rulesets.Rush/Resources/Textures/Player/Run__008.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Resources/Textures/Player/Run__009.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Beamographic/rush/099eb77d51b7e491fd9259221472d351103ca4c8/osu.Game.Rulesets.Rush/Resources/Textures/Player/Run__009.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Resources/Textures/Player/Slide__000.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Beamographic/rush/099eb77d51b7e491fd9259221472d351103ca4c8/osu.Game.Rulesets.Rush/Resources/Textures/Player/Slide__000.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Resources/Textures/Player/Slide__001.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Beamographic/rush/099eb77d51b7e491fd9259221472d351103ca4c8/osu.Game.Rulesets.Rush/Resources/Textures/Player/Slide__001.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Resources/Textures/Player/Slide__002.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Beamographic/rush/099eb77d51b7e491fd9259221472d351103ca4c8/osu.Game.Rulesets.Rush/Resources/Textures/Player/Slide__002.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Resources/Textures/Player/Slide__003.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Beamographic/rush/099eb77d51b7e491fd9259221472d351103ca4c8/osu.Game.Rulesets.Rush/Resources/Textures/Player/Slide__003.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Resources/Textures/Player/Slide__004.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Beamographic/rush/099eb77d51b7e491fd9259221472d351103ca4c8/osu.Game.Rulesets.Rush/Resources/Textures/Player/Slide__004.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Resources/Textures/Player/Slide__005.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Beamographic/rush/099eb77d51b7e491fd9259221472d351103ca4c8/osu.Game.Rulesets.Rush/Resources/Textures/Player/Slide__005.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Resources/Textures/Player/Slide__006.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Beamographic/rush/099eb77d51b7e491fd9259221472d351103ca4c8/osu.Game.Rulesets.Rush/Resources/Textures/Player/Slide__006.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Resources/Textures/Player/Slide__007.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Beamographic/rush/099eb77d51b7e491fd9259221472d351103ca4c8/osu.Game.Rulesets.Rush/Resources/Textures/Player/Slide__007.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Resources/Textures/Player/Slide__008.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Beamographic/rush/099eb77d51b7e491fd9259221472d351103ca4c8/osu.Game.Rulesets.Rush/Resources/Textures/Player/Slide__008.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Resources/Textures/Player/Slide__009.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Beamographic/rush/099eb77d51b7e491fd9259221472d351103ca4c8/osu.Game.Rulesets.Rush/Resources/Textures/Player/Slide__009.png -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/RushDifficultyCalculator.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. 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.Rush 14 | { 15 | public class RushDifficultyCalculator : DifficultyCalculator 16 | { 17 | public RushDifficultyCalculator(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) { StarRating = beatmap.BeatmapInfo.StarRating }; 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.Rush/RushSkinComponent.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. Licensed under the MIT Licence. 2 | // See the LICENCE file in the repository root for full licence text. 3 | 4 | using osu.Game.Skinning; 5 | 6 | namespace osu.Game.Rulesets.Rush 7 | { 8 | public class RushSkinComponent : SkinComponentLookup 9 | { 10 | public RushSkinComponent(RushSkinComponents component) 11 | : base(component) 12 | { 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/RushSkinComponents.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. Licensed under the MIT Licence. 2 | // See the LICENCE file in the repository root for full licence text. 3 | 4 | namespace osu.Game.Rulesets.Rush 5 | { 6 | public enum RushSkinComponents 7 | { 8 | Minion, 9 | StarSheetHead, 10 | StarSheetTail, 11 | StarSheetBody, 12 | StarSheetHold, 13 | StarSheetExplosion, 14 | Miniboss, 15 | Sawblade, 16 | DualHitPart, 17 | DualHitJoin, 18 | Heart, 19 | AirHitTarget, 20 | GroundHitTarget, 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Scoring/HeartHitWindows.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. Licensed under the MIT Licence. 2 | // See the LICENCE file in the repository root for full licence text. 3 | 4 | using osu.Game.Rulesets.Scoring; 5 | 6 | namespace osu.Game.Rulesets.Rush.Scoring 7 | { 8 | public class HeartHitWindows : RushHitWindows 9 | { 10 | protected override DifficultyRange[] GetRanges() => new[] 11 | { 12 | new DifficultyRange(HitResult.Great, 50, 50, 50), 13 | new DifficultyRange(HitResult.Miss, 200, 200, 200) 14 | }; 15 | 16 | public override bool IsHitResultAllowed(HitResult result) => result == HitResult.Great || result == HitResult.Miss; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Scoring/RushHealthProcessor.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. Licensed under the MIT Licence. 2 | // See the LICENCE file in the repository root for full licence text. 3 | 4 | using osu.Game.Rulesets.Judgements; 5 | using osu.Game.Rulesets.Objects; 6 | using osu.Game.Rulesets.Rush.Judgements; 7 | using osu.Game.Rulesets.Rush.Objects; 8 | using osu.Game.Rulesets.Scoring; 9 | 10 | namespace osu.Game.Rulesets.Rush.Scoring 11 | { 12 | public partial class RushHealthProcessor : HealthProcessor 13 | { 14 | public double PlayerHealthPercentage { get; } 15 | 16 | public RushHealthProcessor(double playerHealthPercentage = 100f) 17 | { 18 | PlayerHealthPercentage = playerHealthPercentage; 19 | } 20 | 21 | protected virtual double GetHealthPointIncreaseFor(RushJudgementResult result) => result.Judgement.HealthPointIncreaseFor(result); 22 | 23 | protected sealed override double GetHealthIncreaseFor(JudgementResult result) 24 | { 25 | var pointIncrease = GetHealthPointIncreaseFor((RushJudgementResult)result); 26 | return pointIncrease / PlayerHealthPercentage; 27 | } 28 | 29 | protected override JudgementResult CreateResult(HitObject hitObject, Judgement judgement) => new RushJudgementResult((RushHitObject)hitObject, (RushJudgement)judgement); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Scoring/RushHitWindows.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. Licensed under the MIT Licence. 2 | // See the LICENCE file in the repository root for full licence text. 3 | 4 | using osu.Game.Rulesets.Scoring; 5 | 6 | namespace osu.Game.Rulesets.Rush.Scoring 7 | { 8 | public class RushHitWindows : HitWindows 9 | { 10 | protected override DifficultyRange[] GetRanges() => new[] 11 | { 12 | new DifficultyRange(HitResult.Great, 80, 50, 20), 13 | new DifficultyRange(HitResult.Good, 160, 120, 80), 14 | new DifficultyRange(HitResult.Miss, 200, 180, 160), 15 | }; 16 | 17 | public override bool IsHitResultAllowed(HitResult result) => 18 | result switch 19 | { 20 | HitResult.Miss => true, 21 | HitResult.Good => true, 22 | HitResult.Great => true, 23 | _ => false 24 | }; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Scoring/RushScoreProcessor.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. Licensed under the MIT Licence. 2 | // See the LICENCE file in the repository root for full licence text. 3 | 4 | using osu.Game.Rulesets.Judgements; 5 | using osu.Game.Rulesets.Objects; 6 | using osu.Game.Rulesets.Rush.Judgements; 7 | using osu.Game.Rulesets.Rush.Objects; 8 | using osu.Game.Rulesets.Scoring; 9 | 10 | namespace osu.Game.Rulesets.Rush.Scoring 11 | { 12 | public partial class RushScoreProcessor : ScoreProcessor 13 | { 14 | public RushScoreProcessor(RushRuleset ruleset) : base(ruleset) { } 15 | 16 | protected override JudgementResult CreateResult(HitObject hitObject, Judgement judgement) => 17 | new RushJudgementResult((RushHitObject)hitObject, (RushJudgement)judgement); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/Scoring/SawbladeHitWindows.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. Licensed under the MIT Licence. 2 | // See the LICENCE file in the repository root for full licence text. 3 | 4 | using osu.Game.Rulesets.Scoring; 5 | 6 | namespace osu.Game.Rulesets.Rush.Scoring 7 | { 8 | public class SawbladeHitWindows : RushHitWindows 9 | { 10 | protected override DifficultyRange[] GetRanges() => new[] 11 | { 12 | new DifficultyRange(HitResult.Great, 20, 20, 20), 13 | new DifficultyRange(HitResult.Miss, 50, 50, 50) 14 | }; 15 | 16 | public override bool IsHitResultAllowed(HitResult result) => result == HitResult.Great || result == HitResult.Miss; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/UI/ActionBeatSyncedContainer.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. 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.Audio.Track; 6 | using osu.Game.Beatmaps.ControlPoints; 7 | using osu.Game.Graphics.Containers; 8 | 9 | namespace osu.Game.Rulesets.Rush.UI 10 | { 11 | public partial class ActionBeatSyncedContainer : BeatSyncedContainer 12 | { 13 | public Action NewBeat; 14 | 15 | protected override void OnNewBeat(int beatIndex, TimingControlPoint timingPoint, EffectControlPoint effectPoint, ChannelAmplitudes amplitudes) => 16 | NewBeat?.Invoke(beatIndex, timingPoint, effectPoint, amplitudes); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/UI/DefaultHitExplosion.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. 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.Linq; 6 | using osu.Framework.Allocation; 7 | using osu.Framework.Extensions.Color4Extensions; 8 | using osu.Framework.Graphics; 9 | using osu.Framework.Graphics.Containers; 10 | using osu.Framework.Graphics.Pooling; 11 | using osu.Framework.Graphics.Shapes; 12 | using osu.Framework.Graphics.Sprites; 13 | using osu.Framework.Graphics.Textures; 14 | using osu.Framework.Utils; 15 | using osu.Game.Rulesets.Objects.Drawables; 16 | using osu.Game.Rulesets.Rush.Objects.Drawables; 17 | using osuTK; 18 | using osuTK.Graphics; 19 | 20 | namespace osu.Game.Rulesets.Rush.UI 21 | { 22 | public partial class DefaultHitExplosion : PoolableDrawable 23 | { 24 | private readonly Sprite colouredExplosion; 25 | private readonly Sprite whiteExplosion; 26 | 27 | private readonly Sparks sparks; 28 | 29 | public override bool RemoveWhenNotAlive => true; 30 | public override bool RemoveCompletedTransforms => false; 31 | 32 | public DefaultHitExplosion() 33 | : this(Color4.White) 34 | { 35 | } 36 | 37 | public DefaultHitExplosion(Color4 explosionColour, int sparkCount = 10, Color4? sparkColour = null) 38 | { 39 | Depth = 1f; 40 | Origin = Anchor.Centre; 41 | Size = new Vector2(200, 200); 42 | Scale = new Vector2(0.9f + RNG.NextSingle() * 0.2f); 43 | 44 | InternalChildren = new Drawable[] 45 | { 46 | colouredExplosion = new Sprite 47 | { 48 | Anchor = Anchor.Centre, 49 | Origin = Anchor.Centre, 50 | Colour = explosionColour, 51 | Scale = new Vector2(1f) 52 | }, 53 | whiteExplosion = new Sprite 54 | { 55 | Anchor = Anchor.Centre, 56 | Origin = Anchor.Centre, 57 | Scale = new Vector2(0.75f) 58 | }, 59 | sparks = new Sparks(sparkCount) 60 | { 61 | Anchor = Anchor.Centre, 62 | Origin = Anchor.Centre, 63 | RelativeSizeAxes = Axes.Both, 64 | Size = new Vector2(2f), 65 | Colour = sparkColour ?? Color4.White 66 | } 67 | // TODO: stars 68 | }; 69 | } 70 | 71 | public void Apply(DrawableHitObject hitObject) 72 | { 73 | if (hitObject is DrawableMiniBoss miniBoss) 74 | { 75 | Alpha = 0; 76 | Depth = 0; 77 | Origin = Anchor.Centre; 78 | Anchor = miniBoss.Anchor; 79 | Size = new Vector2(200, 200); 80 | Scale = new Vector2(0.9f + RNG.NextSingle() * 0.2f) * 1.5f; 81 | Rotation = RNG.NextSingle() * 360f; 82 | colouredExplosion.Colour = Color4.Yellow.Darken(0.5f); 83 | } 84 | else if (hitObject is IDrawableLanedHit laned) 85 | { 86 | colouredExplosion.Colour = laned.LaneAccentColour; 87 | Anchor = laned.LaneAnchor; 88 | Rotation = RNG.NextSingle() * 360f; 89 | } 90 | } 91 | 92 | [BackgroundDependencyLoader] 93 | private void load(TextureStore store) 94 | { 95 | colouredExplosion.Texture = store.Get("Effects/explosion"); 96 | whiteExplosion.Texture = store.Get("Effects/explosion"); 97 | } 98 | 99 | protected override void PrepareForUse() 100 | { 101 | ApplyTransformsAt(double.MinValue, true); 102 | ClearTransforms(true); 103 | ApplyExplosionTransforms(); 104 | } 105 | 106 | /// 107 | /// Applies all transforms to animate the explosion. 108 | /// 109 | protected virtual void ApplyExplosionTransforms() 110 | { 111 | this.ScaleTo(Scale * 0.5f, RushPlayfield.HIT_EXPLOSION_DURATION) 112 | .FadeOutFromOne(RushPlayfield.HIT_EXPLOSION_DURATION) 113 | .Expire(true); 114 | 115 | sparks.Animate(); 116 | } 117 | 118 | protected partial class Sparks : CompositeDrawable 119 | { 120 | public override bool RemoveCompletedTransforms => false; 121 | 122 | private const double average_duration = 1500f; 123 | 124 | private readonly Random random = new Random(); 125 | private readonly Triangle[] triangles; 126 | 127 | private double randomDirection(int index, int max) 128 | { 129 | var offset = random.NextDouble() * 2f / max; 130 | return (double)index / max + offset; 131 | } 132 | 133 | public Sparks(int sparkCount) 134 | { 135 | Origin = Anchor.Centre; 136 | Anchor = Anchor.Centre; 137 | RelativeSizeAxes = Axes.Both; 138 | 139 | triangles = Enumerable.Range(0, sparkCount).Select(i => new Triangle 140 | { 141 | Origin = Anchor.Centre, 142 | Anchor = Anchor.Centre, 143 | Size = new Vector2(5f, 10f), 144 | Rotation = (float)(randomDirection(i, sparkCount) * 360), 145 | }).ToArray(); 146 | 147 | InternalChildren = triangles; 148 | } 149 | 150 | public void Animate() 151 | { 152 | foreach (var triangle in triangles) 153 | { 154 | var scale = 0.8f + random.NextDouble() * 0.2f; 155 | var duration = average_duration * (0.8f + random.NextDouble() * 0.4f); 156 | var radians = float.DegreesToRadians(triangle.Rotation + 90); 157 | var distance = DrawWidth * (0.8f + random.NextDouble() * 0.2f); 158 | var target = new Vector2(MathF.Cos(radians), MathF.Sin(radians)) * (float)distance; 159 | triangle.Scale = new Vector2((float)scale); 160 | triangle.MoveTo(target, duration, Easing.OutExpo); 161 | triangle.FadeOutFromOne(duration, Easing.InExpo); 162 | } 163 | } 164 | } 165 | } 166 | } 167 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/UI/DrawableRushRuleset.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. 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.Bindables; 7 | using osu.Framework.Input; 8 | using osu.Game.Beatmaps; 9 | using osu.Game.Configuration; 10 | using osu.Game.Input.Handlers; 11 | using osu.Game.Replays; 12 | using osu.Game.Rulesets.Mods; 13 | using osu.Game.Rulesets.Objects; 14 | using osu.Game.Rulesets.Objects.Drawables; 15 | using osu.Game.Rulesets.Rush.Configuration; 16 | using osu.Game.Rulesets.Rush.Input; 17 | using osu.Game.Rulesets.Rush.Objects; 18 | using osu.Game.Rulesets.Rush.Replays; 19 | using osu.Game.Rulesets.Rush.UI.Fever; 20 | using osu.Game.Rulesets.UI; 21 | using osu.Game.Rulesets.UI.Scrolling; 22 | using osu.Game.Scoring; 23 | 24 | namespace osu.Game.Rulesets.Rush.UI 25 | { 26 | [Cached] 27 | public partial class DrawableRushRuleset : DrawableScrollingRuleset 28 | { 29 | private FeverProcessor feverProcessor; 30 | 31 | protected new RushRulesetConfigManager Config => (RushRulesetConfigManager)base.Config; 32 | 33 | public new RushPlayfield Playfield => (RushPlayfield)base.Playfield; 34 | 35 | public new RushInputManager KeyBindingInputManager => (RushInputManager)base.KeyBindingInputManager; 36 | 37 | public FeverActivationMode FeverActivationMode => KeyBindingInputManager.ReplayInputHandler?.FeverActivationMode ?? feverActivationModeSetting.Value; 38 | 39 | protected override bool UserScrollSpeedAdjustment => true; 40 | 41 | public DrawableRushRuleset(RushRuleset ruleset, IBeatmap beatmap, IReadOnlyList mods = null) 42 | : base(ruleset, beatmap, mods) 43 | { 44 | Direction.Value = ScrollingDirection.Left; 45 | TimeRange.Value = 800; 46 | VisualisationMethod = ScrollVisualisationMethod.Constant; 47 | } 48 | 49 | protected override IReadOnlyDependencyContainer CreateChildDependencies(IReadOnlyDependencyContainer parent) 50 | { 51 | var dependencies = new DependencyContainer(base.CreateChildDependencies(parent)); 52 | 53 | dependencies.CacheAs(feverProcessor = new FeverProcessor()); 54 | 55 | NewResult += feverProcessor.ApplyResult; 56 | RevertResult += feverProcessor.RevertResult; 57 | 58 | return dependencies; 59 | } 60 | 61 | private readonly Bindable feverActivationModeSetting = new Bindable(); 62 | 63 | [BackgroundDependencyLoader] 64 | private void load() 65 | { 66 | Config?.BindWith(RushRulesetSettings.FeverActivationMode, feverActivationModeSetting); 67 | 68 | FrameStableComponents.Add(feverProcessor); 69 | } 70 | 71 | public bool PlayerCollidesWith(HitObject hitObject) => Playfield.PlayerSprite.CollidesWith(hitObject); 72 | 73 | protected override Playfield CreatePlayfield() => new RushPlayfield(); 74 | 75 | protected override ReplayInputHandler CreateReplayInputHandler(Replay replay) => new RushFramedReplayInputHandler(replay); 76 | 77 | protected override ReplayRecorder CreateReplayRecorder(Score score) => new RushReplayRecorder(score); 78 | 79 | public override DrawableHitObject CreateDrawableRepresentation(RushHitObject h) => null; 80 | 81 | protected override PassThroughInputManager CreateInputManager() => new RushInputManager(Ruleset?.RulesetInfo); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/UI/Fever/RushFeverBar.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. 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.Allocation; 6 | using osu.Framework.Bindables; 7 | using osu.Framework.Extensions.Color4Extensions; 8 | using osu.Framework.Graphics; 9 | using osu.Framework.Graphics.Containers; 10 | using osu.Framework.Graphics.Effects; 11 | using osu.Framework.Graphics.Shapes; 12 | using osu.Framework.Localisation; 13 | using osu.Game.Graphics; 14 | using osu.Game.Graphics.Sprites; 15 | using osu.Game.Graphics.UserInterface; 16 | using osu.Game.Rulesets.Rush.Input; 17 | using osuTK; 18 | using osuTK.Graphics; 19 | 20 | namespace osu.Game.Rulesets.Rush.UI.Fever 21 | { 22 | public partial class FeverBar : CircularContainer, IKeyBindingTouchHandler 23 | { 24 | public override bool HandlePositionalInput => true; 25 | 26 | private Box progressBar; 27 | 28 | public override bool RemoveCompletedTransforms => true; 29 | 30 | public FeverBar() 31 | { 32 | Y = 150; 33 | Anchor = Anchor.BottomCentre; 34 | Origin = Anchor.TopCentre; 35 | RelativeSizeAxes = Axes.X; 36 | Size = new Vector2(0.5f, 50); 37 | Masking = true; 38 | BorderColour = Color4.Violet; 39 | BorderThickness = 5; 40 | EdgeEffect = new EdgeEffectParameters 41 | { 42 | Colour = Color4.DeepPink.Opacity(0), 43 | Type = EdgeEffectType.Glow, 44 | Radius = 20, 45 | }; 46 | } 47 | 48 | private IBindable inFeverMode; 49 | private IBindable feverProgress; 50 | 51 | [BackgroundDependencyLoader] 52 | private void load(FeverProcessor processor) 53 | { 54 | feverProgress = processor.FeverProgress.GetBoundCopy(); 55 | inFeverMode = processor.InFeverMode.GetBoundCopy(); 56 | 57 | Children = new Drawable[] 58 | { 59 | new Box 60 | { 61 | RelativeSizeAxes = Axes.Both, 62 | Colour = Color4.Purple, 63 | }, 64 | progressBar = new Box 65 | { 66 | RelativeSizeAxes = Axes.Both, 67 | Colour = Color4.DeepPink, 68 | Size = new Vector2(0, 1), 69 | }, 70 | new Container 71 | { 72 | RelativeSizeAxes = Axes.Both, 73 | Padding = new MarginPadding(15), 74 | Children = new Drawable[] 75 | { 76 | new OsuSpriteText 77 | { 78 | Anchor = Anchor.CentreLeft, 79 | Origin = Anchor.CentreLeft, 80 | Text = "FEVER", 81 | Colour = Color4.White, 82 | Font = OsuFont.Numeric.With(size: 20), 83 | UseFullGlyphHeight = false 84 | }, 85 | new FeverRollingCounter 86 | { 87 | Anchor = Anchor.CentreRight, 88 | Origin = Anchor.CentreRight, 89 | Colour = Color4.White, 90 | Current = { BindTarget = feverProgress } 91 | } 92 | } 93 | } 94 | }; 95 | 96 | feverProgress.ValueChanged += updateProgressBar; 97 | inFeverMode.ValueChanged += updateFeverState; 98 | } 99 | 100 | private void updateProgressBar(ValueChangedEvent valueChanged) 101 | { 102 | if (!inFeverMode.Value) 103 | { 104 | if (valueChanged.NewValue >= 1 && valueChanged.OldValue < 1) 105 | FadeEdgeEffectTo(0.5f, 100); 106 | else if (valueChanged.NewValue < 1 && valueChanged.OldValue >= 1) 107 | FadeEdgeEffectTo(0f); // Just to support rewinds 108 | } 109 | 110 | progressBar.ResizeWidthTo(Math.Min(1, valueChanged.NewValue), 100); 111 | 112 | if (Clock.Rate < 0) 113 | FinishTransforms(true); // Force the animations to finish immediately when rewinding 114 | } 115 | 116 | private void updateFeverState(ValueChangedEvent valueChanged) 117 | { 118 | if (valueChanged.NewValue) 119 | { 120 | FadeEdgeEffectTo(Color4.Red, 100); 121 | progressBar.FadeColour(Color4.Red, 100); 122 | } 123 | else 124 | { 125 | FadeEdgeEffectTo(Color4.DeepPink.Opacity(0), 200); 126 | progressBar.FadeColour(Color4.DeepPink, 200); 127 | } 128 | 129 | if (Clock.Rate < 0) 130 | FinishTransforms(true); // Force the animations to finish immediately when rewinding 131 | } 132 | 133 | private RushInputManager rushActionInputManager; 134 | internal RushInputManager RushActionInputManager => rushActionInputManager ??= GetContainingInputManager() as RushInputManager; 135 | 136 | public RushActionTarget ActionTargetForTouchPosition(Vector2 screenSpaceTouchPos) => RushActionTarget.Fever; 137 | 138 | private partial class FeverRollingCounter : RollingCounter 139 | { 140 | protected override double RollingDuration => 100; 141 | 142 | public FeverRollingCounter() 143 | { 144 | Anchor = Anchor.Centre; 145 | Origin = Anchor.Centre; 146 | } 147 | 148 | protected override OsuSpriteText CreateSpriteText() 149 | { 150 | return new OsuSpriteText 151 | { 152 | Anchor = Anchor.Centre, 153 | Origin = Anchor.Centre, 154 | Font = OsuFont.Numeric.With(size: 20), 155 | UseFullGlyphHeight = false, 156 | }; 157 | } 158 | 159 | protected override LocalisableString FormatCount(float count) => Math.Floor(Math.Min(count, 1) * 100).ToString("0\\%"); 160 | } 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/UI/Ground/DefaultGround.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. 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.Extensions.Color4Extensions; 6 | using osu.Framework.Extensions.EnumExtensions; 7 | using osu.Framework.Graphics; 8 | using osu.Framework.Graphics.Colour; 9 | using osu.Framework.Graphics.Containers; 10 | using osu.Framework.Graphics.Pooling; 11 | using osu.Framework.Graphics.Shapes; 12 | using osu.Framework.Layout; 13 | using osu.Game.Rulesets.UI.Scrolling; 14 | using osuTK; 15 | using osuTK.Graphics; 16 | 17 | namespace osu.Game.Rulesets.Rush.UI.Ground 18 | { 19 | public partial class DefaultGround : CompositeDrawable 20 | { 21 | private static readonly Color4 platform_colour = Color4.Gray.Opacity(0.2f); 22 | 23 | private static readonly ColourInfo slat_colour = ColourInfo.GradientVertical(Color4.Gray.Opacity(0.8f), Color4.Gray.Opacity(0.4f)); 24 | private static readonly Vector2 slat_size = new Vector2(10f, 100f); 25 | 26 | private const float slat_angle = -40f; 27 | 28 | private const float slats_spacing = 100f; 29 | 30 | private static readonly Color4 ground_colour = Color4.Gray.Opacity(0.2f); 31 | 32 | private readonly Container slats; 33 | 34 | private readonly DrawablePool linePool; 35 | 36 | public DefaultGround() 37 | { 38 | RelativeSizeAxes = Axes.Both; 39 | 40 | InternalChild = new FillFlowContainer 41 | { 42 | RelativeSizeAxes = Axes.Both, 43 | Direction = FillDirection.Vertical, 44 | Children = new Drawable[] 45 | { 46 | linePool = new DrawablePool(10), 47 | new Box 48 | { 49 | Name = "Top line", 50 | Colour = platform_colour.Opacity(1f).Lighten(1f), 51 | RelativeSizeAxes = Axes.X, 52 | Height = 3f, 53 | Depth = -1, 54 | }, 55 | new Container 56 | { 57 | Name = "Platform", 58 | Masking = true, 59 | AutoSizeAxes = Axes.Y, 60 | RelativeSizeAxes = Axes.X, 61 | Children = new Drawable[] 62 | { 63 | new Box 64 | { 65 | RelativeSizeAxes = Axes.Both, 66 | Colour = platform_colour, 67 | }, 68 | slats = new Container 69 | { 70 | AutoSizeAxes = Axes.Both, 71 | }, 72 | } 73 | }, 74 | new Box 75 | { 76 | Name = "Bottom line", 77 | Colour = platform_colour.Opacity(1f).Lighten(2f), 78 | RelativeSizeAxes = Axes.X, 79 | Height = 3f, 80 | }, 81 | new Box 82 | { 83 | Name = "Ground", 84 | Colour = ground_colour, 85 | RelativeSizeAxes = Axes.Both, 86 | } 87 | } 88 | }; 89 | } 90 | 91 | [Resolved(canBeNull: true)] 92 | private IScrollingInfo scrollingInfo { get; set; } 93 | 94 | protected override void UpdateAfterChildren() 95 | { 96 | base.UpdateAfterChildren(); 97 | 98 | // Tests don't have scrolling info yet 99 | if (scrollingInfo is null) return; 100 | 101 | var groundX = scrollingInfo.Algorithm.Value.PositionAt(0f, Time.Current, scrollingInfo.TimeRange.Value, DrawWidth - RushPlayfield.HIT_TARGET_OFFSET) % slats_spacing; 102 | 103 | // This is to ensure that the ground is still visible before the start of the track 104 | if (groundX > 0) 105 | groundX = -slats_spacing + groundX; 106 | 107 | slats.X = groundX; 108 | } 109 | 110 | protected override bool OnInvalidate(Invalidation invalidation, InvalidationSource source) 111 | { 112 | if (invalidation.HasFlag(Invalidation.DrawSize)) 113 | { 114 | slats.Clear(false); 115 | 116 | for (float i = 0; i < DrawWidth + slats_spacing; i += slats_spacing) 117 | slats.Add(linePool.Get(l => l.X = i)); 118 | } 119 | 120 | return base.OnInvalidate(invalidation, source); 121 | } 122 | 123 | private partial class GroundLine : PoolableDrawable 124 | { 125 | public override bool RemoveWhenNotAlive => false; 126 | 127 | public GroundLine() 128 | { 129 | Colour = slat_colour; 130 | Anchor = Anchor.TopLeft; 131 | Origin = Anchor.TopLeft; 132 | Size = slat_size; 133 | Rotation = slat_angle; 134 | Margin = new MarginPadding { Bottom = -10f }; 135 | InternalChild = new Box 136 | { 137 | RelativeSizeAxes = Axes.Both 138 | }; 139 | } 140 | } 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/UI/Ground/GroundDisplay.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. Licensed under the MIT Licence. 2 | // See the LICENCE file in the repository root for full licence text. 3 | 4 | using osu.Framework.Graphics; 5 | using osu.Framework.Graphics.Containers; 6 | 7 | namespace osu.Game.Rulesets.Rush.UI.Ground 8 | { 9 | /// 10 | /// Represents a component displaying the ground the player will be standing on. 11 | /// 12 | public partial class GroundDisplay : CompositeDrawable 13 | { 14 | public GroundDisplay() 15 | { 16 | Anchor = Anchor.BottomCentre; 17 | Origin = Anchor.TopCentre; 18 | RelativeSizeAxes = Axes.Both; 19 | Padding = new MarginPadding { Top = 50f }; 20 | 21 | InternalChildren = new Drawable[] 22 | { 23 | new DefaultGround(), 24 | }; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/UI/HealthText.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. Licensed under the MIT Licence. 2 | // See the LICENCE file in the repository root for full licence text. 3 | 4 | using osu.Framework.Graphics; 5 | using osu.Framework.Graphics.Pooling; 6 | using osu.Framework.Graphics.Sprites; 7 | using osuTK; 8 | using osuTK.Graphics; 9 | 10 | namespace osu.Game.Rulesets.Rush.UI 11 | { 12 | public partial class HealthText : PoolableDrawable 13 | { 14 | private readonly SpriteText text; 15 | 16 | public override bool RemoveCompletedTransforms => false; 17 | 18 | public HealthText() 19 | { 20 | Origin = Anchor.Centre; 21 | Anchor = Anchor.CentreLeft; 22 | 23 | InternalChildren = new Drawable[] 24 | { 25 | text = new SpriteText 26 | { 27 | Font = FontUsage.Default.With(size: 40), 28 | Scale = new Vector2(1.2f), 29 | } 30 | }; 31 | } 32 | 33 | public void Apply(double pointDifference) 34 | { 35 | text.Colour = pointDifference > 0 ? Color4.Green : Color4.Red; 36 | text.Text = $"{pointDifference:+0;-0}"; 37 | } 38 | 39 | protected override void PrepareForUse() 40 | { 41 | base.PrepareForUse(); 42 | 43 | const float judgement_time = 250f; 44 | 45 | ApplyTransformsAt(double.MinValue); 46 | ClearTransforms(); 47 | 48 | this.ScaleTo(1f, judgement_time) 49 | .Then() 50 | .FadeOutFromOne(judgement_time) 51 | .MoveToOffset(new Vector2(0f, -20f), judgement_time) 52 | .Expire(true); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/UI/HeartHitExplosion.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. Licensed under the MIT Licence. 2 | // See the LICENCE file in the repository root for full licence text. 3 | 4 | using osu.Framework.Graphics; 5 | using osu.Game.Rulesets.Rush.Objects.Drawables; 6 | using osu.Game.Rulesets.Rush.Objects.Drawables.Pieces; 7 | using osuTK; 8 | 9 | namespace osu.Game.Rulesets.Rush.UI 10 | { 11 | public partial class HeartHitExplosion : HeartPiece 12 | { 13 | public override bool RemoveCompletedTransforms => false; 14 | 15 | public HeartHitExplosion() 16 | { 17 | Origin = Anchor.Centre; 18 | Scale = new Vector2(0.5f); 19 | } 20 | 21 | protected override void PrepareForUse() 22 | { 23 | ApplyTransformsAt(double.MinValue); 24 | ClearTransforms(); 25 | 26 | this.ScaleTo(1.25f, RushPlayfield.HIT_EXPLOSION_DURATION) 27 | .FadeOutFromOne(RushPlayfield.HIT_EXPLOSION_DURATION) 28 | .Expire(true); 29 | } 30 | 31 | public void Apply(DrawableHeart drawableHeart) 32 | { 33 | Anchor = drawableHeart.LaneAnchor; 34 | Size = drawableHeart.Size; 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/UI/HitTarget.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. Licensed under the MIT Licence. 2 | // See the LICENCE file in the repository root for full licence text. 3 | 4 | using osu.Framework.Audio.Track; 5 | using osu.Framework.Graphics; 6 | using osu.Framework.Graphics.Containers; 7 | using osu.Framework.Graphics.Shapes; 8 | using osu.Game.Beatmaps.ControlPoints; 9 | using osu.Game.Graphics.Containers; 10 | using osuTK.Graphics; 11 | 12 | namespace osu.Game.Rulesets.Rush.UI 13 | { 14 | public partial class HitTarget : BeatSyncedContainer 15 | { 16 | public HitTarget() 17 | { 18 | Anchor = Anchor.Centre; 19 | Origin = Anchor.Centre; 20 | Children = new Drawable[] 21 | { 22 | new CircularContainer 23 | { 24 | Anchor = Anchor.Centre, 25 | Origin = Anchor.Centre, 26 | RelativeSizeAxes = Axes.Both, 27 | Masking = true, 28 | BorderColour = Color4.White, 29 | BorderThickness = 3f, 30 | Alpha = 0.35f, 31 | Child = new Box 32 | { 33 | RelativeSizeAxes = Axes.Both, 34 | Alpha = 0, 35 | AlwaysPresent = true 36 | } 37 | }, 38 | }; 39 | } 40 | 41 | protected override void OnNewBeat(int beatIndex, TimingControlPoint timingPoint, EffectControlPoint effectPoint, ChannelAmplitudes amplitudes) => 42 | this.ScaleTo(1.2f) 43 | .Then() 44 | .ScaleTo(1f, timingPoint.BeatLength, Easing.Out); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/UI/LanePlayfield.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. 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.Containers; 7 | using osu.Framework.Graphics.Pooling; 8 | using osu.Game.Rulesets.Judgements; 9 | using osu.Game.Rulesets.Objects.Drawables; 10 | using osu.Game.Rulesets.Rush.Objects; 11 | using osu.Game.Rulesets.Rush.Objects.Drawables; 12 | using osu.Game.Rulesets.UI; 13 | using osu.Game.Rulesets.UI.Scrolling; 14 | using osuTK; 15 | 16 | namespace osu.Game.Rulesets.Rush.UI 17 | { 18 | public partial class LanePlayfield : ScrollingPlayfield 19 | { 20 | private readonly JudgementContainer judgementContainer; 21 | private readonly Container effectsContainer; 22 | 23 | private readonly LanedHitLane lane; 24 | 25 | public LanePlayfield(LanedHitLane type) 26 | { 27 | bool isAirLane = type == LanedHitLane.Air; 28 | lane = type; 29 | 30 | Name = $"{(isAirLane ? "Air" : "Ground")} Playfield"; 31 | Padding = new MarginPadding { Left = RushPlayfield.HIT_TARGET_OFFSET }; 32 | Anchor = Origin = isAirLane ? Anchor.TopCentre : Anchor.BottomCentre; 33 | RelativeSizeAxes = Axes.Both; 34 | Size = new Vector2(1, 0); 35 | 36 | AddRangeInternal(new Drawable[] 37 | { 38 | new Container 39 | { 40 | Name = "Hit Target", 41 | Anchor = Anchor.CentreLeft, 42 | Origin = Anchor.Centre, 43 | Size = new Vector2(RushPlayfield.HIT_TARGET_SIZE), 44 | Child = new HitTarget 45 | { 46 | RelativeSizeAxes = Axes.Both, 47 | }, 48 | }, 49 | effectsContainer = new Container(), 50 | judgementContainer = new JudgementContainer(), 51 | HitObjectContainer, 52 | }); 53 | } 54 | 55 | [Resolved] 56 | private RushHitPolicy hitPolicy { get; set; } 57 | 58 | [BackgroundDependencyLoader] 59 | private void load() 60 | { 61 | registerLanedPool(4); 62 | registerLanedPool(2); 63 | registerLanedPool(8); 64 | registerLanedPool(8); 65 | registerLanedPool(8); 66 | registerLanedPool(8); 67 | RegisterPool(8); 68 | } 69 | 70 | protected override void OnNewDrawableHitObject(DrawableHitObject drawableHitObject) 71 | { 72 | base.OnNewDrawableHitObject(drawableHitObject); 73 | 74 | if (drawableHitObject is DrawableRushHitObject drho) 75 | drho.CheckHittable = hitPolicy.IsHittable; 76 | } 77 | 78 | private void registerLanedPool(int initialSize, int? maximumSize = null) where TObject : LanedHit where TDrawable : DrawableLanedHit, new() 79 | { 80 | RegisterPool(new DrawableLanedObjectPool(lane, initialSize, maximumSize)); 81 | } 82 | 83 | public void AddExplosion(Drawable drawable) => effectsContainer.Add(drawable); 84 | public void AddJudgement(DrawableRushJudgement judgement) => judgementContainer.Add(judgement); 85 | 86 | // This pool pre-initializes created DrawableLanedObjects with a predefined lane value 87 | // The lane value needs to be set beforehand so that the pieces (Minion, etc) can load using the correct information 88 | private partial class DrawableLanedObjectPool : DrawablePool where T : PoolableDrawable, IDrawableLanedHit, new() 89 | { 90 | private readonly LanedHitLane lane; 91 | 92 | public DrawableLanedObjectPool(LanedHitLane lane, int initialSize, int? maximumSize) 93 | : base(initialSize, maximumSize) 94 | { 95 | this.lane = lane; 96 | } 97 | 98 | protected override T CreateNewDrawable() => new T() { Lane = lane }; 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/UI/RushHitPolicy.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. 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.Game.Rulesets.Objects; 7 | using osu.Game.Rulesets.Objects.Drawables; 8 | using osu.Game.Rulesets.Rush.Objects; 9 | using osu.Game.Rulesets.Rush.Objects.Drawables; 10 | 11 | namespace osu.Game.Rulesets.Rush.UI 12 | { 13 | public class RushHitPolicy 14 | { 15 | private readonly RushPlayfield playfield; 16 | 17 | private IEnumerable aliveHitObjects => playfield.AllAliveHitObjects; 18 | 19 | public RushHitPolicy(RushPlayfield playfield) 20 | { 21 | this.playfield = playfield; 22 | } 23 | 24 | public bool IsHittable(DrawableHitObject hitObject) => enumerateHitObjectsUpTo(hitObject.HitObject).All(obj => obj.AllJudged); 25 | 26 | private IEnumerable enumerateHitObjectsUpTo(HitObject hitobject) 27 | { 28 | double targetTime = hitobject.StartTime; 29 | 30 | foreach (var obj in aliveHitObjects) 31 | { 32 | if (obj.HitObject.StartTime >= targetTime) 33 | yield break; 34 | 35 | var laned = hitobject as LanedHit; 36 | 37 | if (laned != null) 38 | { 39 | // We don't want objects from another lane to block inputs 40 | if (obj is IDrawableLanedHit lanedTarget) 41 | if (laned.Lane != lanedTarget.Lane) 42 | continue; 43 | } 44 | 45 | switch (obj) 46 | { 47 | // We have to make sure DualHitParts from another lane don't block 48 | case DrawableDualHit dual: 49 | if (laned != null) 50 | yield return laned.Lane == LanedHitLane.Air ? dual.Air : dual.Ground; 51 | else 52 | yield return dual; 53 | 54 | break; 55 | 56 | case DrawableStarSheet sheet: 57 | yield return sheet.Head; 58 | 59 | break; 60 | 61 | default: 62 | yield return obj; 63 | 64 | break; 65 | } 66 | } 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/UI/RushReplayRecorder.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. 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.Game.Rulesets.Replays; 7 | using osu.Game.Rulesets.Rush.Input; 8 | using osu.Game.Rulesets.Rush.Replays; 9 | using osu.Game.Rulesets.UI; 10 | using osu.Game.Scoring; 11 | using osuTK; 12 | 13 | namespace osu.Game.Rulesets.Rush.UI 14 | { 15 | public partial class RushReplayRecorder : ReplayRecorder 16 | { 17 | [Resolved(canBeNull: true)] 18 | private DrawableRushRuleset drawableRuleset { get; set; } 19 | 20 | public RushReplayRecorder(Score target) 21 | : base(target) 22 | { 23 | } 24 | 25 | protected override ReplayFrame HandleFrame(Vector2 mousePosition, List actions, ReplayFrame previousFrame) 26 | { 27 | var frame = new RushReplayFrame(Time.Current, actions); 28 | 29 | if (drawableRuleset != null) 30 | frame.FeverActivationMode = drawableRuleset.FeverActivationMode; 31 | 32 | return frame; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/UI/RushSettingsSubsection.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. 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.Localisation; 7 | using osu.Game.Overlays.Settings; 8 | using osu.Game.Rulesets.Rush.Configuration; 9 | 10 | namespace osu.Game.Rulesets.Rush.UI 11 | { 12 | public partial class RushSettingsSubsection : RulesetSettingsSubsection 13 | { 14 | private readonly Ruleset ruleset; 15 | 16 | protected new RushRulesetConfigManager Config => (RushRulesetConfigManager)base.Config; 17 | 18 | protected override LocalisableString Header => ruleset.Description; 19 | 20 | public RushSettingsSubsection(Ruleset ruleset) 21 | : base(ruleset) 22 | { 23 | this.ruleset = ruleset; 24 | } 25 | 26 | [BackgroundDependencyLoader] 27 | private void load() 28 | { 29 | Children = new Drawable[] 30 | { 31 | new SettingsEnumDropdown 32 | { 33 | LabelText = "Fever activation mode", 34 | Current = Config.GetBindable(RushRulesetSettings.FeverActivationMode) 35 | }, 36 | }; 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/UI/StarSheetHitExplosion.cs: -------------------------------------------------------------------------------- 1 | // Copyright (c) Shane Woolcock. Licensed under the MIT Licence. 2 | // See the LICENCE file in the repository root for full licence text. 3 | 4 | using osu.Framework.Extensions.Color4Extensions; 5 | using osu.Framework.Graphics; 6 | using osu.Framework.Graphics.Pooling; 7 | using osu.Framework.Graphics.Shapes; 8 | using osu.Game.Rulesets.Objects.Drawables; 9 | using osu.Game.Rulesets.Rush.Objects.Drawables; 10 | using osu.Game.Rulesets.Rush.Objects.Drawables.Pieces; 11 | using osuTK; 12 | 13 | namespace osu.Game.Rulesets.Rush.UI 14 | { 15 | public partial class StarSheetHitExplosion : PoolableDrawable 16 | { 17 | private readonly StarSheetCapStarPiece explosionStar; 18 | private readonly Circle flashCircle; 19 | 20 | public StarSheetHitExplosion() 21 | { 22 | Origin = Anchor.Centre; 23 | Anchor = Anchor.CentreLeft; 24 | 25 | InternalChildren = new Drawable[] 26 | { 27 | explosionStar = new StarSheetCapStarPiece(), 28 | flashCircle = new Circle 29 | { 30 | Anchor = Anchor.Centre, 31 | Origin = Anchor.Centre, 32 | Alpha = 0.4f, 33 | RelativeSizeAxes = Axes.Both, 34 | Scale = new Vector2(0.5f), 35 | } 36 | }; 37 | } 38 | 39 | public void Apply(DrawableHitObject drawable) 40 | { 41 | IDrawableLanedHit laned = (IDrawableLanedHit)drawable; 42 | Size = drawable.Size; 43 | flashCircle.Colour = laned.LaneAccentColour.Lighten(0.5f); 44 | } 45 | 46 | protected override void PrepareForUse() 47 | { 48 | base.PrepareForUse(); 49 | 50 | explosionStar.ScaleTo(1) 51 | .ScaleTo(2f, RushPlayfield.HIT_EXPLOSION_DURATION) 52 | .FadeOutFromOne(RushPlayfield.HIT_EXPLOSION_DURATION) 53 | .Expire(true); 54 | 55 | flashCircle.ScaleTo(0.5f).FadeTo(0.4f) 56 | .ScaleTo(4f, RushPlayfield.HIT_EXPLOSION_DURATION / 2) 57 | .Then() 58 | .ScaleTo(0.5f, RushPlayfield.HIT_EXPLOSION_DURATION / 2) 59 | .FadeOut(RushPlayfield.HIT_EXPLOSION_DURATION / 2) 60 | .Expire(true); 61 | 62 | this.Delay(RushPlayfield.HIT_EXPLOSION_DURATION).Expire(true); 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /osu.Game.Rulesets.Rush/osu.Game.Rulesets.Rush.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | Debug;Release;Development 4 | net8.0 5 | Library 6 | AnyCPU 7 | osu.Game.Rulesets.Rush 8 | 9 | 10 | true 11 | 12 | 13 | 14 | 15 | osu.Game.Rulesets.Rush 16 | rush for osu! 17 | 18 | 19 | 20 | 21 | osu.Game.Rulesets.Rush-dev 22 | rush for osu! (development build) 23 | 24 | 25 | 26 | 27 | 31 | 32 | $(AssemblyName).$([System.String]::Copy(%(Identity)).Replace($([System.IO.Path]::DirectorySeparatorChar.ToString()), '.')) 33 | 34 | 35 | 36 | 37 | 38 | 39 | --------------------------------------------------------------------------------