Merge branch 'master' into fix-autoplay-button-deselect

This commit is contained in:
Dean Herbert
2018-03-16 17:31:14 +09:00
committed by GitHub
107 changed files with 483 additions and 310 deletions

View File

@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.Catch.Beatmaps
{ {
public override void PostProcess(Beatmap<CatchHitObject> beatmap) public override void PostProcess(Beatmap<CatchHitObject> beatmap)
{ {
if (beatmap.ComboColors.Count == 0) if (beatmap.ComboColours.Count == 0)
return; return;
int index = 0; int index = 0;
@ -31,11 +31,11 @@ namespace osu.Game.Rulesets.Catch.Beatmaps
if (obj.NewCombo) if (obj.NewCombo)
{ {
if (lastObj != null) lastObj.LastInCombo = true; if (lastObj != null) lastObj.LastInCombo = true;
colourIndex = (colourIndex + 1) % beatmap.ComboColors.Count; colourIndex = (colourIndex + 1) % beatmap.ComboColours.Count;
} }
obj.IndexInBeatmap = index++; obj.IndexInBeatmap = index++;
obj.ComboColour = beatmap.ComboColors[colourIndex]; obj.ComboColour = beatmap.ComboColours[colourIndex];
lastObj = obj; lastObj = obj;
} }

View File

@ -7,6 +7,6 @@ namespace osu.Game.Rulesets.Catch.Mods
{ {
public class CatchModDaycore : ModDaycore public class CatchModDaycore : ModDaycore
{ {
public override double ScoreMultiplier => 0.5; public override double ScoreMultiplier => 0.3;
} }
} }

View File

@ -7,5 +7,6 @@ namespace osu.Game.Rulesets.Catch.Mods
{ {
public class CatchModEasy : ModEasy public class CatchModEasy : ModEasy
{ {
public override string Description => @"Larger fruits, more forgiving HP drain, less accuracy required, and three lives!";
} }
} }

View File

@ -7,6 +7,6 @@ namespace osu.Game.Rulesets.Catch.Mods
{ {
public class CatchModHalfTime : ModHalfTime public class CatchModHalfTime : ModHalfTime
{ {
public override double ScoreMultiplier => 0.5; public override double ScoreMultiplier => 0.3;
} }
} }

View File

@ -8,6 +8,5 @@ namespace osu.Game.Rulesets.Catch.Mods
public class CatchModHardRock : ModHardRock public class CatchModHardRock : ModHardRock
{ {
public override double ScoreMultiplier => 1.12; public override double ScoreMultiplier => 1.12;
public override bool Ranked => true;
} }
} }

View File

@ -7,7 +7,7 @@ namespace osu.Game.Rulesets.Catch.Mods
{ {
public class CatchModHidden : ModHidden public class CatchModHidden : ModHidden
{ {
public override string Description => @"Play with fading notes for a slight score advantage."; public override string Description => @"Play with fading fruits.";
public override double ScoreMultiplier => 1.06; public override double ScoreMultiplier => 1.06;
} }
} }

View File

@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable
Origin = Anchor.BottomLeft; Origin = Anchor.BottomLeft;
X = 0; X = 0;
Child = bananaContainer = new Container { RelativeSizeAxes = Axes.Both }; InternalChild = bananaContainer = new Container { RelativeSizeAxes = Axes.Both };
foreach (var b in s.NestedHitObjects.Cast<BananaShower.Banana>()) foreach (var b in s.NestedHitObjects.Cast<BananaShower.Banana>())
AddNested(getVisualRepresentation?.Invoke(b)); AddNested(getVisualRepresentation?.Invoke(b));

View File

