1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-12 16:43:00 +08:00

Merge branch 'master' of https://github.com/ppy/osu into license-year (AppVeyor?)

This commit is contained in:
Felix Ang 2018-01-22 18:42:03 +01:00
commit d294fcfb0b
981 changed files with 6110 additions and 3941 deletions

@ -1 +1 @@
Subproject commit 6134dafccb3368dac96d837537325c04b89fb8ee Subproject commit 26c01ca6069296621f76d8ffbfe31ecf8074c687

@ -1 +1 @@
Subproject commit e01f71160fb9b3167efcd177c7d7dba9e5d36604 Subproject commit 7724abdf1d7c9705ba2e3989a9c604e17ccdc871

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- <!--
Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
--> -->
<configuration> <configuration>

View File

@ -1,4 +1,4 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using Newtonsoft.Json; using Newtonsoft.Json;
@ -13,4 +13,4 @@ namespace osu.Desktop.Deploy
[JsonProperty(@"name")] [JsonProperty(@"name")]
public string Name; public string Name;
} }
} }

View File

@ -1,4 +1,4 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using Newtonsoft.Json; using Newtonsoft.Json;
@ -25,4 +25,4 @@ namespace osu.Desktop.Deploy
[JsonProperty(@"upload_url")] [JsonProperty(@"upload_url")]
public string UploadUrl; public string UploadUrl;
} }
} }

View File

@ -1,4 +1,4 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System; using System;

View File

@ -1,4 +1,4 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System.Reflection; using System.Reflection;

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- <!--
Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
--> -->
<packages> <packages>

View File

@ -1,4 +1,4 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System; using System;
@ -45,7 +45,7 @@ namespace osu.Desktop
{ {
protected override string LocateBasePath() protected override string LocateBasePath()
{ {
Func<string, bool> checkExists = p => Directory.Exists(Path.Combine(p, "Songs")); bool checkExists(string p) => Directory.Exists(Path.Combine(p, "Songs"));
string stableInstallPath; string stableInstallPath;

View File

@ -1,4 +1,4 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Framework.Platform; using osu.Framework.Platform;
@ -27,4 +27,4 @@ namespace osu.Desktop
host.Window.CursorState |= CursorState.Hidden; host.Window.CursorState |= CursorState.Hidden;
} }
} }
} }

View File

@ -1,4 +1,4 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System; using System;
@ -31,7 +31,8 @@ namespace osu.Desktop.Overlays
private OsuConfigManager config; private OsuConfigManager config;
private OsuGameBase game; private OsuGameBase game;
public override bool HandleInput => false; public override bool HandleKeyboardInput => false;
public override bool HandleMouseInput => false;
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(NotificationOverlay notification, OsuColour colours, TextureStore textures, OsuGameBase game, OsuConfigManager config) private void load(NotificationOverlay notification, OsuColour colours, TextureStore textures, OsuGameBase game, OsuConfigManager config)

View File

@ -1,4 +1,4 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System; using System;
@ -43,7 +43,6 @@ namespace osu.Desktop
host.Run(new OsuGameDesktop(args)); host.Run(new OsuGameDesktop(args));
break; break;
} }
} }
return 0; return 0;
} }

View File

