protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate) { if (beatmap.HitObjects.Count == 0) { return new TaikoDifficultyAttributes { Mods = mods } } ; var colour = (Colour)skills[0]; var rhythm = (Rhythm)skills[1]; var stamina = (Stamina)skills[2]; double colourRating = colour.DifficultyValue() * colour_skill_multiplier; double rhythmRating = rhythm.DifficultyValue() * rhythm_skill_multiplier; double staminaRating = stamina.DifficultyValue() * stamina_skill_multiplier; double staminaPenalty = simpleColourPenalty(staminaRating, colourRating); staminaRating *= staminaPenalty; //TODO : This is a temporary fix for the stamina rating of converts, due to their low colour variance. if (beatmap.BeatmapInfo.Ruleset.OnlineID == 0 && colourRating < 0.05) { staminaPenalty *= 0.25; } double combinedRating = locallyCombinedDifficulty(colour, rhythm, stamina, staminaPenalty); double separatedRating = norm(1.5, colourRating, rhythmRating, staminaRating); double starRating = 1.4 * separatedRating + 0.5 * combinedRating; starRating = rescale(starRating); HitWindows hitWindows = new TaikoHitWindows(); hitWindows.SetDifficulty(beatmap.Difficulty.OverallDifficulty); return(new TaikoDifficultyAttributes { StarRating = starRating, Mods = mods, StaminaDifficulty = staminaRating, RhythmDifficulty = rhythmRating, ColourDifficulty = colourRating, GreatHitWindow = hitWindows.WindowFor(HitResult.Great) / clockRate, MaxCombo = beatmap.HitObjects.Count(h => h is Hit), }); }
protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate) { if (beatmap.HitObjects.Count == 0) { return new TaikoDifficultyAttributes { Mods = mods, Skills = skills } } ; var colour = (Colour)skills[0]; var rhythm = (Rhythm)skills[1]; var staminaRight = (Stamina)skills[2]; var staminaLeft = (Stamina)skills[3]; double colourRating = colour.DifficultyValue() * colour_skill_multiplier; double rhythmRating = rhythm.DifficultyValue() * rhythm_skill_multiplier; double staminaRating = (staminaRight.DifficultyValue() + staminaLeft.DifficultyValue()) * stamina_skill_multiplier; double staminaPenalty = simpleColourPenalty(staminaRating, colourRating); staminaRating *= staminaPenalty; double combinedRating = locallyCombinedDifficulty(colour, rhythm, staminaRight, staminaLeft, staminaPenalty); double separatedRating = norm(1.5, colourRating, rhythmRating, staminaRating); double starRating = 1.4 * separatedRating + 0.5 * combinedRating; starRating = rescale(starRating); HitWindows hitWindows = new TaikoHitWindows(); hitWindows.SetDifficulty(beatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty); return(new TaikoDifficultyAttributes { StarRating = starRating, Mods = mods, StaminaStrain = staminaRating, RhythmStrain = rhythmRating, ColourStrain = colourRating, // Todo: This int cast is temporary to achieve 1:1 results with osu!stable, and should be removed in the future GreatHitWindow = (int)hitWindows.WindowFor(HitResult.Great) / clockRate, MaxCombo = beatmap.HitObjects.Count(h => h is Hit), Skills = skills }); }
protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate) { if (beatmap.HitObjects.Count == 0) { return new TaikoDifficultyAttributes { Mods = mods } } ; var colour = (Colour)skills[0]; var rhythm = (Rhythm)skills[1]; var staminaRight = (Stamina)skills[2]; var staminaLeft = (Stamina)skills[3]; double colourRating = colour.DifficultyValue() * colour_skill_multiplier; double rhythmRating = rhythm.DifficultyValue() * rhythm_skill_multiplier; double staminaRating = (staminaRight.DifficultyValue() + staminaLeft.DifficultyValue()) * stamina_skill_multiplier; double staminaPenalty = simpleColourPenalty(staminaRating, colourRating); staminaRating *= staminaPenalty; double combinedRating = locallyCombinedDifficulty(colour, rhythm, staminaRight, staminaLeft, staminaPenalty); double separatedRating = norm(1.5, colourRating, rhythmRating, staminaRating); double starRating = 1.4 * separatedRating + 0.5 * combinedRating; starRating = rescale(starRating); HitWindows hitWindows = new TaikoHitWindows(); hitWindows.SetDifficulty(beatmap.Difficulty.OverallDifficulty); return(new TaikoDifficultyAttributes { StarRating = starRating, Mods = mods, StaminaDifficulty = staminaRating, RhythmDifficulty = rhythmRating, ColourDifficulty = colourRating, GreatHitWindow = hitWindows.WindowFor(HitResult.Great) / clockRate, MaxCombo = beatmap.HitObjects.Count(h => h is Hit), }); }
protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate) { if (beatmap.HitObjects.Count == 0) { return new TaikoDifficultyAttributes { Mods = mods, Skills = skills } } ; HitWindows hitWindows = new TaikoHitWindows(); hitWindows.SetDifficulty(beatmap.BeatmapInfo.BaseDifficulty.OverallDifficulty); return(new TaikoDifficultyAttributes { StarRating = skills.Single().DifficultyValue() * star_scaling_factor, Mods = mods, // Todo: This int cast is temporary to achieve 1:1 results with osu!stable, and should be removed in the future GreatHitWindow = (int)(hitWindows.WindowFor(HitResult.Great)) / clockRate, MaxCombo = beatmap.HitObjects.Count(h => h is Hit), Skills = skills }); }
private void load(OsuColour colours) { InternalChildren = new[] { new SkinnableDrawable(new TaikoSkinComponent(TaikoSkinComponents.PlayfieldBackgroundRight), _ => new PlayfieldBackgroundRight()), rightArea = new Container { Name = "Right area", RelativeSizeAxes = Axes.Both, RelativePositionAxes = Axes.Both, Children = new Drawable[] { new Container { Name = "Masked elements before hit objects", RelativeSizeAxes = Axes.Both, FillMode = FillMode.Fit, Children = new[] { hitExplosionContainer = new Container <HitExplosion> { RelativeSizeAxes = Axes.Both, }, HitTarget = new SkinnableDrawable(new TaikoSkinComponent(TaikoSkinComponents.HitTarget), _ => new TaikoHitTarget()) { RelativeSizeAxes = Axes.Both, } } }, hitTargetOffsetContent = new Container { RelativeSizeAxes = Axes.Both, Children = new Drawable[] { barLinePlayfield = new BarLinePlayfield(), new Container { Name = "Hit objects", RelativeSizeAxes = Axes.Both, Children = new Drawable[] { HitObjectContainer, drumRollHitContainer = new DrumRollHitContainer() } }, kiaiExplosionContainer = new Container <KiaiHitExplosion> { Name = "Kiai hit explosions", RelativeSizeAxes = Axes.Both, FillMode = FillMode.Fit, }, judgementContainer = new JudgementContainer <DrawableTaikoJudgement> { Name = "Judgements", RelativeSizeAxes = Axes.Y, }, } }, } }, leftArea = new Container { Name = "Left overlay", RelativeSizeAxes = Axes.Both, FillMode = FillMode.Fit, BorderColour = colours.Gray0, Children = new Drawable[] { new SkinnableDrawable(new TaikoSkinComponent(TaikoSkinComponents.PlayfieldBackgroundLeft), _ => new PlayfieldBackgroundLeft()), new InputDrum(HitObjectContainer) { Anchor = Anchor.CentreLeft, Origin = Anchor.CentreLeft, }, } }, mascot = new SkinnableDrawable(new TaikoSkinComponent(TaikoSkinComponents.Mascot), _ => Empty()) { Origin = Anchor.BottomLeft, Anchor = Anchor.TopLeft, RelativePositionAxes = Axes.Y, RelativeSizeAxes = Axes.None, Y = 0.2f }, topLevelHitContainer = new ProxyContainer { Name = "Top level hit objects", RelativeSizeAxes = Axes.Both, }, drumRollHitContainer.CreateProxy(), }; RegisterPool <Hit, DrawableHit>(50); RegisterPool <Hit.StrongNestedHit, DrawableHit.StrongNestedHit>(50); RegisterPool <DrumRoll, DrawableDrumRoll>(5); RegisterPool <DrumRoll.StrongNestedHit, DrawableDrumRoll.StrongNestedHit>(5); RegisterPool <DrumRollTick, DrawableDrumRollTick>(100); RegisterPool <DrumRollTick.StrongNestedHit, DrawableDrumRollTick.StrongNestedHit>(100); RegisterPool <Swell, DrawableSwell>(5); RegisterPool <SwellTick, DrawableSwellTick>(100); var hitWindows = new TaikoHitWindows(); foreach (var result in Enum.GetValues(typeof(HitResult)).OfType <HitResult>().Where(r => hitWindows.IsHitResultAllowed(r))) { judgementPools.Add(result, new DrawablePool <DrawableTaikoJudgement>(15)); explosionPools.Add(result, new HitExplosionPool(result)); } AddRangeInternal(judgementPools.Values); AddRangeInternal(explosionPools.Values); }