@ -22,7 +22,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load() private void load()
{ {
Child = new Pulp InternalChild = new Pulp
{ {
AccentColour = AccentColour, AccentColour = AccentColour,
Size = Size Size = Size

View File

@ -33,7 +33,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load() private void load()
{ {
Children = new[] InternalChildren = new[]
{ {
createPulp(HitObject.VisualRepresentation), createPulp(HitObject.VisualRepresentation),
border = new Circle border = new Circle
@ -65,7 +65,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable
if (HitObject.HyperDash) if (HitObject.HyperDash)
{ {
Add(new Pulp AddInternal(new Pulp
{ {
RelativePositionAxes = Axes.Both, RelativePositionAxes = Axes.Both,
Anchor = Anchor.Centre, Anchor = Anchor.Centre,

View File

@ -20,7 +20,7 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable
Origin = Anchor.BottomLeft; Origin = Anchor.BottomLeft;
X = 0; X = 0;
Child = dropletContainer = new Container { RelativeSizeAxes = Axes.Both, }; InternalChild = dropletContainer = new Container { RelativeSizeAxes = Axes.Both, };
foreach (var o in s.NestedHitObjects.Cast<CatchHitObject>()) foreach (var o in s.NestedHitObjects.Cast<CatchHitObject>())
AddNested(getVisualRepresentation?.Invoke(o)); AddNested(getVisualRepresentation?.Invoke(o));

View File

@ -7,6 +7,6 @@ namespace osu.Game.Rulesets.Mania.Mods
{ {
public class ManiaModDaycore : ModDaycore public class ManiaModDaycore : ModDaycore
{ {
public override double ScoreMultiplier => 0.3; public override double ScoreMultiplier => 0.5;
} }
} }

View File

@ -7,6 +7,6 @@ namespace osu.Game.Rulesets.Mania.Mods
{ {
public class ManiaModDoubleTime : ModDoubleTime public class ManiaModDoubleTime : ModDoubleTime
{ {
public override double ScoreMultiplier => 1.0; public override double ScoreMultiplier => 1;
} }
} }

View File

@ -16,8 +16,7 @@ namespace osu.Game.Rulesets.Mania.Mods
public override string Name => "Dual Stages"; public override string Name => "Dual Stages";
public override string ShortenedName => "DS"; public override string ShortenedName => "DS";
public override string Description => @"Double the stages, double the fun!"; public override string Description => @"Double the stages, double the fun!";
public override double ScoreMultiplier => 1; public override double ScoreMultiplier => 0;
public override bool Ranked => false;
public void ApplyToBeatmapConverter(BeatmapConverter<ManiaHitObject> beatmapConverter) public void ApplyToBeatmapConverter(BeatmapConverter<ManiaHitObject> beatmapConverter)
{ {

View File

@ -7,5 +7,6 @@ namespace osu.Game.Rulesets.Mania.Mods
{ {
public class ManiaModEasy : ModEasy public class ManiaModEasy : ModEasy
{ {
public override string Description => @"More forgiving HP drain, less accuracy required, and three lives!";
} }
} }

View File

@ -9,10 +9,11 @@ namespace osu.Game.Rulesets.Mania.Mods
{ {
public class ManiaModFadeIn : Mod public class ManiaModFadeIn : Mod
{ {
public override string Name => "FadeIn"; public override string Name => "Fade In";
public override string ShortenedName => "FI"; public override string ShortenedName => "FI";
public override FontAwesome Icon => FontAwesome.fa_osu_mod_hidden; public override FontAwesome Icon => FontAwesome.fa_osu_mod_hidden;
public override ModType Type => ModType.DifficultyIncrease; public override ModType Type => ModType.DifficultyIncrease;
public override string Description => @"Keys appear out of nowhere!";
public override double ScoreMultiplier => 1; public override double ScoreMultiplier => 1;
public override bool Ranked => true; public override bool Ranked => true;
public override Type[] IncompatibleMods => new[] { typeof(ModFlashlight) }; public override Type[] IncompatibleMods => new[] { typeof(ModFlashlight) };

View File

@ -8,7 +8,7 @@ namespace osu.Game.Rulesets.Mania.Mods
{ {
public class ManiaModFlashlight : ModFlashlight public class ManiaModFlashlight : ModFlashlight
{ {
public override double ScoreMultiplier => 1.0; public override double ScoreMultiplier => 1;
public override Type[] IncompatibleMods => new[] { typeof(ModHidden) }; public override Type[] IncompatibleMods => new[] { typeof(ModHidden) };
} }
} }

View File

@ -7,6 +7,6 @@ namespace osu.Game.Rulesets.Mania.Mods
{ {
public class ManiaModHalfTime : ModHalfTime public class ManiaModHalfTime : ModHalfTime
{ {
public override double ScoreMultiplier => 0.3; public override double ScoreMultiplier => 0.5;
} }
} }

View File

@ -7,6 +7,6 @@ namespace osu.Game.Rulesets.Mania.Mods
{ {
public class ManiaModHardRock : ModHardRock public class ManiaModHardRock : ModHardRock
{ {
public override double ScoreMultiplier => 1.0; public override double ScoreMultiplier => 1;
} }
} }

View File

@ -8,8 +8,8 @@ namespace osu.Game.Rulesets.Mania.Mods
{ {
public class ManiaModHidden : ModHidden public class ManiaModHidden : ModHidden
{ {
public override string Description => @"The notes fade out before you hit them!"; public override string Description => @"Keys fade out before you hit them!";
public override double ScoreMultiplier => 1.0; public override double ScoreMultiplier => 1;
public override Type[] IncompatibleMods => new[] { typeof(ModFlashlight) }; public override Type[] IncompatibleMods => new[] { typeof(ModFlashlight) };
} }
} }

View File

@ -6,6 +6,8 @@ namespace osu.Game.Rulesets.Mania.Mods
public class ManiaModKey1 : ManiaKeyMod public class ManiaModKey1 : ManiaKeyMod
{ {
public override int KeyCount => 1; public override int KeyCount => 1;
public override string Name => "1K"; public override string Name => "One Key";
public override string ShortenedName => "1K";
public override string Description => @"Play with one key.";
} }
} }

View File

@ -6,6 +6,8 @@ namespace osu.Game.Rulesets.Mania.Mods
public class ManiaModKey2 : ManiaKeyMod public class ManiaModKey2 : ManiaKeyMod
{ {
public override int KeyCount => 2; public override int KeyCount => 2;
public override string Name => "2K"; public override string Name => "Two Keys";
public override string ShortenedName => "2K";
public override string Description => @"Play with two keys.";
} }
} }

View File

@ -6,6 +6,8 @@ namespace osu.Game.Rulesets.Mania.Mods
public class ManiaModKey3 : ManiaKeyMod public class ManiaModKey3 : ManiaKeyMod
{ {
public override int KeyCount => 3; public override int KeyCount => 3;
public override string Name => "3K"; public override string Name => "Three Keys";
public override string ShortenedName => "3K";
public override string Description => @"Play with three keys.";
} }
} }

View File

@ -6,6 +6,8 @@ namespace osu.Game.Rulesets.Mania.Mods
public class ManiaModKey4 : ManiaKeyMod public class ManiaModKey4 : ManiaKeyMod
{ {
public override int KeyCount => 4; public override int KeyCount => 4;
public override string Name => "4K"; public override string Name => "Four Keys";
public override string ShortenedName => "4K";
public override string Description => @"Play with four keys.";
} }
} }

View File

@ -6,6 +6,8 @@ namespace osu.Game.Rulesets.Mania.Mods
public class ManiaModKey5 : ManiaKeyMod public class ManiaModKey5 : ManiaKeyMod
{ {
public override int KeyCount => 5; public override int KeyCount => 5;
public override string Name => "5K"; public override string Name => "Five Keys";
public override string ShortenedName => "5K";
public override string Description => @"Play with five keys.";
} }
} }

View File

@ -6,6 +6,8 @@ namespace osu.Game.Rulesets.Mania.Mods
public class ManiaModKey6 : ManiaKeyMod public class ManiaModKey6 : ManiaKeyMod
{ {
public override int KeyCount => 6; public override int KeyCount => 6;
public override string Name => "6K"; public override string Name => "Six Keys";
public override string ShortenedName => "6K";
public override string Description => @"Play with six keys.";
} }
} }

View File

@ -6,6 +6,8 @@ namespace osu.Game.Rulesets.Mania.Mods
public class ManiaModKey7 : ManiaKeyMod public class ManiaModKey7 : ManiaKeyMod
{ {
public override int KeyCount => 7; public override int KeyCount => 7;
public override string Name => "7K"; public override string Name => "Seven Keys";
public override string ShortenedName => "7K";
public override string Description => @"Play with seven keys.";
} }
} }

View File

@ -6,6 +6,8 @@ namespace osu.Game.Rulesets.Mania.Mods
public class ManiaModKey8 : ManiaKeyMod public class ManiaModKey8 : ManiaKeyMod
{ {
public override int KeyCount => 8; public override int KeyCount => 8;
public override string Name => "8K"; public override string Name => "Eight Keys";
public override string ShortenedName => "8K";
public override string Description => @"Play with eight keys.";
} }
} }

View File

@ -6,6 +6,8 @@ namespace osu.Game.Rulesets.Mania.Mods
public class ManiaModKey9 : ManiaKeyMod public class ManiaModKey9 : ManiaKeyMod
{ {
public override int KeyCount => 9; public override int KeyCount => 9;
public override string Name => "9K"; public override string Name => "Nine Keys";
public override string ShortenedName => "9K";
public override string Description => @"Play with nine keys.";
} }
} }

View File

@ -7,6 +7,6 @@ namespace osu.Game.Rulesets.Mania.Mods
{ {
public class ManiaModNightcore : ModNightcore public class ManiaModNightcore : ModNightcore
{ {
public override double ScoreMultiplier => 1.0; public override double ScoreMultiplier => 1;
} }
} }

View File

@ -17,8 +17,8 @@ namespace osu.Game.Rulesets.Mania.Mods
public override string Name => "Random"; public override string Name => "Random";
public override string ShortenedName => "RD"; public override string ShortenedName => "RD";
public override FontAwesome Icon => FontAwesome.fa_osu_dice; public override FontAwesome Icon => FontAwesome.fa_osu_dice;
public override string Description => @"Shuffle around the notes!"; public override string Description => @"Shuffle around the keys!";
public override double ScoreMultiplier => 1; public override double ScoreMultiplier => 0;
public void ApplyToRulesetContainer(RulesetContainer<ManiaHitObject> rulesetContainer) public void ApplyToRulesetContainer(RulesetContainer<ManiaHitObject> rulesetContainer)
{ {

View File

@ -30,7 +30,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
RelativeSizeAxes = Axes.X; RelativeSizeAxes = Axes.X;
Height = 1; Height = 1;
Add(new Box AddInternal(new Box
{ {
Name = "Bar line", Name = "Bar line",
Anchor = Anchor.BottomCentre, Anchor = Anchor.BottomCentre,
@ -42,7 +42,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
if (isMajor) if (isMajor)
{ {
Add(new EquilateralTriangle AddInternal(new EquilateralTriangle
{ {
Name = "Left triangle", Name = "Left triangle",
Anchor = Anchor.BottomLeft, Anchor = Anchor.BottomLeft,
@ -52,7 +52,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
Rotation = 90 Rotation = 90
}); });
Add(new EquilateralTriangle AddInternal(new EquilateralTriangle
{ {
Name = "Right triangle", Name = "Right triangle",
Anchor = Anchor.BottomRight, Anchor = Anchor.BottomRight,

View File

@ -42,7 +42,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
{ {
RelativeSizeAxes = Axes.X; RelativeSizeAxes = Axes.X;
AddRange(new Drawable[] InternalChildren = new Drawable[]
{ {
// The hit object itself cannot be used for various elements because the tail overshoots it // The hit object itself cannot be used for various elements because the tail overshoots it
// So a specialized container that is updated to contain the tail height is used // So a specialized container that is updated to contain the tail height is used
@ -68,7 +68,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
Anchor = Anchor.TopCentre, Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre Origin = Anchor.TopCentre
} }
}); };
foreach (var tick in HitObject.NestedHitObjects.OfType<HoldNoteTick>()) foreach (var tick in HitObject.NestedHitObjects.OfType<HoldNoteTick>())
{ {

View File

@ -35,7 +35,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
RelativeSizeAxes = Axes.X; RelativeSizeAxes = Axes.X;
Size = new Vector2(1); Size = new Vector2(1);
Children = new[] InternalChildren = new[]
{ {
glowContainer = new CircularContainer glowContainer = new CircularContainer
{ {

View File

@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
RelativeSizeAxes = Axes.X; RelativeSizeAxes = Axes.X;
AutoSizeAxes = Axes.Y; AutoSizeAxes = Axes.Y;
Children = new Drawable[] InternalChildren = new Drawable[]
{ {
laneGlowPiece = new LaneGlowPiece laneGlowPiece = new LaneGlowPiece
{ {

View File

@ -14,7 +14,7 @@ namespace osu.Game.Rulesets.Osu.Beatmaps
{ {
applyStacking(beatmap); applyStacking(beatmap);
if (beatmap.ComboColors.Count == 0) if (beatmap.ComboColours.Count == 0)
return; return;
int comboIndex = 0; int comboIndex = 0;
@ -25,11 +25,11 @@ namespace osu.Game.Rulesets.Osu.Beatmaps
if (obj.NewCombo) if (obj.NewCombo)
{ {
comboIndex = 0; comboIndex = 0;
colourIndex = (colourIndex + 1) % beatmap.ComboColors.Count; colourIndex = (colourIndex + 1) % beatmap.ComboColours.Count;
} }
obj.IndexInCurrentCombo = comboIndex++; obj.IndexInCurrentCombo = comboIndex++;
obj.ComboColour = beatmap.ComboColors[colourIndex]; obj.ComboColour = beatmap.ComboColours[colourIndex];
} }
} }

View File

@ -7,6 +7,6 @@ namespace osu.Game.Rulesets.Osu.Mods
{ {
public class OsuModDaycore : ModDaycore public class OsuModDaycore : ModDaycore
{ {
public override double ScoreMultiplier => 0.5; public override double ScoreMultiplier => 0.3;
} }
} }

View File

@ -7,5 +7,6 @@ namespace osu.Game.Rulesets.Osu.Mods
{ {
public class OsuModEasy : ModEasy public class OsuModEasy : ModEasy
{ {
public override string Description => @"Larger circles, more forgiving HP drain, less accuracy required, and three lives!";
} }
} }

View File

@ -7,6 +7,6 @@ namespace osu.Game.Rulesets.Osu.Mods
{ {
public class OsuModHalfTime : ModHalfTime public class OsuModHalfTime : ModHalfTime
{ {
public override double ScoreMultiplier => 0.5; public override double ScoreMultiplier => 0.3;
} }
} }

View File

@ -14,7 +14,6 @@ namespace osu.Game.Rulesets.Osu.Mods
public class OsuModHardRock : ModHardRock, IApplicableToHitObject<OsuHitObject> public class OsuModHardRock : ModHardRock, IApplicableToHitObject<OsuHitObject>
{ {
public override double ScoreMultiplier => 1.06; public override double ScoreMultiplier => 1.06;
public override bool Ranked => true;
public void ApplyToHitObject(OsuHitObject hitObject) public void ApplyToHitObject(OsuHitObject hitObject)
{ {

View File

@ -15,7 +15,7 @@ namespace osu.Game.Rulesets.Osu.Mods
{ {
public class OsuModHidden : ModHidden, IApplicableToDrawableHitObjects public class OsuModHidden : ModHidden, IApplicableToDrawableHitObjects
{ {
public override string Description => @"Play with no approach circles and fading notes for a slight score advantage."; public override string Description => @"Play with no approach circles and fading circles/sliders.";
public override double ScoreMultiplier => 1.06; public override double ScoreMultiplier => 1.06;
private const double fade_in_duration_multiplier = 0.4; private const double fade_in_duration_multiplier = 0.4;

View File

@ -9,7 +9,7 @@ namespace osu.Game.Rulesets.Osu.Mods
{ {
public class OsuModRelax : ModRelax public class OsuModRelax : ModRelax
{ {
public override string Description => "You don't need to click.\nGive your clicking/tapping finger a break from the heat of things."; public override string Description => @"You don't need to click. Give your clicking/tapping fingers a break from the heat of things.";
public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(OsuModAutopilot) }).ToArray(); public override Type[] IncompatibleMods => base.IncompatibleMods.Concat(new[] { typeof(OsuModAutopilot) }).ToArray();
} }
} }

View File

@ -12,7 +12,7 @@ namespace osu.Game.Rulesets.Osu.Mods
public override string Name => "Spun Out"; public override string Name => "Spun Out";
public override string ShortenedName => "SO"; public override string ShortenedName => "SO";
public override FontAwesome Icon => FontAwesome.fa_osu_mod_spunout; public override FontAwesome Icon => FontAwesome.fa_osu_mod_spunout;
public override string Description => @"Spinners will be automatically completed"; public override string Description => @"Spinners will be automatically completed.";
public override double ScoreMultiplier => 0.9; public override double ScoreMultiplier => 0.9;
public override bool Ranked => true; public override bool Ranked => true;
public override Type[] IncompatibleMods => new[] { typeof(ModAutoplay), typeof(OsuModAutopilot) }; public override Type[] IncompatibleMods => new[] { typeof(ModAutoplay), typeof(OsuModAutopilot) };

View File

@ -11,7 +11,7 @@ namespace osu.Game.Rulesets.Osu.Mods
public override string Name => "Target"; public override string Name => "Target";
public override string ShortenedName => "TP"; public override string ShortenedName => "TP";
public override FontAwesome Icon => FontAwesome.fa_osu_mod_target; public override FontAwesome Icon => FontAwesome.fa_osu_mod_target;
public override string Description => @""; public override string Description => @"Practice keeping up with the beat of the song.";
public override double ScoreMultiplier => 1; public override double ScoreMultiplier => 1;
} }
} }

View File

@ -28,7 +28,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
Position = HitObject.StackedPosition; Position = HitObject.StackedPosition;
Scale = new Vector2(h.Scale); Scale = new Vector2(h.Scale);
Children = new Drawable[] InternalChildren = new Drawable[]
{ {
glow = new GlowPiece glow = new GlowPiece
{ {

View File

@ -30,7 +30,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
Blending = BlendingMode.Additive; Blending = BlendingMode.Additive;
Origin = Anchor.Centre; Origin = Anchor.Centre;
Children = new Drawable[] InternalChildren = new Drawable[]
{ {
new SpriteIcon new SpriteIcon
{ {

View File

@ -37,7 +37,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
Container<DrawableSliderTick> ticks; Container<DrawableSliderTick> ticks;
Container<DrawableRepeatPoint> repeatPoints; Container<DrawableRepeatPoint> repeatPoints;
Children = new Drawable[] InternalChildren = new Drawable[]
{ {
Body = new SliderBody(s) Body = new SliderBody(s)
{ {

View File

@ -31,7 +31,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
BorderThickness = 2; BorderThickness = 2;
BorderColour = Color4.White; BorderColour = Color4.White;
Children = new Drawable[] InternalChildren = new Drawable[]
{ {
new Box new Box
{ {

View File

@ -52,7 +52,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
Spinner = s; Spinner = s;
Children = new Drawable[] InternalChildren = new Drawable[]
{ {
circleContainer = new Container circleContainer = new Container
{ {

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;
using System.Collections.Generic;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Cursor;
using osu.Game.Graphics.Cursor;
using osu.Game.Rulesets.Osu.UI.Cursor;
using osu.Game.Tests.Visual;
namespace osu.Game.Rulesets.Osu.Tests
{
[TestFixture]
public class TestCaseGameplayCursor : OsuTestCase, IProvideCursor
{
private GameplayCursor cursor;
public override IReadOnlyList<Type> RequiredTypes => new [] { typeof(CursorTrail) };
public CursorContainer Cursor => cursor;
public bool ProvidingUserCursor => true;
[BackgroundDependencyLoader]
private void load()
{
Add(cursor = new GameplayCursor { RelativeSizeAxes = Axes.Both });
}
}
}

View File

@ -3,9 +3,9 @@
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.Runtime.InteropServices;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Framework.Graphics.Colour;
using osu.Framework.Graphics.OpenGL.Buffers; using osu.Framework.Graphics.OpenGL.Buffers;
using osu.Framework.Graphics.OpenGL.Vertices; using osu.Framework.Graphics.OpenGL.Vertices;
using osu.Framework.Graphics.Primitives; using osu.Framework.Graphics.Primitives;
@ -14,11 +14,12 @@ using osu.Framework.Graphics.Textures;
using osu.Framework.Input; using osu.Framework.Input;
using osu.Framework.Timing; using osu.Framework.Timing;
using OpenTK; using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.ES30; using OpenTK.Graphics.ES30;
namespace osu.Game.Rulesets.Osu.UI.Cursor namespace osu.Game.Rulesets.Osu.UI.Cursor
{ {
internal class CursorTrail : Drawable internal class CursorTrail : Drawable, IRequireHighFrequencyMousePosition
{ {
private int currentIndex; private int currentIndex;
@ -31,6 +32,8 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
private float time; private float time;
public override bool IsPresent => true;
private readonly TrailDrawNodeSharedData trailDrawNodeSharedData = new TrailDrawNodeSharedData(); private readonly TrailDrawNodeSharedData trailDrawNodeSharedData = new TrailDrawNodeSharedData();
private const int max_sprites = 2048; private const int max_sprites = 2048;
@ -96,7 +99,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
const int fade_clock_reset_threshold = 1000000; const int fade_clock_reset_threshold = 1000000;
time = (float)(Time.Current - timeOffset) / 500f; time = (float)(Time.Current - timeOffset) / 300f;
if (time > fade_clock_reset_threshold) if (time > fade_clock_reset_threshold)
resetTime(); resetTime();
} }
@ -115,14 +118,16 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
protected override bool OnMouseMove(InputState state) protected override bool OnMouseMove(InputState state)
{ {
Vector2 pos = state.Mouse.NativeState.Position;
if (lastPosition == null) if (lastPosition == null)
{ {
lastPosition = state.Mouse.NativeState.Position; lastPosition = pos;
resampler.AddPosition(lastPosition.Value); resampler.AddPosition(lastPosition.Value);
return base.OnMouseMove(state); return base.OnMouseMove(state);
} }
foreach (Vector2 pos2 in resampler.AddPosition(state.Mouse.NativeState.Position)) foreach (Vector2 pos2 in resampler.AddPosition(pos))
{ {
Trace.Assert(lastPosition.HasValue); Trace.Assert(lastPosition.HasValue);
@ -162,7 +167,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
private class TrailDrawNodeSharedData private class TrailDrawNodeSharedData
{ {
public VertexBuffer<TexturedVertex2D> VertexBuffer; public VertexBuffer<TexturedTrailVertex> VertexBuffer;
} }
private class TrailDrawNode : DrawNode private class TrailDrawNode : DrawNode
@ -188,7 +193,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
public override void Draw(Action<TexturedVertex2D> vertexAction) public override void Draw(Action<TexturedVertex2D> vertexAction)
{ {
if (Shared.VertexBuffer == null) if (Shared.VertexBuffer == null)
Shared.VertexBuffer = new QuadVertexBuffer<TexturedVertex2D>(max_sprites, BufferUsageHint.DynamicDraw); Shared.VertexBuffer = new QuadVertexBuffer<TexturedTrailVertex>(max_sprites, BufferUsageHint.DynamicDraw);
Shader.GetUniform<float>("g_FadeClock").Value = Time; Shader.GetUniform<float>("g_FadeClock").Value = Time;
@ -205,17 +210,19 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
int end = start; int end = start;
Vector2 pos = Parts[i].Position; Vector2 pos = Parts[i].Position;
ColourInfo colour = DrawInfo.Colour; float time = Parts[i].Time;
colour.TopLeft.Linear.A = Parts[i].Time + colour.TopLeft.Linear.A;
colour.TopRight.Linear.A = Parts[i].Time + colour.TopRight.Linear.A;
colour.BottomLeft.Linear.A = Parts[i].Time + colour.BottomLeft.Linear.A;
colour.BottomRight.Linear.A = Parts[i].Time + colour.BottomRight.Linear.A;
Texture.DrawQuad( Texture.DrawQuad(
new Quad(pos.X - Size.X / 2, pos.Y - Size.Y / 2, Size.X, Size.Y), new Quad(pos.X - Size.X / 2, pos.Y - Size.Y / 2, Size.X, Size.Y),
colour, DrawInfo.Colour,
null, null,
v => Shared.VertexBuffer.Vertices[end++] = v); v => Shared.VertexBuffer.Vertices[end++] = new TexturedTrailVertex
{
Position = v.Position,
TexturePosition = v.TexturePosition,
Time = time + 1,
Colour = v.Colour,
});
Parts[i].WasUpdated = false; Parts[i].WasUpdated = false;
} }
@ -240,5 +247,26 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
Shader.Unbind(); Shader.Unbind();
} }
} }
[StructLayout(LayoutKind.Sequential)]
public struct TexturedTrailVertex : IEquatable<TexturedTrailVertex>, IVertex
{
[VertexMember(2, VertexAttribPointerType.Float)]
public Vector2 Position;
[VertexMember(4, VertexAttribPointerType.Float)]
public Color4 Colour;
[VertexMember(2, VertexAttribPointerType.Float)]
public Vector2 TexturePosition;
[VertexMember(1, VertexAttribPointerType.Float)]
public float Time;
public bool Equals(TexturedTrailVertex other)
{
return Position.Equals(other.Position)
&& TexturePosition.Equals(other.TexturePosition)
&& Colour.Equals(other.Colour)
&& Time.Equals(other.Time);
}
}
} }
} }

View File

@ -20,13 +20,66 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
{ {
protected override Drawable CreateCursor() => new OsuCursor(); protected override Drawable CreateCursor() => new OsuCursor();
protected override Container<Drawable> Content => fadeContainer;
private readonly Container<Drawable> fadeContainer;
public GameplayCursor() public GameplayCursor()
{ {
Add(new CursorTrail { Depth = 1 }); InternalChild = fadeContainer = new Container
{
RelativeSizeAxes = Axes.Both,
Children = new Drawable[]
{
new CursorTrail { Depth = 1 }
}
};
} }
private int downCount; private int downCount;
public bool OnPressed(OsuAction action)
{
switch (action)
{
case OsuAction.LeftButton:
case OsuAction.RightButton:
downCount++;
ActiveCursor.ScaleTo(1).ScaleTo(1.2f, 100, Easing.OutQuad);
break;
}
return false;
}
public bool OnReleased(OsuAction action)
{
switch (action)
{
case OsuAction.LeftButton:
case OsuAction.RightButton:
if (--downCount == 0)
ActiveCursor.ScaleTo(1, 200, Easing.OutQuad);
break;
}
return false;
}
public override bool HandleMouseInput => true; // OverlayContainer will set this false when we go hidden, but we always want to receive input.
protected override void PopIn()
{
fadeContainer.FadeTo(1, 300, Easing.OutQuint);
ActiveCursor.ScaleTo(1, 400, Easing.OutQuint);
}
protected override void PopOut()
{
fadeContainer.FadeTo(0.05f, 450, Easing.OutQuint);
ActiveCursor.ScaleTo(0.8f, 450, Easing.OutQuint);
}
public class OsuCursor : Container public class OsuCursor : Container
{ {
private Container cursorContainer; private Container cursorContainer;
@ -131,45 +184,5 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
cursorContainer.Scale = new Vector2(scale); cursorContainer.Scale = new Vector2(scale);
} }
} }
public bool OnPressed(OsuAction action)
{
switch (action)
{
case OsuAction.LeftButton:
case OsuAction.RightButton:
downCount++;
ActiveCursor.ScaleTo(1).ScaleTo(1.2f, 100, Easing.OutQuad);
break;
}
return false;
}
public bool OnReleased(OsuAction action)
{
switch (action)
{
case OsuAction.LeftButton:
case OsuAction.RightButton:
if (--downCount == 0)
ActiveCursor.ScaleTo(1, 200, Easing.OutQuad);
break;
}
return false;
}
protected override void PopIn()
{
ActiveCursor.FadeTo(1, 250, Easing.OutQuint);
ActiveCursor.ScaleTo(1, 400, Easing.OutQuint);
}
protected override void PopOut()
{
ActiveCursor.FadeTo(0, 250, Easing.OutQuint);
ActiveCursor.ScaleTo(0.6f, 250, Easing.In);
}
} }
} }

View File

@ -131,6 +131,7 @@
<Compile Include="Replays\OsuReplayInputHandler.cs" /> <Compile Include="Replays\OsuReplayInputHandler.cs" />
<Compile Include="Tests\OsuBeatmapConversionTest.cs" /> <Compile Include="Tests\OsuBeatmapConversionTest.cs" />
<Compile Include="Tests\TestCaseEditor.cs" /> <Compile Include="Tests\TestCaseEditor.cs" />
<Compile Include="Tests\TestCaseGameplayCursor.cs" />
<Compile Include="Tests\TestCaseHitCircle.cs" /> <Compile Include="Tests\TestCaseHitCircle.cs" />
<Compile Include="Tests\TestCaseHitCircleHidden.cs" /> <Compile Include="Tests\TestCaseHitCircleHidden.cs" />
<Compile Include="Tests\TestCasePerformancePoints.cs" /> <Compile Include="Tests\TestCasePerformancePoints.cs" />

View File

@ -7,6 +7,6 @@ namespace osu.Game.Rulesets.Taiko.Mods
{ {
public class TaikoModDaycore : ModDaycore public class TaikoModDaycore : ModDaycore
{ {
public override double ScoreMultiplier => 0.5; public override double ScoreMultiplier => 0.3;
} }
} }

View File

@ -7,5 +7,6 @@ namespace osu.Game.Rulesets.Taiko.Mods
{ {
public class TaikoModEasy : ModEasy public class TaikoModEasy : ModEasy
{ {
public override string Description => @"Beats move slower, less accuracy required, and three lives!";
} }
} }

View File

@ -7,6 +7,6 @@ namespace osu.Game.Rulesets.Taiko.Mods
{ {
public class TaikoModHalfTime : ModHalfTime public class TaikoModHalfTime : ModHalfTime
{ {
public override double ScoreMultiplier => 0.5; public override double ScoreMultiplier => 0.3;
} }
} }

View File

@ -8,6 +8,5 @@ namespace osu.Game.Rulesets.Taiko.Mods
public class TaikoModHardRock : ModHardRock public class TaikoModHardRock : ModHardRock
{ {
public override double ScoreMultiplier => 1.06; public override double ScoreMultiplier => 1.06;
public override bool Ranked => true;
} }
} }

View File

@ -7,7 +7,7 @@ namespace osu.Game.Rulesets.Taiko.Mods
{ {
public class TaikoModHidden : ModHidden public class TaikoModHidden : ModHidden
{ {
public override string Description => @"The notes fade out before you hit them!"; public override string Description => @"Beats fade out before you hit them!";
public override double ScoreMultiplier => 1.06; public override double ScoreMultiplier => 1.06;
} }
} }

View File

@ -7,6 +7,6 @@ namespace osu.Game.Rulesets.Taiko.Mods
{ {
public class TaikoModRelax : ModRelax public class TaikoModRelax : ModRelax
{ {
public override string Description => @"Relax! You will no longer get dizzyfied by ninja-like spinners, demanding drumrolls or unexpected katu's."; public override string Description => @"No ninja-like spinners, demanding drumrolls or unexpected katu's.";
} }
} }

View File

@ -44,7 +44,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
RelativeSizeAxes = Axes.Y; RelativeSizeAxes = Axes.Y;
Width = tracker_width; Width = tracker_width;
Children = new[] InternalChildren = new[]
{ {
Tracker = new Box Tracker = new Box
{ {

View File

@ -25,7 +25,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
public DrawableBarLineMajor(BarLine barLine) public DrawableBarLineMajor(BarLine barLine)
: base(barLine) : base(barLine)
{ {
Add(triangleContainer = new Container AddInternal(triangleContainer = new Container
{ {
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Origin = Anchor.Centre, Origin = Anchor.Centre,

View File

@ -43,7 +43,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
switch (state) switch (state)
{ {
case ArmedState.Hit: case ArmedState.Hit:
Content.ScaleTo(0, 100, Easing.OutQuint).Expire(); this.ScaleTo(0, 100, Easing.OutQuint).Expire();
break; break;
} }
} }

View File

@ -103,7 +103,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
const float gravity_time = 300; const float gravity_time = 300;
const float gravity_travel_height = 200; const float gravity_travel_height = 200;
Content.ScaleTo(0.8f, gravity_time * 2, Easing.OutQuad); this.ScaleTo(0.8f, gravity_time * 2, Easing.OutQuad);
this.MoveToY(-gravity_travel_height, gravity_time, Easing.Out) this.MoveToY(-gravity_travel_height, gravity_time, Easing.Out)
.Then() .Then()

View File

@ -48,7 +48,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
{ {
FillMode = FillMode.Fit; FillMode = FillMode.Fit;
Add(bodyContainer = new Container AddInternal(bodyContainer = new Container
{ {
RelativeSizeAxes = Axes.Both, RelativeSizeAxes = Axes.Both,
Depth = 1, Depth = 1,

View File

@ -34,7 +34,7 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
RelativeSizeAxes = Axes.Both; RelativeSizeAxes = Axes.Both;
Size = BaseSize = new Vector2(HitObject.IsStrong ? TaikoHitObject.DEFAULT_STRONG_SIZE : TaikoHitObject.DEFAULT_SIZE); Size = BaseSize = new Vector2(HitObject.IsStrong ? TaikoHitObject.DEFAULT_STRONG_SIZE : TaikoHitObject.DEFAULT_SIZE);
Add(MainPiece = CreateMainPiece()); InternalChild = MainPiece = CreateMainPiece();
MainPiece.KiaiMode = HitObject.Kiai; MainPiece.KiaiMode = HitObject.Kiai;
} }

View File

@ -167,7 +167,7 @@ namespace osu.Game.Tests.Beatmaps.Formats
using (var resStream = Resource.OpenResource("Soleily - Renatus (Gamu) [Insane].osu")) using (var resStream = Resource.OpenResource("Soleily - Renatus (Gamu) [Insane].osu"))
using (var stream = new StreamReader(resStream)) using (var stream = new StreamReader(resStream))
{ {
var comboColors = decoder.Decode(stream).ComboColors; var comboColors = decoder.Decode(stream).ComboColours;
Color4[] expectedColors = Color4[] expectedColors =
{ {

View File

@ -102,9 +102,9 @@ namespace osu.Game.Tests.Beatmaps.Formats
new Color4(255, 187, 255, 255), new Color4(255, 187, 255, 255),
new Color4(255, 177, 140, 255), new Color4(255, 177, 140, 255),
}; };
Assert.AreEqual(expected.Length, beatmap.ComboColors.Count); Assert.AreEqual(expected.Length, beatmap.ComboColours.Count);
for (int i = 0; i < expected.Length; i++) for (int i = 0; i < expected.Length; i++)
Assert.AreEqual(expected[i], beatmap.ComboColors[i]); Assert.AreEqual(expected[i], beatmap.ComboColours[i]);
} }
[Test] [Test]

View File

@ -140,12 +140,12 @@ namespace osu.Game.Tests.Visual
{ {
Origin = Anchor.Centre; Origin = Anchor.Centre;
Add(new Box InternalChild = new Box
{ {
Anchor = Anchor.Centre, Anchor = Anchor.Centre,
Origin = Anchor.Centre, Origin = Anchor.Centre,
RelativeSizeAxes = Axes.Both RelativeSizeAxes = Axes.Both
}); };
switch (direction) switch (direction)
{ {
@ -175,7 +175,7 @@ namespace osu.Game.Tests.Visual
Origin = Anchor.Centre; Origin = Anchor.Centre;
AutoSizeAxes = Axes.Both; AutoSizeAxes = Axes.Both;
Add(new Box { Size = new Vector2(75) }); InternalChild = new Box { Size = new Vector2(75) };
} }
protected override void UpdateState(ArmedState state) protected override void UpdateState(ArmedState state)

View File

@ -13,7 +13,7 @@ namespace osu.Game.Tests.Visual
{ {
base.LoadComplete(); base.LoadComplete();
Add(new SkipButton(Clock.CurrentTime + 5000)); Add(new SkipOverlay(Clock.CurrentTime + 5000));
} }
} }
} }

View File

@ -9,6 +9,7 @@ using System.Linq;
using osu.Game.Beatmaps.ControlPoints; using osu.Game.Beatmaps.ControlPoints;
using osu.Game.IO.Serialization; using osu.Game.IO.Serialization;
using Newtonsoft.Json; using Newtonsoft.Json;
using osu.Game.Beatmaps.Formats;
using osu.Game.IO.Serialization.Converters; using osu.Game.IO.Serialization.Converters;
namespace osu.Game.Beatmaps namespace osu.Game.Beatmaps
@ -16,14 +17,14 @@ namespace osu.Game.Beatmaps
/// <summary> /// <summary>
/// A Beatmap containing converted HitObjects. /// A Beatmap containing converted HitObjects.
/// </summary> /// </summary>
public class Beatmap<T> : IJsonSerializable public class Beatmap<T> : IJsonSerializable, IHasComboColours
where T : HitObject where T : HitObject
{ {
public BeatmapInfo BeatmapInfo = new BeatmapInfo(); public BeatmapInfo BeatmapInfo = new BeatmapInfo();
public ControlPointInfo ControlPointInfo = new ControlPointInfo(); public ControlPointInfo ControlPointInfo = new ControlPointInfo();
public List<BreakPeriod> Breaks = new List<BreakPeriod>(); public List<BreakPeriod> Breaks = new List<BreakPeriod>();
public List<Color4> ComboColors = new List<Color4> public List<Color4> ComboColours { get; set; } = new List<Color4>
{ {
new Color4(17, 136, 170, 255), new Color4(17, 136, 170, 255),
new Color4(102, 136, 0, 255), new Color4(102, 136, 0, 255),
@ -55,7 +56,7 @@ namespace osu.Game.Beatmaps
BeatmapInfo = original?.BeatmapInfo.DeepClone() ?? BeatmapInfo; BeatmapInfo = original?.BeatmapInfo.DeepClone() ?? BeatmapInfo;
ControlPointInfo = original?.ControlPointInfo ?? ControlPointInfo; ControlPointInfo = original?.ControlPointInfo ?? ControlPointInfo;
Breaks = original?.Breaks ?? Breaks; Breaks = original?.Breaks ?? Breaks;
ComboColors = original?.ComboColors ?? ComboColors; ComboColours = original?.ComboColours ?? ComboColours;
HitObjects = original?.HitObjects ?? HitObjects; HitObjects = original?.HitObjects ?? HitObjects;
if (original == null && Metadata == null) if (original == null && Metadata == null)

View File

@ -50,9 +50,14 @@ namespace osu.Game.Beatmaps
protected virtual Beatmap<T> ConvertBeatmap(Beatmap original) protected virtual Beatmap<T> ConvertBeatmap(Beatmap original)
{ {
var beatmap = CreateBeatmap(); var beatmap = CreateBeatmap();
// todo: this *must* share logic (or directly use) Beatmap<T>'s constructor.
// right now this isn't easily possible due to generic entanglement.
beatmap.BeatmapInfo = original.BeatmapInfo; beatmap.BeatmapInfo = original.BeatmapInfo;
beatmap.ControlPointInfo = original.ControlPointInfo; beatmap.ControlPointInfo = original.ControlPointInfo;
beatmap.HitObjects = original.HitObjects.SelectMany(h => convert(h, original)).ToList(); beatmap.HitObjects = original.HitObjects.SelectMany(h => convert(h, original)).ToList();
beatmap.Breaks = original.Breaks;
beatmap.ComboColours = original.ComboColours;
return beatmap; return beatmap;
} }

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 System.Collections.Generic;
using OpenTK.Graphics;
namespace osu.Game.Beatmaps.Formats
{
public interface IHasComboColours
{
List<Color4> ComboColours { get; set; }
}
}

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 System.Collections.Generic;
using OpenTK.Graphics;
namespace osu.Game.Beatmaps.Formats
{
public interface IHasCustomColours
{
Dictionary<string, Color4> CustomColours { get; set; }
}
}

View File

@ -5,7 +5,6 @@ using System;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using OpenTK.Graphics;
using osu.Game.Beatmaps.Timing; using osu.Game.Beatmaps.Timing;
using osu.Game.Rulesets.Objects.Legacy; using osu.Game.Rulesets.Objects.Legacy;
using osu.Game.Beatmaps.ControlPoints; using osu.Game.Beatmaps.ControlPoints;
@ -19,7 +18,6 @@ namespace osu.Game.Beatmaps.Formats
private Beatmap beatmap; private Beatmap beatmap;
private bool hasCustomColours;
private ConvertHitObjectParser parser; private ConvertHitObjectParser parser;
private LegacySampleBank defaultSampleBank; private LegacySampleBank defaultSampleBank;
@ -72,29 +70,28 @@ namespace osu.Game.Beatmaps.Formats
{ {
case Section.General: case Section.General:
handleGeneral(line); handleGeneral(line);
break; return;
case Section.Editor: case Section.Editor:
handleEditor(line); handleEditor(line);
break; return;
case Section.Metadata: case Section.Metadata:
handleMetadata(line); handleMetadata(line);
break; return;
case Section.Difficulty: case Section.Difficulty:
handleDifficulty(line); handleDifficulty(line);
break; return;
case Section.Events: case Section.Events:
handleEvents(line); handleEvents(line);
break; return;
case Section.TimingPoints: case Section.TimingPoints:
handleTimingPoints(line); handleTimingPoints(line);
break; return;
case Section.Colours:
handleColours(line);
break;
case Section.HitObjects: case Section.HitObjects:
handleHitObjects(line); handleHitObjects(line);
break; return;
} }
base.ParseLine(beatmap, section, line);
} }
private void handleGeneral(string line) private void handleGeneral(string line)
@ -364,38 +361,6 @@ namespace osu.Game.Beatmaps.Formats
} }
} }
private void handleColours(string line)
{
var pair = SplitKeyVal(line, ':');
string[] split = pair.Value.Split(',');
if (split.Length != 3)
throw new InvalidOperationException($@"Color specified in incorrect format (should be R,G,B): {pair.Value}");
byte r, g, b;
if (!byte.TryParse(split[0], out r) || !byte.TryParse(split[1], out g) || !byte.TryParse(split[2], out b))
throw new InvalidOperationException(@"Color must be specified with 8-bit integer components");
if (!hasCustomColours)
{
beatmap.ComboColors.Clear();
hasCustomColours = true;
}
// Note: the combo index specified in the beatmap is discarded
if (pair.Key.StartsWith(@"Combo"))
{
beatmap.ComboColors.Add(new Color4
{
R = r / 255f,
G = g / 255f,
B = b / 255f,
A = 1f,
});
}
}
private void handleHitObjects(string line) private void handleHitObjects(string line)
{ {
// If the ruleset wasn't specified, assume the osu!standard ruleset. // If the ruleset wasn't specified, assume the osu!standard ruleset.

View File

@ -4,6 +4,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using OpenTK.Graphics;
namespace osu.Game.Beatmaps.Formats namespace osu.Game.Beatmaps.Formats
{ {
@ -40,7 +41,53 @@ namespace osu.Game.Beatmaps.Formats
protected virtual bool ShouldSkipLine(string line) => string.IsNullOrWhiteSpace(line) || line.StartsWith("//"); protected virtual bool ShouldSkipLine(string line) => string.IsNullOrWhiteSpace(line) || line.StartsWith("//");
protected abstract void ParseLine(T output, Section section, string line); protected virtual void ParseLine(T output, Section section, string line)
{
switch (section)
{
case Section.Colours:
handleColours(output, line);
return;
}
}
private bool hasComboColours;
private void handleColours(T output, string line)
{
var pair = SplitKeyVal(line, ':');
bool isCombo = pair.Key.StartsWith(@"Combo");
string[] split = pair.Value.Split(',');
if (split.Length != 3)
throw new InvalidOperationException($@"Color specified in incorrect format (should be R,G,B): {pair.Value}");
if (!byte.TryParse(split[0], out var r) || !byte.TryParse(split[1], out var g) || !byte.TryParse(split[2], out var b))
throw new InvalidOperationException(@"Color must be specified with 8-bit integer components");
Color4 colour = new Color4(r, g, b, 255);
if (isCombo)
{
if (!(output is IHasComboColours tHasComboColours)) return;
if (!hasComboColours)
{
// remove default colours.
tHasComboColours.ComboColours.Clear();
hasComboColours = true;
}
tHasComboColours.ComboColours.Add(colour);
}
else
{
if (!(output is IHasCustomColours tHasCustomColours)) return;
tHasCustomColours.CustomColours[pair.Key] = colour;
}
}
protected KeyValuePair<string, string> SplitKeyVal(string line, char separator) protected KeyValuePair<string, string> SplitKeyVal(string line, char separator)
{ {
@ -65,6 +112,7 @@ namespace osu.Game.Beatmaps.Formats
Colours, Colours,
HitObjects, HitObjects,
Variables, Variables,
Fonts
} }
internal enum LegacySampleBank internal enum LegacySampleBank

View File

@ -46,11 +46,13 @@ namespace osu.Game.Beatmaps.Formats
{ {
case Section.Events: case Section.Events:
handleEvents(line); handleEvents(line);
break; return;
case Section.Variables: case Section.Variables:
handleVariables(line); handleVariables(line);
break; return;
} }
base.ParseLine(storyboard, section, line);
} }
private void handleEvents(string line) private void handleEvents(string line)

View File

@ -8,15 +8,17 @@ using System.Diagnostics;
using System.Net; using System.Net;
using System.Threading; using System.Threading;
using osu.Framework.Configuration; using osu.Framework.Configuration;
using osu.Framework.Graphics;
using osu.Framework.Logging; using osu.Framework.Logging;
using osu.Framework.Threading; using osu.Game.Configuration;
using osu.Game.Online.API.Requests; using osu.Game.Online.API.Requests;
using osu.Game.Users; using osu.Game.Users;
namespace osu.Game.Online.API namespace osu.Game.Online.API
{ {
public class APIAccess : IAPIProvider public class APIAccess : Component, IAPIProvider
{ {
private readonly OsuConfigManager config;
private readonly OAuth authentication; private readonly OAuth authentication;
public string Endpoint = @"https://osu.ppy.sh"; public string Endpoint = @"https://osu.ppy.sh";
@ -25,13 +27,12 @@ namespace osu.Game.Online.API
private ConcurrentQueue<APIRequest> queue = new ConcurrentQueue<APIRequest>(); private ConcurrentQueue<APIRequest> queue = new ConcurrentQueue<APIRequest>();
public Scheduler Scheduler = new Scheduler(); /// <summary>
/// The username/email provided by the user when initiating a login.
/// </summary>
public string ProvidedUsername { get; private set; }
public string Username; private string password;
//private SecurePassword password;
public string Password;
public Bindable<User> LocalUser { get; } = new Bindable<User>(createGuestUser()); public Bindable<User> LocalUser { get; } = new Bindable<User>(createGuestUser());
@ -41,24 +42,31 @@ namespace osu.Game.Online.API
set { authentication.Token = string.IsNullOrEmpty(value) ? null : OAuthToken.Parse(value); } set { authentication.Token = string.IsNullOrEmpty(value) ? null : OAuthToken.Parse(value); }
} }
protected bool HasLogin => Token != null || !string.IsNullOrEmpty(Username) && !string.IsNullOrEmpty(Password); protected bool HasLogin => Token != null || !string.IsNullOrEmpty(ProvidedUsername) && !string.IsNullOrEmpty(password);
// ReSharper disable once PrivateFieldCanBeConvertedToLocalVariable (should dispose of this or at very least keep a reference). // ReSharper disable once PrivateFieldCanBeConvertedToLocalVariable (should dispose of this or at very least keep a reference).
private readonly Thread thread; private readonly Thread thread;
private readonly Logger log; private readonly Logger log;
public APIAccess() public APIAccess(OsuConfigManager config)
{ {
this.config = config;
authentication = new OAuth(client_id, client_secret, Endpoint); authentication = new OAuth(client_id, client_secret, Endpoint);
log = Logger.GetLogger(LoggingTarget.Network); log = Logger.GetLogger(LoggingTarget.Network);
ProvidedUsername = config.Get<string>(OsuSetting.Username);
Token = config.Get<string>(OsuSetting.Token);
thread = new Thread(run) { IsBackground = true }; thread = new Thread(run) { IsBackground = true };
thread.Start(); thread.Start();
} }
private readonly List<IOnlineComponent> components = new List<IOnlineComponent>(); private readonly List<IOnlineComponent> components = new List<IOnlineComponent>();
internal void Schedule(Action action) => base.Schedule(action);
public void Register(IOnlineComponent component) public void Register(IOnlineComponent component)
{ {
Scheduler.Add(delegate Scheduler.Add(delegate
@ -111,12 +119,15 @@ namespace osu.Game.Online.API
State = APIState.Connecting; State = APIState.Connecting;
if (!authentication.HasValidAccessToken && !authentication.AuthenticateWithLogin(Username, Password)) // save the username at this point, if the user requested for it to be.
config.Set(OsuSetting.Username, config.Get<bool>(OsuSetting.SaveUsername) ? ProvidedUsername : string.Empty);
if (!authentication.HasValidAccessToken && !authentication.AuthenticateWithLogin(ProvidedUsername, password))
{ {
//todo: this fails even on network-related issues. we should probably handle those differently. //todo: this fails even on network-related issues. we should probably handle those differently.
//NotificationOverlay.ShowMessage("Login failed!"); //NotificationOverlay.ShowMessage("Login failed!");
log.Add(@"Login failed!"); log.Add(@"Login failed!");
Password = null; password = null;
authentication.Clear(); authentication.Clear();
continue; continue;
} }
@ -173,8 +184,8 @@ namespace osu.Game.Online.API
{ {
Debug.Assert(State == APIState.Offline); Debug.Assert(State == APIState.Offline);
Username = username; ProvidedUsername = username;
Password = password; this.password = password;
} }
/// <summary> /// <summary>
@ -283,8 +294,8 @@ namespace osu.Game.Online.API
public void Logout(bool clearUsername = true) public void Logout(bool clearUsername = true)
{ {
flushQueue(); flushQueue();
if (clearUsername) Username = null; if (clearUsername) ProvidedUsername = null;
Password = null; password = null;
authentication.Clear(); authentication.Clear();
LocalUser.Value = createGuestUser(); LocalUser.Value = createGuestUser();
} }
@ -295,9 +306,12 @@ namespace osu.Game.Online.API
Id = 1, Id = 1,
}; };
public void Update() protected override void Dispose(bool isDisposing)
{ {
Scheduler.Update(); base.Dispose(isDisposing);
config.Set(OsuSetting.Token, config.Get<bool>(OsuSetting.SavePassword) ? Token : string.Empty);
config.Save();
} }
} }

View File

@ -14,7 +14,7 @@ namespace osu.Game.Online.API
return request; return request;
} }
private void request_Progress(long current, long total) => API.Scheduler.Add(delegate { Progress?.Invoke(current, total); }); private void request_Progress(long current, long total) => API.Schedule(() => Progress?.Invoke(current, total));
protected APIDownloadRequest() protected APIDownloadRequest()
{ {

View File

@ -85,7 +85,7 @@ namespace osu.Game.Online.API
if (checkAndProcessFailure()) if (checkAndProcessFailure())
return; return;
api.Scheduler.Add(delegate { Success?.Invoke(); }); api.Schedule(delegate { Success?.Invoke(); });
} }
public void Cancel() => Fail(new OperationCanceledException(@"Request cancelled")); public void Cancel() => Fail(new OperationCanceledException(@"Request cancelled"));
@ -108,7 +108,7 @@ namespace osu.Game.Online.API
{ {
if (API == null || pendingFailure == null) return cancelled; if (API == null || pendingFailure == null) return cancelled;
API.Scheduler.Add(pendingFailure); API.Schedule(pendingFailure);
pendingFailure = null; pendingFailure = null;
return true; return true;
} }

View File

@ -1,13 +1,12 @@
// Copyright (c) 2007-2018 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;
using osu.Framework.Configuration; using osu.Framework.Configuration;
using osu.Game.Users; using osu.Game.Users;
namespace osu.Game.Online.API namespace osu.Game.Online.API
{ {
public interface IAPIProvider : IUpdateable public interface IAPIProvider
{ {
/// <summary> /// <summary>
/// The local user. /// The local user.

View File

@ -34,7 +34,7 @@ using osu.Game.Skinning;
namespace osu.Game namespace osu.Game
{ {
public class OsuGameBase : Framework.Game, IOnlineComponent, ICanAcceptFiles public class OsuGameBase : Framework.Game, ICanAcceptFiles
{ {
protected OsuConfigManager LocalConfig; protected OsuConfigManager LocalConfig;
@ -56,8 +56,6 @@ namespace osu.Game
protected override string MainResourceFile => @"osu.Game.Resources.dll"; protected override string MainResourceFile => @"osu.Game.Resources.dll";
public APIAccess API;
private Container content; private Container content;
protected override Container<Drawable> Content => content; protected override Container<Drawable> Content => content;
@ -108,16 +106,14 @@ namespace osu.Game
dependencies.Cache(SkinManager = new SkinManager(Host.Storage, contextFactory, Host, Audio)); dependencies.Cache(SkinManager = new SkinManager(Host.Storage, contextFactory, Host, Audio));
dependencies.Cache(API = new APIAccess var api = new APIAccess(LocalConfig);
{
Username = LocalConfig.Get<string>(OsuSetting.Username), dependencies.Cache(api);
Token = LocalConfig.Get<string>(OsuSetting.Token) dependencies.CacheAs<IAPIProvider>(api);
});
dependencies.CacheAs<IAPIProvider>(API);
dependencies.Cache(RulesetStore = new RulesetStore(contextFactory)); dependencies.Cache(RulesetStore = new RulesetStore(contextFactory));
dependencies.Cache(FileStore = new FileStore(contextFactory, Host.Storage)); dependencies.Cache(FileStore = new FileStore(contextFactory, Host.Storage));
dependencies.Cache(BeatmapManager = new BeatmapManager(Host.Storage, contextFactory, RulesetStore, API, Host)); dependencies.Cache(BeatmapManager = new BeatmapManager(Host.Storage, contextFactory, RulesetStore, api, Host));
dependencies.Cache(ScoreStore = new ScoreStore(Host.Storage, contextFactory, Host, BeatmapManager, RulesetStore)); dependencies.Cache(ScoreStore = new ScoreStore(Host.Storage, contextFactory, Host, BeatmapManager, RulesetStore));
dependencies.Cache(KeyBindingStore = new KeyBindingStore(contextFactory, RulesetStore)); dependencies.Cache(KeyBindingStore = new KeyBindingStore(contextFactory, RulesetStore));
dependencies.Cache(SettingsStore = new SettingsStore(contextFactory)); dependencies.Cache(SettingsStore = new SettingsStore(contextFactory));
@ -183,9 +179,9 @@ namespace osu.Game
lastBeatmap = b; lastBeatmap = b;
}; };
API.Register(this);
FileStore.Cleanup(); FileStore.Cleanup();
AddInternal(api);
} }
private void runMigrations() private void runMigrations()
@ -211,16 +207,6 @@ namespace osu.Game
private WorkingBeatmap lastBeatmap; private WorkingBeatmap lastBeatmap;
public void APIStateChanged(APIAccess api, APIState state)
{
switch (state)
{
case APIState.Online:
LocalConfig.Set(OsuSetting.Username, LocalConfig.Get<bool>(OsuSetting.SaveUsername) ? API.Username : string.Empty);
break;
}
}
protected override void LoadComplete() protected override void LoadComplete()
{ {
base.LoadComplete(); base.LoadComplete();
@ -253,24 +239,6 @@ namespace osu.Game
base.SetHost(host); base.SetHost(host);
} }
protected override void Update()
{
base.Update();
API.Update();
}
protected override void Dispose(bool isDisposing)
{
//refresh token may have changed.
if (LocalConfig != null && API != null)
{
LocalConfig.Set(OsuSetting.Token, LocalConfig.Get<bool>(OsuSetting.SavePassword) ? API.Token : string.Empty);
LocalConfig.Save();
}
base.Dispose(isDisposing);
}
private readonly List<ICanAcceptFiles> fileImporters = new List<ICanAcceptFiles>(); private readonly List<ICanAcceptFiles> fileImporters = new List<ICanAcceptFiles>();
public void Import(params string[] paths) public void Import(params string[] paths)

View File

@ -186,7 +186,7 @@ namespace osu.Game.Overlays.Direct
progressBar.FadeOut(500); progressBar.FadeOut(500);
}; };
request.DownloadProgressed += progress => progressBar.Current.Value = progress; request.DownloadProgressed += progress => Schedule(() => progressBar.Current.Value = progress);
request.Success += data => request.Success += data =>
{ {

View File

@ -21,7 +21,7 @@ namespace osu.Game.Overlays.Mods
public DifficultyIncreaseSection() public DifficultyIncreaseSection()
{ {
Header = @"Gameplay Difficulty Increase"; Header = @"Difficulty Increase";
} }
} }
} }

View File

@ -21,7 +21,7 @@ namespace osu.Game.Overlays.Mods
public DifficultyReductionSection() public DifficultyReductionSection()
{ {
Header = @"Gameplay Difficulty Reduction"; Header = @"Difficulty Reduction";
} }
} }
} }

View File

@ -287,7 +287,7 @@ namespace osu.Game.Overlays.Mods
Anchor = Anchor.TopCentre, Anchor = Anchor.TopCentre,
Action = modButtonPressed, Action = modButtonPressed,
}, },
new AssistedSection new SpecialSection
{ {
RelativeSizeAxes = Axes.X, RelativeSizeAxes = Axes.X,
Origin = Anchor.TopCentre, Origin = Anchor.TopCentre,

View File

@ -8,7 +8,7 @@ using osu.Game.Rulesets.Mods;
namespace osu.Game.Overlays.Mods namespace osu.Game.Overlays.Mods
{ {
public class AssistedSection : ModSection public class SpecialSection : ModSection
{ {
protected override Key[] ToggleKeys => new[] { Key.Z, Key.X, Key.C, Key.V, Key.B, Key.N, Key.M }; protected override Key[] ToggleKeys => new[] { Key.Z, Key.X, Key.C, Key.V, Key.B, Key.N, Key.M };
public override ModType ModType => ModType.Special; public override ModType ModType => ModType.Special;
@ -19,9 +19,9 @@ namespace osu.Game.Overlays.Mods
SelectedColour = colours.BlueLight; SelectedColour = colours.BlueLight;
} }
public AssistedSection() public SpecialSection()
{ {
Header = @"Assisted"; Header = @"Special";
} }
} }
} }

View File

@ -210,7 +210,7 @@ namespace osu.Game.Overlays.Settings.Sections.General
{ {
PlaceholderText = "Email address", PlaceholderText = "Email address",
RelativeSizeAxes = Axes.X, RelativeSizeAxes = Axes.X,
Text = api?.Username ?? string.Empty, Text = api?.ProvidedUsername ?? string.Empty,
TabbableContentContainer = this TabbableContentContainer = this
}, },
password = new OsuPasswordTextBox password = new OsuPasswordTextBox

View File

@ -26,7 +26,7 @@ namespace osu.Game.Rulesets.Mods
public override string Name => "Autoplay"; public override string Name => "Autoplay";
public override string ShortenedName => "AT"; public override string ShortenedName => "AT";
public override FontAwesome Icon => FontAwesome.fa_osu_mod_auto; public override FontAwesome Icon => FontAwesome.fa_osu_mod_auto;
public override string Description => "Watch a perfect automated play through the song"; public override string Description => "Watch a perfect automated play through the song.";
public override double ScoreMultiplier => 0; public override double ScoreMultiplier => 0;
public bool AllowFail => false; public bool AllowFail => false;
public override Type[] IncompatibleMods => new[] { typeof(ModRelax), typeof(ModSuddenDeath), typeof(ModNoFail) }; public override Type[] IncompatibleMods => new[] { typeof(ModRelax), typeof(ModSuddenDeath), typeof(ModNoFail) };

View File

@ -11,5 +11,6 @@ namespace osu.Game.Rulesets.Mods
public override string ShortenedName => "CN"; public override string ShortenedName => "CN";
public override bool HasImplementation => false; public override bool HasImplementation => false;
public override FontAwesome Icon => FontAwesome.fa_osu_mod_cinema; public override FontAwesome Icon => FontAwesome.fa_osu_mod_cinema;
public override string Description => "Watch the video without visual distractions.";
} }
} }

View File

@ -12,7 +12,7 @@ namespace osu.Game.Rulesets.Mods
public override string Name => "Daycore"; public override string Name => "Daycore";
public override string ShortenedName => "DC"; public override string ShortenedName => "DC";
public override FontAwesome Icon => FontAwesome.fa_question; public override FontAwesome Icon => FontAwesome.fa_question;
public override string Description => "whoaaaaa"; public override string Description => "Whoaaaaa...";
public override void ApplyToClock(IAdjustableClock clock) public override void ApplyToClock(IAdjustableClock clock)
{ {

View File

@ -7,18 +7,16 @@ using osu.Game.Graphics;
namespace osu.Game.Rulesets.Mods namespace osu.Game.Rulesets.Mods
{ {
public class ModDoubleTime : Mod, IApplicableToClock public abstract class ModDoubleTime : Mod, IApplicableToClock
{ {
public override string Name => "Double Time"; public override string Name => "Double Time";
public override string ShortenedName => "DT"; public override string ShortenedName => "DT";
public override FontAwesome Icon => FontAwesome.fa_osu_mod_doubletime; public override FontAwesome Icon => FontAwesome.fa_osu_mod_doubletime;
public override ModType Type => ModType.DifficultyIncrease; public override ModType Type => ModType.DifficultyIncrease;
public override string Description => "Zoooooooooom"; public override string Description => "Zoooooooooom...";
public override bool Ranked => true; public override bool Ranked => true;
public override Type[] IncompatibleMods => new[] { typeof(ModHalfTime) }; public override Type[] IncompatibleMods => new[] { typeof(ModHalfTime) };
public override double ScoreMultiplier => 1.12;
public virtual void ApplyToClock(IAdjustableClock clock) public virtual void ApplyToClock(IAdjustableClock clock)
{ {
clock.Rate = 1.5; clock.Rate = 1.5;

View File

@ -13,7 +13,6 @@ namespace osu.Game.Rulesets.Mods
public override string ShortenedName => "EZ"; public override string ShortenedName => "EZ";
public override FontAwesome Icon => FontAwesome.fa_osu_mod_easy; public override FontAwesome Icon => FontAwesome.fa_osu_mod_easy;
public override ModType Type => ModType.DifficultyReduction; public override ModType Type => ModType.DifficultyReduction;
public override string Description => "Reduces overall difficulty - larger circles, more forgiving HP drain, less accuracy required.";
public override double ScoreMultiplier => 0.5; public override double ScoreMultiplier => 0.5;
public override bool Ranked => true; public override bool Ranked => true;
public override Type[] IncompatibleMods => new[] { typeof(ModHardRock) }; public override Type[] IncompatibleMods => new[] { typeof(ModHardRock) };

View File

@ -13,12 +13,10 @@ namespace osu.Game.Rulesets.Mods
public override string ShortenedName => "HT"; public override string ShortenedName => "HT";
public override FontAwesome Icon => FontAwesome.fa_osu_mod_halftime; public override FontAwesome Icon => FontAwesome.fa_osu_mod_halftime;
public override ModType Type => ModType.DifficultyReduction; public override ModType Type => ModType.DifficultyReduction;
public override string Description => "Less zoom"; public override string Description => "Less zoom...";
public override bool Ranked => true; public override bool Ranked => true;
public override Type[] IncompatibleMods => new[] { typeof(ModDoubleTime) }; public override Type[] IncompatibleMods => new[] { typeof(ModDoubleTime) };
public override double ScoreMultiplier => 1.12;
public virtual void ApplyToClock(IAdjustableClock clock) public virtual void ApplyToClock(IAdjustableClock clock)
{ {
clock.Rate = 0.75; clock.Rate = 0.75;

View File

@ -14,6 +14,7 @@ namespace osu.Game.Rulesets.Mods
public override FontAwesome Icon => FontAwesome.fa_osu_mod_hardrock; public override FontAwesome Icon => FontAwesome.fa_osu_mod_hardrock;
public override ModType Type => ModType.DifficultyIncrease; public override ModType Type => ModType.DifficultyIncrease;
public override string Description => "Everything just got a bit harder..."; public override string Description => "Everything just got a bit harder...";
public override bool Ranked => true;
public override Type[] IncompatibleMods => new[] { typeof(ModEasy) }; public override Type[] IncompatibleMods => new[] { typeof(ModEasy) };
public void ApplyToDifficulty(BeatmapDifficulty difficulty) public void ApplyToDifficulty(BeatmapDifficulty difficulty)

View File

@ -12,7 +12,7 @@ namespace osu.Game.Rulesets.Mods
public override string Name => "Nightcore"; public override string Name => "Nightcore";
public override string ShortenedName => "NC"; public override string ShortenedName => "NC";
public override FontAwesome Icon => FontAwesome.fa_osu_mod_nightcore; public override FontAwesome Icon => FontAwesome.fa_osu_mod_nightcore;
public override string Description => "uguuuuuuuu"; public override string Description => "Uguuuuuuuu...";
public override void ApplyToClock(IAdjustableClock clock) public override void ApplyToClock(IAdjustableClock clock)
{ {

View File

@ -8,7 +8,7 @@ namespace osu.Game.Rulesets.Mods
{ {
public abstract class ModNoFail : Mod, IApplicableFailOverride public abstract class ModNoFail : Mod, IApplicableFailOverride
{ {
public override string Name => "NoFail"; public override string Name => "No Fail";
public override string ShortenedName => "NF"; public override string ShortenedName => "NF";
public override FontAwesome Icon => FontAwesome.fa_osu_mod_nofail; public override FontAwesome Icon => FontAwesome.fa_osu_mod_nofail;
public override ModType Type => ModType.DifficultyReduction; public override ModType Type => ModType.DifficultyReduction;

View File

@ -1,6 +1,7 @@
// Copyright (c) 2007-2018 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.Graphics;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Mods namespace osu.Game.Rulesets.Mods
@ -9,6 +10,7 @@ namespace osu.Game.Rulesets.Mods
{ {
public override string Name => "Perfect"; public override string Name => "Perfect";
public override string ShortenedName => "PF"; public override string ShortenedName => "PF";
public override FontAwesome Icon => FontAwesome.fa_question;
public override string Description => "SS or quit."; public override string Description => "SS or quit.";
protected override bool FailCondition(ScoreProcessor scoreProcessor) => scoreProcessor.Accuracy.Value != 1; protected override bool FailCondition(ScoreProcessor scoreProcessor) => scoreProcessor.Accuracy.Value != 1;

View File

@ -13,7 +13,7 @@ namespace osu.Game.Rulesets.Mods
public override string ShortenedName => "SD"; public override string ShortenedName => "SD";
public override FontAwesome Icon => FontAwesome.fa_osu_mod_suddendeath; public override FontAwesome Icon => FontAwesome.fa_osu_mod_suddendeath;
public override ModType Type => ModType.DifficultyIncrease; public override ModType Type => ModType.DifficultyIncrease;
public override string Description => "Miss a note and fail."; public override string Description => "Miss and fail.";
public override double ScoreMultiplier => 1; public override double ScoreMultiplier => 1;
public override bool Ranked => true; public override bool Ranked => true;
public override Type[] IncompatibleMods => new[] { typeof(ModNoFail), typeof(ModRelax), typeof(ModAutoplay) }; public override Type[] IncompatibleMods => new[] { typeof(ModNoFail), typeof(ModRelax), typeof(ModAutoplay) };

View File

@ -8,7 +8,7 @@ namespace osu.Game.Rulesets.Mods
public override string Name => string.Empty; public override string Name => string.Empty;
public override string ShortenedName => string.Empty; public override string ShortenedName => string.Empty;
public override string Description => string.Empty; public override string Description => string.Empty;
public override double ScoreMultiplier => 0.0; public override double ScoreMultiplier => 0;
public Mod[] Mods; public Mod[] Mods;
} }

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