From d1000b2e6c527f170e9fd1dd525d2ba296c31f17 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Sat, 23 Dec 2023 23:36:15 +0900 Subject: [PATCH 1/4] remove HP density --- .../Scoring/OsuHealthProcessor.cs | 2 - .../Scoring/DrainingHealthProcessor.cs | 42 ++----------------- 2 files changed, 3 insertions(+), 41 deletions(-) diff --git a/osu.Game.Rulesets.Osu/Scoring/OsuHealthProcessor.cs b/osu.Game.Rulesets.Osu/Scoring/OsuHealthProcessor.cs index 5ae5766cda..7463bb565c 100644 --- a/osu.Game.Rulesets.Osu/Scoring/OsuHealthProcessor.cs +++ b/osu.Game.Rulesets.Osu/Scoring/OsuHealthProcessor.cs @@ -17,8 +17,6 @@ namespace osu.Game.Rulesets.Osu.Scoring { } - protected override int? GetDensityGroup(HitObject hitObject) => (hitObject as IHasComboInformation)?.ComboIndex; - protected override double GetHealthIncreaseFor(JudgementResult result) { switch (result.Type) diff --git a/osu.Game/Rulesets/Scoring/DrainingHealthProcessor.cs b/osu.Game/Rulesets/Scoring/DrainingHealthProcessor.cs index 4f6f8598fb..629a84ea62 100644 --- a/osu.Game/Rulesets/Scoring/DrainingHealthProcessor.cs +++ b/osu.Game/Rulesets/Scoring/DrainingHealthProcessor.cs @@ -62,7 +62,6 @@ namespace osu.Game.Rulesets.Scoring protected readonly double DrainLenience; private readonly List healthIncreases = new List(); - private readonly Dictionary densityMultiplierByGroup = new Dictionary(); private double gameplayEndTime; private double targetMinimumHealth; @@ -139,29 +138,14 @@ namespace osu.Game.Rulesets.Scoring { healthIncreases.Add(new HealthIncrease( result.HitObject.GetEndTime() + result.TimeOffset, - GetHealthIncreaseFor(result), - GetDensityGroup(result.HitObject))); + GetHealthIncreaseFor(result))); } } - protected override double GetHealthIncreaseFor(JudgementResult result) => base.GetHealthIncreaseFor(result) * getDensityMultiplier(GetDensityGroup(result.HitObject)); - - private double getDensityMultiplier(int? group) - { - if (group == null) - return 1; - - return densityMultiplierByGroup.TryGetValue(group.Value, out double multiplier) ? multiplier : 1; - } - - protected virtual int? GetDensityGroup(HitObject hitObject) => null; - protected override void Reset(bool storeResults) { base.Reset(storeResults); - densityMultiplierByGroup.Clear(); - if (storeResults) DrainRate = ComputeDrainRate(); @@ -173,24 +157,6 @@ namespace osu.Game.Rulesets.Scoring if (healthIncreases.Count <= 1) return 0; - // Normalise the health gain during sections with higher densities. - (int group, double avgIncrease)[] avgIncreasesByGroup = healthIncreases - .Where(i => i.Group != null) - .GroupBy(i => i.Group) - .Select(g => ((int)g.Key!, g.Sum(i => i.Amount) / (g.Max(i => i.Time) - g.Min(i => i.Time) + 1))) - .ToArray(); - - if (avgIncreasesByGroup.Length > 1) - { - double overallAverageIncrease = avgIncreasesByGroup.Average(g => g.avgIncrease); - - foreach ((int group, double avgIncrease) in avgIncreasesByGroup) - { - // Reduce the health increase for groups that return more health than average. - densityMultiplierByGroup[group] = Math.Min(1, overallAverageIncrease / avgIncrease); - } - } - int adjustment = 1; double result = 1; @@ -216,12 +182,10 @@ namespace osu.Game.Rulesets.Scoring currentBreak++; } - double multiplier = getDensityMultiplier(healthIncreases[i].Group); - // Apply health adjustments currentHealth -= (currentTime - lastTime) * result; lowestHealth = Math.Min(lowestHealth, currentHealth); - currentHealth = Math.Min(1, currentHealth + healthIncreases[i].Amount * multiplier); + currentHealth = Math.Min(1, currentHealth + healthIncreases[i].Amount); // Common scenario for when the drain rate is definitely too harsh if (lowestHealth < 0) @@ -240,6 +204,6 @@ namespace osu.Game.Rulesets.Scoring return result; } - private record struct HealthIncrease(double Time, double Amount, int? Group); + private record struct HealthIncrease(double Time, double Amount); } } From 00090bc527989b6caa094a40caf67023aeb352b3 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Sat, 23 Dec 2023 23:36:24 +0900 Subject: [PATCH 2/4] Add combo end bonus to HP --- .../Scoring/OsuHealthProcessor.cs | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/osu.Game.Rulesets.Osu/Scoring/OsuHealthProcessor.cs b/osu.Game.Rulesets.Osu/Scoring/OsuHealthProcessor.cs index 7463bb565c..672a8c91ba 100644 --- a/osu.Game.Rulesets.Osu/Scoring/OsuHealthProcessor.cs +++ b/osu.Game.Rulesets.Osu/Scoring/OsuHealthProcessor.cs @@ -1,10 +1,12 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using osu.Game.Beatmaps; using osu.Game.Rulesets.Judgements; using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; +using osu.Game.Rulesets.Osu.Judgements; using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Scoring; @@ -12,12 +14,68 @@ namespace osu.Game.Rulesets.Osu.Scoring { public partial class OsuHealthProcessor : DrainingHealthProcessor { + private ComboResult currentComboResult = ComboResult.Perfect; + public OsuHealthProcessor(double drainStartTime, double drainLenience = 0) : base(drainStartTime, drainLenience) { } protected override double GetHealthIncreaseFor(JudgementResult result) + { + if (IsSimulating) + return getHealthIncreaseFor(result); + + if (result.HitObject is not IHasComboInformation combo) + return getHealthIncreaseFor(result); + + if (combo.NewCombo) + currentComboResult = ComboResult.Perfect; + + switch (result.Type) + { + case HitResult.LargeTickMiss: + case HitResult.Ok: + setComboResult(ComboResult.Good); + break; + + case HitResult.Meh: + case HitResult.Miss: + setComboResult(ComboResult.None); + break; + } + + // The tail has a special IgnoreMiss judgement + if (result.HitObject is SliderTailCircle && !result.IsHit) + setComboResult(ComboResult.Good); + + if (combo.LastInCombo && result.Type.IsHit()) + { + switch (currentComboResult) + { + case ComboResult.Perfect: + return getHealthIncreaseFor(result) + 0.07; + + case ComboResult.Good: + return getHealthIncreaseFor(result) + 0.05; + + default: + return getHealthIncreaseFor(result) + 0.03; + } + } + + return getHealthIncreaseFor(result); + + void setComboResult(ComboResult comboResult) => currentComboResult = (ComboResult)Math.Min((int)currentComboResult, (int)comboResult); + } + + protected override void Reset(bool storeResults) + { + base.Reset(storeResults); + currentComboResult = ComboResult.Perfect; + } + + private double getHealthIncreaseFor(JudgementResult result) { switch (result.Type) { From 8b11bcc6ea617bbb689b793443a90b977ae2d5e9 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Sun, 24 Dec 2023 00:08:15 +0900 Subject: [PATCH 3/4] Remove unused using --- osu.Game.Rulesets.Osu/Scoring/OsuHealthProcessor.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Scoring/OsuHealthProcessor.cs b/osu.Game.Rulesets.Osu/Scoring/OsuHealthProcessor.cs index 672a8c91ba..bd6281a7d3 100644 --- a/osu.Game.Rulesets.Osu/Scoring/OsuHealthProcessor.cs +++ b/osu.Game.Rulesets.Osu/Scoring/OsuHealthProcessor.cs @@ -4,7 +4,6 @@ using System; using osu.Game.Beatmaps; using osu.Game.Rulesets.Judgements; -using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Osu.Judgements; using osu.Game.Rulesets.Osu.Objects; From 7437d21f498cca28084c7ed70341e714392e0690 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Sun, 24 Dec 2023 00:45:22 +0900 Subject: [PATCH 4/4] Adjust comment regarding slider tail --- osu.Game.Rulesets.Osu/Scoring/OsuHealthProcessor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game.Rulesets.Osu/Scoring/OsuHealthProcessor.cs b/osu.Game.Rulesets.Osu/Scoring/OsuHealthProcessor.cs index bd6281a7d3..2eb257b3e6 100644 --- a/osu.Game.Rulesets.Osu/Scoring/OsuHealthProcessor.cs +++ b/osu.Game.Rulesets.Osu/Scoring/OsuHealthProcessor.cs @@ -44,7 +44,7 @@ namespace osu.Game.Rulesets.Osu.Scoring break; } - // The tail has a special IgnoreMiss judgement + // The slider tail has a special judgement that can't accurately be described above. if (result.HitObject is SliderTailCircle && !result.IsHit) setComboResult(ComboResult.Good);