@ -1,4 +1,4 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System.Reflection; using System.Reflection;
@ -12,7 +12,7 @@ using System.Runtime.InteropServices;
[assembly: AssemblyConfiguration("")] [assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("ppy Pty Ltd")] [assembly: AssemblyCompany("ppy Pty Ltd")]
[assembly: AssemblyProduct("osu!lazer")] [assembly: AssemblyProduct("osu!lazer")]
[assembly: AssemblyCopyright("ppy Pty Ltd 2007-2017")] [assembly: AssemblyCopyright("ppy Pty Ltd 2007-2018")]
[assembly: AssemblyTrademark("")] [assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")] [assembly: AssemblyCulture("")]

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- <!--
Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
--> -->
<packages> <packages>

View File

@ -1,4 +1,4 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
@ -11,7 +11,7 @@ using osu.Game.Rulesets.Objects;
namespace osu.Game.Rulesets.Catch.Beatmaps namespace osu.Game.Rulesets.Catch.Beatmaps
{ {
internal class CatchBeatmapConverter : BeatmapConverter<CatchHitObject> public class CatchBeatmapConverter : BeatmapConverter<CatchHitObject>
{ {
protected override IEnumerable<Type> ValidConversionTypes { get; } = new[] { typeof(IHasXPosition) }; protected override IEnumerable<Type> ValidConversionTypes { get; } = new[] { typeof(IHasXPosition) };
@ -20,6 +20,7 @@ namespace osu.Game.Rulesets.Catch.Beatmaps
var curveData = obj as IHasCurve; var curveData = obj as IHasCurve;
var positionData = obj as IHasXPosition; var positionData = obj as IHasXPosition;
var comboData = obj as IHasCombo; var comboData = obj as IHasCombo;
var endTime = obj as IHasEndTime;
if (positionData == null) if (positionData == null)
yield break; yield break;
@ -42,6 +43,19 @@ namespace osu.Game.Rulesets.Catch.Beatmaps
yield break; yield break;
} }
if (endTime != null)
{
yield return new BananaShower
{
StartTime = obj.StartTime,
Samples = obj.Samples,
Duration = endTime.Duration,
NewCombo = comboData?.NewCombo ?? false
};
yield break;
}
yield return new Fruit yield return new Fruit
{ {
StartTime = obj.StartTime, StartTime = obj.StartTime,

View File

@ -1,4 +1,4 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System; using System;
@ -12,14 +12,14 @@ using OpenTK;
namespace osu.Game.Rulesets.Catch.Beatmaps namespace osu.Game.Rulesets.Catch.Beatmaps
{ {
internal class CatchBeatmapProcessor : BeatmapProcessor<CatchHitObject> public class CatchBeatmapProcessor : BeatmapProcessor<CatchHitObject>
{ {
public override void PostProcess(Beatmap<CatchHitObject> beatmap) public override void PostProcess(Beatmap<CatchHitObject> beatmap)
{ {
if (beatmap.ComboColors.Count == 0) if (beatmap.ComboColors.Count == 0)
return; return;
int comboIndex = 0; int index = 0;
int colourIndex = 0; int colourIndex = 0;
CatchHitObject lastObj = null; CatchHitObject lastObj = null;
@ -31,12 +31,10 @@ namespace osu.Game.Rulesets.Catch.Beatmaps
if (obj.NewCombo) if (obj.NewCombo)
{ {
if (lastObj != null) lastObj.LastInCombo = true; if (lastObj != null) lastObj.LastInCombo = true;
comboIndex = 0;
colourIndex = (colourIndex + 1) % beatmap.ComboColors.Count; colourIndex = (colourIndex + 1) % beatmap.ComboColors.Count;
} }
obj.ComboIndex = comboIndex++; obj.IndexInBeatmap = index++;
obj.ComboColour = beatmap.ComboColors[colourIndex]; obj.ComboColour = beatmap.ComboColors[colourIndex];
lastObj = obj; lastObj = obj;

View File

@ -1,4 +1,4 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Beatmaps; using osu.Game.Beatmaps;

View File

@ -1,4 +1,4 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System.ComponentModel; using System.ComponentModel;
@ -22,6 +22,6 @@ namespace osu.Game.Rulesets.Catch
[Description("Move right")] [Description("Move right")]
MoveRight, MoveRight,
[Description("Engage dash")] [Description("Engage dash")]
Dash Dash,
} }
} }

View File

@ -1,4 +1,4 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
@ -80,7 +80,7 @@ namespace osu.Game.Rulesets.Catch
{ {
Mods = new Mod[] Mods = new Mod[]
{ {
new ModAutoplay(), new CatchModAutoplay(),
new ModCinema(), new ModCinema(),
}, },
}, },
@ -101,7 +101,7 @@ namespace osu.Game.Rulesets.Catch
public override int LegacyID => 2; public override int LegacyID => 2;
public CatchRuleset(RulesetInfo rulesetInfo) public CatchRuleset(RulesetInfo rulesetInfo = null)
: base(rulesetInfo) : base(rulesetInfo)
{ {
} }

View File

@ -1,4 +1,4 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Judgements;

View File

@ -1,69 +0,0 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Rulesets.Mods;
namespace osu.Game.Rulesets.Catch.Mods
{
public class CatchModNoFail : ModNoFail
{
}
public class CatchModEasy : ModEasy
{
}
public class CatchModHidden : ModHidden
{
public override string Description => @"Play with fading notes for a slight score advantage.";
public override double ScoreMultiplier => 1.06;
}
public class CatchModHardRock : ModHardRock
{
public override double ScoreMultiplier => 1.12;
public override bool Ranked => true;
}
public class CatchModSuddenDeath : ModSuddenDeath
{
}
public class CatchModDaycore : ModDaycore
{
public override double ScoreMultiplier => 0.5;
}
public class CatchModDoubleTime : ModDoubleTime
{
public override double ScoreMultiplier => 1.06;
}
public class CatchModRelax : ModRelax
{
public override string Description => @"Use the mouse to control the catcher.";
}
public class CatchModHalfTime : ModHalfTime
{
public override double ScoreMultiplier => 0.5;
}
public class CatchModNightcore : ModNightcore
{
public override double ScoreMultiplier => 1.06;
}
public class CatchModFlashlight : ModFlashlight
{
public override double ScoreMultiplier => 1.12;
}
public class CatchModPerfect : ModPerfect
{
}
}

View File

@ -0,0 +1,24 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Beatmaps;
using osu.Game.Rulesets.Catch.Objects;
using osu.Game.Rulesets.Catch.Replays;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Scoring;
using osu.Game.Users;
namespace osu.Game.Rulesets.Catch.Mods
{
public class CatchModAutoplay : ModAutoplay<CatchHitObject>
{
protected override Score CreateReplayScore(Beatmap<CatchHitObject> beatmap)
{
return new Score
{
User = new User { Username = "osu!salad!" },
Replay = new CatchAutoGenerator(beatmap).Generate(),
};
}
}
}

View File

@ -0,0 +1,12 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Rulesets.Mods;
namespace osu.Game.Rulesets.Catch.Mods
{
public class CatchModDaycore : ModDaycore
{
public override double ScoreMultiplier => 0.5;
}
}

View File

@ -0,0 +1,12 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Rulesets.Mods;
namespace osu.Game.Rulesets.Catch.Mods
{
public class CatchModDoubleTime : ModDoubleTime
{
public override double ScoreMultiplier => 1.06;
}
}

View File

@ -0,0 +1,11 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Rulesets.Mods;
namespace osu.Game.Rulesets.Catch.Mods
{
public class CatchModEasy : ModEasy
{
}
}

View File

@ -0,0 +1,12 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Rulesets.Mods;
namespace osu.Game.Rulesets.Catch.Mods
{
public class CatchModFlashlight : ModFlashlight
{
public override double ScoreMultiplier => 1.12;
}
}

View File

@ -0,0 +1,12 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Rulesets.Mods;
namespace osu.Game.Rulesets.Catch.Mods
{
public class CatchModHalfTime : ModHalfTime
{
public override double ScoreMultiplier => 0.5;
}
}

View File

@ -0,0 +1,13 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Rulesets.Mods;
namespace osu.Game.Rulesets.Catch.Mods
{
public class CatchModHardRock : ModHardRock
{
public override double ScoreMultiplier => 1.12;
public override bool Ranked => true;
}
}

View File

@ -0,0 +1,13 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Rulesets.Mods;
namespace osu.Game.Rulesets.Catch.Mods
{
public class CatchModHidden : ModHidden
{
public override string Description => @"Play with fading notes for a slight score advantage.";
public override double ScoreMultiplier => 1.06;
}
}

View File

@ -0,0 +1,12 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Rulesets.Mods;
namespace osu.Game.Rulesets.Catch.Mods
{
public class CatchModNightcore : ModNightcore
{
public override double ScoreMultiplier => 1.06;
}
}

View File

@ -0,0 +1,11 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Rulesets.Mods;
namespace osu.Game.Rulesets.Catch.Mods
{
public class CatchModNoFail : ModNoFail
{
}
}

View File

@ -0,0 +1,11 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Rulesets.Mods;
namespace osu.Game.Rulesets.Catch.Mods
{
public class CatchModPerfect : ModPerfect
{
}
}

View File

@ -0,0 +1,12 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Rulesets.Mods;
namespace osu.Game.Rulesets.Catch.Mods
{
public class CatchModRelax : ModRelax
{
public override string Description => @"Use the mouse to control the catcher.";
}
}

View File

@ -0,0 +1,11 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Rulesets.Mods;
namespace osu.Game.Rulesets.Catch.Mods
{
public class CatchModSuddenDeath : ModSuddenDeath
{
}
}

View File

@ -0,0 +1,63 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Framework.MathUtils;
using osu.Game.Rulesets.Objects.Types;
using OpenTK.Graphics;
namespace osu.Game.Rulesets.Catch.Objects
{
public class BananaShower : CatchHitObject, IHasEndTime
{
public override FruitVisualRepresentation VisualRepresentation => FruitVisualRepresentation.Banana;
public override bool LastInCombo => true;
protected override void CreateNestedHitObjects()
{
base.CreateNestedHitObjects();
createBananas();
}
private void createBananas()
{
double spacing = Duration;
while (spacing > 100)
spacing /= 2;
if (spacing <= 0)
return;
for (double i = StartTime; i <= EndTime; i += spacing)
AddNested(new Banana
{
Samples = Samples,
ComboColour = getNextComboColour(),
StartTime = i,
X = RNG.NextSingle()
});
}
private Color4 getNextComboColour()
{
switch (RNG.Next(0, 3))
{
default:
return new Color4(255, 240, 0, 255);
case 1:
return new Color4(255, 192, 0, 255);
case 2:
return new Color4(214, 221, 28, 255);
}
}
public double EndTime => StartTime + Duration;
public double Duration { get; set; }
public class Banana : Fruit
{
public override FruitVisualRepresentation VisualRepresentation => FruitVisualRepresentation.Banana;
}
}
}

View File

@ -1,4 +1,4 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
@ -15,8 +15,11 @@ namespace osu.Game.Rulesets.Catch.Objects
public float X { get; set; } public float X { get; set; }
public Color4 ComboColour { get; set; } = Color4.Gray; public Color4 ComboColour { get; set; }
public int ComboIndex { get; set; }
public int IndexInBeatmap { get; set; }
public virtual FruitVisualRepresentation VisualRepresentation => (FruitVisualRepresentation)(IndexInBeatmap % 4);
public virtual bool NewCombo { get; set; } public virtual bool NewCombo { get; set; }
@ -44,4 +47,13 @@ namespace osu.Game.Rulesets.Catch.Objects
Scale = 1.0f - 0.7f * (difficulty.CircleSize - 5) / 5; Scale = 1.0f - 0.7f * (difficulty.CircleSize - 5) / 5;
} }
} }
public enum FruitVisualRepresentation
{
Pear,
Grape,
Raspberry,
Pineapple,
Banana // banananananannaanana
}
} }

View File

@ -0,0 +1,44 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
using System.Linq;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Catch.Objects.Drawable
{
public class DrawableBananaShower : DrawableCatchHitObject<BananaShower>
{
private readonly Container bananaContainer;
public DrawableBananaShower(BananaShower s, Func<CatchHitObject, DrawableHitObject<CatchHitObject>> getVisualRepresentation = null)
: base(s)
{
RelativeSizeAxes = Axes.X;
Origin = Anchor.BottomLeft;
X = 0;
Child = bananaContainer = new Container { RelativeSizeAxes = Axes.Both };
foreach (var b in s.NestedHitObjects.Cast<BananaShower.Banana>())
AddNested(getVisualRepresentation?.Invoke(b));
}
protected override void CheckForJudgements(bool userTriggered, double timeOffset)
{
if (timeOffset >= 0)
AddJudgement(new Judgement { Result = NestedHitObjects.Cast<DrawableCatchHitObject>().Any(n => n.Judgements.Any(j => j.IsHit)) ? HitResult.Perfect : HitResult.Miss });
}
protected override void AddNested(DrawableHitObject h)
{
((DrawableCatchHitObject)h).CheckPosition = o => CheckPosition?.Invoke(o) ?? false;
bananaContainer.Add(h);
base.AddNested(h);
}
}
}

View File

@ -1,15 +1,28 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System; using System;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Objects.Types;
using OpenTK; using OpenTK;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Catch.Objects.Drawable namespace osu.Game.Rulesets.Catch.Objects.Drawable
{ {
public abstract class PalpableCatchHitObject<TObject> : DrawableCatchHitObject<TObject>
where TObject : CatchHitObject
{
public override bool CanBePlated => true;
protected PalpableCatchHitObject(TObject hitObject)
: base(hitObject)
{
Scale = new Vector2(HitObject.Scale);
}
}
public abstract class DrawableCatchHitObject<TObject> : DrawableCatchHitObject public abstract class DrawableCatchHitObject<TObject> : DrawableCatchHitObject
where TObject : CatchHitObject where TObject : CatchHitObject
{ {
@ -19,27 +32,29 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable
: base(hitObject) : base(hitObject)
{ {
HitObject = hitObject; HitObject = hitObject;
Anchor = Anchor.BottomLeft;
Scale = new Vector2(HitObject.Scale);
} }
} }
public abstract class DrawableCatchHitObject : DrawableScrollingHitObject<CatchHitObject> public abstract class DrawableCatchHitObject : DrawableHitObject<CatchHitObject>
{ {
public virtual bool CanBePlated => false;
protected DrawableCatchHitObject(CatchHitObject hitObject) protected DrawableCatchHitObject(CatchHitObject hitObject)
: base(hitObject) : base(hitObject)
{ {
RelativePositionAxes = Axes.Both; RelativePositionAxes = Axes.X;
X = hitObject.X; X = hitObject.X;
Y = (float)HitObject.StartTime;
} }
public Func<CatchHitObject, bool> CheckPosition; public Func<CatchHitObject, bool> CheckPosition;
protected override void CheckForJudgements(bool userTriggered, double timeOffset) protected override void CheckForJudgements(bool userTriggered, double timeOffset)
{ {
if (CheckPosition == null) return;
if (timeOffset > 0) if (timeOffset > 0)
AddJudgement(new Judgement { Result = CheckPosition?.Invoke(HitObject) ?? false ? HitResult.Perfect : HitResult.Miss }); AddJudgement(new Judgement { Result = CheckPosition.Invoke(HitObject) ? HitResult.Perfect : HitResult.Miss });
} }
private const float preempt = 1000; private const float preempt = 1000;
@ -47,17 +62,21 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable
protected override void UpdateState(ArmedState state) protected override void UpdateState(ArmedState state)
{ {
using (BeginAbsoluteSequence(HitObject.StartTime - preempt)) using (BeginAbsoluteSequence(HitObject.StartTime - preempt))
{
// animation
this.FadeIn(200); this.FadeIn(200);
}
switch (state) var endTime = (HitObject as IHasEndTime)?.EndTime ?? HitObject.StartTime;
using (BeginAbsoluteSequence(endTime, true))
{ {
case ArmedState.Miss: switch (state)
using (BeginAbsoluteSequence(HitObject.StartTime, true)) {
this.FadeOut(250).RotateTo(Rotation * 2, 250, Easing.Out); case ArmedState.Miss:
break; this.FadeOut(250).RotateTo(Rotation * 2, 250, Easing.Out).Expire();
break;
case ArmedState.Hit:
this.FadeOut().Expire();
break;
}
} }
} }
} }

View File

@ -1,4 +1,4 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Framework.Allocation; using osu.Framework.Allocation;
@ -8,15 +8,13 @@ using OpenTK;
namespace osu.Game.Rulesets.Catch.Objects.Drawable namespace osu.Game.Rulesets.Catch.Objects.Drawable
{ {
public class DrawableDroplet : DrawableCatchHitObject<Droplet> public class DrawableDroplet : PalpableCatchHitObject<Droplet>
{ {
public DrawableDroplet(Droplet h) public DrawableDroplet(Droplet h)
: base(h) : base(h)
{ {
Origin = Anchor.Centre; Origin = Anchor.Centre;
Size = new Vector2((float)CatchHitObject.OBJECT_RADIUS) / 4;
Size = new Vector2(Pulp.PULP_SIZE);
AccentColour = h.ComboColour; AccentColour = h.ComboColour;
Masking = false; Masking = false;
} }
@ -27,7 +25,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable
Child = new Pulp Child = new Pulp
{ {
AccentColour = AccentColour, AccentColour = AccentColour,
Scale = new Vector2(0.8f), Size = Size
}; };
} }
} }

View File

@ -1,9 +1,12 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Framework.MathUtils; using osu.Framework.MathUtils;
using osu.Game.Rulesets.Catch.Objects.Drawable.Pieces; using osu.Game.Rulesets.Catch.Objects.Drawable.Pieces;
using OpenTK; using OpenTK;
@ -11,14 +14,16 @@ using OpenTK.Graphics;
namespace osu.Game.Rulesets.Catch.Objects.Drawable namespace osu.Game.Rulesets.Catch.Objects.Drawable
{ {
public class DrawableFruit : DrawableCatchHitObject<Fruit> public class DrawableFruit : PalpableCatchHitObject<Fruit>
{ {
private Circle border;
public DrawableFruit(Fruit h) public DrawableFruit(Fruit h)
: base(h) : base(h)
{ {
Origin = Anchor.Centre; Origin = Anchor.Centre;
Size = new Vector2(Pulp.PULP_SIZE * 2.2f, Pulp.PULP_SIZE * 2.8f); Size = new Vector2((float)CatchHitObject.OBJECT_RADIUS);
AccentColour = HitObject.ComboColour; AccentColour = HitObject.ComboColour;
Masking = false; Masking = false;
@ -28,48 +33,34 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load() private void load()
{ {
Children = new Framework.Graphics.Drawable[] Children = new[]
{ {
//todo: share this more createPulp(HitObject.VisualRepresentation),
new BufferedContainer border = new Circle
{ {
RelativeSizeAxes = Axes.Both, EdgeEffect = new EdgeEffectParameters
CacheDrawnFrameBuffer = true, {
Hollow = !HitObject.HyperDash,
Type = EdgeEffectType.Glow,
Radius = 4,
Colour = HitObject.HyperDash ? Color4.Red : AccentColour.Darken(1).Opacity(0.6f)
},
Size = new Vector2(Height * 1.5f),
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
BorderColour = Color4.White,
BorderThickness = 4f,
Children = new Framework.Graphics.Drawable[] Children = new Framework.Graphics.Drawable[]
{ {
new Pulp new Box
{ {
RelativePositionAxes = Axes.Both, AlwaysPresent = true,
Anchor = Anchor.TopCentre, Colour = AccentColour,
Origin = Anchor.TopCentre, Alpha = 0,
AccentColour = AccentColour, RelativeSizeAxes = Axes.Both
Scale = new Vector2(0.6f), }
},
new Pulp
{
RelativePositionAxes = Axes.Both,
Anchor = Anchor.CentreLeft,
Origin = Anchor.CentreLeft,
AccentColour = AccentColour,
Y = -0.08f
},
new Pulp
{
RelativePositionAxes = Axes.Both,
Anchor = Anchor.CentreRight,
Origin = Anchor.CentreRight,
AccentColour = AccentColour,
Y = -0.08f
},
new Pulp
{
RelativePositionAxes = Axes.Both,
Anchor = Anchor.BottomCentre,
Origin = Anchor.BottomCentre,
AccentColour = AccentColour,
},
} }
} },
}; };
if (HitObject.HyperDash) if (HitObject.HyperDash)
@ -82,9 +73,205 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable
AccentColour = Color4.Red, AccentColour = Color4.Red,
Blending = BlendingMode.Additive, Blending = BlendingMode.Additive,
Alpha = 0.5f, Alpha = 0.5f,
Scale = new Vector2(2) Scale = new Vector2(1.333f)
}); });
} }
} }
private Framework.Graphics.Drawable createPulp(FruitVisualRepresentation representation)
{
const float large_pulp_3 = 13f;
const float distance_from_centre_3 = 0.23f;
const float large_pulp_4 = large_pulp_3 * 0.925f;
const float distance_from_centre_4 = distance_from_centre_3 / 0.925f;
const float small_pulp = large_pulp_3 / 2;
Vector2 positionAt(float angle, float distance) => new Vector2(
distance * (float)Math.Sin(angle * Math.PI / 180),
distance * (float)Math.Cos(angle * Math.PI / 180));
switch (representation)
{
default:
return new Container();
case FruitVisualRepresentation.Raspberry:
return new Container
{
RelativeSizeAxes = Axes.Both,
Children = new Framework.Graphics.Drawable[]
{
new Pulp
{
Anchor = Anchor.TopCentre,
Origin = Anchor.BottomCentre,
AccentColour = AccentColour,
Size = new Vector2(small_pulp),
Y = 0.05f,
},
new Pulp
{
AccentColour = AccentColour,
Size = new Vector2(large_pulp_4),
Position = positionAt(0, distance_from_centre_4),
},
new Pulp
{
AccentColour = AccentColour,
Size = new Vector2(large_pulp_4),
Position = positionAt(90, distance_from_centre_4),
},
new Pulp
{
AccentColour = AccentColour,
Size = new Vector2(large_pulp_4),
Position = positionAt(180, distance_from_centre_4),
},
new Pulp
{
Size = new Vector2(large_pulp_4),
AccentColour = AccentColour,
Position = positionAt(270, distance_from_centre_4),
},
}
};
case FruitVisualRepresentation.Pineapple:
return new Container
{
RelativeSizeAxes = Axes.Both,
Children = new Framework.Graphics.Drawable[]
{
new Pulp
{
Anchor = Anchor.TopCentre,
Origin = Anchor.BottomCentre,
AccentColour = AccentColour,
Size = new Vector2(small_pulp),
Y = 0.1f,
},
new Pulp
{
AccentColour = AccentColour,
Size = new Vector2(large_pulp_4),
Position = positionAt(45, distance_from_centre_4),
},
new Pulp
{
AccentColour = AccentColour,
Size = new Vector2(large_pulp_4),
Position = positionAt(135, distance_from_centre_4),
},
new Pulp
{
AccentColour = AccentColour,
Size = new Vector2(large_pulp_4),
Position = positionAt(225, distance_from_centre_4),
},
new Pulp
{
Size = new Vector2(large_pulp_4),
AccentColour = AccentColour,
Position = positionAt(315, distance_from_centre_4),
},
}
};
case FruitVisualRepresentation.Pear:
return new Container
{
RelativeSizeAxes = Axes.Both,
Children = new Framework.Graphics.Drawable[]
{
new Pulp
{
Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre,
AccentColour = AccentColour,
Size = new Vector2(small_pulp),
Y = -0.1f,
},
new Pulp
{
AccentColour = AccentColour,
Size = new Vector2(large_pulp_3),
Position = positionAt(60, distance_from_centre_3),
},
new Pulp
{
AccentColour = AccentColour,
Size = new Vector2(large_pulp_3),
Position = positionAt(180, distance_from_centre_3),
},
new Pulp
{
Size = new Vector2(large_pulp_3),
AccentColour = AccentColour,
Position = positionAt(300, distance_from_centre_3),
},
}
};
case FruitVisualRepresentation.Grape:
return new Container
{
RelativeSizeAxes = Axes.Both,
Children = new Framework.Graphics.Drawable[]
{
new Pulp
{
Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre,
AccentColour = AccentColour,
Size = new Vector2(small_pulp),
},
new Pulp
{
AccentColour = AccentColour,
Size = new Vector2(large_pulp_3),
Position = positionAt(0, distance_from_centre_3),
},
new Pulp
{
AccentColour = AccentColour,
Size = new Vector2(large_pulp_3),
Position = positionAt(120, distance_from_centre_3),
},
new Pulp
{
Size = new Vector2(large_pulp_3),
AccentColour = AccentColour,
Position = positionAt(240, distance_from_centre_3),
},
}
};
case FruitVisualRepresentation.Banana:
return new Container
{
RelativeSizeAxes = Axes.Both,
Children = new Framework.Graphics.Drawable[]
{
new Pulp
{
Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre,
AccentColour = AccentColour,
Size = new Vector2(small_pulp),
Y = -0.15f
},
new Pulp
{
AccentColour = AccentColour,
Size = new Vector2(large_pulp_4 * 1.2f, large_pulp_4 * 3),
},
}
};
}
}
protected override void Update()
{
base.Update();
border.Alpha = (float)MathHelper.Clamp((HitObject.StartTime - Time.Current) / 500, 0, 1);
}
} }
} }

View File

