1
0
mirror of https://github.com/ppy/osu.git synced 2026-05-15 12:42:48 +08:00

Compare commits

...

182 Commits

174 changed files with 4640 additions and 1034 deletions
@@ -1,4 +1,6 @@
using osu.Framework.Graphics.Containers;
#define SoloTesting
using osu.Framework.Graphics.Containers;
using osu.Framework.Logging;
using System;
using System.Collections.Generic;
@@ -96,7 +98,7 @@ namespace Symcol.Core.Networking
public Action OnAbort;
/// <summary>
/// Called to load the game
/// Called to load the game (Includes Host)
/// </summary>
public Action<List<ClientInfo>> OnLoadGame;
@@ -286,8 +288,10 @@ namespace Symcol.Core.Networking
}
}
#if !SoloTesting
if (InMatchClients.Count == 0 && LoadedClients.Count > 0 && Loaded && !InGame)
SendStartGame();
#endif
//Peers
else if (SendClient != null)
@@ -333,6 +337,11 @@ namespace Symcol.Core.Networking
}
}
#if SoloTesting
if (Loaded && !InGame)
SendStartGame();
#endif
if (p != null)
OnPacketReceive?.Invoke(p);
@@ -552,7 +561,7 @@ namespace Symcol.Core.Networking
}
/// <summary>
/// Send tto all but the one that sent it
/// Send to all but the one that sent it
/// </summary>
/// <param name="packet"></param>
/// <param name="playerID"></param>
@@ -14,6 +14,10 @@ namespace Symcol.Rulesets.Core.HitObjects
public abstract class DrawableSymcolHitObject<TObject> : DrawableHitObject<TObject>
where TObject : HitObject
{
//Future prep?
//public override void ClearTransformsAfter(double time, bool propagateChildren = false, string targetMember = null) { }
//public override void ApplyTransformsAt(double time, bool propagateChildren = false) { }
protected virtual Container<Drawable> Content => new Container();
public IReadOnlyList<Drawable> Children
@@ -0,0 +1,22 @@
using Symcol.Core.Networking;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Symcol.Rulesets.Core.Multiplayer.Networking
{
[Serializable]
public class ScorePacket : Packet
{
public override int PacketSize => 2048;
public int Score;
public ScorePacket(ClientInfo clientInfo, int score) : base(clientInfo)
{
Score = score;
}
}
}
@@ -62,12 +62,12 @@ namespace Symcol.Rulesets.Core.Multiplayer.Pieces
},
TabControl = new OsuTabControl<MatchScreenMode>
{
Position = new Vector2(36, 0),
Position = new Vector2(72, 0),
Anchor = Anchor.TopCentre,
Origin = Anchor.TopCentre,
RelativeSizeAxes = Axes.Both,
Height = 0.08f,
Width = 0.6f
Width = 0.8f
},
SelectedContent = new Container
{
@@ -0,0 +1,93 @@
using OpenTK;
using OpenTK.Input;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Input;
using osu.Game.Rulesets.Scoring;
using Symcol.Core.Networking;
using Symcol.Rulesets.Core.Multiplayer.Networking;
using System.Collections.Generic;
namespace Symcol.Rulesets.Core.Multiplayer.Pieces
{
public class MultiplayerScoreboard : Container
{
public readonly Container<MultiplayerScoreboardItem> ScoreboardItems;
private readonly RulesetNetworkingClientHandler rulesetNetworkingClientHandler;
private readonly ScoreProcessor scoreProcessor;
private double updateScoreTime = 0;
public MultiplayerScoreboard(RulesetNetworkingClientHandler rulesetNetworkingClientHandler, List<ClientInfo> playerList, ScoreProcessor scoreProcessor)
{
this.rulesetNetworkingClientHandler = rulesetNetworkingClientHandler;
this.scoreProcessor = scoreProcessor;
AlwaysPresent = true;
AutoSizeAxes = Axes.Y;
Width = 120;
Position = new Vector2(0, -200);
Anchor = Anchor.CentreLeft;
Origin = Anchor.TopLeft;
Child = ScoreboardItems = new Container<MultiplayerScoreboardItem>
{
RelativeSizeAxes = Axes.X,
AutoSizeAxes = Axes.Y,
};
int i = 1;
foreach (ClientInfo clientInfo in playerList)
{
if (clientInfo is RulesetClientInfo rulesetClientInfo)
{
ScoreboardItems.Add(new MultiplayerScoreboardItem(rulesetClientInfo, i) { });
i++;
}
}
rulesetNetworkingClientHandler.OnPacketReceive += (Packet packet) =>
{
if (packet is ScorePacket scorePacket)
{
rulesetNetworkingClientHandler.ShareWithOtherPeers(scorePacket);
foreach (MultiplayerScoreboardItem item in ScoreboardItems)
if (scorePacket.ClientInfo == item.ClientInfo)
item.Score = scorePacket.Score;
}
};
}
protected override void Update()
{
base.Update();
if (Time.Current >= updateScoreTime)
{
updateScoreTime = Time.Current + 500;
foreach (MultiplayerScoreboardItem item in ScoreboardItems)
if (rulesetNetworkingClientHandler.ClientInfo == item.ClientInfo)
item.Score = (int)scoreProcessor.TotalScore.Value;
rulesetNetworkingClientHandler.SendToHost(new ScorePacket(rulesetNetworkingClientHandler.ClientInfo, (int)scoreProcessor.TotalScore.Value));
rulesetNetworkingClientHandler.SendToInGameClients(new ScorePacket(rulesetNetworkingClientHandler.ClientInfo, (int)scoreProcessor.TotalScore.Value));
}
}
protected override bool OnKeyDown(InputState state, KeyDownEventArgs args)
{
if (args.Key == Key.Tab)
{
if (Alpha > 0)
this.FadeOut(100);
else
this.FadeIn(100);
}
return base.OnKeyDown(state, args);
}
}
}
@@ -0,0 +1,107 @@
using OpenTK;
using OpenTK.Graphics;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Graphics.Sprites;
using Symcol.Rulesets.Core.Multiplayer.Networking;
using System.Collections.Generic;
namespace Symcol.Rulesets.Core.Multiplayer.Pieces
{
public class MultiplayerScoreboardItem : Container
{
public int Score
{
get { return score; }
set
{
if (value != score)
{
score = value;
scoreText.Text = value.ToString();
foreach(MultiplayerScoreboardItem item in itemList)
if (value > item.Score && Place > item.Place)
{
Place = item.Place;
foreach (MultiplayerScoreboardItem i in itemList)
if (i.Place < Place)
i.Place -= 1;
}
}
}
}
public int Place
{
get { return place; }
set
{
if (Place != place)
{
place = value;
this.MoveTo(new Vector2(0, (-height - 8) * (value - 1)), 200, Easing.OutQuint);
}
}
}
private int place = 0;
private int score = 0;
private const int height = 60;
public readonly RulesetClientInfo ClientInfo;
private readonly SpriteText scoreText;
private static List<MultiplayerScoreboardItem> itemList = new List<MultiplayerScoreboardItem>();
public MultiplayerScoreboardItem(RulesetClientInfo clientInfo, int place)
{
ClientInfo = clientInfo;
this.place = place;
itemList.Add(this);
RelativeSizeAxes = Axes.X;
Height = height;
Masking = true;
CornerRadius = 8;
Children = new Drawable[]
{
new Box
{
RelativeSizeAxes = Axes.Both,
Colour = Color4.Black,
Alpha = 0.8f,
},
new SpriteText
{
Anchor = Anchor.TopLeft,
Origin = Anchor.TopLeft,
Position = new Vector2(4),
Text = clientInfo.Username
},
scoreText = new SpriteText
{
Anchor = Anchor.BottomRight,
Origin = Anchor.BottomRight,
Position = new Vector2(-4),
Text = Score.ToString()
}
};
this.MoveTo(new Vector2(0, (-height - 8) * (Place - 1)), 200, Easing.OutQuint);
}
protected override void Dispose(bool isDisposing)
{
itemList.Remove(this);
base.Dispose(isDisposing);
}
}
}
@@ -30,6 +30,9 @@ using osu.Game.Screens;
using osu.Game.Screens.Play;
using OpenTK.Input;
using Symcol.Rulesets.Core.Multiplayer.Networking;
using Symcol.Rulesets.Core.Multiplayer.Pieces;
using System.Collections.Generic;
using Symcol.Core.Networking;
namespace Symcol.Rulesets.Core.Multiplayer.Screens
{
@@ -85,13 +88,18 @@ namespace Symcol.Rulesets.Core.Multiplayer.Screens
private HUDOverlay hudOverlay;
private MultiplayerScoreboard scoreboard;
private bool loadedSuccessfully => RulesetContainer?.Objects.Any() == true;
public MultiPlayer(RulesetNetworkingClientHandler rulesetNetworkingClientHandler)//, WorkingBeatmap beatmap = null)
private readonly List<ClientInfo> playerList;
public MultiPlayer(RulesetNetworkingClientHandler rulesetNetworkingClientHandler, List<ClientInfo> playerList)//, WorkingBeatmap beatmap = null)
{
RulesetNetworkingClientHandler = rulesetNetworkingClientHandler;
RulesetNetworkingClientHandler.OnAbort = () => Exit();
RulesetNetworkingClientHandler.StartGame = () => start();
this.playerList = playerList;
}
[BackgroundDependencyLoader]
@@ -191,7 +199,8 @@ namespace Symcol.Rulesets.Core.Multiplayer.Screens
Origin = Anchor.Centre,
ProcessCustomClock = false,
Breaks = beatmap.Breaks
}
},
scoreboard = new MultiplayerScoreboard(RulesetNetworkingClientHandler, playerList, scoreProcessor)
}
}
};
@@ -137,6 +137,7 @@ namespace Symcol.Rulesets.Core.Multiplayer.Screens
protected virtual void Load(List<ClientInfo> playerList)
{
MakeCurrent();
Push(new MultiPlayer(RulesetNetworkingClientHandler, playerList));
}
private void openSongSelect()
@@ -1,6 +1,6 @@
//osu.Game.Screens.Symcol.SymcolMenu
//Symcol.Rulesets.Core.SymcolSettingsSubsection
//#define SymcolMods
#define SymcolMods
using OpenTK;
using OpenTK.Graphics;
@@ -44,6 +44,7 @@
<Compile Include="Containers\LinkText.cs" />
<Compile Include="Containers\ProfileLink.cs" />
<Compile Include="HitObjects\DrawableSymcolHitObject.cs" />
<Compile Include="Multiplayer\Networking\ScorePacket.cs" />
<Compile Include="Multiplayer\Pieces\Chat.cs" />
<Compile Include="Multiplayer\Pieces\ChatMessage.cs" />
<Compile Include="Multiplayer\Networking\ChatPacket.cs" />
@@ -54,6 +55,8 @@
<Compile Include="Multiplayer\Options\MultiplayerDropdownEnumOption.cs" />
<Compile Include="Multiplayer\Options\MultiplayerOption.cs" />
<Compile Include="Multiplayer\Options\MultiplayerToggleOption.cs" />
<Compile Include="Multiplayer\Pieces\MultiplayerScoreboard.cs" />
<Compile Include="Multiplayer\Pieces\MultiplayerScoreboardItem.cs" />
<Compile Include="Multiplayer\Screens\MatchSongSelect.cs" />
<Compile Include="Multiplayer\Screens\MultiPlayer.cs" />
<Compile Include="Multiplayer\Screens\RulesetLobbyScreen.cs" />
@@ -1,6 +1,6 @@
//osu.Game.Screens.Symcol.SymcolMenu
//Symcol.Rulesets.Core.Multiplayer.Screens.RulesetMultiplayerSelection
//#define SymcolMods
#define SymcolMods
using osu.Framework.Allocation;
using osu.Game;
+4
View File
@@ -237,6 +237,10 @@
<Project>{c92a607b-1fdd-4954-9f92-03ff547d9080}</Project>
<Name>osu.Game.Rulesets.Osu</Name>
</ProjectReference>
<ProjectReference Include="..\osu.Game.Rulesets.Shape\osu.Game.Rulesets.Shape.csproj">
<Project>{baf6d7b6-5e48-4278-ab81-f079af640e31}</Project>
<Name>osu.Game.Rulesets.Shape</Name>
</ProjectReference>
<ProjectReference Include="..\osu.Game.Rulesets.Taiko\osu.Game.Rulesets.Taiko.csproj">
<Project>{f167e17a-7de6-4af5-b920-a5112296c695}</Project>
<Name>osu.Game.Rulesets.Taiko</Name>
+3 -5
View File
@@ -16,11 +16,9 @@
<language>en-AU</language>
</metadata>
<files>
<file src="*.exe" target="lib\net45\" exclude="**vshost**"/>
<file src="*.dll" target="lib\net45\"/>
<file src="*.config" target="lib\net45\"/>
<file src="x86\*.dll" target="lib\net45\x86\"/>
<file src="x64\*.dll" target="lib\net45\x64\"/>
<file src="**.exe" target="lib\net45\" exclude="**vshost**"/>
<file src="**.dll" target="lib\net45\"/>
<file src="**.config" target="lib\net45\"/>
</files>
</package>
@@ -16,29 +16,13 @@ namespace osu.Game.Rulesets.Catch.Beatmaps
{
public override void PostProcess(Beatmap<CatchHitObject> beatmap)
{
if (beatmap.ComboColours.Count == 0)
return;
int index = 0;
int colourIndex = 0;
CatchHitObject lastObj = null;
initialiseHyperDash(beatmap.HitObjects);
base.PostProcess(beatmap);
int index = 0;
foreach (var obj in beatmap.HitObjects)
{
if (obj.NewCombo)
{
if (lastObj != null) lastObj.LastInCombo = true;
colourIndex = (colourIndex + 1) % beatmap.ComboColours.Count;
}
obj.IndexInBeatmap = index++;
obj.ComboColour = beatmap.ComboColours[colourIndex];
lastObj = obj;
}
}
private void initialiseHyperDash(List<CatchHitObject> objects)
@@ -3,7 +3,6 @@
using osu.Framework.MathUtils;
using osu.Game.Rulesets.Objects.Types;
using OpenTK.Graphics;
namespace osu.Game.Rulesets.Catch.Objects
{
@@ -32,25 +31,11 @@ namespace osu.Game.Rulesets.Catch.Objects
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; }
@@ -5,24 +5,25 @@ using osu.Game.Beatmaps;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Objects.Types;
using OpenTK.Graphics;
namespace osu.Game.Rulesets.Catch.Objects
{
public abstract class CatchHitObject : HitObject, IHasXPosition, IHasCombo
public abstract class CatchHitObject : HitObject, IHasXPosition, IHasComboInformation
{
public const double OBJECT_RADIUS = 44;
public float X { get; set; }
public Color4 ComboColour { get; set; }
public int IndexInBeatmap { get; set; }
public virtual FruitVisualRepresentation VisualRepresentation => (FruitVisualRepresentation)(IndexInBeatmap % 4);
public virtual bool NewCombo { get; set; }
public int IndexInCurrentCombo { get; set; }
public int ComboIndex { get; set; }
/// <summary>
/// The next fruit starts a new combo. Used for explodey.
/// </summary>
@@ -8,6 +8,8 @@ using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Objects.Types;
using OpenTK;
using osu.Game.Rulesets.Scoring;
using osu.Game.Skinning;
using OpenTK.Graphics;
namespace osu.Game.Rulesets.Catch.Objects.Drawable
{
@@ -57,6 +59,14 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable
AddJudgement(new Judgement { Result = CheckPosition.Invoke(HitObject) ? HitResult.Perfect : HitResult.Miss });
}
protected override void SkinChanged(ISkinSource skin, bool allowFallback)
{
base.SkinChanged(skin, allowFallback);
if (HitObject is IHasComboInformation combo)
AccentColour = skin.GetValue<SkinConfiguration, Color4>(s => s.ComboColours.Count > 0 ? s.ComboColours[combo.ComboIndex % s.ComboColours.Count] : (Color4?)null) ?? Color4.White;
}
private const float preempt = 1000;
protected override void UpdateState(ArmedState state)
@@ -5,28 +5,39 @@ using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Game.Rulesets.Catch.Objects.Drawable.Pieces;
using OpenTK;
using OpenTK.Graphics;
namespace osu.Game.Rulesets.Catch.Objects.Drawable
{
public class DrawableDroplet : PalpableCatchHitObject<Droplet>
{
private Pulp pulp;
public DrawableDroplet(Droplet h)
: base(h)
{
Origin = Anchor.Centre;
Size = new Vector2((float)CatchHitObject.OBJECT_RADIUS) / 4;
AccentColour = h.ComboColour;
Masking = false;
}
[BackgroundDependencyLoader]
private void load()
{
InternalChild = new Pulp
InternalChild = pulp = new Pulp
{
AccentColour = AccentColour,
Size = Size
};
}
public override Color4 AccentColour
{
get { return base.AccentColour; }
set
{
base.AccentColour = value;
pulp.AccentColour = AccentColour;
}
}
}
}
@@ -24,7 +24,6 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable
Origin = Anchor.Centre;
Size = new Vector2((float)CatchHitObject.OBJECT_RADIUS);
AccentColour = HitObject.ComboColour;
Masking = false;
Rotation = (float)(RNG.NextDouble() - 0.5f) * 40;
@@ -33,6 +32,9 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable
[BackgroundDependencyLoader]
private void load()
{
// todo: this should come from the skin.
AccentColour = colourForRrepesentation(HitObject.VisualRepresentation);
InternalChildren = new[]
{
createPulp(HitObject.VisualRepresentation),
@@ -273,5 +275,31 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable
border.Alpha = (float)MathHelper.Clamp((HitObject.StartTime - Time.Current) / 500, 0, 1);
}
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);
}
}
}
}
}
@@ -33,7 +33,6 @@ namespace osu.Game.Rulesets.Catch.Objects.Drawable
var catchObject = (DrawableCatchHitObject)h;
catchObject.CheckPosition = o => CheckPosition?.Invoke(o) ?? false;
catchObject.AccentColour = HitObject.ComboColour;
dropletContainer.Add(h);
base.AddNested(h);
+38 -37
View File
@@ -60,65 +60,66 @@ namespace osu.Game.Rulesets.Catch.Objects
AddNested(new Fruit
{
Samples = Samples,
ComboColour = ComboColour,
StartTime = StartTime,
X = X
});
for (var span = 0; span < this.SpanCount(); span++)
double lastDropletTime = StartTime;
for (int span = 0; span < this.SpanCount(); span++)
{
var spanStartTime = StartTime + span * spanDuration;
var reversed = span % 2 == 1;
for (var d = tickDistance; d <= length; d += tickDistance)
for (double d = 0; d <= length; d += tickDistance)
{
if (d > length - minDistanceFromEnd)
break;
var timeProgress = d / length;
var distanceProgress = reversed ? 1 - timeProgress : timeProgress;
var lastTickTime = spanStartTime + timeProgress * spanDuration;
AddNested(new Droplet
double time = spanStartTime + timeProgress * spanDuration;
double tinyTickInterval = time - lastDropletTime;
while (tinyTickInterval > 100)
tinyTickInterval /= 2;
for (double t = lastDropletTime + tinyTickInterval; t < time; t += tinyTickInterval)
{
StartTime = lastTickTime,
ComboColour = ComboColour,
X = X + Curve.PositionAt(distanceProgress).X / CatchPlayfield.BASE_WIDTH,
Samples = new List<SampleInfo>(Samples.Select(s => new SampleInfo
double progress = reversed ? 1 - (t - spanStartTime) / spanDuration : (t - spanStartTime) / spanDuration;
AddNested(new TinyDroplet
{
Bank = s.Bank,
Name = @"slidertick",
Volume = s.Volume
}))
});
}
StartTime = t,
X = X + Curve.PositionAt(progress).X / CatchPlayfield.BASE_WIDTH,
Samples = new List<SampleInfo>(Samples.Select(s => new SampleInfo
{
Bank = s.Bank,
Name = @"slidertick",
Volume = s.Volume
}))
});
}
double tinyTickInterval = tickDistance / length * spanDuration;
while (tinyTickInterval > 100)
tinyTickInterval /= 2;
for (double t = 0; t < spanDuration; t += tinyTickInterval)
{
double progress = reversed ? 1 - t / spanDuration : t / spanDuration;
AddNested(new TinyDroplet
if (d > minDistanceFromEnd && Math.Abs(d - length) > minDistanceFromEnd)
{
StartTime = spanStartTime + t,
ComboColour = ComboColour,
X = X + Curve.PositionAt(progress).X / CatchPlayfield.BASE_WIDTH,
Samples = new List<SampleInfo>(Samples.Select(s => new SampleInfo
AddNested(new Droplet
{
Bank = s.Bank,
Name = @"slidertick",
Volume = s.Volume
}))
});
StartTime = time,
X = X + Curve.PositionAt(distanceProgress).X / CatchPlayfield.BASE_WIDTH,
Samples = new List<SampleInfo>(Samples.Select(s => new SampleInfo
{
Bank = s.Bank,
Name = @"slidertick",
Volume = s.Volume
}))
});
}
lastDropletTime = time;
}
AddNested(new Fruit
{
Samples = Samples,
ComboColour = ComboColour,
StartTime = spanStartTime + spanDuration,
X = X + Curve.PositionAt(reversed ? 0 : 1).X / CatchPlayfield.BASE_WIDTH
});
@@ -18,7 +18,7 @@ namespace osu.Game.Rulesets.Catch.Tests
{
protected override string ResourceAssembly => "osu.Game.Rulesets.Catch";
[TestCase("basic"), Ignore("See: https://github.com/ppy/osu/issues/2149")]
[TestCase("basic"), Ignore("See: https://github.com/ppy/osu/issues/2232")]
public new void Test(string name)
{
base.Test(name);
@@ -6,13 +6,11 @@ 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
{
@@ -62,8 +60,6 @@ namespace osu.Game.Rulesets.Catch.Tests
Scale = 1.5f,
};
fruit.ComboColour = colourForRrepesentation(fruit.VisualRepresentation);
return new DrawableFruit(fruit)
{
Anchor = Anchor.Centre,
@@ -74,31 +70,5 @@ namespace osu.Game.Rulesets.Catch.Tests
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);
}
}
}
}
}
@@ -54,7 +54,6 @@ namespace osu.Game.Rulesets.Catch.UI
if (caughtFruit == null) return;
caughtFruit.AccentColour = fruit.AccentColour;
caughtFruit.RelativePositionAxes = Axes.None;
caughtFruit.Position = new Vector2(MovableCatcher.ToLocalSpace(fruit.ScreenSpaceDrawQuad.Centre).X - MovableCatcher.DrawSize.X / 2, 0);
@@ -8,7 +8,6 @@ using osu.Game.Rulesets.Mania.Objects.Drawables.Pieces;
using OpenTK.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Rulesets.Mania.Judgements;
using osu.Framework.Extensions.IEnumerableExtensions;
using osu.Framework.Input.Bindings;
using osu.Game.Rulesets.Scoring;
@@ -24,7 +23,6 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
private readonly GlowPiece glowPiece;
private readonly BodyPiece bodyPiece;
private readonly Container<DrawableHoldNoteTick> tickContainer;
private readonly Container fullHeightContainer;
/// <summary>
@@ -40,6 +38,7 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
public DrawableHoldNote(HoldNote hitObject, ManiaAction action)
: base(hitObject, action)
{
Container<DrawableHoldNoteTick> tickContainer;
RelativeSizeAxes = Axes.X;
InternalChildren = new Drawable[]
@@ -57,7 +56,14 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
Origin = Anchor.TopCentre,
RelativeSizeAxes = Axes.X,
},
tickContainer = new Container<DrawableHoldNoteTick> { RelativeSizeAxes = Axes.Both },
tickContainer = new Container<DrawableHoldNoteTick>
{
RelativeSizeAxes = Axes.Both,
ChildrenEnumerable = HitObject.NestedHitObjects.OfType<HoldNoteTick>().Select(tick => new DrawableHoldNoteTick(tick)
{
HoldStartTime = () => holdStartTime
})
},
head = new DrawableHeadNote(this, action)
{
Anchor = Anchor.TopCentre,
@@ -70,16 +76,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
}
};
foreach (var tick in HitObject.NestedHitObjects.OfType<HoldNoteTick>())
{
var drawableTick = new DrawableHoldNoteTick(tick)
{
HoldStartTime = () => holdStartTime
};
tickContainer.Add(drawableTick);
AddNested(drawableTick);
}
foreach (var tick in tickContainer)
AddNested(tick);
AddNested(head);
AddNested(tail);
@@ -90,12 +88,8 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
get { return base.AccentColour; }
set
{
if (base.AccentColour == value)
return;
base.AccentColour = value;
tickContainer.Children.ForEach(t => t.AccentColour = value);
glowPiece.AccentColour = value;
bodyPiece.AccentColour = value;
head.AccentColour = value;
@@ -2,7 +2,6 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Framework.Graphics;
using OpenTK.Graphics;
using osu.Game.Rulesets.Objects.Drawables;
namespace osu.Game.Rulesets.Mania.Objects.Drawables
@@ -28,16 +27,5 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
if (action != null)
Action = action.Value;
}
public override Color4 AccentColour
{
get { return base.AccentColour; }
set
{
if (base.AccentColour == value)
return;
base.AccentColour = value;
}
}
}
}
@@ -48,13 +48,10 @@ namespace osu.Game.Rulesets.Mania.Objects.Drawables
get { return base.AccentColour; }
set
{
if (base.AccentColour == value)
return;
base.AccentColour = value;
laneGlowPiece.AccentColour = value;
GlowPiece.AccentColour = value;
headPiece.AccentColour = value;
laneGlowPiece.AccentColour = AccentColour;
GlowPiece.AccentColour = AccentColour;
headPiece.AccentColour = AccentColour;
}
}
@@ -13,24 +13,7 @@ namespace osu.Game.Rulesets.Osu.Beatmaps
public override void PostProcess(Beatmap<OsuHitObject> beatmap)
{
applyStacking(beatmap);
if (beatmap.ComboColours.Count == 0)
return;
int comboIndex = 0;
int colourIndex = 0;
foreach (var obj in beatmap.HitObjects)
{
if (obj.NewCombo)
{
comboIndex = 0;
colourIndex = (colourIndex + 1) % beatmap.ComboColours.Count;
}
obj.IndexInCurrentCombo = comboIndex++;
obj.ComboColour = beatmap.ComboColours[colourIndex];
}
base.PostProcess(beatmap);
}
private void applyStacking(Beatmap<OsuHitObject> beatmap)
@@ -8,6 +8,7 @@ using osu.Game.Rulesets.Osu.Objects.Drawables.Pieces;
using OpenTK;
using osu.Game.Rulesets.Osu.Judgements;
using osu.Game.Rulesets.Scoring;
using OpenTK.Graphics;
namespace osu.Game.Rulesets.Osu.Objects.Drawables
{
@@ -21,7 +22,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
private readonly NumberPiece number;
private readonly GlowPiece glow;
public DrawableHitCircle(HitCircle h) : base(h)
public DrawableHitCircle(HitCircle h)
: base(h)
{
Origin = Anchor.Centre;
@@ -30,13 +32,9 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
InternalChildren = new Drawable[]
{
glow = new GlowPiece
{
Colour = AccentColour
},
glow = new GlowPiece(),
circle = new CirclePiece
{
Colour = AccentColour,
Hit = () =>
{
if (AllJudged)
@@ -52,15 +50,11 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
},
ring = new RingPiece(),
flash = new FlashPiece(),
explode = new ExplodePiece
{
Colour = AccentColour,
},
explode = new ExplodePiece(),
ApproachCircle = new ApproachCircle
{
Alpha = 0,
Scale = new Vector2(4),
Colour = AccentColour,
}
};
@@ -70,6 +64,19 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
HitObject.PositionChanged += _ => Position = HitObject.StackedPosition;
}
public override Color4 AccentColour
{
get { return base.AccentColour; }
set
{
base.AccentColour = value;
explode.Colour = AccentColour;
glow.Colour = AccentColour;
circle.Colour = AccentColour;
ApproachCircle.Colour = AccentColour;
}
}
protected override void CheckForJudgements(bool userTriggered, double timeOffset)
{
if (!userTriggered)
@@ -5,6 +5,9 @@ using System.ComponentModel;
using osu.Game.Rulesets.Objects.Drawables;
using osu.Framework.Graphics;
using System.Linq;
using osu.Game.Rulesets.Objects.Types;
using osu.Game.Skinning;
using OpenTK.Graphics;
namespace osu.Game.Rulesets.Osu.Objects.Drawables
{
@@ -15,7 +18,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
protected DrawableOsuHitObject(OsuHitObject hitObject)
: base(hitObject)
{
AccentColour = HitObject.ComboColour;
Alpha = 0;
}
@@ -35,6 +37,14 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
}
}
protected override void SkinChanged(ISkinSource skin, bool allowFallback)
{
base.SkinChanged(skin, allowFallback);
if (HitObject is IHasComboInformation combo)
AccentColour = skin.GetValue<SkinConfiguration, Color4>(s => s.ComboColours.Count > 0 ? s.ComboColours[combo.ComboIndex % s.ComboColours.Count] : (Color4?)null) ?? Color4.White;
}
protected virtual void UpdatePreemptState() => this.FadeIn(HitObject.TimeFadein);
protected virtual void UpdateCurrentState(ArmedState state)
@@ -13,6 +13,7 @@ using osu.Game.Rulesets.Osu.Judgements;
using osu.Framework.Graphics.Primitives;
using osu.Game.Configuration;
using osu.Game.Rulesets.Scoring;
using OpenTK.Graphics;
namespace osu.Game.Rulesets.Osu.Objects.Drawables
{
@@ -41,7 +42,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
{
Body = new SliderBody(s)
{
AccentColour = AccentColour,
PathWidth = s.Scale * 64,
},
ticks = new Container<DrawableSliderTick> { RelativeSizeAxes = Axes.Both },
@@ -50,7 +50,6 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
{
BypassAutoSizeAxes = Axes.Both,
Scale = new Vector2(s.Scale),
AccentColour = AccentColour,
AlwaysPresent = true,
Alpha = 0
},
@@ -87,6 +86,17 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables
HitObject.PositionChanged += _ => Position = HitObject.StackedPosition;
}
public override Color4 AccentColour
{
get { return base.AccentColour; }
set
{
base.AccentColour = value;
Body.AccentColour = AccentColour;
Ball.AccentColour = AccentColour;
}
}
[BackgroundDependencyLoader]
private void load(OsuConfigManager config)
{
@@ -25,7 +25,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
Blending = BlendingMode.Additive,
RelativeSizeAxes = Axes.Both,
Alpha = 0.2f,
}, false);
}, s => s.GetTexture("Play/osu/hitcircle") == null);
}
}
}
@@ -29,7 +29,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
{
RelativeSizeAxes = Axes.Both
}
}, false);
}, s => s.GetTexture("Play/osu/hitcircle") == null);
}
}
}
@@ -29,7 +29,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
Texture = textures.Get(name),
Blending = BlendingMode.Additive,
Alpha = 0.5f
}, false);
}, s => s.GetTexture("Play/osu/hitcircle") == null);
}
}
}
@@ -40,7 +40,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
Colour = Color4.White.Opacity(0.5f),
},
Child = new Box()
}, false),
}, s => s.GetTexture("Play/osu/hitcircle") == null),
number = new OsuSpriteText
{
Text = @"1",
@@ -42,7 +42,7 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
public double? SnakedStart { get; private set; }
public double? SnakedEnd { get; private set; }
private Color4 accentColour;
private Color4 accentColour = Color4.White;
/// <summary>
/// Used to colour the path.
/// </summary>
@@ -173,6 +173,8 @@ namespace osu.Game.Rulesets.Osu.Objects.Drawables.Pieces
texture.SetData(upload);
path.Texture = texture;
container.ForceRedraw();
}
private void computeSize()
@@ -6,13 +6,11 @@ using osu.Game.Beatmaps;
using osu.Game.Rulesets.Objects;
using OpenTK;
using osu.Game.Rulesets.Objects.Types;
using OpenTK.Graphics;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Rulesets.Edit.Types;
namespace osu.Game.Rulesets.Osu.Objects
{
public abstract class OsuHitObject : HitObject, IHasCombo, IHasEditablePosition
public abstract class OsuHitObject : HitObject, IHasComboInformation, IHasPosition
{
public const double OBJECT_RADIUS = 64;
@@ -53,10 +51,14 @@ namespace osu.Game.Rulesets.Osu.Objects
public float Scale { get; set; } = 1;
public Color4 ComboColour { get; set; } = Color4.Gray;
public virtual bool NewCombo { get; set; }
public int IndexInCurrentCombo { get; set; }
public int ComboIndex { get; set; }
public bool LastInCombo { get; set; }
protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty)
{
base.ApplyDefaultsToSelf(controlPointInfo, difficulty);
+4 -6
View File
@@ -99,10 +99,10 @@ namespace osu.Game.Rulesets.Osu.Objects
{
StartTime = StartTime,
Position = Position,
IndexInCurrentCombo = IndexInCurrentCombo,
ComboColour = ComboColour,
Samples = Samples,
SampleControlPoint = SampleControlPoint
SampleControlPoint = SampleControlPoint,
IndexInCurrentCombo = IndexInCurrentCombo,
ComboIndex = ComboIndex,
};
TailCircle = new SliderCircle(this)
@@ -110,7 +110,7 @@ namespace osu.Game.Rulesets.Osu.Objects
StartTime = EndTime,
Position = EndPosition,
IndexInCurrentCombo = IndexInCurrentCombo,
ComboColour = ComboColour
ComboIndex = ComboIndex,
};
AddNested(HeadCircle);
@@ -160,7 +160,6 @@ namespace osu.Game.Rulesets.Osu.Objects
Position = Position + Curve.PositionAt(distanceProgress),
StackHeight = StackHeight,
Scale = Scale,
ComboColour = ComboColour,
Samples = sampleList
});
}
@@ -179,7 +178,6 @@ namespace osu.Game.Rulesets.Osu.Objects
Position = Position + Curve.PositionAt(repeat % 2),
StackHeight = StackHeight,
Scale = Scale,
ComboColour = ComboColour,
Samples = new List<SampleInfo>(RepeatSamples[repeatIndex])
});
}
@@ -10,7 +10,6 @@ using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Rulesets.Osu.Objects.Drawables;
using osu.Game.Tests.Visual;
using OpenTK;
using OpenTK.Graphics;
using osu.Game.Rulesets.Osu.Judgements;
using System.Collections.Generic;
using System;
@@ -61,7 +60,6 @@ namespace osu.Game.Rulesets.Osu.Tests
{
StartTime = Time.Current + 1000 + timeOffset,
Position = positionOffset.Value,
ComboColour = Color4.LightSeaGreen
};
circle.ApplyDefaults(new ControlPointInfo(), new BeatmapDifficulty { CircleSize = circleSize });
@@ -117,7 +117,6 @@ namespace osu.Game.Rulesets.Osu.Tests
{
StartTime = Time.Current + 1000,
Position = new Vector2(-(distance / 2), 0),
ComboColour = Color4.LightSeaGreen,
ControlPoints = new List<Vector2>
{
Vector2.Zero,
@@ -138,7 +137,6 @@ namespace osu.Game.Rulesets.Osu.Tests
{
StartTime = Time.Current + 1000,
Position = new Vector2(-200, 0),
ComboColour = Color4.LightSeaGreen,
ControlPoints = new List<Vector2>
{
Vector2.Zero,
@@ -162,7 +160,6 @@ namespace osu.Game.Rulesets.Osu.Tests
CurveType = CurveType.Linear,
StartTime = Time.Current + 1000,
Position = new Vector2(-200, 0),
ComboColour = Color4.LightSeaGreen,
ControlPoints = new List<Vector2>
{
Vector2.Zero,
@@ -189,7 +186,6 @@ namespace osu.Game.Rulesets.Osu.Tests
CurveType = CurveType.Bezier,
StartTime = Time.Current + 1000,
Position = new Vector2(-200, 0),
ComboColour = Color4.LightSeaGreen,
ControlPoints = new List<Vector2>
{
Vector2.Zero,
@@ -215,7 +211,6 @@ namespace osu.Game.Rulesets.Osu.Tests
CurveType = CurveType.Linear,
StartTime = Time.Current + 1000,
Position = new Vector2(0, 0),
ComboColour = Color4.LightSeaGreen,
ControlPoints = new List<Vector2>
{
Vector2.Zero,
@@ -245,7 +240,6 @@ namespace osu.Game.Rulesets.Osu.Tests
{
StartTime = Time.Current + 1000,
Position = new Vector2(-100, 0),
ComboColour = Color4.LightSeaGreen,
CurveType = CurveType.Catmull,
ControlPoints = new List<Vector2>
{
@@ -0,0 +1,5 @@
info face="vitaru!font" size=100 bold=0 italic=0 charset="" unicode=1 stretchH=100 smooth=1 aa=4 padding=0,0,0,0 spacing=4,4 outline=0
common lineHeight=100 base=83 scaleW=1024 scaleH=1024 pages=1 packed=0 alphaChnl=0 redChnl=4 greenChnl=4 blueChnl=4
page id=0 file="symcolFont_0.png"
chars count=1
char id=57419 x=495 y=537 width=88 height=89 xoffset=0 yoffset=8 xadvance=89 page=0 chnl=15
Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

@@ -0,0 +1,76 @@
using OpenTK;
using osu.Game.Beatmaps;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Shape.Objects;
using System.Collections.Generic;
using osu.Game.Rulesets.Objects.Types;
using System;
using osu.Game.Audio;
using System.Linq;
namespace osu.Game.Rulesets.Shape.Beatmaps
{
internal class ShapeBeatmapConverter : BeatmapConverter<ShapeHitObject>
{
protected override IEnumerable<Type> ValidConversionTypes { get; } = new[] { typeof(IHasPosition) };
protected override IEnumerable<ShapeHitObject> ConvertHitObject(HitObject original, Beatmap beatmap)
{
var curveData = original as IHasCurve;
var endTimeData = original as IHasEndTime;
var positionData = original as IHasPosition;
var comboData = original as IHasCombo;
List<SampleInfo> samples = original.Samples;
bool isSquare = samples.Any(s => s.Name == SampleInfo.HIT_WHISTLE);
bool isTriangle = samples.Any(s => s.Name == SampleInfo.HIT_FINISH);
bool isX = samples.Any(s => s.Name == SampleInfo.HIT_CLAP);
if (isSquare)
{
yield return new BaseShape
{
StartTime = original.StartTime,
StartPosition = positionData?.Position ?? Vector2.Zero,
Samples = original.Samples,
NewCombo = comboData?.NewCombo ?? false,
ShapeID = 2,
};
}
else if (isTriangle)
{
yield return new BaseShape
{
StartTime = original.StartTime,
StartPosition = positionData?.Position ?? Vector2.Zero,
Samples = original.Samples,
NewCombo = comboData?.NewCombo ?? false,
ShapeID = 3,
};
}
else if (isX)
{
yield return new BaseShape
{
StartTime = original.StartTime,
StartPosition = positionData?.Position ?? Vector2.Zero,
Samples = original.Samples,
NewCombo = comboData?.NewCombo ?? false,
ShapeID = 4,
};
}
else
{
yield return new BaseShape
{
StartTime = original.StartTime,
StartPosition = positionData?.Position ?? Vector2.Zero,
Samples = original.Samples,
NewCombo = comboData?.NewCombo ?? false,
ShapeID = 1,
};
}
}
}
}
@@ -0,0 +1,13 @@
using osu.Game.Beatmaps;
using osu.Game.Rulesets.Shape.Objects;
namespace osu.Game.Rulesets.Shape.Beatmaps
{
internal class ShapeBeatmapProcessor : BeatmapProcessor<ShapeHitObject>
{
public override void PostProcess(Beatmap<ShapeHitObject> beatmap)
{
base.PostProcess(beatmap);
}
}
}
@@ -0,0 +1,18 @@
using System;
using OpenTK;
using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Shape.Objects.Drawables;
using osu.Framework.Extensions;
namespace osu.Game.Rulesets.Shape.Judgements
{
public class ShapeJudgement : Judgement
{
/// <summary>
/// The positional hit offset.
/// </summary>
public Vector2 PositionOffset;
public ComboResult Combo;
}
}
+74
View File
@@ -0,0 +1,74 @@
using osu.Game.Beatmaps;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Shape.Objects;
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Shape.Mods
{
public class ShapeModNoFail : ModNoFail
{
}
public class ShapeModEasy : ModEasy
{
}
public class ShapeModHidden : ModHidden
{
public override string Description => @"Notes fade out";
public override double ScoreMultiplier => 1.06;
}
public class ShapeModHardRock : ModHardRock
{
public override double ScoreMultiplier => 1.08;
public override bool Ranked => true;
}
public class ShapeModSuddenDeath : ModSuddenDeath
{
public override string Description => "Don't Miss";
public override bool Ranked => true;
}
public class ShapeModDaycore : ModDaycore
{
public override double ScoreMultiplier => 0.3;
}
public class ShapeModDoubleTime : ModDoubleTime
{
public override double ScoreMultiplier => 1.16;
}
public class ShapeModHalfTime : ModHalfTime
{
public override double ScoreMultiplier => 0.3;
}
public class ShapeModNightcore : ModNightcore
{
public override double ScoreMultiplier => 1.16;
}
public class ShapeModFlashlight : ModFlashlight
{
public override string Description => @"I don't even know how to play with this";
public override double ScoreMultiplier => 1.18;
}
public class ShapeRelax : ModRelax
{
public override bool Ranked => false;
}
public class ShapeModAutoplay : ModAutoplay<ShapeHitObject>
{
protected override Score CreateReplayScore(Beatmap<ShapeHitObject> beatmap) => new Score
{
};
}
}
@@ -0,0 +1,17 @@
using osu.Framework.Graphics.Textures;
using osu.Game.Rulesets.Shape;
using Symcol.Rulesets.Core.Multiplayer.Screens;
namespace osu.Game.Rulesets.Shape.Multi
{
public class ShapeLobbyItem : RulesetLobbyItem
{
public override Texture Icon => ShapeRuleset.ShapeTextures.Get("icon");
public override string RulesetName => "Shape!";
//public override Texture Background => ShapeRuleset.ShapeTextures.Get("VitaruTouhosuModeTrue2560x1440");
public override RulesetLobbyScreen RulesetLobbyScreen => new ShapeLobbyScreen();
}
}
@@ -0,0 +1,14 @@
using Symcol.Rulesets.Core.Multiplayer.Networking;
using Symcol.Rulesets.Core.Multiplayer.Screens;
using System;
using System.Collections.Generic;
namespace osu.Game.Rulesets.Shape.Multi
{
public class ShapeLobbyScreen : RulesetLobbyScreen
{
public override string RulesetName => "shape";
public override RulesetMatchScreen MatchScreen => new ShapeMatchScreen(RulesetNetworkingClientHandler);
}
}
@@ -0,0 +1,15 @@
using Symcol.Rulesets.Core.Multiplayer.Networking;
using Symcol.Rulesets.Core.Multiplayer.Screens;
namespace osu.Game.Rulesets.Shape.Multi
{
public class ShapeMatchScreen : RulesetMatchScreen
{
public readonly RulesetNetworkingClientHandler ShapeNetworkingClientHandler;
public ShapeMatchScreen(RulesetNetworkingClientHandler shapeNetworkingClientHandler) : base(shapeNetworkingClientHandler)
{
ShapeNetworkingClientHandler = shapeNetworkingClientHandler;
}
}
}
@@ -0,0 +1,43 @@
using OpenTK;
using osu.Game.Beatmaps;
using osu.Game.Beatmaps.ControlPoints;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace osu.Game.Rulesets.Shape.Objects
{
public class BaseShape : ShapeHitObject
{
public override HitObjectType Type => HitObjectType.Shape;
public Vector2 StartPosition { get; set; }
public float ShapeSize { get; set; } = 40;
public int ShapeID { get; set; }
/// <summary>
/// The hit window that results in a "GREAT" hit.
/// </summary>
public double HitWindowGreat = 35;
/// <summary>
/// The hit window that results in a "GOOD" hit.
/// </summary>
public double HitWindowGood = 80;
/// <summary>
/// The hit window that results in a "MISS".
/// </summary>
public double HitWindowMiss = 95;
protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty)
{
base.ApplyDefaultsToSelf(controlPointInfo, difficulty);
HitWindowGreat = BeatmapDifficulty.DifficultyRange(difficulty.OverallDifficulty, 50, 35, 20);
HitWindowGood = BeatmapDifficulty.DifficultyRange(difficulty.OverallDifficulty, 120, 80, 50);
HitWindowMiss = BeatmapDifficulty.DifficultyRange(difficulty.OverallDifficulty, 135, 95, 70);
}
}
}
@@ -0,0 +1,217 @@
using OpenTK;
using OpenTK.Graphics;
using osu.Framework.Graphics;
using osu.Framework.MathUtils;
using osu.Game.Rulesets.Shape.Objects.Drawables.Pieces;
using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Shape.Judgements;
using System.Linq;
using System;
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Shape.Objects.Drawables
{
public class DrawableBaseShape : DrawableShapeHitObject<ShapeHitObject>
{
private BaseDial baseDial;
private ShapeCircle circle;
private ShapeSquare square;
private ShapeTriangle triangle;
private ShapeX x;
private bool validKeyPressed;
private readonly BaseShape shape;
public DrawableBaseShape(BaseShape Shape) : base(Shape)
{
shape = Shape;
Position = shape.StartPosition;
Alpha = 0;
AlwaysPresent = true;
Anchor = Anchor.TopLeft;
Origin = Anchor.Centre;
}
protected override void LoadComplete()
{
base.LoadComplete();
LifetimeStart = shape.StartTime - (TIME_PREEMPT + 1000f);
}
protected override void CheckForJudgements(bool userTriggered, double timeOffset)
{
base.CheckForJudgements(userTriggered, timeOffset);
if (LifetimeStart <= Time.Current)
{
if (!userTriggered)
{
if (timeOffset > shape.HitWindowGood)
{
AddJudgement(new ShapeJudgement { Result = HitResult.Miss });
Delete();
}
return;
}
double hitOffset = Math.Abs(timeOffset);
if (hitOffset > shape.HitWindowMiss)
return;
if (!validKeyPressed)
{
AddJudgement(new ShapeJudgement { Result = HitResult.Miss });
Delete();
}
else if (hitOffset < shape.HitWindowGood)
{
AddJudgement(new ShapeJudgement { Result = hitOffset < shape.HitWindowGreat ? HitResult.Great : HitResult.Good });
Delete();
}
else
{
AddJudgement(new ShapeJudgement { Result = HitResult.Miss });
Delete();
}
}
}
public override bool OnPressed(ShapeAction action)
{
if (LifetimeStart <= Time.Current)
{
switch (shape.ShapeID)
{
case 1:
ShapeAction[] hitActionsNorth = { ShapeAction.SouthLeftButton, ShapeAction.SouthRightButton };
validKeyPressed = hitActionsNorth.Contains(action);
return UpdateJudgement(true);
case 2:
ShapeAction[] hitActionsSouth = { ShapeAction.WestLeftButton, ShapeAction.WestRightButton };
validKeyPressed = hitActionsSouth.Contains(action);
return UpdateJudgement(true);
case 3:
ShapeAction[] hitActionsWest = { ShapeAction.EastLeftButton, ShapeAction.EastRightButton };
validKeyPressed = hitActionsWest.Contains(action);
return UpdateJudgement(true);
case 4:
ShapeAction[] hitActionsEast = { ShapeAction.NorthLeftButton, ShapeAction.NorthRightButton };
validKeyPressed = hitActionsEast.Contains(action);
return UpdateJudgement(true);
}
}
return UpdateJudgement(false);
}
protected override void Update()
{
base.Update();
if (LifetimeStart <= Time.Current)
{
if (Time.Current >= (shape.StartTime - TIME_PREEMPT) - 500 && !loaded)
{
preLoad();
}
if (Time.Current >= shape.StartTime - TIME_PREEMPT && !started)
{
start();
}
}
}
private bool loaded = false;
private bool started = false;
private void preLoad()
{
loaded = true;
switch (shape.ShapeID)
{
case 1:
Children = new Drawable[]
{
baseDial = new BaseDial(shape)
{
Depth = -1,
ShapeID = shape.ShapeID,
},
circle = new ShapeCircle(shape) { Depth = -2, Colour = Color4.Red, },
};
break;
case 2:
Children = new Drawable[]
{
baseDial = new BaseDial(shape)
{
Depth = -1,
ShapeID = shape.ShapeID,
},
square = new ShapeSquare(shape) { Depth = -2, Colour = Color4.Violet, },
};
break;
case 3:
Children = new Drawable[]
{
baseDial = new BaseDial(shape)
{
Depth = -1,
ShapeID = shape.ShapeID,
},
triangle = new ShapeTriangle(shape) { Depth = -2, Colour = Color4.Green, },
};
break;
case 4:
Children = new Drawable[]
{
baseDial = new BaseDial(shape)
{
Depth = -1,
ShapeID = shape.ShapeID,
},
x = new ShapeX(shape) { Depth = -2, Colour = Color4.Blue, },
};
break;
}
}
private void start()
{
started = true;
this.FadeIn(TIME_FADEIN);
baseDial.StartSpinning(TIME_PREEMPT);
switch (shape.ShapeID)
{
case 1:
circle.Position = new Vector2(RNG.Next(-200, 200), -400);
circle.MoveTo(baseDial.Position, TIME_PREEMPT);
break;
case 2:
square.Position = new Vector2(RNG.Next(-200, 200), -400);
square.MoveTo(baseDial.Position, TIME_PREEMPT);
break;
case 3:
triangle.Position = new Vector2(RNG.Next(-200, 200), -400);
triangle.MoveTo(baseDial.Position, TIME_PREEMPT);
break;
case 4:
x.Position = new Vector2(RNG.Next(-200, 200), -400);
x.MoveTo(baseDial.Position, TIME_PREEMPT);
break;
}
}
//Marks this for death
internal void Delete()
{
AlwaysPresent = true;
Alpha = 0;
LifetimeEnd = Time.Current;
Expire();
}
}
}
@@ -0,0 +1,51 @@
using osu.Game.Rulesets.Objects.Drawables;
using System;
using System.ComponentModel;
using osu.Game.Rulesets.Shape.Judgements;
using osu.Framework.Input.Bindings;
using Symcol.Rulesets.Core.HitObjects;
namespace osu.Game.Rulesets.Shape.Objects.Drawables
{
public abstract class DrawableShapeHitObject<ShapeObject> : DrawableSymcolHitObject<ShapeHitObject>, IKeyBindingHandler<ShapeAction>
where ShapeObject : ShapeHitObject
{
public float TIME_PREEMPT = 800;
public float TIME_FADEIN = 400;
public float TIME_FADEOUT = 400;
public DrawableShapeHitObject(ShapeHitObject hitObject)
: base(hitObject)
{
}
protected override void UpdateState(ArmedState state)
{
}
protected virtual void UpdatePreemptState()
{
}
protected virtual void UpdateInitialState()
{
}
public abstract bool OnPressed(ShapeAction action);
public virtual bool OnReleased(ShapeAction action) => false;
}
public enum ComboResult
{
[Description(@"")]
None,
[Description(@"Good")]
Good,
[Description(@"Amazing!")]
Perfect
}
}
@@ -0,0 +1,25 @@
using osu.Framework.Graphics;
using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Shape.Judgements;
using OpenTK;
using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Shape.Objects.Drawables
{
public class DrawableShapeJudgement : DrawableJudgement
{
public DrawableShapeJudgement(Judgement judgement, DrawableHitObject judgedObject)
: base(judgement, judgedObject)
{
}
protected override void LoadComplete()
{
if (Judgement.Result != HitResult.Miss)
JudgementText.TransformSpacingTo(new Vector2(14, 0), 1800, Easing.OutQuint);
base.LoadComplete();
}
}
}
@@ -0,0 +1,102 @@
using OpenTK;
using OpenTK.Graphics;
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
namespace osu.Game.Rulesets.Shape.Objects.Drawables.Pieces
{
//The cat in the hat is the creepiest fucker you will ever meet
public class Arrow : Container
{
private readonly BaseShape shape;
private Container line1;
private Container line1Glow;
private Container line2;
public Arrow(BaseShape Shape)
{
shape = Shape;
}
protected override void LoadComplete()
{
base.LoadComplete();
Children = new Drawable[]
{
line1 = new Container
{
Rotation = 360 - 45,
Size = new Vector2(shape.ShapeSize / 6 , shape.ShapeSize),
Masking = true,
Origin = Anchor.Centre,
Anchor = Anchor.Centre,
Depth = -2,
Colour = Color4.White,
Children = new[]
{
new Box
{
AlwaysPresent = true,
Alpha = 1,
RelativeSizeAxes = Axes.Both
},
},
},
line2 = new Container
{
Rotation = 45,
Size = new Vector2(shape.ShapeSize / 6 , shape.ShapeSize),
Masking = true,
Origin = Anchor.Centre,
Anchor = Anchor.Centre,
Depth = -1,
Colour = Color4.White,
Children = new[]
{
new Box
{
AlwaysPresent = true,
Alpha = 1,
RelativeSizeAxes = Axes.Both
},
},
EdgeEffect = new EdgeEffectParameters
{
Hollow = true,
Type = EdgeEffectType.Shadow,
Colour = Color4.White.Opacity(0.25f),
Radius = shape.ShapeSize / 4,
}
},
line1Glow = new Container
{
Rotation = 360 - 45,
Size = new Vector2(shape.ShapeSize / 6 , shape.ShapeSize),
Masking = true,
Origin = Anchor.Centre,
Anchor = Anchor.Centre,
Depth = 0,
Colour = Color4.White,
Children = new[]
{
new Box
{
AlwaysPresent = true,
Alpha = 0,
RelativeSizeAxes = Axes.Both
},
},
EdgeEffect = new EdgeEffectParameters
{
Hollow = true,
Type = EdgeEffectType.Shadow,
Colour = Color4.White.Opacity(0.25f),
Radius = shape.ShapeSize / 4,
}
},
};
}
}
}
@@ -0,0 +1,130 @@
using OpenTK;
using OpenTK.Graphics;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Graphics.Containers;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using osu.Framework.Audio.Track;
using osu.Game.Beatmaps.ControlPoints;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Allocation;
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics.Shapes;
namespace osu.Game.Rulesets.Shape.Objects.Drawables.Pieces
{
public class BaseDial : BeatSyncedContainer
{
private BaseShape shape;
private ShapeCircle baseCircle;
private ShapeSquare baseSquare;
private ShapeTriangle baseTriangle;
private ShapeX baseX;
private Container arrow;
private Container box;
public int ShapeID { get; set; }
public BaseDial(BaseShape Shape)
{
shape = Shape;
}
protected override void OnNewBeat(int beatIndex, TimingControlPoint timingPoint, EffectControlPoint effectPoint, TrackAmplitudes amplitudes)
{
base.OnNewBeat(beatIndex, timingPoint, effectPoint, amplitudes);
}
protected override void LoadComplete()
{
base.LoadComplete();
Children = new Drawable[]
{
arrow = new Container
{
Depth = 0,
Origin = Anchor.BottomCentre,
Anchor = Anchor.Centre,
Size = new Vector2(shape.ShapeSize / 6 , shape.ShapeSize * 0.6f),
Colour = Color4.DarkGray,
Children = new Drawable[]
{
new Box
{
Alpha = 1,
RelativeSizeAxes = Axes.Both,
Colour = Color4.White,
},
new Triangle
{
Colour = Color4.White,
Size = new Vector2(shape.ShapeSize / 4),
Origin = Anchor.BottomCentre,
Anchor = Anchor.TopCentre,
},
}
},
box = new Container
{
Depth = -1,
Origin = Anchor.Centre,
Anchor = Anchor.Centre,
Size = new Vector2(shape.ShapeSize / 4),
Colour = Color4.DarkGray,
Children = new Drawable[]
{
new Box
{
Alpha = 1,
RelativeSizeAxes = Axes.Both,
Colour = Color4.White,
},
}
},
};
switch (ShapeID)
{
case 1:
AddRange(new Drawable[]
{
baseCircle = new ShapeCircle(shape) { Colour = Color4.Gray, Depth = 1 },
});
break;
case 2:
AddRange(new Drawable[]
{
baseSquare = new ShapeSquare(shape) { Colour = Color4.Gray, Depth = 1 },
});
break;
case 3:
AddRange(new Drawable[]
{
baseTriangle = new ShapeTriangle(shape) { Colour = Color4.Gray, Depth = 1 },
});
break;
case 4:
AddRange(new Drawable[]
{
baseX = new ShapeX(shape) { Colour = Color4.Gray, Depth = 1 },
});
break;
}
}
[BackgroundDependencyLoader]
private void load()
{
}
public void StartSpinning(float time)
{
box.RotateTo(360, time);
arrow.RotateTo(360, time);
}
}
}
@@ -0,0 +1,55 @@
using OpenTK;
using OpenTK.Graphics;
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
namespace osu.Game.Rulesets.Shape.Objects.Drawables.Pieces
{
public class ShapeCircle : Container
{
private BaseShape shape;
private Container ring;
public ShapeCircle(BaseShape Shape)
{
shape = Shape;
}
protected override void LoadComplete()
{
base.LoadComplete();
Children = new Drawable[]
{
ring = new Container
{
Size = new Vector2(shape.ShapeSize),
Masking = true,
Origin = Anchor.Centre,
Anchor = Anchor.Centre,
BorderThickness = shape.ShapeSize / 6,
Depth = -2,
BorderColour = Color4.White,
CornerRadius = shape.ShapeSize / 2,
Children = new[]
{
new Box
{
AlwaysPresent = true,
Alpha = 0,
RelativeSizeAxes = Axes.Both
},
},
EdgeEffect = new EdgeEffectParameters
{
Hollow = true,
Type = EdgeEffectType.Shadow,
Colour = Color4.White.Opacity(0.25f),
Radius = shape.ShapeSize / 4,
}
}
};
}
}
}
@@ -0,0 +1,55 @@
using OpenTK;
using OpenTK.Graphics;
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
namespace osu.Game.Rulesets.Shape.Objects.Drawables.Pieces
{
public class ShapeSquare : Container
{
private BaseShape shape;
private Container box;
public ShapeSquare(BaseShape Shape)
{
shape = Shape;
}
protected override void LoadComplete()
{
base.LoadComplete();
Children = new Drawable[]
{
box = new Container
{
Size = new Vector2(shape.ShapeSize),
Masking = true,
Origin = Anchor.Centre,
Anchor = Anchor.Centre,
BorderThickness = shape.ShapeSize / 6,
Depth = -2,
BorderColour = Color4.White,
CornerRadius = shape.ShapeSize / 8,
Children = new[]
{
new Box
{
AlwaysPresent = true,
Alpha = 0,
RelativeSizeAxes = Axes.Both
},
},
EdgeEffect = new EdgeEffectParameters
{
Hollow = true,
Type = EdgeEffectType.Shadow,
Colour = Color4.White.Opacity(0.25f),
Radius = shape.ShapeSize / 4,
}
}
};
}
}
}
@@ -0,0 +1,35 @@
using OpenTK;
using OpenTK.Graphics;
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
namespace osu.Game.Rulesets.Shape.Objects.Drawables.Pieces
{
public class ShapeTriangle : Container
{
private BaseShape shape;
private Triangle triangle;
public ShapeTriangle(BaseShape Shape)
{
shape = Shape;
}
protected override void LoadComplete()
{
base.LoadComplete();
Children = new Drawable[]
{
triangle = new Triangle
{
Size = new Vector2(shape.ShapeSize),
Origin = Anchor.Centre,
Anchor = Anchor.Centre,
Depth = -2,
}
};
}
}
}
@@ -0,0 +1,101 @@
using OpenTK;
using OpenTK.Graphics;
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
namespace osu.Game.Rulesets.Shape.Objects.Drawables.Pieces
{
public class ShapeX : Container
{
private BaseShape shape;
private Container line1;
private Container line1Glow;
private Container line2;
public ShapeX(BaseShape Shape)
{
shape = Shape;
}
protected override void LoadComplete()
{
base.LoadComplete();
Children = new Drawable[]
{
line1 = new Container
{
Rotation = 360 - 45,
Size = new Vector2(shape.ShapeSize / 6 , shape.ShapeSize),
Masking = true,
Origin = Anchor.Centre,
Anchor = Anchor.Centre,
Depth = -2,
Colour = Color4.White,
Children = new[]
{
new Box
{
AlwaysPresent = true,
Alpha = 1,
RelativeSizeAxes = Axes.Both
},
},
},
line2 = new Container
{
Rotation = 45,
Size = new Vector2(shape.ShapeSize / 6 , shape.ShapeSize),
Masking = true,
Origin = Anchor.Centre,
Anchor = Anchor.Centre,
Depth = -1,
Colour = Color4.White,
Children = new[]
{
new Box
{
AlwaysPresent = true,
Alpha = 1,
RelativeSizeAxes = Axes.Both
},
},
EdgeEffect = new EdgeEffectParameters
{
Hollow = true,
Type = EdgeEffectType.Shadow,
Colour = Color4.White.Opacity(0.25f),
Radius = shape.ShapeSize / 4,
}
},
line1Glow = new Container
{
Rotation = 360 - 45,
Size = new Vector2(shape.ShapeSize / 6 , shape.ShapeSize),
Masking = true,
Origin = Anchor.Centre,
Anchor = Anchor.Centre,
Depth = 0,
Colour = Color4.White,
Children = new[]
{
new Box
{
AlwaysPresent = true,
Alpha = 0,
RelativeSizeAxes = Axes.Both
},
},
EdgeEffect = new EdgeEffectParameters
{
Hollow = true,
Type = EdgeEffectType.Shadow,
Colour = Color4.White.Opacity(0.25f),
Radius = shape.ShapeSize / 4,
}
},
};
}
}
}
@@ -0,0 +1,8 @@
namespace osu.Game.Rulesets.Shape.Objects
{
public enum HitObjectType
{
Shape,
Arrow,
}
}
@@ -0,0 +1,48 @@
using osu.Game.Rulesets.Objects;
using OpenTK;
using osu.Game.Rulesets.Shape.Objects.Drawables;
using OpenTK.Graphics;
using osu.Game.Database;
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Beatmaps;
namespace osu.Game.Rulesets.Shape.Objects
{
public abstract class ShapeHitObject : HitObject
{
public const double HitboxSize = 8;
public float BPM;
public Vector2 Position { get; set; }
public Vector2 StackedPosition => Position + StackOffset;
public virtual Vector2 EndPosition => Position;
public Vector2 StackedEndPosition => EndPosition + StackOffset;
public virtual int StackHeight { get; set; }
public Vector2 StackOffset => new Vector2(0,0);
public double Radius => HitboxSize * Scale;
public float Scale { get; set; } = 1;
public abstract HitObjectType Type { get; }
public Color4 ComboColour { get; set; }
public virtual bool NewCombo { get; set; }
public int ComboIndex { get; set; }
protected override void ApplyDefaultsToSelf(ControlPointInfo controlPointInfo, BeatmapDifficulty difficulty)
{
base.ApplyDefaultsToSelf(controlPointInfo, difficulty);
EffectControlPoint effectPoint = controlPointInfo.EffectPointAt(StartTime);
Scale = (1.0f - 0.7f * (difficulty.CircleSize - 5) / 5) / 2;
}
}
}
@@ -0,0 +1,120 @@
using OpenTK;
using System;
using System.Diagnostics;
using System.Linq;
namespace osu.Game.Rulesets.Shape.Objects
{
internal class ShapeHitObjectDifficulty
{
/// <summary>
/// Factor by how much speed / aim strain decays per second.
/// </summary>
/// <remarks>
/// These values are results of tweaking a lot and taking into account general feedback.
/// Opinionated observation: Speed is easier to maintain than accurate jumps.
/// </remarks>
internal static readonly double[] DECAY_BASE = { 0.3, 0.15 };
/// <summary>
/// Pseudo threshold values to distinguish between "singles" and "streams"
/// </summary>
/// <remarks>
/// Of course the border can not be defined clearly, therefore the algorithm has a smooth transition between those values.
/// They also are based on tweaking and general feedback.
/// </remarks>
private const double stream_spacing_threshold = 110,
single_spacing_threshold = 125;
/// <summary>
/// Scaling values for weightings to keep aim and speed difficulty in balance.
/// </summary>
/// <remarks>
/// Found from testing a very large map pool (containing all ranked maps) and keeping the average values the same.
/// </remarks>
private static readonly double[] spacing_weight_scaling = { 1400, 26.25 };
/// <summary>
/// Almost the normed diameter of a hitbox (104 osu pixel). That is -after- position transforming.
/// </summary>
private const double almost_diameter = 90;
internal ShapeHitObject BaseHitObject;
internal double[] Strains = { 1, 1 };
internal int MaxCombo = 1;
private float scalingFactor;
private Vector2 startPosition = new Vector2(0);
private Vector2 endPosition;
internal ShapeHitObjectDifficulty(ShapeHitObject baseHitObject)
{
BaseHitObject = baseHitObject;
float hitboxRadius = baseHitObject.Scale * 64;
// We will scale everything by this factor, so we can assume a uniform HitboxSize among beatmaps.
scalingFactor = 52.0f / hitboxRadius;
if (hitboxRadius < 4)
{
float smallHitboxBonus = Math.Min(30.0f - hitboxRadius, 5.0f) / 50.0f;
scalingFactor *= 1.0f + smallHitboxBonus;
}
else
endPosition = startPosition;
}
internal void CalculateStrains(ShapeHitObjectDifficulty previousHitObject, double timeRate)
{
calculateSpecificStrain(previousHitObject, ShapeDifficultyCalculator.DifficultyType.Speed, timeRate);
calculateSpecificStrain(previousHitObject, ShapeDifficultyCalculator.DifficultyType.Aim, timeRate);
}
// Caution: The subjective values are strong with this one
private static double spacingWeight(double distance, ShapeDifficultyCalculator.DifficultyType type)
{
switch (type)
{
case ShapeDifficultyCalculator.DifficultyType.Speed:
if (distance > single_spacing_threshold)
return 2.5;
else if (distance > stream_spacing_threshold)
return 1.6 + 0.9 * (distance - stream_spacing_threshold) / (single_spacing_threshold - stream_spacing_threshold);
else if (distance > almost_diameter)
return 1.2 + 0.4 * (distance - almost_diameter) / (stream_spacing_threshold - almost_diameter);
else if (distance > almost_diameter / 2)
return 0.95 + 0.25 * (distance - almost_diameter / 2) / (almost_diameter / 2);
else
return 0.95;
case ShapeDifficultyCalculator.DifficultyType.Aim:
return Math.Pow(distance, 0.99);
}
Debug.Assert(false, "Invalid Shape difficulty hit object type.");
return 0;
}
private void calculateSpecificStrain(ShapeHitObjectDifficulty previousHitObject, ShapeDifficultyCalculator.DifficultyType type, double timeRate)
{
double addition = 0;
double timeElapsed = (BaseHitObject.StartTime - previousHitObject.BaseHitObject.StartTime) / timeRate;
double decay = Math.Pow(DECAY_BASE[(int)type], timeElapsed / 1000);
addition = spacingWeight(DistanceTo(previousHitObject), type) * spacing_weight_scaling[(int)type];
// You will never find maps that require this amongst ranked maps.
addition /= Math.Max(timeElapsed, 50);
Strains[(int)type] = previousHitObject.Strains[(int)type] * decay + addition;
}
internal double DistanceTo(ShapeHitObjectDifficulty other)
{
// Scale the distance by hitbox size.
return (startPosition - other.endPosition).Length * scalingFactor;
}
}
}
@@ -0,0 +1,33 @@
using System;
using System.Collections.Generic;
using osu.Game.Beatmaps;
using osu.Game.Modes.Objects;
using osu.Game.Modes.Osu.Objects;
using osu.Game.Modes.Vitaru.Objects.Characters;
namespace osu.Game.Modes.Vitaru.Objects
{
internal class VitaruConverter : HitObjectConverter<VitaruHitObject>
{
public override List<VitaruHitObject> Convert(Beatmap beatmap)
{
List<VitaruHitObject> output = new List<VitaruHitObject>();
foreach (HitObject i in beatmap.HitObjects)
{
VitaruHitObject h = i as VitaruHitObject;
if (h == null)
{
OsuHitObject o = i as OsuHitObject;
if (o == null) throw new HitObjectConvertException(@"Vitaru", i);
h = new Enemy();
}
output.Add(h);
}
return output;
}
}
}
+25
View File
@@ -0,0 +1,25 @@
<configuration>
<dllmap os="linux" dll="opengl32.dll" target="libGL.so.1"/>
<dllmap os="linux" dll="glu32.dll" target="libGLU.so.1"/>
<dllmap os="linux" dll="openal32.dll" target="libopenal.so.1"/>
<dllmap os="linux" dll="alut.dll" target="libalut.so.0"/>
<dllmap os="linux" dll="opencl.dll" target="libOpenCL.so"/>
<dllmap os="linux" dll="libX11" target="libX11.so.6"/>
<dllmap os="linux" dll="libXi" target="libXi.so.6"/>
<dllmap os="linux" dll="SDL2.dll" target="libSDL2-2.0.so.0"/>
<dllmap os="osx" dll="opengl32.dll" target="/System/Library/Frameworks/OpenGL.framework/OpenGL"/>
<dllmap os="osx" dll="openal32.dll" target="/System/Library/Frameworks/OpenAL.framework/OpenAL" />
<dllmap os="osx" dll="alut.dll" target="/System/Library/Frameworks/OpenAL.framework/OpenAL" />
<dllmap os="osx" dll="libGLES.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" />
<dllmap os="osx" dll="libGLESv1_CM.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" />
<dllmap os="osx" dll="libGLESv2.dll" target="/System/Library/Frameworks/OpenGLES.framework/OpenGLES" />
<dllmap os="osx" dll="opencl.dll" target="/System/Library/Frameworks/OpenCL.framework/OpenCL"/>
<dllmap os="osx" dll="SDL2.dll" target="libSDL2.dylib"/>
<!-- XQuartz compatibility (X11 on Mac) -->
<dllmap os="osx" dll="libGL.so.1" target="/usr/X11/lib/libGL.dylib"/>
<dllmap os="osx" dll="libX11" target="/usr/X11/lib/libX11.dylib"/>
<dllmap os="osx" dll="libXcursor.so.1" target="/usr/X11/lib/libXcursor.dylib"/>
<dllmap os="osx" dll="libXi" target="/usr/X11/lib/libXi.dylib"/>
<dllmap os="osx" dll="libXinerama" target="/usr/X11/lib/libXinerama.dylib"/>
<dllmap os="osx" dll="libXrandr.so.2" target="/usr/X11/lib/libXrandr.dylib"/>
</configuration>
@@ -0,0 +1,38 @@
// 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.Reflection;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("osu.Game.Modes.Vitaru")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("osu.Game.Modes.Vitaru")]
[assembly: AssemblyCopyright("Copyright © 2016 - 2017")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("58f6c80c-1253-4a0e-a465-b8c85ebeadf3")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
@@ -0,0 +1,92 @@
using System.Collections.Generic;
using osu.Framework.Extensions;
using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Shape.Judgements;
using osu.Game.Rulesets.Shape.Objects;
using osu.Game.Rulesets.Shape.Objects.Drawables;
using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.UI;
using osu.Game.Beatmaps;
using osu.Game.Rulesets.Judgements;
namespace osu.Game.Rulesets.Shape.Scoring
{
internal class ShapeScoreProcessor : ScoreProcessor<ShapeHitObject>
{
public ShapeScoreProcessor()
{
}
public ShapeScoreProcessor(RulesetContainer<ShapeHitObject> rulesetContainer)
: base(rulesetContainer)
{
}
protected override void Reset(bool storeResults)
{
base.Reset(storeResults);
Health.Value = 1;
TotalScore.Value = 0;
scoreResultCounts.Clear();
comboResultCounts.Clear();
}
private readonly Dictionary<HitResult, int> scoreResultCounts = new Dictionary<HitResult, int>();
private readonly Dictionary<ComboResult, int> comboResultCounts = new Dictionary<ComboResult, int>();
private float hpDrainRate;
private int totalAccurateJudgements;
public override void PopulateScore(Score score)
{
base.PopulateScore(score);
score.Statistics[HitResult.Perfect] = scoreResultCounts.GetOrDefault(HitResult.Perfect);
score.Statistics[HitResult.Great] = scoreResultCounts.GetOrDefault(HitResult.Great);
score.Statistics[HitResult.Good] = scoreResultCounts.GetOrDefault(HitResult.Good);
score.Statistics[HitResult.Meh] = scoreResultCounts.GetOrDefault(HitResult.Meh);
score.Statistics[HitResult.Miss] = scoreResultCounts.GetOrDefault(HitResult.Miss);
}
protected override void SimulateAutoplay(Beatmap<ShapeHitObject> beatmap)
{
hpDrainRate = beatmap.BeatmapInfo.BaseDifficulty.DrainRate;
totalAccurateJudgements = beatmap.HitObjects.Count;
foreach (var unused in beatmap.HitObjects)
{
AddJudgement(new ShapeJudgement { Result = HitResult.Perfect });
}
}
protected override void OnNewJudgement(Judgement judgement)
{
base.OnNewJudgement(judgement);
var shapeJudgement = (ShapeJudgement)judgement;
if (judgement != null)
{
if (judgement.Result != HitResult.None)
{
scoreResultCounts[judgement.Result] = scoreResultCounts.GetOrDefault(judgement.Result) + 1;
comboResultCounts[shapeJudgement.Combo] = comboResultCounts.GetOrDefault(shapeJudgement.Combo) + 1;
}
switch (judgement.Result)
{
case HitResult.Great:
Health.Value = Health.Value + 0.05f;
break;
case HitResult.Miss:
Health.Value = Health.Value - 0.1f;
break;
}
}
}
}
}
@@ -0,0 +1,23 @@
using osu.Framework.Configuration;
using osu.Framework.Platform;
namespace osu.Game.Rulesets.Shape.Settings
{
public class ShapeConfigManager : IniConfigManager<ShapeSetting>
{
protected override string Filename => @"shape.ini";
public ShapeConfigManager(Storage storage) : base(storage) { }
protected override void InitialiseDefaults()
{
Set(ShapeSetting.Skin, "default");
}
}
public enum ShapeSetting
{
Skin
}
}
@@ -0,0 +1,44 @@
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Platform;
using osu.Game.Overlays.Settings;
using Symcol.Rulesets.Core;
using Symcol.Rulesets.Core.Wiki;
using osu.Game.Rulesets.Shape.Wiki;
using Symcol.Rulesets.Core.Multiplayer.Screens;
using osu.Game.Rulesets.Shape.Multi;
namespace osu.Game.Rulesets.Shape.Settings
{
public class ShapeSettings : SymcolSettingsSubsection
{
protected override string Header => "shape!";
public override WikiOverlay Wiki => shapeWiki;
private readonly ShapeWikiOverlay shapeWiki = new ShapeWikiOverlay();
public override RulesetLobbyItem RulesetLobbyItem => shapeLobby;
private readonly ShapeLobbyItem shapeLobby = new ShapeLobbyItem();
public static ShapeConfigManager ShapeConfigManager;
[BackgroundDependencyLoader]
private void load(GameHost host, Storage storage)
{
ShapeConfigManager = new ShapeConfigManager(host.Storage);
Storage skinsStorage = storage.GetStorageForDirectory("Skins");
Children = new Drawable[]
{
new SettingsButton
{
Text = "Open In-game Wiki",
Action = shapeWiki.Show
}
};
}
}
}
@@ -0,0 +1,136 @@
using osu.Game.Beatmaps;
using osu.Game.Rulesets.Shape.Objects;
using osu.Game.Rulesets.Shape.Beatmaps;
using osu.Game.Rulesets.Objects;
using System;
using System.Collections.Generic;
using osu.Game.Rulesets.Objects.Types;
using osu.Game.Rulesets.Mods;
namespace osu.Game.Rulesets.Shape
{
public class ShapeDifficultyCalculator : DifficultyCalculator<ShapeHitObject>
{
private const double star_scaling_factor = 0.0675;
private const double extreme_scaling_factor = 0.5;
internal List<ShapeHitObjectDifficulty> DifficultyHitObjects = new List<ShapeHitObjectDifficulty>();
public ShapeDifficultyCalculator(Beatmap beatmap, Mod[] mods) : base(beatmap, mods) { }
public ShapeDifficultyCalculator(Beatmap beatmap) : base(beatmap) { }
protected override void PreprocessHitObjects()
{
foreach (var h in Beatmap.HitObjects) { }
}
protected override BeatmapConverter<ShapeHitObject> CreateBeatmapConverter(Beatmap beatmap) => new ShapeBeatmapConverter();
public override double Calculate(Dictionary<string, double> categoryDifficulty = null)
{
// Fill our custom DifficultyHitObject class, that carries additional information
DifficultyHitObjects.Clear();
foreach (var hitObject in Beatmap.HitObjects)
DifficultyHitObjects.Add(new ShapeHitObjectDifficulty(hitObject));
// Sort DifficultyHitObjects by StartTime of the HitObjects - just to make sure.
DifficultyHitObjects.Sort((a, b) => a.BaseHitObject.StartTime.CompareTo(b.BaseHitObject.StartTime));
if (!CalculateStrainValues()) return 0;
double speedDifficulty = (CalculateDifficulty(DifficultyType.Speed) * 0.75f);
double aimDifficulty = (CalculateDifficulty(DifficultyType.Aim) * 1.5f);
double speedStars = Math.Sqrt(speedDifficulty) * star_scaling_factor;
double aimStars = Math.Sqrt(aimDifficulty) * star_scaling_factor;
double starRating = speedStars + aimStars + Math.Abs(speedStars - aimStars) * extreme_scaling_factor;
return starRating;
}
protected bool CalculateStrainValues()
{
// Traverse hitObjects in pairs to calculate the strain value of NextHitObject from the strain value of CurrentHitObject and environment.
using (List<ShapeHitObjectDifficulty>.Enumerator hitObjectsEnumerator = DifficultyHitObjects.GetEnumerator())
{
if (!hitObjectsEnumerator.MoveNext()) return false;
ShapeHitObjectDifficulty current = hitObjectsEnumerator.Current;
// First hitObject starts at strain 1. 1 is the default for strain values, so we don't need to set it here. See DifficultyHitObject.
while (hitObjectsEnumerator.MoveNext())
{
var next = hitObjectsEnumerator.Current;
next?.CalculateStrains(current, TimeRate);
current = next;
}
return true;
}
}
protected const double STRAIN_STEP = 200;
protected const double DECAY_WEIGHT = 0.75;
protected double CalculateDifficulty(DifficultyType type)
{
double actualStrainStep = STRAIN_STEP * TimeRate;
List<double> highestStrains = new List<double>();
double intervalEndTime = actualStrainStep;
double maximumStrain = 0;
ShapeHitObjectDifficulty previousHitObject = null;
foreach (ShapeHitObjectDifficulty hitObject in DifficultyHitObjects)
{
while (hitObject.BaseHitObject.StartTime > intervalEndTime)
{
highestStrains.Add(maximumStrain);
// The maximum strain of the next interval is not zero by default! We need to take the last hitObject we encountered, take its strain and apply the decay
// until the beginning of the next interval.
if (previousHitObject == null)
{
maximumStrain = 0;
}
else
{
double decay = Math.Pow(ShapeHitObjectDifficulty.DECAY_BASE[(int)type], (intervalEndTime - previousHitObject.BaseHitObject.StartTime) / 1000);
maximumStrain = previousHitObject.Strains[(int)type] * decay;
}
// Go to the next time interval
intervalEndTime += actualStrainStep;
}
// Obtain maximum strain
maximumStrain = Math.Max(hitObject.Strains[(int)type], maximumStrain);
previousHitObject = hitObject;
}
// Build the weighted sum over the highest strains for each interval
double difficulty = 0;
double weight = 1;
highestStrains.Sort((a, b) => b.CompareTo(a)); // Sort from highest to lowest strain.
foreach (double strain in highestStrains)
{
difficulty += weight * strain;
weight *= DECAY_WEIGHT;
}
return difficulty;
}
public enum DifficultyType
{
Speed = 0,
Aim,
};
}
}
@@ -0,0 +1,34 @@
using osu.Framework.Input.Bindings;
using osu.Game.Rulesets.UI;
using System.ComponentModel;
namespace osu.Game.Rulesets.Shape
{
class ShapeInputManager : RulesetInputManager<ShapeAction>
{
public ShapeInputManager(RulesetInfo ruleset) : base(ruleset, 0, SimultaneousBindingMode.Unique)
{
}
}
public enum ShapeAction
{
//Movement
[Description("West Left")]
WestLeftButton,
[Description("West Right")]
WestRightButton,
[Description("East Left")]
EastLeftButton,
[Description("East Right")]
EastRightButton,
[Description("North Left")]
NorthLeftButton,
[Description("North Right")]
NorthRightButton,
[Description("South Left")]
SouthLeftButton,
[Description("South Right")]
SouthRightButton,
}
}
+110
View File
@@ -0,0 +1,110 @@
using System.Collections.Generic;
using osu.Game.Rulesets.UI;
using osu.Game.Beatmaps;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Shape.Mods;
using osu.Framework.Graphics.Textures;
using osu.Framework.IO.Stores;
using osu.Framework.Audio;
using osu.Framework.Input.Bindings;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Sprites;
using osu.Game.Overlays.Settings;
using osu.Game.Rulesets.Shape.Settings;
namespace osu.Game.Rulesets.Shape
{
public class ShapeRuleset : Ruleset
{
public override Drawable CreateIcon() => new Sprite { Texture = ShapeTextures.Get("icon") };
public static ResourceStore<byte[]> ShapeResources;
public static TextureStore ShapeTextures;
public static AudioManager ShapeClassicAudio;
public ShapeRuleset(RulesetInfo rulesetInfo)
: base(rulesetInfo)
{
ShapeResources = new ResourceStore<byte[]>();
ShapeResources.AddStore(new NamespacedResourceStore<byte[]>(new DllResourceStore("osu.Game.Rulesets.Shape.dll"), ("Assets")));
ShapeResources.AddStore(new DllResourceStore("osu.Game.Rulesets.Shape.dll"));
ShapeTextures = new TextureStore(new RawTextureLoaderStore(new NamespacedResourceStore<byte[]>(ShapeResources, @"Textures")));
ShapeTextures.AddStore(new RawTextureLoaderStore(new OnlineStore()));
}
public override RulesetContainer CreateRulesetContainerWith(WorkingBeatmap beatmap, bool isForCurrentRuleset) => new ShapeRulesetContainer(this, beatmap, isForCurrentRuleset);
public override int? LegacyID => 5;
public override string Description => "shape!";
public override string ShortName => "shape";
public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap, Mod[] mods = null) => new ShapeDifficultyCalculator(beatmap, mods);
public override SettingsSubsection CreateSettings() => new ShapeSettings();
public override IEnumerable<KeyBinding> GetDefaultKeyBindings(int variant = 0) => new[]
{
new KeyBinding(InputKey.A, ShapeAction.EastLeftButton),
new KeyBinding(InputKey.S, ShapeAction.WestLeftButton),
new KeyBinding(InputKey.D, ShapeAction.NorthLeftButton),
new KeyBinding(InputKey.F, ShapeAction.SouthLeftButton),
new KeyBinding(InputKey.J, ShapeAction.SouthRightButton),
new KeyBinding(InputKey.K, ShapeAction.NorthRightButton),
new KeyBinding(InputKey.L, ShapeAction.WestRightButton),
new KeyBinding(InputKey.Semicolon, ShapeAction.EastRightButton),
};
public override IEnumerable<Mod> GetModsFor(ModType type)
{
switch (type)
{
case ModType.DifficultyReduction:
return new Mod[]
{
new ShapeModEasy(),
new ShapeModNoFail(),
new MultiMod
{
Mods = new Mod[]
{
new ShapeModHalfTime(),
new ShapeModDaycore(),
},
},
};
case ModType.DifficultyIncrease:
return new Mod[]
{
new ShapeModHardRock(),
new ShapeModSuddenDeath(),
new MultiMod
{
Mods = new Mod[]
{
new ShapeModDoubleTime(),
new ShapeModNightcore(),
},
},
new MultiMod
{
Mods = new Mod[]
{
new ShapeModHidden(),
new ShapeModFlashlight(),
},
},
};
case ModType.Special:
return new Mod[]
{
new ShapeRelax()
};
default : return new Mod[] { };
}
}
}
}
@@ -0,0 +1,83 @@
using osu.Framework.Graphics;
using osu.Game.Rulesets.Shape.Objects;
using osu.Game.Rulesets.Shape.Objects.Drawables;
using osu.Game.Rulesets.UI;
using OpenTK;
using osu.Game.Rulesets.Shape.Judgements;
using osu.Framework.Graphics.Containers;
using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Judgements;
namespace osu.Game.Rulesets.Shape.UI
{
public class ShapePlayfield : Playfield
{
private Container shapePlayfield;
private readonly Container judgementLayer;
//public override bool ProvidingUserCursor => false;
public static readonly Vector2 BASE_SIZE = new Vector2(512, 384);
public override Vector2 Size
{
get
{
var parentSize = Parent.DrawSize;
var aspectSize = parentSize.X * 0.75f < parentSize.Y ? new Vector2(parentSize.X, parentSize.X * 0.75f) : new Vector2(parentSize.Y * 4f / 3f, parentSize.Y);
return new Vector2(aspectSize.X / parentSize.X, aspectSize.Y / parentSize.Y) * base.Size;
}
}
public ShapePlayfield() : base(BASE_SIZE.X)
{
Anchor = Anchor.Centre;
Origin = Anchor.Centre;
AddRange(new Drawable[]
{
shapePlayfield = new Container
{
RelativeSizeAxes = Axes.Both,
Depth = -3,
},
judgementLayer = new Container
{
RelativeSizeAxes = Axes.Both,
Depth = -2,
},
//Will need custom UI like vitaru does it
});
}
public override void Add(DrawableHitObject h)
{
h.Depth = (float)h.HitObject.StartTime;
h.OnJudgement += onJudgement;
IDrawableHitObjectWithProxiedApproach c = h as IDrawableHitObjectWithProxiedApproach;
if (c != null)
shapePlayfield.Add(c.ProxiedLayer.CreateProxy());
base.Add(h);
}
private void onJudgement(DrawableHitObject judgedObject, Judgement judgement)
{
var shapeJudgement = (ShapeJudgement)judgement;
var shapeObject = (ShapeHitObject)judgedObject.HitObject;
DrawableShapeJudgement explosion = new DrawableShapeJudgement(shapeJudgement, judgedObject)
{
Scale = new Vector2(0.5f),
Alpha = 0.5f,
Origin = Anchor.Centre,
Position = judgedObject.Position,
};
judgementLayer.Add(explosion);
}
}
}
@@ -0,0 +1,44 @@
using osu.Game.Rulesets.UI;
using osu.Game.Rulesets.Shape.Judgements;
using osu.Game.Rulesets.Shape.Objects;
using osu.Game.Rulesets.Shape.Objects.Drawables;
using osu.Game.Rulesets.Shape.Beatmaps;
using osu.Game.Rulesets.Shape.UI;
using osu.Game.Beatmaps;
using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Scoring;
using OpenTK;
using osu.Game.Rulesets.Shape.Scoring;
using osu.Framework.Input;
using System;
namespace osu.Game.Rulesets.Shape
{
internal class ShapeRulesetContainer : RulesetContainer<ShapeHitObject>
{
public ShapeRulesetContainer(Ruleset ruleset, WorkingBeatmap beatmap, bool isForCurrentRuleset)
: base(ruleset, beatmap, isForCurrentRuleset)
{
}
public override ScoreProcessor CreateScoreProcessor() => new ShapeScoreProcessor(this);
protected override BeatmapConverter<ShapeHitObject> CreateBeatmapConverter() => new ShapeBeatmapConverter();
protected override BeatmapProcessor<ShapeHitObject> CreateBeatmapProcessor() => new ShapeBeatmapProcessor();
protected override Playfield CreatePlayfield() => new ShapePlayfield();
public override PassThroughInputManager CreateInputManager() => new ShapeInputManager(Ruleset.RulesetInfo);
protected override DrawableHitObject<ShapeHitObject> GetVisualRepresentation(ShapeHitObject h)
{
var shape = h as BaseShape;
if (shape != null)
return new DrawableBaseShape(shape);
return null;
}
protected override Vector2 GetAspectAdjustedSize() => new Vector2(0.75f);
}
}
@@ -0,0 +1,9 @@
using Symcol.Rulesets.Core.Wiki;
namespace osu.Game.Rulesets.Shape.Wiki.Sections
{
public class Gameplay : WikiSection
{
public override string Title => "Gameplay";
}
}
@@ -0,0 +1,26 @@
using osu.Framework.Graphics.Sprites;
using osu.Framework.Graphics.Textures;
using osu.Game.Users;
using Symcol.Rulesets.Core.Wiki;
namespace osu.Game.Rulesets.Shape.Wiki
{
public class ShapeWikiHeader : WikiHeader
{
protected override Texture RulesetIcon => ShapeRuleset.ShapeTextures.Get("icon");
protected override string RulesetName => "shape";
protected override string RulesetDescription => "shape! is a 3rd party ruleset developed for osu!lazer.";
protected override string RulesetUrl => $@"https://github.com/Symcol/osu/tree/symcol/osu.Game.Rulesets.Shape";
protected override User Creator => new User
{
Username = "Shawdooow",
Id = 7726082
};
protected override string DiscordInvite => $@"https://discord.gg/JvS5cxA";
}
}
@@ -0,0 +1,15 @@
using osu.Game.Rulesets.Shape.Wiki.Sections;
using Symcol.Rulesets.Core.Wiki;
namespace osu.Game.Rulesets.Shape.Wiki
{
public class ShapeWikiOverlay : WikiOverlay
{
protected override WikiHeader Header => new ShapeWikiHeader();
protected override WikiSection[] Sections => new WikiSection[]
{
new Gameplay()
};
}
}
+15
View File
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-10.0.0.0" newVersion="10.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="SharpCompress" publicKeyToken="afb0a02973931d96" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-0.18.1.0" newVersion="0.18.1.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
@@ -0,0 +1,119 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{BAF6D7B6-5E48-4278-AB81-F079AF640E31}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>osu.Game.Rulesets.Shape</RootNamespace>
<AssemblyName>osu.Game.Rulesets.Shape</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>..\osu.Game\bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>..\osu.Game\bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="OpenTK, Version=3.0.0.0, Culture=neutral, PublicKeyToken=bad199fe84eb3df4, processorArchitecture=MSIL">
<HintPath>$(SolutionDir)\packages\ppy.OpenTK.3.0\lib\net45\OpenTK.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Drawing" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Beatmaps\ShapeBeatmapConverter.cs" />
<Compile Include="Beatmaps\ShapeBeatmapProcessor.cs" />
<Compile Include="Judgements\ShapeJudgement.cs" />
<Compile Include="Multi\ShapeLobbyItem.cs" />
<Compile Include="Multi\ShapeLobbyScreen.cs" />
<Compile Include="Multi\ShapeMatchScreen.cs" />
<Compile Include="Objects\Drawables\Pieces\Arrow.cs" />
<Compile Include="Objects\Drawables\Pieces\Circle.cs" />
<Compile Include="Objects\Drawables\Pieces\Square.cs" />
<Compile Include="Objects\Drawables\Pieces\Triangle.cs" />
<Compile Include="Objects\Drawables\Pieces\X.cs" />
<Compile Include="Objects\BaseShape.cs" />
<Compile Include="Objects\Drawables\DrawableBaseShape.cs" />
<Compile Include="Objects\Drawables\DrawableShapeJudgement.cs" />
<Compile Include="Mods\ShapeMod.cs" />
<Compile Include="Objects\Drawables\DrawableShapeHitObject.cs" />
<Compile Include="Objects\Drawables\Pieces\BaseDial.cs" />
<Compile Include="Objects\HitObjectType.cs" />
<Compile Include="Objects\ShapeHitObjectDifficulty.cs" />
<Compile Include="Objects\ShapeHitObject.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Settings\ShapeConfigManager.cs" />
<Compile Include="Settings\ShapeSettings.cs" />
<Compile Include="ShapeDifficultyCalculator.cs" />
<Compile Include="UI\ShapeRulsesetContainer.cs" />
<Compile Include="Scoring\ShapeScoreProcessor.cs" />
<Compile Include="UI\ShapePlayfield.cs" />
<Compile Include="ShapeRuleset.cs" />
<Compile Include="ShapeInputManager.cs" />
<Compile Include="Wiki\Sections\Gamemodes.cs" />
<Compile Include="Wiki\ShapeWikiHeader.cs" />
<Compile Include="Wiki\ShapeWikiOverlay.cs" />
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
<None Include="OpenTK.dll.config" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\osu-framework\osu.Framework\osu.Framework.csproj">
<Project>{C76BF5B3-985E-4D39-95FE-97C9C879B83A}</Project>
<Name>osu.Framework</Name>
</ProjectReference>
<ProjectReference Include="..\osu-resources\osu.Game.Resources\osu.Game.Resources.csproj">
<Project>{d9a367c9-4c1a-489f-9b05-a0cea2b53b58}</Project>
<Name>osu.Game.Resources</Name>
</ProjectReference>
<ProjectReference Include="..\osu.Game\osu.Game.csproj">
<Project>{0D3FBF8A-7464-4CF7-8C90-3E7886DF2D4D}</Project>
<Name>osu.Game</Name>
</ProjectReference>
<ProjectReference Include="..\Symcol.Rulesets.Core\Symcol.Rulesets.Core.csproj">
<Project>{552b5940-c647-4060-aa4d-61baac415c72}</Project>
<Name>Symcol.Rulesets.Core</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Folder Include="Assets\Audio\" />
<Folder Include="Assets\Font\" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Assets\Textures\icon.png" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
+5
View File
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="NUnit" version="3.8.1" targetFramework="net461" />
<package id="OpenTK" version="3.0.0-git00009" targetFramework="net461" />
</packages>
@@ -20,11 +20,9 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
public class DrawableDrumRoll : DrawableTaikoHitObject<DrumRoll>
{
/// <summary>
/// Number of rolling hits required to reach the dark/final accent colour.
/// Number of rolling hits required to reach the dark/final colour.
/// </summary>
private const int rolling_hits_for_dark_accent = 5;
private Color4 accentDarkColour;
private const int rolling_hits_for_engaged_colour = 5;
/// <summary>
/// Rolling number of tick hits. This increases for hits and decreases for misses.
@@ -53,11 +51,14 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
public override bool OnPressed(TaikoAction action) => false;
private Color4 colourIdle;
private Color4 colourEngaged;
[BackgroundDependencyLoader]
private void load(OsuColour colours)
{
MainPiece.AccentColour = AccentColour = colours.YellowDark;
accentDarkColour = colours.YellowDarker;
MainPiece.AccentColour = colourIdle = colours.YellowDark;
colourEngaged = colours.YellowDarker;
}
private void onTickJudgement(DrawableHitObject obj, Judgement judgement)
@@ -67,10 +68,10 @@ namespace osu.Game.Rulesets.Taiko.Objects.Drawables
else
rollingHits--;
rollingHits = MathHelper.Clamp(rollingHits, 0, rolling_hits_for_dark_accent);
rollingHits = MathHelper.Clamp(rollingHits, 0, rolling_hits_for_engaged_colour);
Color4 newAccent = Interpolation.ValueAt((float)rollingHits / rolling_hits_for_dark_accent, AccentColour, accentDarkColour, 0, 1);
MainPiece.FadeAccent(newAccent, 100);
Color4 newColour = Interpolation.ValueAt((float)rollingHits / rolling_hits_for_engaged_colour, colourIdle, colourEngaged, 0, 1);
MainPiece.FadeAccent(newColour, 100);
}
protected override void CheckForJudgements(bool userTriggered, double timeOffset)
Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

@@ -24,7 +24,6 @@ namespace osu.Game.Rulesets.Vitaru.Beatmaps
protected override IEnumerable<VitaruHitObject> ConvertHitObject(HitObject original, Beatmap beatmap)
{
var curveData = original as IHasCurve;
var endTimeData = original as IHasEndTime;
var positionData = original as IHasPosition;
var comboData = original as IHasCombo;
@@ -43,9 +42,8 @@ namespace osu.Game.Rulesets.Vitaru.Beatmaps
bool isCoolWave = samples.Any(s => s.Name == SampleInfo.HIT_CLAP);
Pattern p;
Pattern a;
if (curveData != null)
if (original is IHasCurve curveData)
{
if (isLine)
{
@@ -245,8 +243,7 @@ namespace osu.Game.Rulesets.Vitaru.Beatmaps
}
}
a = p;
HitObjectList.Add(a);
HitObjectList.Add(p);
yield return p;
}
@@ -7,23 +7,7 @@ namespace osu.Game.Rulesets.Vitaru.Beatmaps
{
public override void PostProcess(Beatmap<VitaruHitObject> beatmap)
{
if (beatmap.ComboColours.Count == 0)
return;
int comboIndex = 0;
int colourIndex = 0;
foreach (var obj in beatmap.HitObjects)
{
if (obj.NewCombo)
{
comboIndex = 0;
colourIndex = (colourIndex + 1) % beatmap.ComboColours.Count;
}
obj.ComboIndex = comboIndex++;
obj.ComboColour = beatmap.ComboColours[colourIndex];
}
base.PostProcess(beatmap);
}
}
}
@@ -70,13 +70,12 @@ namespace osu.Game.Rulesets.Vitaru.Multi
protected override void Load(List<ClientInfo> playerList)
{
base.Load(playerList);
MakeCurrent();
foreach (ClientInfo client in playerList)
if (client is VitaruClientInfo vitaruClientInfo)
VitaruPlayfield.LoadPlayerList.Add(vitaruClientInfo);
Push(new MultiPlayer(VitaruNetworkingClientHandler));
Push(new MultiPlayer(VitaruNetworkingClientHandler, playerList));
}
}
}
@@ -24,5 +24,7 @@ namespace osu.Game.Rulesets.Vitaru.Multi
public Dictionary<VitaruAction, bool> Actions;
public VitaruAction PressedAction;
public VitaruAction ReleasedAction;
}
}
@@ -24,7 +24,7 @@ namespace osu.Game.Rulesets.Vitaru.Objects.Characters
AlwaysPresent = true;
CharacterName = "enemy";
Team = 1;
CharacterColor = pattern.ComboColour;
CharacterColor = drawablePattern.AccentColour;
HitboxWidth = 27;
}
@@ -0,0 +1,130 @@
using OpenTK.Graphics;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Sprites;
using osu.Framework.Extensions.Color4Extensions;
using OpenTK;
namespace osu.Game.Rulesets.Vitaru.Objects.Characters.Pieces
{
public class Seal : Container
{
private readonly Container characterSigil;
private readonly VitaruPlayer vitaruPlayer;
private readonly Sprite gear1;
private readonly Sprite gear2;
private readonly Sprite gear3;
private readonly Sprite gear4;
private readonly Sprite gear5;
public Seal(VitaruPlayer character)
{
vitaruPlayer = character;
Color4 lightColor = vitaruPlayer.CharacterColor.Lighten(0.5f);
Color4 darkColor = vitaruPlayer.CharacterColor.Darken(0.5f);
Scale = new Vector2(0.6f);
AutoSizeAxes = Axes.Both;
Anchor = Anchor.Centre;
Origin = Anchor.Centre;
AlwaysPresent = true;
Alpha = 0.5f;
Children = new Drawable[]
{
characterSigil = new Container
{
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Masking = true,
Size = new Vector2(90),
CornerRadius = 45
},
new Sprite
{
Colour = vitaruPlayer.CharacterColor,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Texture = VitaruRuleset.VitaruTextures.Get("seal"),
},
};
switch (vitaruPlayer.CurrentCharacter)
{
default:
break;
case Characters.SakuyaIzayoi:
characterSigil.Children = new Drawable[]
{
gear1 = new Sprite
{
Colour = lightColor,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Texture = VitaruRuleset.VitaruTextures.Get("gearSmall"),
Position = new Vector2(-41, 10),
},
gear2 = new Sprite
{
Colour = vitaruPlayer.CharacterColor,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Texture = VitaruRuleset.VitaruTextures.Get("gearMedium"),
Position = new Vector2(-4, 16),
},
gear3 = new Sprite
{
Colour = darkColor,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Texture = VitaruRuleset.VitaruTextures.Get("gearLarge"),
Position = new Vector2(-16, -34),
},
gear4 = new Sprite
{
Colour = vitaruPlayer.CharacterColor,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Texture = VitaruRuleset.VitaruTextures.Get("gearMedium"),
Position = new Vector2(35, -40),
},
gear5 = new Sprite
{
Colour = lightColor,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Texture = VitaruRuleset.VitaruTextures.Get("gearSmall"),
Position = new Vector2(33, 8),
},
};
break;
}
}
protected override void Update()
{
base.Update();
this.RotateTo((float)(-Clock.CurrentTime / 1000 * 90) * 0.1f);
switch (vitaruPlayer.CurrentCharacter)
{
default:
break;
case Characters.SakuyaIzayoi:
float speed = 0.25f;
gear1.RotateTo((float)(Clock.CurrentTime / 1000 * 90) * 1.25f * speed);
gear2.RotateTo((float)(-Clock.CurrentTime / 1000 * 90) * 1.1f * speed);
gear3.RotateTo((float)(Clock.CurrentTime / 1000 * 90) * speed);
gear4.RotateTo((float)(-Clock.CurrentTime / 1000 * 90) * 1.1f * speed);
gear5.RotateTo((float)(Clock.CurrentTime / 1000 * 90) * 1.25f * speed);
break;
}
}
}
}
@@ -24,7 +24,7 @@ namespace osu.Game.Rulesets.Vitaru.Objects.Characters.Pieces
Team = ParentCharacter.Team,
BulletSpeed = 0.8f,
BulletDamage = 5,
ComboColour = ParentCharacter.CharacterColor,
ColorOverride = ParentCharacter.CharacterColor,
StartAngle = StartAngle,
}));
s.MoveTo(ToSpaceOfOtherDrawable(new Vector2(0, 0), s));
File diff suppressed because it is too large Load Diff
@@ -22,6 +22,8 @@ namespace osu.Game.Rulesets.Vitaru.Objects.Drawables
private bool loaded;
private bool started;
private bool done;
private readonly double endTime;
private int currentRepeat;
@@ -37,9 +39,12 @@ namespace osu.Game.Rulesets.Vitaru.Objects.Drawables
this.pattern = pattern;
if (!pattern.IsSlider && !pattern.IsSpinner)
this.pattern.EndTime = this.pattern.StartTime + TIME_FADEOUT;
{
endTime = this.pattern.StartTime + TIME_FADEOUT;
this.pattern.EndTime = endTime;
}
else if (pattern.IsSlider)
this.pattern.EndTime += TIME_FADEOUT;
endTime = this.pattern.EndTime += TIME_FADEOUT;
}
protected override void LoadComplete()
@@ -48,9 +53,6 @@ namespace osu.Game.Rulesets.Vitaru.Objects.Drawables
PatternCount++;
if (pattern.IsSlider)
pattern.EndTime = pattern.StartTime + pattern.RepeatCount * pattern.Curve.Distance / pattern.Velocity;
LifetimeStart = pattern.StartTime - (TIME_PREEMPT + 1000f);
}
@@ -81,7 +83,7 @@ namespace osu.Game.Rulesets.Vitaru.Objects.Drawables
Size = new Vector2(30),
CornerRadius = 30f / 2,
BorderThickness = 10,
BorderColour = pattern.ComboColour,
BorderColour = AccentColour,
Children = new Drawable[]
{
new Box
@@ -92,7 +94,7 @@ namespace osu.Game.Rulesets.Vitaru.Objects.Drawables
EdgeEffect = new EdgeEffectParameters
{
Type = EdgeEffectType.Shadow,
Colour = pattern.ComboColour.Opacity(0.5f),
Colour = AccentColour.Opacity(0.5f),
Radius = Width / 2,
}
};
@@ -109,7 +111,7 @@ namespace osu.Game.Rulesets.Vitaru.Objects.Drawables
Origin = Anchor.Centre,
Size = new Vector2(20),
BorderThickness = 6,
BorderColour = pattern.ComboColour,
BorderColour = AccentColour,
Children = new Drawable[]
{
new Box
@@ -120,7 +122,7 @@ namespace osu.Game.Rulesets.Vitaru.Objects.Drawables
EdgeEffect = new EdgeEffectParameters
{
Type = EdgeEffectType.Shadow,
Colour = pattern.ComboColour.Opacity(0.5f),
Colour = AccentColour.Opacity(0.5f),
Radius = Width / 2,
}
};
@@ -141,7 +143,6 @@ namespace osu.Game.Rulesets.Vitaru.Objects.Drawables
foreach (var o in pattern.NestedHitObjects)
{
var b = (Bullet)o;
b.ComboColour = pattern.ComboColour;
DrawableBullet drawableBullet = new DrawableBullet(ParentContainer, b, this);
ParentContainer.Add(drawableBullet);
AddNested(drawableBullet);
@@ -304,9 +305,8 @@ namespace osu.Game.Rulesets.Vitaru.Objects.Drawables
#region Slider Stuff
private void sliderUpdate()
{
double progress = MathHelper.Clamp((Time.Current - pattern.StartTime) / pattern.Duration, 0, 1);
int repeat = pattern.RepeatAt(progress);
progress = pattern.ProgressAt(progress);
double completionProgress = MathHelper.Clamp((Time.Current - pattern.StartTime) / pattern.Duration, 0, 1);
int repeat = pattern.RepeatAt(completionProgress);
if (HitObject.StartTime <= Time.Current && !started)
{
@@ -316,9 +316,9 @@ namespace osu.Game.Rulesets.Vitaru.Objects.Drawables
if (!done && started)
{
Position = pattern.Curve.PositionAt(progress);
Position = pattern.PositionAt(completionProgress);
if (currentGameMode != VitaruGamemode.Dodge)
enemy.Position = pattern.Curve.PositionAt(progress);
enemy.Position = pattern.PositionAt(completionProgress);
}
if (repeat > currentRepeat)
@@ -1,6 +1,9 @@
using osu.Game.Rulesets.Objects.Drawables;
using Symcol.Rulesets.Core.HitObjects;
using System.ComponentModel;
using osu.Game.Rulesets.Objects.Types;
using osu.Game.Skinning;
using OpenTK.Graphics;
namespace osu.Game.Rulesets.Vitaru.Objects.Drawables
{
@@ -12,6 +15,16 @@ namespace osu.Game.Rulesets.Vitaru.Objects.Drawables
public readonly Framework.Graphics.Containers.Container ParentContainer;
protected override void SkinChanged(ISkinSource skin, bool allowFallback)
{
base.SkinChanged(skin, allowFallback);
if (HitObject is IHasComboInformation combo && HitObject.ColorOverride == Color4.White)
AccentColour = skin.GetValue<SkinConfiguration, Color4>(s => s.ComboColours.Count > 0 ? s.ComboColours[combo.ComboIndex % s.ComboColours.Count] : (Color4?)null) ?? Color4.White;
else
AccentColour = HitObject.ColorOverride;
}
public DrawableVitaruHitObject(VitaruHitObject hitObject, Framework.Graphics.Containers.Container parent) : base(hitObject)
{
ParentContainer = parent;
@@ -78,7 +78,7 @@ namespace osu.Game.Rulesets.Vitaru.Objects.Drawables.Pieces
Alpha = 0,
Origin = Anchor.Centre,
Anchor = Anchor.Centre,
Colour = drawableBullet.Bullet.ComboColour,
Colour = drawableBullet.AccentColour,
Texture = VitaruRuleset.VitaruTextures.Get("bulletKiai"),
};
@@ -88,7 +88,7 @@ namespace osu.Game.Rulesets.Vitaru.Objects.Drawables.Pieces
Origin = Anchor.Centre,
Alpha = 1,
RelativeSizeAxes = Axes.Both,
BorderColour = drawableBullet.Bullet.ComboColour,
BorderColour = drawableBullet.AccentColour,
BorderThickness = 6,
Masking = true,
@@ -103,10 +103,10 @@ namespace osu.Game.Rulesets.Vitaru.Objects.Drawables.Pieces
{
Radius = drawableBullet.Bullet.BulletDiameter,
Type = EdgeEffectType.Shadow,
Colour = drawableBullet.Bullet.ComboColour.Opacity(0.2f)
Colour = drawableBullet.AccentColour.Opacity(0.2f)
};
if (drawableBullet.Bullet.Ghost && currentCharacter == Characters.Characters.Kaguya | currentCharacter == Characters.Characters.AliceMuyart)
if (drawableBullet.Bullet.Ghost && currentCharacter == Characters.Characters.YuyukoSaigyouji | currentCharacter == Characters.Characters.AliceMuyart)
box.Colour = Color4.Cyan;
}
}
@@ -19,7 +19,7 @@ namespace osu.Game.Rulesets.Vitaru.Objects.Drawables.Pieces
CornerRadius = 16;
BorderThickness = 8;
BorderColour = drawableLaser.Laser.ComboColour;
BorderColour = drawableLaser.AccentColour;
Child = new Box
{
@@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.Vitaru.Objects.Drawables.Pieces
Anchor = Anchor.Centre;
BorderThickness = 4;
AlwaysPresent = true;
BorderColour = seekingBullet.SeekingBullet.ComboColour;
BorderColour = seekingBullet.AccentColour;
CornerRadius = 4;
Child = new Box
@@ -27,7 +27,7 @@ namespace osu.Game.Rulesets.Vitaru.Objects.Drawables.Pieces
{
Type = EdgeEffectType.Shadow,
Radius = 8,
Colour = seekingBullet.SeekingBullet.ComboColour.Opacity(0.25f),
Colour = seekingBullet.AccentColour.Opacity(0.25f),
};
}

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