@ -1,10 +1,10 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
using System.Linq; using System.Linq;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using OpenTK;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables;
namespace osu.Game.Rulesets.Catch.Objects.Drawable namespace osu.Game.Rulesets.Catch.Objects.Drawable
@ -13,41 +13,26 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable
{ {
private readonly Container dropletContainer; private readonly Container dropletContainer;
public DrawableJuiceStream(JuiceStream s) : base(s) public DrawableJuiceStream(JuiceStream s, Func<CatchHitObject, DrawableHitObject<CatchHitObject>> getVisualRepresentation = null)
: base(s)
{ {
RelativeSizeAxes = Axes.Both; RelativeSizeAxes = Axes.Both;
Height = (float)HitObject.Duration; Origin = Anchor.BottomLeft;
X = 0; X = 0;
Child = dropletContainer = new Container Child = dropletContainer = new Container { RelativeSizeAxes = Axes.Both, };
{
RelativeSizeAxes = Axes.Both,
RelativeChildOffset = new Vector2(0, (float)HitObject.StartTime),
RelativeChildSize = new Vector2(1, (float)HitObject.Duration)
};
foreach (CatchHitObject tick in s.NestedHitObjects.OfType<CatchHitObject>()) foreach (var o in s.NestedHitObjects.Cast<CatchHitObject>())
{ AddNested(getVisualRepresentation?.Invoke(o));
TinyDroplet tiny = tick as TinyDroplet;
if (tiny != null)
{
AddNested(new DrawableDroplet(tiny) { Scale = new Vector2(0.5f) });
continue;
}
Droplet droplet = tick as Droplet;
if (droplet != null)
AddNested(new DrawableDroplet(droplet));
Fruit fruit = tick as Fruit;
if (fruit != null)
AddNested(new DrawableFruit(fruit));
}
} }
protected override void AddNested(DrawableHitObject<CatchHitObject> h) protected override void AddNested(DrawableHitObject h)
{ {
((DrawableCatchHitObject)h).CheckPosition = o => CheckPosition?.Invoke(o) ?? false; var catchObject = (DrawableCatchHitObject)h;
catchObject.CheckPosition = o => CheckPosition?.Invoke(o) ?? false;
catchObject.AccentColour = HitObject.ComboColour;
dropletContainer.Add(h); dropletContainer.Add(h);
base.AddNested(h); base.AddNested(h);
} }

View File

@ -1,4 +1,4 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Framework.Extensions.Color4Extensions; using osu.Framework.Extensions.Color4Extensions;
@ -6,18 +6,17 @@ using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes; using osu.Framework.Graphics.Shapes;
using osu.Game.Graphics; using osu.Game.Graphics;
using OpenTK;
using OpenTK.Graphics; using OpenTK.Graphics;
namespace osu.Game.Rulesets.Catch.Objects.Drawable.Pieces namespace osu.Game.Rulesets.Catch.Objects.Drawable.Pieces
{ {
public class Pulp : Circle, IHasAccentColour public class Pulp : Circle, IHasAccentColour
{ {
public const float PULP_SIZE = (float)CatchHitObject.OBJECT_RADIUS / 2.2f;
public Pulp() public Pulp()
{ {
Size = new Vector2(PULP_SIZE); RelativePositionAxes = Axes.Both;
Anchor = Anchor.Centre;
Origin = Anchor.Centre;
Blending = BlendingMode.Additive; Blending = BlendingMode.Additive;
Colour = Color4.White.Opacity(0.9f); Colour = Color4.White.Opacity(0.9f);
@ -34,8 +33,8 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable.Pieces
EdgeEffect = new EdgeEffectParameters EdgeEffect = new EdgeEffectParameters
{ {
Type = EdgeEffectType.Glow, Type = EdgeEffectType.Glow,
Radius = 5, Radius = 8,
Colour = accentColour.Lighten(100), Colour = accentColour.Darken(0.2f).Opacity(0.75f)
}; };
} }
} }

View File

@ -1,4 +1,4 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
namespace osu.Game.Rulesets.Catch.Objects namespace osu.Game.Rulesets.Catch.Objects

View File

@ -1,4 +1,4 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
namespace osu.Game.Rulesets.Catch.Objects namespace osu.Game.Rulesets.Catch.Objects

View File

@ -1,4 +1,4 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System; using System;
@ -125,10 +125,8 @@ namespace osu.Game.Rulesets.Catch.Objects
X = Curve.PositionAt(reversed ? 0 : 1).X / CatchPlayfield.BASE_WIDTH X = Curve.PositionAt(reversed ? 0 : 1).X / CatchPlayfield.BASE_WIDTH
}); });
} }
} }
public double EndTime => StartTime + RepeatCount * Curve.Distance / Velocity; public double EndTime => StartTime + RepeatCount * Curve.Distance / Velocity;
public float EndX => Curve.PositionAt(ProgressAt(1)).X / CatchPlayfield.BASE_WIDTH; public float EndX => Curve.PositionAt(ProgressAt(1)).X / CatchPlayfield.BASE_WIDTH;

View File

@ -1,4 +1,4 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
namespace osu.Game.Rulesets.Catch.Objects namespace osu.Game.Rulesets.Catch.Objects

View File

@ -1,4 +1,4 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System.Reflection; using System.Reflection;
@ -12,7 +12,7 @@ using System.Runtime.InteropServices;
[assembly: AssemblyConfiguration("")] [assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("ppy Pty Ltd")] [assembly: AssemblyCompany("ppy Pty Ltd")]
[assembly: AssemblyProduct("osu.Game.Rulesets.Catch")] [assembly: AssemblyProduct("osu.Game.Rulesets.Catch")]
[assembly: AssemblyCopyright("ppy Pty Ltd 2007-2017")] [assembly: AssemblyCopyright("ppy Pty Ltd 2007-2018")]
[assembly: AssemblyTrademark("")] [assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")] [assembly: AssemblyCulture("")]

View File

@ -0,0 +1,120 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
using System.Linq;
using osu.Framework.MathUtils;
using osu.Game.Beatmaps;
using osu.Game.Rulesets.Catch.Objects;
using osu.Game.Rulesets.Catch.UI;
using osu.Game.Rulesets.Replays;
using osu.Game.Users;
namespace osu.Game.Rulesets.Catch.Replays
{
internal class CatchAutoGenerator : AutoGenerator<CatchHitObject>
{
public const double RELEASE_DELAY = 20;
public CatchAutoGenerator(Beatmap<CatchHitObject> beatmap)
: base(beatmap)
{
Replay = new Replay { User = new User { Username = @"Autoplay" } };
}
protected Replay Replay;
public override Replay Generate()
{
// todo: add support for HT DT
const double dash_speed = CatcherArea.Catcher.BASE_SPEED;
const double movement_speed = dash_speed / 2;
float lastPosition = 0.5f;
double lastTime = 0;
// Todo: Realistically this shouldn't be needed, but the first frame is skipped with the way replays are currently handled
Replay.Frames.Add(new CatchReplayFrame(-100000, lastPosition));
void moveToNext(CatchHitObject h)
{
float positionChange = Math.Abs(lastPosition - h.X);
double timeAvailable = h.StartTime - lastTime;
//So we can either make it there without a dash or not.
double speedRequired = positionChange / timeAvailable;
bool dashRequired = speedRequired > movement_speed && h.StartTime != 0;
// todo: get correct catcher size, based on difficulty CS.
const float catcher_width_half = CatcherArea.CATCHER_SIZE / CatchPlayfield.BASE_WIDTH * 0.3f * 0.5f;
if (lastPosition - catcher_width_half < h.X && lastPosition + catcher_width_half > h.X)
{
//we are already in the correct range.
lastTime = h.StartTime;
Replay.Frames.Add(new CatchReplayFrame(h.StartTime, lastPosition));
return;
}
if (h is BananaShower.Banana)
{
// auto bananas unrealistically warp to catch 100% combo.
Replay.Frames.Add(new CatchReplayFrame(h.StartTime, h.X));
}
else if (h.HyperDash)
{
Replay.Frames.Add(new CatchReplayFrame(h.StartTime - timeAvailable, lastPosition, ReplayButtonState.Right1));
Replay.Frames.Add(new CatchReplayFrame(h.StartTime, h.X));
}
else if (dashRequired)
{
//we do a movement in two parts - the dash part then the normal part...
double timeAtNormalSpeed = positionChange / movement_speed;
double timeWeNeedToSave = timeAtNormalSpeed - timeAvailable;
double timeAtDashSpeed = timeWeNeedToSave / 2;
float midPosition = (float)Interpolation.Lerp(lastPosition, h.X, (float)timeAtDashSpeed / timeAvailable);
//dash movement
Replay.Frames.Add(new CatchReplayFrame(h.StartTime - timeAvailable + 1, lastPosition, ReplayButtonState.Left1));
Replay.Frames.Add(new CatchReplayFrame(h.StartTime - timeAvailable + timeAtDashSpeed, midPosition));
Replay.Frames.Add(new CatchReplayFrame(h.StartTime, h.X));
}
else
{
double timeBefore = positionChange / movement_speed;
Replay.Frames.Add(new CatchReplayFrame(h.StartTime - timeBefore, lastPosition, ReplayButtonState.Right1));
Replay.Frames.Add(new CatchReplayFrame(h.StartTime, h.X));
}
lastTime = h.StartTime;
lastPosition = h.X;
}
foreach (var obj in Beatmap.HitObjects)
{
switch (obj)
{
case Fruit _:
moveToNext(obj);
break;
}
foreach (var nestedObj in obj.NestedHitObjects.Cast<CatchHitObject>())
{
switch (nestedObj)
{
case BananaShower.Banana _:
case TinyDroplet _:
case Droplet _:
moveToNext(nestedObj);
break;
}
}
}
return Replay;
}
}
}

View File

@ -0,0 +1,46 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System.Collections.Generic;
using osu.Framework.Input;
using osu.Game.Rulesets.Replays;
namespace osu.Game.Rulesets.Catch.Replays
{
public class CatchFramedReplayInputHandler : FramedReplayInputHandler
{
public CatchFramedReplayInputHandler(Replay replay)
: base(replay)
{
}
public override List<InputState> GetPendingStates()
{
if (!Position.HasValue) return new List<InputState>();
var action = new List<CatchAction>();
if (CurrentFrame.ButtonState == ReplayButtonState.Left1)
action.Add(CatchAction.Dash);
if (Position.Value.X > CurrentFrame.Position.X)
action.Add(CatchAction.MoveRight);
else if (Position.Value.X < CurrentFrame.Position.X)
action.Add(CatchAction.MoveLeft);
return new List<InputState>
{
new CatchReplayState
{
PressedActions = action,
CatcherX = Position.Value.X
},
};
}
public class CatchReplayState : ReplayState<CatchAction>
{
public float? CatcherX { get; set; }
}
}
}

View File

@ -0,0 +1,17 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Rulesets.Replays;
namespace osu.Game.Rulesets.Catch.Replays
{
public class CatchReplayFrame : ReplayFrame
{
public override bool IsImportant => MouseX > 0;
public CatchReplayFrame(double time, float? x = null, ReplayButtonState button = ReplayButtonState.None)
: base(time, x ?? -1, null, button)
{
}
}
}

View File

@ -1,4 +1,4 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System.Linq; using System.Linq;
@ -10,7 +10,7 @@ using osu.Game.Rulesets.UI;
namespace osu.Game.Rulesets.Catch.Scoring namespace osu.Game.Rulesets.Catch.Scoring
{ {
internal class CatchScoreProcessor : ScoreProcessor<CatchHitObject> public class CatchScoreProcessor : ScoreProcessor<CatchHitObject>
{ {
public CatchScoreProcessor(RulesetContainer<CatchHitObject> rulesetContainer) public CatchScoreProcessor(RulesetContainer<CatchHitObject> rulesetContainer)
: base(rulesetContainer) : base(rulesetContainer)
@ -21,23 +21,25 @@ namespace osu.Game.Rulesets.Catch.Scoring
{ {
foreach (var obj in beatmap.HitObjects) foreach (var obj in beatmap.HitObjects)
{ {
var stream = obj as JuiceStream; switch (obj)
if (stream != null)
{ {
AddJudgement(new CatchJudgement { Result = HitResult.Perfect }); case JuiceStream stream:
AddJudgement(new CatchJudgement { Result = HitResult.Perfect }); AddJudgement(new CatchJudgement { Result = HitResult.Perfect });
foreach (var unused in stream.NestedHitObjects.OfType<CatchHitObject>())
AddJudgement(new CatchJudgement { Result = HitResult.Perfect }); AddJudgement(new CatchJudgement { Result = HitResult.Perfect });
continue; foreach (var _ in stream.NestedHitObjects.Cast<CatchHitObject>())
AddJudgement(new CatchJudgement { Result = HitResult.Perfect });
break;
case BananaShower shower:
AddJudgement(new CatchJudgement { Result = HitResult.Perfect });
foreach (var _ in shower.NestedHitObjects.Cast<CatchHitObject>())
AddJudgement(new CatchJudgement { Result = HitResult.Perfect });
break;
case Fruit _:
AddJudgement(new CatchJudgement { Result = HitResult.Perfect });
break;
} }
var fruit = obj as Fruit;
if (fruit != null)
AddJudgement(new CatchJudgement { Result = HitResult.Perfect });
} }
base.SimulateAutoplay(beatmap); base.SimulateAutoplay(beatmap);

View File

@ -0,0 +1,50 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
using System.Collections.Generic;
using NUnit.Framework;
using osu.Game.Beatmaps;
using osu.Game.Rulesets.Catch.Objects;
using osu.Game.Rulesets.Catch.Objects.Drawable;
using osu.Game.Rulesets.Catch.UI;
namespace osu.Game.Rulesets.Catch.Tests
{
[TestFixture]
[Ignore("getting CI working")]
public class TestCaseBananaShower : Game.Tests.Visual.TestCasePlayer
{
public override IReadOnlyList<Type> RequiredTypes => new[]
{
typeof(BananaShower),
typeof(DrawableBananaShower),
typeof(CatchRuleset),
typeof(CatchRulesetContainer),
};
public TestCaseBananaShower()
: base(new CatchRuleset())
{
}
protected override Beatmap CreateBeatmap()
{
var beatmap = new Beatmap
{
BeatmapInfo = new BeatmapInfo
{
BaseDifficulty = new BeatmapDifficulty
{
CircleSize = 6,
}
}
};
beatmap.HitObjects.Add(new BananaShower { StartTime = 200, Duration = 5000, NewCombo = true });
return beatmap;
}
}
}

View File

@ -1,4 +1,4 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using NUnit.Framework; using NUnit.Framework;
@ -9,7 +9,7 @@ namespace osu.Game.Rulesets.Catch.Tests
[Ignore("getting CI working")] [Ignore("getting CI working")]
public class TestCaseCatchPlayer : Game.Tests.Visual.TestCasePlayer public class TestCaseCatchPlayer : Game.Tests.Visual.TestCasePlayer
{ {
public TestCaseCatchPlayer() : base(typeof(CatchRuleset)) public TestCaseCatchPlayer() : base(new CatchRuleset())
{ {
} }
} }

View File

@ -1,4 +1,4 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using NUnit.Framework; using NUnit.Framework;
@ -12,7 +12,7 @@ namespace osu.Game.Rulesets.Catch.Tests
public class TestCaseCatchStacker : Game.Tests.Visual.TestCasePlayer public class TestCaseCatchStacker : Game.Tests.Visual.TestCasePlayer
{ {
public TestCaseCatchStacker() public TestCaseCatchStacker()
: base(typeof(CatchRuleset)) : base(new CatchRuleset())
{ {
} }

View File

@ -1,4 +1,4 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System; using System;

View File

@ -0,0 +1,104 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
using System.Collections.Generic;
using NUnit.Framework;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.MathUtils;
using osu.Game.Rulesets.Catch.Objects;
using osu.Game.Rulesets.Catch.Objects.Drawable;
using osu.Game.Rulesets.Catch.Objects.Drawable.Pieces;
using osu.Game.Tests.Visual;
using OpenTK;
using OpenTK.Graphics;
namespace osu.Game.Rulesets.Catch.Tests
{
[Ignore("getting CI working")]
public class TestCaseFruitObjects : OsuTestCase
{
public override IReadOnlyList<Type> RequiredTypes => new[]
{
typeof(CatchHitObject),
typeof(Fruit),
typeof(Droplet),
typeof(DrawableCatchHitObject),
typeof(DrawableFruit),
typeof(DrawableDroplet),
typeof(Pulp),
};
public TestCaseFruitObjects()
{
Add(new GridContainer
{
RelativeSizeAxes = Axes.Both,
Content = new[]
{
new Drawable[]
{
createDrawable(0),
createDrawable(1),
createDrawable(2),
},
new Drawable[]
{
createDrawable(3),
createDrawable(4),
createDrawable(5),
},
}
});
}
private DrawableFruit createDrawable(int index)
{
var fruit = new Fruit
{
StartTime = 1000000000000,
IndexInBeatmap = index,
Scale = 1.5f,
};
fruit.ComboColour = colourForRrepesentation(fruit.VisualRepresentation);
return new DrawableFruit(fruit)
{
Anchor = Anchor.Centre,
RelativePositionAxes = Axes.Both,
Position = Vector2.Zero,
Alpha = 1,
LifetimeStart = double.NegativeInfinity,
LifetimeEnd = double.PositiveInfinity,
};
}
private Color4 colourForRrepesentation(FruitVisualRepresentation representation)
{
switch (representation)
{
default:
case FruitVisualRepresentation.Pear:
return new Color4(17, 136, 170, 255);
case FruitVisualRepresentation.Grape:
return new Color4(204, 102, 0, 255);
case FruitVisualRepresentation.Raspberry:
return new Color4(121, 9, 13, 255);
case FruitVisualRepresentation.Pineapple:
return new Color4(102, 136, 0, 255);
case FruitVisualRepresentation.Banana:
switch (RNG.Next(0, 3))
{
default:
return new Color4(255, 240, 0, 255);
case 1:
return new Color4(255, 192, 0, 255);
case 2:
return new Color4(214, 221, 28, 255);
}
}
}
}
}

View File

@ -1,4 +1,4 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using NUnit.Framework; using NUnit.Framework;
@ -12,7 +12,7 @@ namespace osu.Game.Rulesets.Catch.Tests
public class TestCaseHyperdash : Game.Tests.Visual.TestCasePlayer public class TestCaseHyperdash : Game.Tests.Visual.TestCasePlayer
{ {
public TestCaseHyperdash() public TestCaseHyperdash()
: base(typeof(CatchRuleset)) : base(new CatchRuleset())
{ {
} }

View File

@ -1,4 +1,4 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using NUnit.Framework; using NUnit.Framework;
@ -9,7 +9,7 @@ namespace osu.Game.Rulesets.Catch.Tests
public class TestCasePerformancePoints : Game.Tests.Visual.TestCasePerformancePoints public class TestCasePerformancePoints : Game.Tests.Visual.TestCasePerformancePoints
{ {
public TestCasePerformancePoints() public TestCasePerformancePoints()
: base(new CatchRuleset(new RulesetInfo())) : base(new CatchRuleset())
{ {
} }
} }

View File

@ -1,15 +1,15 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Game.Rulesets.UI;
using OpenTK;
using osu.Framework.Graphics.Containers; using osu.Framework.Graphics.Containers;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.Objects;
using osu.Game.Rulesets.Catch.Objects.Drawable; using osu.Game.Rulesets.Catch.Objects.Drawable;
using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.UI.Scrolling;
namespace osu.Game.Rulesets.Catch.UI namespace osu.Game.Rulesets.Catch.UI
{ {
@ -22,17 +22,18 @@ namespace osu.Game.Rulesets.Catch.UI
private readonly CatcherArea catcherArea; private readonly CatcherArea catcherArea;
public CatchPlayfield(BeatmapDifficulty difficulty) public CatchPlayfield(BeatmapDifficulty difficulty, Func<CatchHitObject, DrawableHitObject<CatchHitObject>> getVisualRepresentation)
: base(Axes.Y) : base(ScrollingDirection.Down, BASE_WIDTH)
{ {
Container explodingFruitContainer; Container explodingFruitContainer;
Reversed.Value = true;
Anchor = Anchor.TopCentre; Anchor = Anchor.TopCentre;
Origin = Anchor.TopCentre; Origin = Anchor.TopCentre;
InternalChildren = new Drawable[] ScaledContent.Anchor = Anchor.BottomLeft;
ScaledContent.Origin = Anchor.BottomLeft;
ScaledContent.AddRange(new Drawable[]
{ {
content = new Container<Drawable> content = new Container<Drawable>
{ {
@ -44,11 +45,12 @@ namespace osu.Game.Rulesets.Catch.UI
}, },
catcherArea = new CatcherArea(difficulty) catcherArea = new CatcherArea(difficulty)
{ {
GetVisualRepresentation = getVisualRepresentation,
ExplodingFruitTarget = explodingFruitContainer, ExplodingFruitTarget = explodingFruitContainer,
Anchor = Anchor.BottomLeft, Anchor = Anchor.BottomLeft,
Origin = Anchor.TopLeft, Origin = Anchor.TopLeft,
} }
}; });
} }
public bool CheckIfWeCanCatch(CatchHitObject obj) => catcherArea.AttemptCatch(obj); public bool CheckIfWeCanCatch(CatchHitObject obj) => catcherArea.AttemptCatch(obj);
@ -56,6 +58,7 @@ namespace osu.Game.Rulesets.Catch.UI
public override void Add(DrawableHitObject h) public override void Add(DrawableHitObject h)
{ {
h.Depth = (float)h.HitObject.StartTime; h.Depth = (float)h.HitObject.StartTime;
h.OnJudgement += onJudgement;
base.Add(h); base.Add(h);
@ -63,18 +66,6 @@ namespace osu.Game.Rulesets.Catch.UI
fruit.CheckPosition = CheckIfWeCanCatch; fruit.CheckPosition = CheckIfWeCanCatch;
} }
public override void OnJudgement(DrawableHitObject judgedObject, Judgement judgement) private void onJudgement(DrawableHitObject judgedObject, Judgement judgement) => catcherArea.OnJudgement((DrawableCatchHitObject)judgedObject, judgement);
{
if (judgement.IsHit)
{
Vector2 screenPosition = judgedObject.ScreenSpaceDrawQuad.Centre;
// todo: don't do this
(judgedObject.Parent as Container<DrawableHitObject>)?.Remove(judgedObject);
(judgedObject.Parent as Container)?.Remove(judgedObject);
catcherArea.Add(judgedObject, screenPosition);
}
}
} }
} }

View File

@ -1,4 +1,4 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Framework.Input; using osu.Framework.Input;
@ -6,10 +6,14 @@ using osu.Game.Beatmaps;
using osu.Game.Rulesets.Catch.Beatmaps; using osu.Game.Rulesets.Catch.Beatmaps;
using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.Objects;
using osu.Game.Rulesets.Catch.Objects.Drawable; using osu.Game.Rulesets.Catch.Objects.Drawable;
using osu.Game.Rulesets.Catch.Replays;
using osu.Game.Rulesets.Catch.Scoring; using osu.Game.Rulesets.Catch.Scoring;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Replays;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI;
using osu.Game.Rulesets.UI.Scrolling;
using OpenTK;
namespace osu.Game.Rulesets.Catch.UI namespace osu.Game.Rulesets.Catch.UI
{ {
@ -22,23 +26,31 @@ namespace osu.Game.Rulesets.Catch.UI
public override ScoreProcessor CreateScoreProcessor() => new CatchScoreProcessor(this); public override ScoreProcessor CreateScoreProcessor() => new CatchScoreProcessor(this);
protected override FramedReplayInputHandler CreateReplayInputHandler(Replay replay) => new CatchFramedReplayInputHandler(replay);
protected override BeatmapProcessor<CatchHitObject> CreateBeatmapProcessor() => new CatchBeatmapProcessor(); protected override BeatmapProcessor<CatchHitObject> CreateBeatmapProcessor() => new CatchBeatmapProcessor();
protected override BeatmapConverter<CatchHitObject> CreateBeatmapConverter() => new CatchBeatmapConverter(); protected override BeatmapConverter<CatchHitObject> CreateBeatmapConverter() => new CatchBeatmapConverter();
protected override Playfield CreatePlayfield() => new CatchPlayfield(Beatmap.BeatmapInfo.BaseDifficulty); protected override Playfield CreatePlayfield() => new CatchPlayfield(Beatmap.BeatmapInfo.BaseDifficulty, GetVisualRepresentation);
public override PassThroughInputManager CreateInputManager() => new CatchInputManager(Ruleset.RulesetInfo); public override PassThroughInputManager CreateInputManager() => new CatchInputManager(Ruleset.RulesetInfo);
protected override DrawableHitObject<CatchHitObject> GetVisualRepresentation(CatchHitObject h) protected override DrawableHitObject<CatchHitObject> GetVisualRepresentation(CatchHitObject h)
{ {
var fruit = h as Fruit; switch (h)
if (fruit != null) {
return new DrawableFruit(fruit); case Fruit fruit:
return new DrawableFruit(fruit);
var stream = h as JuiceStream; case JuiceStream stream:
if (stream != null) return new DrawableJuiceStream(stream, GetVisualRepresentation);
return new DrawableJuiceStream(stream); case BananaShower banana:
return new DrawableBananaShower(banana, GetVisualRepresentation);
case TinyDroplet tiny:
return new DrawableDroplet(tiny) { Scale = new Vector2(0.5f) };
case Droplet droplet:
return new DrawableDroplet(droplet);
}
return null; return null;
} }

View File

@ -1,4 +1,4 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System; using System;
@ -12,6 +12,9 @@ using osu.Framework.Input.Bindings;
using osu.Framework.MathUtils; using osu.Framework.MathUtils;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.Objects;
using osu.Game.Rulesets.Catch.Objects.Drawable;
using osu.Game.Rulesets.Catch.Replays;
using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables;
using OpenTK; using OpenTK;
using OpenTK.Graphics; using OpenTK.Graphics;
@ -24,6 +27,8 @@ namespace osu.Game.Rulesets.Catch.UI
protected readonly Catcher MovableCatcher; protected readonly Catcher MovableCatcher;
public Func<CatchHitObject, DrawableHitObject<CatchHitObject>> GetVisualRepresentation;
public Container ExplodingFruitTarget public Container ExplodingFruitTarget
{ {
set { MovableCatcher.ExplodingFruitTarget = value; } set { MovableCatcher.ExplodingFruitTarget = value; }
@ -39,19 +44,58 @@ namespace osu.Game.Rulesets.Catch.UI
}; };
} }
public void Add(DrawableHitObject fruit, Vector2 absolutePosition) private DrawableCatchHitObject lastPlateableFruit;
public void OnJudgement(DrawableCatchHitObject fruit, Judgement judgement)
{ {
fruit.RelativePositionAxes = Axes.None; if (judgement.IsHit && fruit.CanBePlated)
fruit.Position = new Vector2(MovableCatcher.ToLocalSpace(absolutePosition).X - MovableCatcher.DrawSize.X / 2, 0); {
var caughtFruit = (DrawableCatchHitObject)GetVisualRepresentation?.Invoke(fruit.HitObject);
fruit.Anchor = Anchor.TopCentre; if (caughtFruit == null) return;
fruit.Origin = Anchor.BottomCentre;
fruit.Scale *= 0.7f;
fruit.LifetimeEnd = double.MaxValue;
MovableCatcher.Add(fruit); caughtFruit.AccentColour = fruit.AccentColour;
caughtFruit.RelativePositionAxes = Axes.None;
caughtFruit.Position = new Vector2(MovableCatcher.ToLocalSpace(fruit.ScreenSpaceDrawQuad.Centre).X - MovableCatcher.DrawSize.X / 2, 0);
caughtFruit.Anchor = Anchor.TopCentre;
caughtFruit.Origin = Anchor.Centre;
caughtFruit.Scale *= 0.7f;
caughtFruit.LifetimeEnd = double.MaxValue;
MovableCatcher.Add(caughtFruit);
lastPlateableFruit = caughtFruit;
}
if (fruit.HitObject.LastInCombo)
{
if (judgement.IsHit)
{
// this is required to make this run after the last caught fruit runs UpdateState at least once.
// TODO: find a better alternative
if (lastPlateableFruit.IsLoaded)
MovableCatcher.Explode();
else
lastPlateableFruit.OnLoadComplete = _ => { MovableCatcher.Explode(); };
}
else
MovableCatcher.Drop();
}
} }
protected override void Update()
{
base.Update();
var state = GetContainingInputManager().CurrentState as CatchFramedReplayInputHandler.CatchReplayState;
if (state?.CatcherX != null)
MovableCatcher.X = state.CatcherX.Value;
}
public bool OnReleased(CatchAction action) => false;
public bool AttemptCatch(CatchHitObject obj) => MovableCatcher.AttemptCatch(obj); public bool AttemptCatch(CatchHitObject obj) => MovableCatcher.AttemptCatch(obj);
public class Catcher : Container, IKeyBindingHandler<CatchAction> public class Catcher : Container, IKeyBindingHandler<CatchAction>
@ -84,12 +128,12 @@ namespace osu.Game.Rulesets.Catch.UI
Children = new Drawable[] Children = new Drawable[]
{ {
createCatcherSprite(),
caughtFruit = new Container<DrawableHitObject> caughtFruit = new Container<DrawableHitObject>
{ {
Anchor = Anchor.TopCentre, Anchor = Anchor.TopCentre,
Origin = Anchor.BottomCentre, Origin = Anchor.BottomCentre,
} },
createCatcherSprite(),
}; };
} }
@ -167,20 +211,23 @@ namespace osu.Game.Rulesets.Catch.UI
/// <param name="fruit">The fruit that was caught.</param> /// <param name="fruit">The fruit that was caught.</param>
public void Add(DrawableHitObject fruit) public void Add(DrawableHitObject fruit)
{ {
float distance = fruit.DrawSize.X / 2 * fruit.Scale.X; float ourRadius = fruit.DrawSize.X / 2 * fruit.Scale.X;
float theirRadius = 0;
while (caughtFruit.Any(f => f.LifetimeEnd == double.MaxValue && Vector2Extensions.DistanceSquared(f.Position, fruit.Position) < distance * distance)) const float allowance = 6;
while (caughtFruit.Any(f =>
f.LifetimeEnd == double.MaxValue &&
Vector2Extensions.Distance(f.Position, fruit.Position) < (ourRadius + (theirRadius = f.DrawSize.X / 2 * f.Scale.X)) / (allowance / 2)))
{ {
fruit.X += RNG.Next(-5, 5); float diff = (ourRadius + theirRadius) / allowance;
fruit.Y -= RNG.Next(0, 5); fruit.X += (RNG.NextSingle() - 0.5f) * 2 * diff;
fruit.Y -= RNG.NextSingle() * diff;
} }
fruit.X = MathHelper.Clamp(fruit.X, -CATCHER_SIZE / 2, CATCHER_SIZE / 2);
caughtFruit.Add(fruit); caughtFruit.Add(fruit);
var catchObject = (CatchHitObject)fruit.HitObject;
if (catchObject.LastInCombo)
explode();
} }
/// <summary> /// <summary>
@ -190,15 +237,15 @@ namespace osu.Game.Rulesets.Catch.UI
/// <returns>Whether the catch is possible.</returns> /// <returns>Whether the catch is possible.</returns>
public bool AttemptCatch(CatchHitObject fruit) public bool AttemptCatch(CatchHitObject fruit)
{ {
const double relative_catcher_width = CATCHER_SIZE / 2; double halfCatcherWidth = CATCHER_SIZE * Math.Abs(Scale.X) * 0.5f;
// this stuff wil disappear once we move fruit to non-relative coordinate space in the future. // this stuff wil disappear once we move fruit to non-relative coordinate space in the future.
var catchObjectPosition = fruit.X * CatchPlayfield.BASE_WIDTH; var catchObjectPosition = fruit.X * CatchPlayfield.BASE_WIDTH;
var catcherPosition = Position.X * CatchPlayfield.BASE_WIDTH; var catcherPosition = Position.X * CatchPlayfield.BASE_WIDTH;
var validCatch = var validCatch =
catchObjectPosition >= catcherPosition - relative_catcher_width / 2 && catchObjectPosition >= catcherPosition - halfCatcherWidth &&
catchObjectPosition <= catcherPosition + relative_catcher_width / 2; catchObjectPosition <= catcherPosition + halfCatcherWidth;
if (validCatch && fruit.HyperDash) if (validCatch && fruit.HyperDash)
{ {
@ -309,7 +356,35 @@ namespace osu.Game.Rulesets.Catch.UI
X = (float)MathHelper.Clamp(X + direction * Clock.ElapsedFrameTime * BASE_SPEED * dashModifier, 0, 1); X = (float)MathHelper.Clamp(X + direction * Clock.ElapsedFrameTime * BASE_SPEED * dashModifier, 0, 1);
} }
private void explode() /// <summary>
/// Drop any fruit off the plate.
/// </summary>
public void Drop()
{
var fruit = caughtFruit.ToArray();
foreach (var f in fruit)
{
if (ExplodingFruitTarget != null)
{
f.Anchor = Anchor.TopLeft;
f.Position = caughtFruit.ToSpaceOfOtherDrawable(f.DrawPosition, ExplodingFruitTarget);
caughtFruit.Remove(f);
ExplodingFruitTarget.Add(f);
}
f.MoveToY(f.Y + 75, 750, Easing.InSine);
f.FadeOut(750);
f.Expire();
}
}
/// <summary>
/// Explode any fruit off the plate.
/// </summary>
public void Explode()
{ {
var fruit = caughtFruit.ToArray(); var fruit = caughtFruit.ToArray();

View File

@ -49,11 +49,28 @@
<Compile Include="Beatmaps\CatchBeatmapProcessor.cs" /> <Compile Include="Beatmaps\CatchBeatmapProcessor.cs" />
<Compile Include="CatchDifficultyCalculator.cs" /> <Compile Include="CatchDifficultyCalculator.cs" />
<Compile Include="CatchInputManager.cs" /> <Compile Include="CatchInputManager.cs" />
<Compile Include="Mods\CatchModDaycore.cs" />
<Compile Include="Mods\CatchModDoubleTime.cs" />
<Compile Include="Mods\CatchModEasy.cs" />
<Compile Include="Mods\CatchModFlashlight.cs" />
<Compile Include="Mods\CatchModHalfTime.cs" />
<Compile Include="Mods\CatchModHardRock.cs" />
<Compile Include="Mods\CatchModHidden.cs" />
<Compile Include="Mods\CatchModNightcore.cs" />
<Compile Include="Mods\CatchModPerfect.cs" />
<Compile Include="Mods\CatchModRelax.cs" />
<Compile Include="Mods\CatchModSuddenDeath.cs" />
<Compile Include="Mods\CatchModAutoplay.cs" />
<Compile Include="Objects\BananaShower.cs" />
<Compile Include="Objects\Drawable\DrawableBananaShower.cs" />
<Compile Include="Objects\Drawable\DrawableCatchHitObject.cs" /> <Compile Include="Objects\Drawable\DrawableCatchHitObject.cs" />
<Compile Include="Objects\Drawable\DrawableDroplet.cs" /> <Compile Include="Objects\Drawable\DrawableDroplet.cs" />
<Compile Include="Objects\Drawable\DrawableJuiceStream.cs" /> <Compile Include="Objects\Drawable\DrawableJuiceStream.cs" />
<Compile Include="Objects\Drawable\Pieces\Pulp.cs" /> <Compile Include="Objects\Drawable\Pieces\Pulp.cs" />
<Compile Include="Objects\JuiceStream.cs" /> <Compile Include="Objects\JuiceStream.cs" />
<Compile Include="Replays\CatchAutoGenerator.cs" />
<Compile Include="Replays\CatchFramedReplayInputHandler.cs" />
<Compile Include="Replays\CatchReplayFrame.cs" />
<Compile Include="Scoring\CatchScoreProcessor.cs" /> <Compile Include="Scoring\CatchScoreProcessor.cs" />
<Compile Include="Judgements\CatchJudgement.cs" /> <Compile Include="Judgements\CatchJudgement.cs" />
<Compile Include="Objects\CatchHitObject.cs" /> <Compile Include="Objects\CatchHitObject.cs" />
@ -62,8 +79,10 @@
<Compile Include="Objects\Fruit.cs" /> <Compile Include="Objects\Fruit.cs" />
<Compile Include="Objects\TinyDroplet.cs" /> <Compile Include="Objects\TinyDroplet.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Tests\TestCaseBananaShower.cs" />
<Compile Include="Tests\TestCaseCatcherArea.cs" /> <Compile Include="Tests\TestCaseCatcherArea.cs" />
<Compile Include="Tests\TestCaseCatchStacker.cs" /> <Compile Include="Tests\TestCaseCatchStacker.cs" />
<Compile Include="Tests\TestCaseFruitObjects.cs" />
<Compile Include="Tests\TestCasePerformancePoints.cs" /> <Compile Include="Tests\TestCasePerformancePoints.cs" />
<Compile Include="Tests\TestCaseCatchPlayer.cs" /> <Compile Include="Tests\TestCaseCatchPlayer.cs" />
<Compile Include="Tests\TestCaseHyperdash.cs" /> <Compile Include="Tests\TestCaseHyperdash.cs" />
@ -71,7 +90,7 @@
<Compile Include="UI\CatchRulesetContainer.cs" /> <Compile Include="UI\CatchRulesetContainer.cs" />
<Compile Include="UI\CatchPlayfield.cs" /> <Compile Include="UI\CatchPlayfield.cs" />
<Compile Include="CatchRuleset.cs" /> <Compile Include="CatchRuleset.cs" />
<Compile Include="Mods\CatchMod.cs" /> <Compile Include="Mods\CatchModNoFail.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="app.config" /> <None Include="app.config" />

View File

@ -0,0 +1,33 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System.Collections.Generic;
using System.Linq;
using osu.Game.Beatmaps;
using osu.Game.Rulesets.Mania.Objects;
using osu.Game.Rulesets.Mania.UI;
namespace osu.Game.Rulesets.Mania.Beatmaps
{
public class ManiaBeatmap : Beatmap<ManiaHitObject>
{
/// <summary>
/// The definitions for each stage in a <see cref="ManiaPlayfield"/>.
/// </summary>
public readonly List<StageDefinition> Stages = new List<StageDefinition>();
/// <summary>
/// Total number of columns represented by all stages in this <see cref="ManiaBeatmap"/>.
/// </summary>
public int TotalColumns => Stages.Sum(g => g.Columns);
/// <summary>
/// Creates a new <see cref="ManiaBeatmap"/>.
/// </summary>
/// <param name="initialStage">The initial stage.</param>
public ManiaBeatmap(StageDefinition initialStage)
{
Stages.Add(initialStage);
}
}
}

View File

@ -1,8 +1,9 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects;
using System; using System;
using System.Linq;
using System.Collections.Generic; using System.Collections.Generic;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects;
@ -24,25 +25,39 @@ namespace osu.Game.Rulesets.Mania.Beatmaps
protected override IEnumerable<Type> ValidConversionTypes { get; } = new[] { typeof(IHasXPosition) }; protected override IEnumerable<Type> ValidConversionTypes { get; } = new[] { typeof(IHasXPosition) };
public int TargetColumns;
public readonly bool IsForCurrentRuleset;
private Pattern lastPattern = new Pattern(); private Pattern lastPattern = new Pattern();
private FastRandom random; private FastRandom random;
private Beatmap beatmap;
private readonly int availableColumns; private ManiaBeatmap beatmap;
private readonly bool isForCurrentRuleset;
public ManiaBeatmapConverter(bool isForCurrentRuleset, int availableColumns) public ManiaBeatmapConverter(bool isForCurrentRuleset, Beatmap original)
{ {
if (availableColumns <= 0) throw new ArgumentOutOfRangeException(nameof(availableColumns)); IsForCurrentRuleset = isForCurrentRuleset;
this.isForCurrentRuleset = isForCurrentRuleset; var roundedCircleSize = Math.Round(original.BeatmapInfo.BaseDifficulty.CircleSize);
this.availableColumns = availableColumns; var roundedOverallDifficulty = Math.Round(original.BeatmapInfo.BaseDifficulty.OverallDifficulty);
if (isForCurrentRuleset)
TargetColumns = (int)Math.Max(1, roundedCircleSize);
else
{
float percentSliderOrSpinner = (float)original.HitObjects.Count(h => h is IHasEndTime) / original.HitObjects.Count;
if (percentSliderOrSpinner < 0.2)
TargetColumns = 7;
else if (percentSliderOrSpinner < 0.3 || roundedCircleSize >= 5)
TargetColumns = roundedOverallDifficulty > 5 ? 7 : 6;
else if (percentSliderOrSpinner > 0.6)
TargetColumns = roundedOverallDifficulty > 4 ? 5 : 4;
else
TargetColumns = Math.Max(4, Math.Min((int)roundedOverallDifficulty + 1, 7));
}
} }
protected override Beatmap<ManiaHitObject> ConvertBeatmap(Beatmap original) protected override Beatmap<ManiaHitObject> ConvertBeatmap(Beatmap original)
{ {
beatmap = original;
BeatmapDifficulty difficulty = original.BeatmapInfo.BaseDifficulty; BeatmapDifficulty difficulty = original.BeatmapInfo.BaseDifficulty;
int seed = (int)Math.Round(difficulty.DrainRate + difficulty.CircleSize) * 20 + (int)(difficulty.OverallDifficulty * 41.2) + (int)Math.Round(difficulty.ApproachRate); int seed = (int)Math.Round(difficulty.DrainRate + difficulty.CircleSize) * 20 + (int)(difficulty.OverallDifficulty * 41.2) + (int)Math.Round(difficulty.ApproachRate);
@ -51,6 +66,8 @@ namespace osu.Game.Rulesets.Mania.Beatmaps
return base.ConvertBeatmap(original); return base.ConvertBeatmap(original);
} }
protected override Beatmap<ManiaHitObject> CreateBeatmap() => beatmap = new ManiaBeatmap(new StageDefinition { Columns = TargetColumns });
protected override IEnumerable<ManiaHitObject> ConvertHitObject(HitObject original, Beatmap beatmap) protected override IEnumerable<ManiaHitObject> ConvertHitObject(HitObject original, Beatmap beatmap)
{ {
var maniaOriginal = original as ManiaHitObject; var maniaOriginal = original as ManiaHitObject;
@ -60,7 +77,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps
yield break; yield break;
} }
var objects = isForCurrentRuleset ? generateSpecific(original) : generateConverted(original); var objects = IsForCurrentRuleset ? generateSpecific(original) : generateConverted(original);
if (objects == null) if (objects == null)
yield break; yield break;
@ -96,7 +113,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps
/// <returns>The hit objects generated.</returns> /// <returns>The hit objects generated.</returns>
private IEnumerable<ManiaHitObject> generateSpecific(HitObject original) private IEnumerable<ManiaHitObject> generateSpecific(HitObject original)
{ {
var generator = new SpecificBeatmapPatternGenerator(random, original, beatmap, availableColumns, lastPattern); var generator = new SpecificBeatmapPatternGenerator(random, original, beatmap, lastPattern);
Pattern newPattern = generator.Generate(); Pattern newPattern = generator.Generate();
lastPattern = newPattern; lastPattern = newPattern;
@ -120,14 +137,14 @@ namespace osu.Game.Rulesets.Mania.Beatmaps
Patterns.PatternGenerator conversion = null; Patterns.PatternGenerator conversion = null;
if (distanceData != null) if (distanceData != null)
conversion = new DistanceObjectPatternGenerator(random, original, beatmap, availableColumns, lastPattern); conversion = new DistanceObjectPatternGenerator(random, original, beatmap, lastPattern);
else if (endTimeData != null) else if (endTimeData != null)
conversion = new EndTimeObjectPatternGenerator(random, original, beatmap, availableColumns); conversion = new EndTimeObjectPatternGenerator(random, original, beatmap);
else if (positionData != null) else if (positionData != null)
{ {
computeDensity(original.StartTime); computeDensity(original.StartTime);
conversion = new HitObjectPatternGenerator(random, original, beatmap, availableColumns, lastPattern, lastTime, lastPosition, density, lastStair); conversion = new HitObjectPatternGenerator(random, original, beatmap, lastPattern, lastTime, lastPosition, density, lastStair);
recordNote(original.StartTime, positionData.Position); recordNote(original.StartTime, positionData.Position);
} }
@ -149,8 +166,8 @@ namespace osu.Game.Rulesets.Mania.Beatmaps
/// </summary> /// </summary>
private class SpecificBeatmapPatternGenerator : Patterns.Legacy.PatternGenerator private class SpecificBeatmapPatternGenerator : Patterns.Legacy.PatternGenerator
{ {
public SpecificBeatmapPatternGenerator(FastRandom random, HitObject hitObject, Beatmap beatmap, int availableColumns, Pattern previousPattern) public SpecificBeatmapPatternGenerator(FastRandom random, HitObject hitObject, ManiaBeatmap beatmap, Pattern previousPattern)
: base(random, hitObject, beatmap, availableColumns, previousPattern) : base(random, hitObject, beatmap, previousPattern)
{ {
} }

View File

@ -1,11 +1,10 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using osu.Game.Audio; using osu.Game.Audio;
using osu.Game.Beatmaps;
using osu.Game.Rulesets.Mania.MathUtils; using osu.Game.Rulesets.Mania.MathUtils;
using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Objects.Types;
@ -30,8 +29,8 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
private PatternType convertType; private PatternType convertType;
public DistanceObjectPatternGenerator(FastRandom random, HitObject hitObject, Beatmap beatmap, int availableColumns, Pattern previousPattern) public DistanceObjectPatternGenerator(FastRandom random, HitObject hitObject, ManiaBeatmap beatmap, Pattern previousPattern)
: base(random, hitObject, beatmap, availableColumns, previousPattern) : base(random, hitObject, beatmap, previousPattern)
{ {
convertType = PatternType.None; convertType = PatternType.None;
if (Beatmap.ControlPointInfo.EffectPointAt(hitObject.StartTime).KiaiMode) if (Beatmap.ControlPointInfo.EffectPointAt(hitObject.StartTime).KiaiMode)
@ -79,7 +78,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
if (duration >= 4000) if (duration >= 4000)
return generateNRandomNotes(HitObject.StartTime, 0.23, 0, 0); return generateNRandomNotes(HitObject.StartTime, 0.23, 0, 0);
if (segmentDuration > 400 && repeatCount < AvailableColumns - 1 - RandomStart) if (segmentDuration > 400 && repeatCount < TotalColumns - 1 - RandomStart)
return generateTiledHoldNotes(HitObject.StartTime); return generateTiledHoldNotes(HitObject.StartTime);
return generateHoldAndNormalNotes(HitObject.StartTime); return generateHoldAndNormalNotes(HitObject.StartTime);
@ -87,7 +86,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
if (segmentDuration <= 110) if (segmentDuration <= 110)
{ {
if (PreviousPattern.ColumnWithObjects < AvailableColumns) if (PreviousPattern.ColumnWithObjects < TotalColumns)
convertType |= PatternType.ForceNotStack; convertType |= PatternType.ForceNotStack;
else else
convertType &= ~PatternType.ForceNotStack; convertType &= ~PatternType.ForceNotStack;
@ -135,12 +134,12 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
var pattern = new Pattern(); var pattern = new Pattern();
int usableColumns = AvailableColumns - RandomStart - PreviousPattern.ColumnWithObjects; int usableColumns = TotalColumns - RandomStart - PreviousPattern.ColumnWithObjects;
int nextColumn = Random.Next(RandomStart, AvailableColumns); int nextColumn = Random.Next(RandomStart, TotalColumns);
for (int i = 0; i < Math.Min(usableColumns, noteCount); i++) for (int i = 0; i < Math.Min(usableColumns, noteCount); i++)
{ {
while (pattern.ColumnHasObject(nextColumn) || PreviousPattern.ColumnHasObject(nextColumn)) //find available column while (pattern.ColumnHasObject(nextColumn) || PreviousPattern.ColumnHasObject(nextColumn)) //find available column
nextColumn = Random.Next(RandomStart, AvailableColumns); nextColumn = Random.Next(RandomStart, TotalColumns);
addToPattern(pattern, nextColumn, startTime, endTime); addToPattern(pattern, nextColumn, startTime, endTime);
} }
@ -148,7 +147,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
for (int i = 0; i < noteCount - usableColumns; i++) for (int i = 0; i < noteCount - usableColumns; i++)
{ {
while (pattern.ColumnHasObject(nextColumn)) while (pattern.ColumnHasObject(nextColumn))
nextColumn = Random.Next(RandomStart, AvailableColumns); nextColumn = Random.Next(RandomStart, TotalColumns);
addToPattern(pattern, nextColumn, startTime, endTime); addToPattern(pattern, nextColumn, startTime, endTime);
} }
@ -172,10 +171,10 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
var pattern = new Pattern(); var pattern = new Pattern();
int nextColumn = GetColumn((HitObject as IHasXPosition)?.X ?? 0, true); int nextColumn = GetColumn((HitObject as IHasXPosition)?.X ?? 0, true);
if ((convertType & PatternType.ForceNotStack) > 0 && PreviousPattern.ColumnWithObjects < AvailableColumns) if ((convertType & PatternType.ForceNotStack) > 0 && PreviousPattern.ColumnWithObjects < TotalColumns)
{ {
while (PreviousPattern.ColumnHasObject(nextColumn)) while (PreviousPattern.ColumnHasObject(nextColumn))
nextColumn = Random.Next(RandomStart, AvailableColumns); nextColumn = Random.Next(RandomStart, TotalColumns);
} }
int lastColumn = nextColumn; int lastColumn = nextColumn;
@ -183,7 +182,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
{ {
addToPattern(pattern, nextColumn, startTime, startTime); addToPattern(pattern, nextColumn, startTime, startTime);
while (nextColumn == lastColumn) while (nextColumn == lastColumn)
nextColumn = Random.Next(RandomStart, AvailableColumns); nextColumn = Random.Next(RandomStart, TotalColumns);
lastColumn = nextColumn; lastColumn = nextColumn;
startTime += segmentDuration; startTime += segmentDuration;
@ -221,7 +220,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
// Check if we're at the borders of the stage, and invert the pattern if so // Check if we're at the borders of the stage, and invert the pattern if so
if (increasing) if (increasing)
{ {
if (column >= AvailableColumns - 1) if (column >= TotalColumns - 1)
{ {
increasing = false; increasing = false;
column--; column--;
@ -259,8 +258,8 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
var pattern = new Pattern(); var pattern = new Pattern();
bool legacy = AvailableColumns >= 4 && AvailableColumns <= 8; bool legacy = TotalColumns >= 4 && TotalColumns <= 8;
int interval = Random.Next(1, AvailableColumns - (legacy ? 1 : 0)); int interval = Random.Next(1, TotalColumns - (legacy ? 1 : 0));
int nextColumn = GetColumn((HitObject as IHasXPosition)?.X ?? 0, true); int nextColumn = GetColumn((HitObject as IHasXPosition)?.X ?? 0, true);
for (int i = 0; i <= repeatCount; i++) for (int i = 0; i <= repeatCount; i++)
@ -268,15 +267,15 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
addToPattern(pattern, nextColumn, startTime, startTime); addToPattern(pattern, nextColumn, startTime, startTime);
nextColumn += interval; nextColumn += interval;
if (nextColumn >= AvailableColumns - RandomStart) if (nextColumn >= TotalColumns - RandomStart)
nextColumn = nextColumn - AvailableColumns - RandomStart + (legacy ? 1 : 0); nextColumn = nextColumn - TotalColumns - RandomStart + (legacy ? 1 : 0);
nextColumn += RandomStart; nextColumn += RandomStart;
// If we're in 2K, let's not add many consecutive doubles // If we're in 2K, let's not add many consecutive doubles
if (AvailableColumns > 2) if (TotalColumns > 2)
addToPattern(pattern, nextColumn, startTime, startTime); addToPattern(pattern, nextColumn, startTime, startTime);
nextColumn = Random.Next(RandomStart, AvailableColumns); nextColumn = Random.Next(RandomStart, TotalColumns);
startTime += segmentDuration; startTime += segmentDuration;
} }
@ -298,7 +297,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
// □ - □ □ // □ - □ □
// ■ - ■ ■ // ■ - ■ ■
switch (AvailableColumns) switch (TotalColumns)
{ {
case 2: case 2:
p2 = 0; p2 = 0;
@ -322,7 +321,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
break; break;
} }
Func<SampleInfo, bool> isDoubleSample = sample => sample.Name == SampleInfo.HIT_CLAP && sample.Name == SampleInfo.HIT_FINISH; bool isDoubleSample(SampleInfo sample) => sample.Name == SampleInfo.HIT_CLAP && sample.Name == SampleInfo.HIT_FINISH;
bool canGenerateTwoNotes = (convertType & PatternType.LowProbability) == 0; bool canGenerateTwoNotes = (convertType & PatternType.LowProbability) == 0;
canGenerateTwoNotes &= HitObject.Samples.Any(isDoubleSample) || sampleInfoListAt(HitObject.StartTime).Any(isDoubleSample); canGenerateTwoNotes &= HitObject.Samples.Any(isDoubleSample) || sampleInfoListAt(HitObject.StartTime).Any(isDoubleSample);
@ -351,19 +350,19 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
var pattern = new Pattern(); var pattern = new Pattern();
int columnRepeat = Math.Min(repeatCount, AvailableColumns); int columnRepeat = Math.Min(repeatCount, TotalColumns);
int nextColumn = GetColumn((HitObject as IHasXPosition)?.X ?? 0, true); int nextColumn = GetColumn((HitObject as IHasXPosition)?.X ?? 0, true);
if ((convertType & PatternType.ForceNotStack) > 0 && PreviousPattern.ColumnWithObjects < AvailableColumns) if ((convertType & PatternType.ForceNotStack) > 0 && PreviousPattern.ColumnWithObjects < TotalColumns)
{ {
while (PreviousPattern.ColumnHasObject(nextColumn)) while (PreviousPattern.ColumnHasObject(nextColumn))
nextColumn = Random.Next(RandomStart, AvailableColumns); nextColumn = Random.Next(RandomStart, TotalColumns);
} }
for (int i = 0; i < columnRepeat; i++) for (int i = 0; i < columnRepeat; i++)
{ {
while (pattern.ColumnHasObject(nextColumn)) while (pattern.ColumnHasObject(nextColumn))
nextColumn = Random.Next(RandomStart, AvailableColumns); nextColumn = Random.Next(RandomStart, TotalColumns);
addToPattern(pattern, nextColumn, startTime, endTime); addToPattern(pattern, nextColumn, startTime, endTime);
startTime += segmentDuration; startTime += segmentDuration;
@ -388,10 +387,10 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
var pattern = new Pattern(); var pattern = new Pattern();
int holdColumn = GetColumn((HitObject as IHasXPosition)?.X ?? 0, true); int holdColumn = GetColumn((HitObject as IHasXPosition)?.X ?? 0, true);
if ((convertType & PatternType.ForceNotStack) > 0 && PreviousPattern.ColumnWithObjects < AvailableColumns) if ((convertType & PatternType.ForceNotStack) > 0 && PreviousPattern.ColumnWithObjects < TotalColumns)
{ {
while (PreviousPattern.ColumnHasObject(holdColumn)) while (PreviousPattern.ColumnHasObject(holdColumn))
holdColumn = Random.Next(RandomStart, AvailableColumns); holdColumn = Random.Next(RandomStart, TotalColumns);
} }
// Create the hold note // Create the hold note
@ -401,13 +400,13 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
if (ConversionDifficulty > 6.5) if (ConversionDifficulty > 6.5)
noteCount = GetRandomNoteCount(0.63, 0); noteCount = GetRandomNoteCount(0.63, 0);
else if (ConversionDifficulty > 4) else if (ConversionDifficulty > 4)
noteCount = GetRandomNoteCount(AvailableColumns < 6 ? 0.12 : 0.45, 0); noteCount = GetRandomNoteCount(TotalColumns < 6 ? 0.12 : 0.45, 0);
else if (ConversionDifficulty > 2.5) else if (ConversionDifficulty > 2.5)
noteCount = GetRandomNoteCount(AvailableColumns < 6 ? 0 : 0.24, 0); noteCount = GetRandomNoteCount(TotalColumns < 6 ? 0 : 0.24, 0);
noteCount = Math.Min(AvailableColumns - 1, noteCount); noteCount = Math.Min(TotalColumns - 1, noteCount);
bool ignoreHead = !sampleInfoListAt(startTime).Any(s => s.Name == SampleInfo.HIT_WHISTLE || s.Name == SampleInfo.HIT_FINISH || s.Name == SampleInfo.HIT_CLAP); bool ignoreHead = !sampleInfoListAt(startTime).Any(s => s.Name == SampleInfo.HIT_WHISTLE || s.Name == SampleInfo.HIT_FINISH || s.Name == SampleInfo.HIT_CLAP);
int nextColumn = Random.Next(RandomStart, AvailableColumns); int nextColumn = Random.Next(RandomStart, TotalColumns);
var rowPattern = new Pattern(); var rowPattern = new Pattern();
for (int i = 0; i <= repeatCount; i++) for (int i = 0; i <= repeatCount; i++)
@ -417,7 +416,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
for (int j = 0; j < noteCount; j++) for (int j = 0; j < noteCount; j++)
{ {
while (rowPattern.ColumnHasObject(nextColumn) || nextColumn == holdColumn) while (rowPattern.ColumnHasObject(nextColumn) || nextColumn == holdColumn)
nextColumn = Random.Next(RandomStart, AvailableColumns); nextColumn = Random.Next(RandomStart, TotalColumns);
addToPattern(rowPattern, nextColumn, startTime, startTime); addToPattern(rowPattern, nextColumn, startTime, startTime);
} }
} }

View File

@ -1,8 +1,7 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System.Collections.Generic; using System.Collections.Generic;
using osu.Game.Beatmaps;
using osu.Game.Rulesets.Mania.MathUtils; using osu.Game.Rulesets.Mania.MathUtils;
using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Objects.Types;
@ -16,8 +15,8 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
{ {
private readonly double endTime; private readonly double endTime;
public EndTimeObjectPatternGenerator(FastRandom random, HitObject hitObject, Beatmap beatmap, int availableColumns) public EndTimeObjectPatternGenerator(FastRandom random, HitObject hitObject, ManiaBeatmap beatmap)
: base(random, hitObject, beatmap, availableColumns, new Pattern()) : base(random, hitObject, beatmap, new Pattern())
{ {
var endtimeData = HitObject as IHasEndTime; var endtimeData = HitObject as IHasEndTime;
@ -30,14 +29,14 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
bool generateHold = endTime - HitObject.StartTime >= 100; bool generateHold = endTime - HitObject.StartTime >= 100;
if (AvailableColumns == 8) if (TotalColumns == 8)
{ {
if (HitObject.Samples.Any(s => s.Name == SampleInfo.HIT_FINISH) && endTime - HitObject.StartTime < 1000) if (HitObject.Samples.Any(s => s.Name == SampleInfo.HIT_FINISH) && endTime - HitObject.StartTime < 1000)
addToPattern(pattern, 0, generateHold); addToPattern(pattern, 0, generateHold);
else else
addToPattern(pattern, getNextRandomColumn(RandomStart), generateHold); addToPattern(pattern, getNextRandomColumn(RandomStart), generateHold);
} }
else if (AvailableColumns > 0) else if (TotalColumns > 0)
addToPattern(pattern, getNextRandomColumn(0), generateHold); addToPattern(pattern, getNextRandomColumn(0), generateHold);
return pattern; return pattern;
@ -50,10 +49,10 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
/// <returns>A random column after <paramref name="start"/>.</returns> /// <returns>A random column after <paramref name="start"/>.</returns>
private int getNextRandomColumn(int start) private int getNextRandomColumn(int start)
{ {
int nextColumn = Random.Next(start, AvailableColumns); int nextColumn = Random.Next(start, TotalColumns);
while (PreviousPattern.ColumnHasObject(nextColumn)) while (PreviousPattern.ColumnHasObject(nextColumn))
nextColumn = Random.Next(start, AvailableColumns); nextColumn = Random.Next(start, TotalColumns);
return nextColumn; return nextColumn;
} }

View File

@ -1,11 +1,10 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System; using System;
using System.Linq; using System.Linq;
using OpenTK; using OpenTK;
using osu.Game.Audio; using osu.Game.Audio;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.ControlPoints; using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Rulesets.Mania.MathUtils; using osu.Game.Rulesets.Mania.MathUtils;
using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects;
@ -20,8 +19,8 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
private readonly PatternType convertType; private readonly PatternType convertType;
public HitObjectPatternGenerator(FastRandom random, HitObject hitObject, Beatmap beatmap, int availableColumns, Pattern previousPattern, double previousTime, Vector2 previousPosition, double density, PatternType lastStair) public HitObjectPatternGenerator(FastRandom random, HitObject hitObject, ManiaBeatmap beatmap, Pattern previousPattern, double previousTime, Vector2 previousPosition, double density, PatternType lastStair)
: base(random, hitObject, beatmap, availableColumns, previousPattern) : base(random, hitObject, beatmap, previousPattern)
{ {
if (previousTime > hitObject.StartTime) throw new ArgumentOutOfRangeException(nameof(previousTime)); if (previousTime > hitObject.StartTime) throw new ArgumentOutOfRangeException(nameof(previousTime));
if (density < 0) throw new ArgumentOutOfRangeException(nameof(density)); if (density < 0) throw new ArgumentOutOfRangeException(nameof(density));
@ -88,23 +87,23 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
// Generate a new pattern by copying the last hit objects in reverse-column order // Generate a new pattern by copying the last hit objects in reverse-column order
var pattern = new Pattern(); var pattern = new Pattern();
for (int i = RandomStart; i < AvailableColumns; i++) for (int i = RandomStart; i < TotalColumns; i++)
if (PreviousPattern.ColumnHasObject(i)) if (PreviousPattern.ColumnHasObject(i))
addToPattern(pattern, RandomStart + AvailableColumns - i - 1); addToPattern(pattern, RandomStart + TotalColumns - i - 1);
return pattern; return pattern;
} }
if ((convertType & PatternType.Cycle) > 0 && PreviousPattern.HitObjects.Count() == 1 if ((convertType & PatternType.Cycle) > 0 && PreviousPattern.HitObjects.Count() == 1
// If we convert to 7K + 1, let's not overload the special key // If we convert to 7K + 1, let's not overload the special key
&& (AvailableColumns != 8 || lastColumn != 0) && (TotalColumns != 8 || lastColumn != 0)
// Make sure the last column was not the centre column // Make sure the last column was not the centre column
&& (AvailableColumns % 2 == 0 || lastColumn != AvailableColumns / 2)) && (TotalColumns % 2 == 0 || lastColumn != TotalColumns / 2))
{ {
// Generate a new pattern by cycling backwards (similar to Reverse but for only one hit object) // Generate a new pattern by cycling backwards (similar to Reverse but for only one hit object)
var pattern = new Pattern(); var pattern = new Pattern();
int column = RandomStart + AvailableColumns - lastColumn - 1; int column = RandomStart + TotalColumns - lastColumn - 1;
addToPattern(pattern, column); addToPattern(pattern, column);
return pattern; return pattern;
@ -115,7 +114,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
// Generate a new pattern by placing on the already filled columns // Generate a new pattern by placing on the already filled columns
var pattern = new Pattern(); var pattern = new Pattern();
for (int i = RandomStart; i < AvailableColumns; i++) for (int i = RandomStart; i < TotalColumns; i++)
if (PreviousPattern.ColumnHasObject(i)) if (PreviousPattern.ColumnHasObject(i))
addToPattern(pattern, i); addToPattern(pattern, i);
@ -128,7 +127,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
var pattern = new Pattern(); var pattern = new Pattern();
int targetColumn = lastColumn + 1; int targetColumn = lastColumn + 1;
if (targetColumn == AvailableColumns) if (targetColumn == TotalColumns)
{ {
targetColumn = RandomStart; targetColumn = RandomStart;
StairType = PatternType.ReverseStair; StairType = PatternType.ReverseStair;
@ -146,7 +145,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
int targetColumn = lastColumn - 1; int targetColumn = lastColumn - 1;
if (targetColumn == RandomStart - 1) if (targetColumn == RandomStart - 1)
{ {
targetColumn = AvailableColumns - 1; targetColumn = TotalColumns - 1;
StairType = PatternType.Stair; StairType = PatternType.Stair;
} }
@ -206,7 +205,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
bool allowStacking = (convertType & PatternType.ForceNotStack) == 0; bool allowStacking = (convertType & PatternType.ForceNotStack) == 0;
if (!allowStacking) if (!allowStacking)
noteCount = Math.Min(noteCount, AvailableColumns - RandomStart - PreviousPattern.ColumnWithObjects); noteCount = Math.Min(noteCount, TotalColumns - RandomStart - PreviousPattern.ColumnWithObjects);
int nextColumn = GetColumn((HitObject as IHasXPosition)?.X ?? 0, true); int nextColumn = GetColumn((HitObject as IHasXPosition)?.X ?? 0, true);
for (int i = 0; i < noteCount; i++) for (int i = 0; i < noteCount; i++)
@ -216,11 +215,11 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
if ((convertType & PatternType.Gathered) > 0) if ((convertType & PatternType.Gathered) > 0)
{ {
nextColumn++; nextColumn++;
if (nextColumn == AvailableColumns) if (nextColumn == TotalColumns)
nextColumn = RandomStart; nextColumn = RandomStart;
} }
else else
nextColumn = Random.Next(RandomStart, AvailableColumns); nextColumn = Random.Next(RandomStart, TotalColumns);
} }
addToPattern(pattern, nextColumn); addToPattern(pattern, nextColumn);
@ -268,7 +267,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
bool addToCentre; bool addToCentre;
int noteCount = getRandomNoteCountMirrored(centreProbability, p2, p3, out addToCentre); int noteCount = getRandomNoteCountMirrored(centreProbability, p2, p3, out addToCentre);
int columnLimit = (AvailableColumns % 2 == 0 ? AvailableColumns : AvailableColumns - 1) / 2; int columnLimit = (TotalColumns % 2 == 0 ? TotalColumns : TotalColumns - 1) / 2;
int nextColumn = Random.Next(RandomStart, columnLimit); int nextColumn = Random.Next(RandomStart, columnLimit);
for (int i = 0; i < noteCount; i++) for (int i = 0; i < noteCount; i++)
{ {
@ -278,11 +277,11 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
// Add normal note // Add normal note
addToPattern(pattern, nextColumn); addToPattern(pattern, nextColumn);
// Add mirrored note // Add mirrored note
addToPattern(pattern, RandomStart + AvailableColumns - nextColumn - 1); addToPattern(pattern, RandomStart + TotalColumns - nextColumn - 1);
} }
if (addToCentre) if (addToCentre)
addToPattern(pattern, AvailableColumns / 2); addToPattern(pattern, TotalColumns / 2);
if (RandomStart > 0 && hasSpecialColumn) if (RandomStart > 0 && hasSpecialColumn)
addToPattern(pattern, 0); addToPattern(pattern, 0);
@ -300,7 +299,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
/// <returns>The amount of notes to be generated.</returns> /// <returns>The amount of notes to be generated.</returns>
private int getRandomNoteCount(double p2, double p3, double p4, double p5) private int getRandomNoteCount(double p2, double p3, double p4, double p5)
{ {
switch (AvailableColumns) switch (TotalColumns)
{ {
case 2: case 2:
p2 = 0; p2 = 0;
@ -348,7 +347,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
if ((convertType & PatternType.ForceNotStack) > 0) if ((convertType & PatternType.ForceNotStack) > 0)
return getRandomNoteCount(p2 / 2, p2, (p2 + p3) / 2, p3); return getRandomNoteCount(p2 / 2, p2, (p2 + p3) / 2, p3);
switch (AvailableColumns) switch (TotalColumns)
{ {
case 2: case 2:
centreProbability = 0; centreProbability = 0;
@ -379,7 +378,7 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
double centreVal = Random.NextDouble(); double centreVal = Random.NextDouble();
int noteCount = GetRandomNoteCount(p2, p3); int noteCount = GetRandomNoteCount(p2, p3);
addToCentre = AvailableColumns % 2 != 0 && noteCount != 3 && centreVal > 1 - centreProbability; addToCentre = TotalColumns % 2 != 0 && noteCount != 3 && centreVal > 1 - centreProbability;
return noteCount; return noteCount;
} }

View File

@ -1,4 +1,4 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System; using System;
@ -25,16 +25,15 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
/// </summary> /// </summary>
protected readonly FastRandom Random; protected readonly FastRandom Random;
protected PatternGenerator(FastRandom random, HitObject hitObject, Beatmap beatmap, int availableColumns, Pattern previousPattern) protected PatternGenerator(FastRandom random, HitObject hitObject, ManiaBeatmap beatmap, Pattern previousPattern)
: base(hitObject, beatmap, availableColumns, previousPattern) : base(hitObject, beatmap, previousPattern)
{ {
if (random == null) throw new ArgumentNullException(nameof(random)); if (random == null) throw new ArgumentNullException(nameof(random));
if (beatmap == null) throw new ArgumentNullException(nameof(beatmap)); if (beatmap == null) throw new ArgumentNullException(nameof(beatmap));
if (availableColumns <= 0) throw new ArgumentOutOfRangeException(nameof(availableColumns));
if (previousPattern == null) throw new ArgumentNullException(nameof(previousPattern)); if (previousPattern == null) throw new ArgumentNullException(nameof(previousPattern));
Random = random; Random = random;
RandomStart = AvailableColumns == 8 ? 1 : 0; RandomStart = TotalColumns == 8 ? 1 : 0;
} }
/// <summary> /// <summary>
@ -45,14 +44,14 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns.Legacy
/// <returns>The column.</returns> /// <returns>The column.</returns>
protected int GetColumn(float position, bool allowSpecial = false) protected int GetColumn(float position, bool allowSpecial = false)
{ {
if (allowSpecial && AvailableColumns == 8) if (allowSpecial && TotalColumns == 8)
{ {
const float local_x_divisor = 512f / 7; const float local_x_divisor = 512f / 7;
return MathHelper.Clamp((int)Math.Floor(position / local_x_divisor), 0, 6) + 1; return MathHelper.Clamp((int)Math.Floor(position / local_x_divisor), 0, 6) + 1;
} }
float localXDivisor = 512f / AvailableColumns; float localXDivisor = 512f / TotalColumns;
return MathHelper.Clamp((int)Math.Floor(position / localXDivisor), 0, AvailableColumns - 1); return MathHelper.Clamp((int)Math.Floor(position / localXDivisor), 0, TotalColumns - 1);
} }
/// <summary> /// <summary>

View File

@ -1,4 +1,4 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System; using System;

View File

@ -1,4 +1,4 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System.Collections.Generic; using System.Collections.Generic;

View File

@ -1,8 +1,7 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System; using System;
using osu.Game.Beatmaps;
using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects;
namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns
@ -12,11 +11,6 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns
/// </summary> /// </summary>
internal abstract class PatternGenerator internal abstract class PatternGenerator
{ {
/// <summary>
/// The number of columns available to create the pattern.
/// </summary>
protected readonly int AvailableColumns;
/// <summary> /// <summary>
/// The last pattern. /// The last pattern.
/// </summary> /// </summary>
@ -30,19 +24,21 @@ namespace osu.Game.Rulesets.Mania.Beatmaps.Patterns
/// <summary> /// <summary>
/// The beatmap which <see cref="HitObject"/> is a part of. /// The beatmap which <see cref="HitObject"/> is a part of.
/// </summary> /// </summary>
protected readonly Beatmap Beatmap; protected readonly ManiaBeatmap Beatmap;
protected PatternGenerator(HitObject hitObject, Beatmap beatmap, int availableColumns, Pattern previousPattern) protected readonly int TotalColumns;
protected PatternGenerator(HitObject hitObject, ManiaBeatmap beatmap, Pattern previousPattern)
{ {
if (hitObject == null) throw new ArgumentNullException(nameof(hitObject)); if (hitObject == null) throw new ArgumentNullException(nameof(hitObject));
if (beatmap == null) throw new ArgumentNullException(nameof(beatmap)); if (beatmap == null) throw new ArgumentNullException(nameof(beatmap));
if (availableColumns <= 0) throw new ArgumentOutOfRangeException(nameof(availableColumns));
if (previousPattern == null) throw new ArgumentNullException(nameof(previousPattern)); if (previousPattern == null) throw new ArgumentNullException(nameof(previousPattern));
HitObject = hitObject; HitObject = hitObject;
Beatmap = beatmap; Beatmap = beatmap;
AvailableColumns = availableColumns;
PreviousPattern = previousPattern; PreviousPattern = previousPattern;
TotalColumns = Beatmap.TotalColumns;
} }
/// <summary> /// <summary>

View File

@ -0,0 +1,18 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Rulesets.Mania.UI;
namespace osu.Game.Rulesets.Mania.Beatmaps
{
/// <summary>
/// Defines properties for each stage in a <see cref="ManiaPlayfield"/>.
/// </summary>
public struct StageDefinition
{
/// <summary>
/// The number of <see cref="Column"/>s which this stage contains.
/// </summary>
public int Columns;
}
}

View File

@ -1,4 +1,4 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Beatmaps; using osu.Game.Beatmaps;

View File

@ -1,4 +1,4 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;

View File

@ -1,4 +1,4 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;

View File

@ -1,4 +1,4 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Judgements;

View File

@ -1,11 +1,10 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Beatmaps;
using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects;
using System.Collections.Generic; using System.Collections.Generic;
using System;
namespace osu.Game.Rulesets.Mania namespace osu.Game.Rulesets.Mania
{ {
@ -18,6 +17,6 @@ namespace osu.Game.Rulesets.Mania
public override double Calculate(Dictionary<string, double> categoryDifficulty = null) => 0; public override double Calculate(Dictionary<string, double> categoryDifficulty = null) => 0;
protected override BeatmapConverter<ManiaHitObject> CreateBeatmapConverter(Beatmap beatmap) => new ManiaBeatmapConverter(true, (int)Math.Max(1, Math.Round(beatmap.BeatmapInfo.BaseDifficulty.CircleSize))); protected override BeatmapConverter<ManiaHitObject> CreateBeatmapConverter(Beatmap beatmap) => new ManiaBeatmapConverter(true, beatmap);
} }
} }

View File

@ -1,4 +1,4 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System.ComponentModel; using System.ComponentModel;

View File

@ -1,4 +1,4 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
@ -95,7 +95,6 @@ namespace osu.Game.Rulesets.Mania
new ModCinema(), new ModCinema(),
}, },
}, },
new ManiaModGravity()
}; };
default: default:
@ -113,7 +112,7 @@ namespace osu.Game.Rulesets.Mania
public override int LegacyID => 3; public override int LegacyID => 3;
public ManiaRuleset(RulesetInfo rulesetInfo) public ManiaRuleset(RulesetInfo rulesetInfo = null)
: base(rulesetInfo) : base(rulesetInfo)
{ {
} }

View File

@ -1,4 +1,4 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System; using System;

View File

@ -1,23 +0,0 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System.Collections.Generic;
using osu.Game.Rulesets.Mania.UI;
using osu.Game.Rulesets.Timing;
namespace osu.Game.Rulesets.Mania.Mods
{
/// <summary>
/// A type of mod which generates speed adjustments that scroll the hit objects and bar lines.
/// </summary>
internal interface IGenerateSpeedAdjustments
{
/// <summary>
/// Applies this mod to a hit renderer.
/// </summary>
/// <param name="rulesetContainer">The hit renderer to apply to.</param>
/// <param name="hitObjectTimingChanges">The per-column list of speed adjustments for hit objects.</param>
/// <param name="barlineTimingChanges">The list of speed adjustments for bar lines.</param>
void ApplyToRulesetContainer(ManiaRulesetContainer rulesetContainer, ref List<SpeedAdjustmentContainer>[] hitObjectTimingChanges, ref List<SpeedAdjustmentContainer> barlineTimingChanges);
}
}

View File

@ -0,0 +1,29 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Beatmaps;
using osu.Game.Rulesets.Mania.Beatmaps;
using osu.Game.Rulesets.Mania.Objects;
using osu.Game.Rulesets.Mods;
namespace osu.Game.Rulesets.Mania.Mods
{
public abstract class ManiaKeyMod : Mod, IApplicableToBeatmapConverter<ManiaHitObject>
{
public override string ShortenedName => Name;
public abstract int KeyCount { get; }
public override double ScoreMultiplier => 1; // TODO: Implement the mania key mod score multiplier
public override bool Ranked => true;
public void ApplyToBeatmapConverter(BeatmapConverter<ManiaHitObject> beatmapConverter)
{
var mbc = (ManiaBeatmapConverter)beatmapConverter;
// Although this can work, for now let's not allow keymods for mania-specific beatmaps
if (mbc.IsForCurrentRuleset)
return;
mbc.TargetColumns = KeyCount;
}
}
}

View File

@ -1,185 +0,0 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Graphics;
using osu.Game.Rulesets.Mods;
using System;
using System.Linq;
using osu.Framework.Extensions.IEnumerableExtensions;
using osu.Framework.MathUtils;
using osu.Game.Beatmaps;
using osu.Game.Rulesets.Mania.Objects;
using osu.Game.Rulesets.Mania.Replays;
using osu.Game.Rulesets.Mania.UI;
using osu.Game.Rulesets.Scoring;
using osu.Game.Users;
using osu.Game.Rulesets.UI;
namespace osu.Game.Rulesets.Mania.Mods
{
public class ManiaModNoFail : ModNoFail
{
}
public class ManiaModEasy : ModEasy
{
}
public class ManiaModHidden : ModHidden
{
public override string Description => @"The notes fade out before you hit them!";
public override double ScoreMultiplier => 1.0;
public override Type[] IncompatibleMods => new[] { typeof(ModFlashlight) };
}
public class ManiaModHardRock : ModHardRock
{
public override double ScoreMultiplier => 1.0;
}
public class ManiaModSuddenDeath : ModSuddenDeath
{
}
public class ManiaModDaycore : ModDaycore
{
public override double ScoreMultiplier => 0.3;
}
public class ManiaModDoubleTime : ModDoubleTime
{
public override double ScoreMultiplier => 1.0;
}
public class ManiaModHalfTime : ModHalfTime
{
public override double ScoreMultiplier => 0.3;
}
public class ManiaModNightcore : ModNightcore
{
public override double ScoreMultiplier => 1.0;
}
public class ManiaModFlashlight : ModFlashlight
{
public override double ScoreMultiplier => 1.0;
public override Type[] IncompatibleMods => new[] { typeof(ModHidden) };
}
public class ManiaModPerfect : ModPerfect
{
}
public class ManiaModFadeIn : Mod
{
public override string Name => "FadeIn";
public override string ShortenedName => "FI";
public override FontAwesome Icon => FontAwesome.fa_osu_mod_hidden;
public override ModType Type => ModType.DifficultyIncrease;
public override double ScoreMultiplier => 1;
public override bool Ranked => true;
public override Type[] IncompatibleMods => new[] { typeof(ModFlashlight) };
}
public class ManiaModRandom : Mod, IApplicableToRulesetContainer<ManiaHitObject>
{
public override string Name => "Random";
public override string ShortenedName => "RD";
public override FontAwesome Icon => FontAwesome.fa_osu_dice;
public override string Description => @"Shuffle around the notes!";
public override double ScoreMultiplier => 1;
public void ApplyToRulesetContainer(RulesetContainer<ManiaHitObject> rulesetContainer)
{
int availableColumns = ((ManiaRulesetContainer)rulesetContainer).AvailableColumns;
var shuffledColumns = Enumerable.Range(0, availableColumns).OrderBy(item => RNG.Next()).ToList();
rulesetContainer.Objects.OfType<ManiaHitObject>().ForEach(h => h.Column = shuffledColumns[h.Column]);
}
}
public abstract class ManiaKeyMod : Mod
{
public override string ShortenedName => Name;
public abstract int KeyCount { get; }
public override double ScoreMultiplier => 1; // TODO: Implement the mania key mod score multiplier
public override bool Ranked => true;
}
public class ManiaModKey1 : ManiaKeyMod
{
public override int KeyCount => 1;
public override string Name => "1K";
}
public class ManiaModKey2 : ManiaKeyMod
{
public override int KeyCount => 2;
public override string Name => "2K";
}
public class ManiaModKey3 : ManiaKeyMod
{
public override int KeyCount => 3;
public override string Name => "3K";
}
public class ManiaModKey4 : ManiaKeyMod
{
public override int KeyCount => 4;
public override string Name => "4K";
}
public class ManiaModKey5 : ManiaKeyMod
{
public override int KeyCount => 5;
public override string Name => "5K";
}
public class ManiaModKey6 : ManiaKeyMod
{
public override int KeyCount => 6;
public override string Name => "6K";
}
public class ManiaModKey7 : ManiaKeyMod
{
public override int KeyCount => 7;
public override string Name => "7K";
}
public class ManiaModKey8 : ManiaKeyMod
{
public override int KeyCount => 8;
public override string Name => "8K";
}
public class ManiaModKey9 : ManiaKeyMod
{
public override int KeyCount => 9;
public override string Name => "9K";
}
public class ManiaModKeyCoop : Mod
{
public override string Name => "KeyCoop";
public override string ShortenedName => "2P";
public override string Description => @"Double the key amount, double the fun!";
public override double ScoreMultiplier => 1;
public override bool Ranked => true;
}
public class ManiaModAutoplay : ModAutoplay<ManiaHitObject>
{
protected override Score CreateReplayScore(Beatmap<ManiaHitObject> beatmap) => new Score
{
User = new User { Username = "osu!topus!" },
Replay = new ManiaAutoGenerator(beatmap).Generate(),
};
}
}

View File

@ -0,0 +1,24 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Beatmaps;
using osu.Game.Rulesets.Mania.Objects;
using osu.Game.Rulesets.Mania.Replays;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Scoring;
using osu.Game.Users;
namespace osu.Game.Rulesets.Mania.Mods
{
public class ManiaModAutoplay : ModAutoplay<ManiaHitObject>
{
protected override Score CreateReplayScore(Beatmap<ManiaHitObject> beatmap)
{
return new Score
{
User = new User { Username = "osu!topus!" },
Replay = new ManiaAutoGenerator(beatmap).Generate(),
};
}
}
}

View File

@ -0,0 +1,12 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Rulesets.Mods;
namespace osu.Game.Rulesets.Mania.Mods
{
public class ManiaModDaycore : ModDaycore
{
public override double ScoreMultiplier => 0.3;
}
}

View File

@ -0,0 +1,12 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Rulesets.Mods;
namespace osu.Game.Rulesets.Mania.Mods
{
public class ManiaModDoubleTime : ModDoubleTime
{
public override double ScoreMultiplier => 1.0;
}
}

View File

@ -0,0 +1,11 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Rulesets.Mods;
namespace osu.Game.Rulesets.Mania.Mods
{
public class ManiaModEasy : ModEasy
{
}
}

View File

@ -0,0 +1,20 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
using osu.Game.Graphics;
using osu.Game.Rulesets.Mods;
namespace osu.Game.Rulesets.Mania.Mods
{
public class ManiaModFadeIn : Mod
{
public override string Name => "FadeIn";
public override string ShortenedName => "FI";
public override FontAwesome Icon => FontAwesome.fa_osu_mod_hidden;
public override ModType Type => ModType.DifficultyIncrease;
public override double ScoreMultiplier => 1;
public override bool Ranked => true;
public override Type[] IncompatibleMods => new[] { typeof(ModFlashlight) };
}
}

View File

@ -0,0 +1,14 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
using osu.Game.Rulesets.Mods;
namespace osu.Game.Rulesets.Mania.Mods
{
public class ManiaModFlashlight : ModFlashlight
{
public override double ScoreMultiplier => 1.0;
public override Type[] IncompatibleMods => new[] { typeof(ModHidden) };
}
}

View File

@ -1,48 +0,0 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System.Collections.Generic;
using System.Linq;
using osu.Game.Rulesets.Mania.Objects;
using osu.Game.Rulesets.Mania.UI;
using osu.Game.Rulesets.Mods;
using osu.Game.Graphics;
using osu.Game.Rulesets.Mania.Timing;
using osu.Game.Rulesets.Timing;
using osu.Game.Rulesets.Mania.Objects.Drawables;
namespace osu.Game.Rulesets.Mania.Mods
{
public class ManiaModGravity : Mod, IGenerateSpeedAdjustments
{
public override string Name => "Gravity";
public override string ShortenedName => "GR";
public override double ScoreMultiplier => 0;
public override FontAwesome Icon => FontAwesome.fa_sort_desc;
public void ApplyToRulesetContainer(ManiaRulesetContainer rulesetContainer, ref List<SpeedAdjustmentContainer>[] hitObjectTimingChanges, ref List<SpeedAdjustmentContainer> barlineTimingChanges)
{
// We have to generate one speed adjustment per hit object for gravity
foreach (ManiaHitObject obj in rulesetContainer.Objects.OfType<ManiaHitObject>())
{
MultiplierControlPoint controlPoint = rulesetContainer.CreateControlPointAt(obj.StartTime);
// Beat length has too large of an effect for gravity, so we'll force it to a constant value for now
controlPoint.TimingPoint.BeatLength = 1000;
hitObjectTimingChanges[obj.Column].Add(new ManiaSpeedAdjustmentContainer(controlPoint, ScrollingAlgorithm.Gravity));
}
// Like with hit objects, we need to generate one speed adjustment per bar line
foreach (DrawableBarLine barLine in rulesetContainer.BarLines)
{
var controlPoint = rulesetContainer.CreateControlPointAt(barLine.HitObject.StartTime);
// Beat length has too large of an effect for gravity, so we'll force it to a constant value for now
controlPoint.TimingPoint.BeatLength = 1000;
barlineTimingChanges.Add(new ManiaSpeedAdjustmentContainer(controlPoint, ScrollingAlgorithm.Gravity));
}
}
}
}

View File

@ -0,0 +1,12 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Rulesets.Mods;
namespace osu.Game.Rulesets.Mania.Mods
{
public class ManiaModHalfTime : ModHalfTime
{
public override double ScoreMultiplier => 0.3;
}
}

View File

@ -0,0 +1,12 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Rulesets.Mods;
namespace osu.Game.Rulesets.Mania.Mods
{
public class ManiaModHardRock : ModHardRock
{
public override double ScoreMultiplier => 1.0;
}
}

View File

@ -0,0 +1,15 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
using osu.Game.Rulesets.Mods;
namespace osu.Game.Rulesets.Mania.Mods
{
public class ManiaModHidden : ModHidden
{
public override string Description => @"The notes fade out before you hit them!";
public override double ScoreMultiplier => 1.0;
public override Type[] IncompatibleMods => new[] { typeof(ModFlashlight) };
}
}

View File

@ -0,0 +1,11 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
namespace osu.Game.Rulesets.Mania.Mods
{
public class ManiaModKey1 : ManiaKeyMod
{
public override int KeyCount => 1;
public override string Name => "1K";
}
}

View File

@ -0,0 +1,11 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
namespace osu.Game.Rulesets.Mania.Mods
{
public class ManiaModKey2 : ManiaKeyMod
{
public override int KeyCount => 2;
public override string Name => "2K";
}
}

View File

@ -0,0 +1,11 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
namespace osu.Game.Rulesets.Mania.Mods
{
public class ManiaModKey3 : ManiaKeyMod
{
public override int KeyCount => 3;
public override string Name => "3K";
}
}

View File

@ -0,0 +1,11 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
namespace osu.Game.Rulesets.Mania.Mods
{
public class ManiaModKey4 : ManiaKeyMod
{
public override int KeyCount => 4;
public override string Name => "4K";
}
}

View File

@ -0,0 +1,11 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
namespace osu.Game.Rulesets.Mania.Mods
{
public class ManiaModKey5 : ManiaKeyMod
{
public override int KeyCount => 5;
public override string Name => "5K";
}
}

View File

@ -0,0 +1,11 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
namespace osu.Game.Rulesets.Mania.Mods
{
public class ManiaModKey6 : ManiaKeyMod
{
public override int KeyCount => 6;
public override string Name => "6K";
}
}

View File

@ -0,0 +1,11 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
namespace osu.Game.Rulesets.Mania.Mods
{
public class ManiaModKey7 : ManiaKeyMod
{
public override int KeyCount => 7;
public override string Name => "7K";
}
}

Some files were not shown because too many files have changed in this diff Show More