diff --git a/HitScoreVisualizer/Config-Documentation.md b/HitScoreVisualizer/Config-Documentation.md index 213999f..d12d744 100644 --- a/HitScoreVisualizer/Config-Documentation.md +++ b/HitScoreVisualizer/Config-Documentation.md @@ -38,6 +38,12 @@ Number of decimal places to show time dependence to ### "timeDependencyDecimalOffset" Which power of 10 to multiply the time dependence by +### "doIntermediateUpdates" +Disabling this only updates the score number once the note is cut and once the post swing score is done calculating; this slightly improves performance + +### "assumeMaxPostSwing" +When the note is first cut, should the post swing score show the max rating before it finishes calculating + ### "judgments" Order from highest threshold to lowest; the first matching judgment will be applied @@ -73,6 +79,7 @@ Judgments for time dependence (score is from 0-1) "timeDependencyDecimalPrecision": 1, "timeDependencyDecimalOffset": 2, "doIntermediateUpdates": true, + "assumeMaxPostSwing": false, "judgments": [ { "threshold": 115, "text": "•", "color": [1, 1, 1, 1] }, { "threshold": 108, "text": "%B%c%A", "color": [1, 1, 1, 1] }, diff --git a/HitScoreVisualizer/HarmonyPatches/EffectPoolsManualInstallerPatch.cs b/HitScoreVisualizer/HarmonyPatches/EffectPoolsManualInstallerPatch.cs index edb3716..b97a8fe 100644 --- a/HitScoreVisualizer/HarmonyPatches/EffectPoolsManualInstallerPatch.cs +++ b/HitScoreVisualizer/HarmonyPatches/EffectPoolsManualInstallerPatch.cs @@ -2,13 +2,20 @@ using HitScoreVisualizer.Settings; using SiraUtil.Affinity; using TMPro; +// ReSharper disable InconsistentNaming namespace HitScoreVisualizer.HarmonyPatches { - internal class EffectPoolsManualInstallerPatch(BloomFontProvider bloomFontProvider, HSVConfig hsvConfig) : IAffinity + internal class EffectPoolsManualInstallerPatch : IAffinity { - private readonly BloomFontProvider bloomFontProvider = bloomFontProvider; - private readonly HSVConfig hsvConfig = hsvConfig; + private readonly BloomFontProvider bloomFontProvider; + private readonly HSVConfig hsvConfig; + + private EffectPoolsManualInstallerPatch(BloomFontProvider bloomFontProvider, HSVConfig hsvConfig) + { + this.bloomFontProvider = bloomFontProvider; + this.hsvConfig = hsvConfig; + } [AffinityPrefix] [AffinityPatch(typeof(EffectPoolsManualInstaller), nameof(EffectPoolsManualInstaller.ManualInstallBindings))] diff --git a/HitScoreVisualizer/HarmonyPatches/FlyingScoreEffectPatch.cs b/HitScoreVisualizer/HarmonyPatches/FlyingScoreEffectPatch.cs index 0272a04..e1da7c2 100644 --- a/HitScoreVisualizer/HarmonyPatches/FlyingScoreEffectPatch.cs +++ b/HitScoreVisualizer/HarmonyPatches/FlyingScoreEffectPatch.cs @@ -4,34 +4,40 @@ namespace HitScoreVisualizer.HarmonyPatches { - internal class FlyingScoreEffectPatch(JudgmentService judgmentService, ConfigProvider configProvider) : IAffinity + internal class FlyingScoreEffectPatch : IAffinity { - private readonly JudgmentService judgmentService = judgmentService; - private readonly ConfigProvider configProvider = configProvider; + private readonly JudgmentService judgmentService; + private readonly ConfigProvider configProvider; + + private FlyingScoreEffectPatch(JudgmentService judgmentService, ConfigProvider configProvider) + { + this.judgmentService = judgmentService; + this.configProvider = configProvider; + } + + // When the flying score effect spawns, InitAndPresent is called + // When the post swing score changes - as the saber moves - HandleCutScoreBufferDidChange is called + // When the post swing score stops changing - HandleCutScoreBufferDidFinish is called [AffinityPrefix] [AffinityPatch(typeof(FlyingScoreEffect), nameof(FlyingScoreEffect.InitAndPresent))] - internal bool InitAndPresent(ref FlyingScoreEffect __instance, IReadonlyCutScoreBuffer cutScoreBuffer, float duration, Vector3 targetPos, Color color) + internal bool InitAndPresent(ref FlyingScoreEffect __instance, IReadonlyCutScoreBuffer cutScoreBuffer, float duration, Vector3 targetPos) { var configuration = configProvider.CurrentConfig; - var noteCutInfo = cutScoreBuffer.noteCutInfo; - if (configuration != null) + if (configuration == null) { - if (configuration.FixedPosition != null) - { - // Set current and target position to the desired fixed position - targetPos = configuration.FixedPosition.Value; - __instance.transform.position = targetPos; - } - else if (configuration.TargetPositionOffset != null) - { - targetPos += configuration.TargetPositionOffset.Value; - } + // Run original implementation + return true; } + var (text, color) = judgmentService.Judge(cutScoreBuffer, configuration.AssumeMaxPostSwing); + __instance._text.text = text; __instance._color = color; __instance._cutScoreBuffer = cutScoreBuffer; + __instance._maxCutDistanceScoreIndicator.enabled = false; + __instance._colorAMultiplier = 1f; + if (!cutScoreBuffer.isFinished) { cutScoreBuffer.RegisterDidChangeReceiver(__instance); @@ -39,32 +45,18 @@ internal bool InitAndPresent(ref FlyingScoreEffect __instance, IReadonlyCutScore __instance._registeredToCallbacks = true; } - if (configuration == null) + if (configuration.FixedPosition != null) { - __instance._text.text = cutScoreBuffer.cutScore.ToString(); - __instance._maxCutDistanceScoreIndicator.enabled = cutScoreBuffer.centerDistanceCutScore == cutScoreBuffer.noteScoreDefinition.maxCenterDistanceCutScore; - __instance._colorAMultiplier = (double) cutScoreBuffer.cutScore > (double) cutScoreBuffer.maxPossibleCutScore * 0.9f ? 1f : 0.3f; + // Set current and target position to the desired fixed position + targetPos = configuration.FixedPosition.Value; + __instance.transform.position = targetPos; } - else + else if (configuration.TargetPositionOffset != null) { - __instance._maxCutDistanceScoreIndicator.enabled = false; - - // Apply judgments a total of twice - once when the effect is created, once when it finishes. - Judge(__instance, (CutScoreBuffer)cutScoreBuffer); + targetPos += configuration.TargetPositionOffset.Value; } - __instance.InitAndPresent(duration, targetPos, noteCutInfo.worldRotation, false); - - return false; - } - - [AffinityPrefix] - [AffinityPatch(typeof(FlyingScoreEffect), nameof(FlyingScoreEffect.ManualUpdate))] - internal bool ManualUpdate(FlyingScoreEffect __instance, float t) - { - var color = __instance._color.ColorWithAlpha(__instance._fadeAnimationCurve.Evaluate(t)); - __instance._text.color = color; - __instance._maxCutDistanceScoreIndicator.color = color; + __instance.InitAndPresent(duration, targetPos, cutScoreBuffer.noteCutInfo.worldRotation, false); return false; } @@ -80,11 +72,15 @@ internal bool HandleCutScoreBufferDidChange(FlyingScoreEffect __instance, CutSco return true; } - if (configuration.DoIntermediateUpdates) + if (!configuration.DoIntermediateUpdates) { - Judge(__instance, cutScoreBuffer); + return false; } + var (text, color) = judgmentService.Judge(cutScoreBuffer, false); + __instance._text.text = text; + __instance._color = color; + return false; } @@ -92,15 +88,14 @@ internal bool HandleCutScoreBufferDidChange(FlyingScoreEffect __instance, CutSco [AffinityPatch(typeof(FlyingScoreEffect), nameof(FlyingScoreEffect.HandleCutScoreBufferDidFinish))] internal void HandleCutScoreBufferDidFinish(FlyingScoreEffect __instance, CutScoreBuffer cutScoreBuffer) { - if (configProvider.CurrentConfig != null) + if (configProvider.CurrentConfig == null) { - Judge(__instance, cutScoreBuffer); + return; } - } - private void Judge(FlyingScoreEffect flyingScoreEffect, IReadonlyCutScoreBuffer cutScoreBuffer) - { - (flyingScoreEffect._text.text, flyingScoreEffect._color) = judgmentService.Judge(cutScoreBuffer); + var (text, color) = judgmentService.Judge(cutScoreBuffer, false); + __instance._text.text = text; + __instance._color = color; } } } diff --git a/HitScoreVisualizer/Installers/HsvAppInstaller.cs b/HitScoreVisualizer/Installers/HsvAppInstaller.cs index 7804768..330edeb 100644 --- a/HitScoreVisualizer/Installers/HsvAppInstaller.cs +++ b/HitScoreVisualizer/Installers/HsvAppInstaller.cs @@ -1,13 +1,20 @@ using HitScoreVisualizer.HarmonyPatches; using HitScoreVisualizer.Services; using HitScoreVisualizer.Settings; +using JetBrains.Annotations; using Zenject; namespace HitScoreVisualizer.Installers { - internal sealed class HsvAppInstaller(HSVConfig hsvConfig) : Installer + [UsedImplicitly] + internal sealed class HsvAppInstaller : Installer { - private readonly HSVConfig hsvConfig = hsvConfig; + private readonly HSVConfig hsvConfig; + + private HsvAppInstaller(HSVConfig hsvConfig) + { + this.hsvConfig = hsvConfig; + } public override void InstallBindings() { diff --git a/HitScoreVisualizer/Services/JudgmentService.cs b/HitScoreVisualizer/Services/JudgmentService.cs index 2d23a4a..82d5ec6 100644 --- a/HitScoreVisualizer/Services/JudgmentService.cs +++ b/HitScoreVisualizer/Services/JudgmentService.cs @@ -4,29 +4,39 @@ using HitScoreVisualizer.Extensions; using HitScoreVisualizer.Models; using HitScoreVisualizer.Settings; +using JetBrains.Annotations; +using SiraUtil.Logging; using IPA.Utilities; using UnityEngine; namespace HitScoreVisualizer.Services { - internal class JudgmentService(ConfigProvider configProvider) + [UsedImplicitly] + internal class JudgmentService { - private readonly ConfigProvider configProvider = configProvider; + private readonly ConfigProvider configProvider; + + private JudgmentService(ConfigProvider configProvider) + { + this.configProvider = configProvider; + } private Configuration Config => configProvider.CurrentConfig ?? Configuration.Default; - public (string hitScoreText, Color hitScoreColor) Judge(IReadonlyCutScoreBuffer cutScoreBuffer) + public (string hitScoreText, Color hitScoreColor) Judge(IReadonlyCutScoreBuffer cutScoreBuffer, bool assumeMaxPostSwing) { + var afterCutScore = assumeMaxPostSwing ? cutScoreBuffer.noteScoreDefinition.maxAfterCutScore : cutScoreBuffer.afterCutScore; + return cutScoreBuffer.noteCutInfo.noteData.gameplayType switch { - NoteData.GameplayType.Normal => GetNormalDisplay(cutScoreBuffer), - NoteData.GameplayType.BurstSliderHead => GetChainHeadDisplay(cutScoreBuffer), - NoteData.GameplayType.BurstSliderElement => GetChainSegmentDisplay(cutScoreBuffer), + NoteData.GameplayType.Normal => GetNormalDisplay(cutScoreBuffer, afterCutScore), + NoteData.GameplayType.BurstSliderHead => GetChainHeadDisplay(cutScoreBuffer, afterCutScore), + NoteData.GameplayType.BurstSliderElement => GetChainSegmentDisplay(cutScoreBuffer, afterCutScore), _ => (string.Empty, Color.white), }; } - private (string, Color) GetNormalDisplay(IReadonlyCutScoreBuffer cutScoreBuffer) + private (string, Color) GetNormalDisplay(IReadonlyCutScoreBuffer cutScoreBuffer, int afterCutScore) { var judgment = NormalJudgment.Default; var fadeJudgment = NormalJudgment.Default; @@ -52,12 +62,12 @@ internal class JudgmentService(ConfigProvider configProvider) Mathf.InverseLerp(judgment.Threshold, fadeJudgment.Threshold, cutScoreBuffer.cutScore)) : judgment.Color.ToColor(); - var text = FormatJudgmentTextByMode(judgment.Text, cutScoreBuffer); + var text = FormatJudgmentTextByMode(judgment.Text, cutScoreBuffer, afterCutScore); return (text, color); } - private (string, Color) GetChainHeadDisplay(IReadonlyCutScoreBuffer cutScoreBuffer) + private (string, Color) GetChainHeadDisplay(IReadonlyCutScoreBuffer cutScoreBuffer, int afterCutScore) { var judgment = ChainHeadJudgment.Default; var fadeJudgment = ChainHeadJudgment.Default; @@ -83,22 +93,22 @@ internal class JudgmentService(ConfigProvider configProvider) Mathf.InverseLerp(judgment.Threshold, fadeJudgment.Threshold, cutScoreBuffer.cutScore)) : judgment.Color?.ToColor(); - var text = FormatJudgmentTextByMode(judgment.Text, cutScoreBuffer); + var text = FormatJudgmentTextByMode(judgment.Text, cutScoreBuffer, afterCutScore); return (text, color ?? Color.white); } - private (string, Color) GetChainSegmentDisplay(IReadonlyCutScoreBuffer cutScoreBuffer) + private (string, Color) GetChainSegmentDisplay(IReadonlyCutScoreBuffer cutScoreBuffer, int afterCutScore) { var chainLinkDisplay = Config.ChainLinkDisplay ?? ChainLinkDisplay.Default; - return (chainLinkDisplay.Text, chainLinkDisplay.Color.ToColor()); + return (FormatJudgmentTextByMode(chainLinkDisplay.Text, cutScoreBuffer, afterCutScore), chainLinkDisplay.Color.ToColor()); } - private string FormatJudgmentTextByMode(string unformattedText, IReadonlyCutScoreBuffer cutScoreBuffer) + private string FormatJudgmentTextByMode(string unformattedText, IReadonlyCutScoreBuffer cutScoreBuffer, int afterCutScore) { return Config.DisplayMode switch { - "format" => FormatJudgmentText(unformattedText, cutScoreBuffer), + "format" => FormatJudgmentText(unformattedText, cutScoreBuffer, afterCutScore), "textOnly" => unformattedText, "numeric" => cutScoreBuffer.cutScore.ToString(), "scoreOnTop" => $"{cutScoreBuffer.cutScore}\n{unformattedText}\n", @@ -107,7 +117,7 @@ private string FormatJudgmentTextByMode(string unformattedText, IReadonlyCutScor }; } - private string FormatJudgmentText(string unformattedText, IReadonlyCutScoreBuffer cutScoreBuffer) + private string FormatJudgmentText(string unformattedText, IReadonlyCutScoreBuffer cutScoreBuffer, int afterCutScore) { var formattedBuilder = new StringBuilder(); var nextPercentIndex = unformattedText.IndexOf('%'); @@ -133,7 +143,7 @@ private string FormatJudgmentText(string unformattedText, IReadonlyCutScoreBuffe formattedBuilder.Append(cutScoreBuffer.centerDistanceCutScore); break; case 'a': - formattedBuilder.Append(cutScoreBuffer.afterCutScore); + formattedBuilder.Append(afterCutScore); break; case 't': formattedBuilder.Append((timeDependence * Mathf.Pow(10, Config.TimeDependenceDecimalOffset)).ToString($"n{Config.TimeDependenceDecimalPrecision}")); @@ -145,7 +155,7 @@ private string FormatJudgmentText(string unformattedText, IReadonlyCutScoreBuffe formattedBuilder.Append(Config.AccuracyJudgments.JudgeSegment(cutScoreBuffer.centerDistanceCutScore)); break; case 'A': - formattedBuilder.Append(Config.AfterCutAngleJudgments.JudgeSegment(cutScoreBuffer.afterCutScore)); + formattedBuilder.Append(Config.AfterCutAngleJudgments.JudgeSegment(afterCutScore)); break; case 'T': formattedBuilder.Append(Config.TimeDependenceJudgments.JudgeTimeDependenceSegment(timeDependence, Config.TimeDependenceDecimalOffset, Config.TimeDependenceDecimalPrecision)); diff --git a/HitScoreVisualizer/Settings/ChainHeadJudgment.cs b/HitScoreVisualizer/Settings/ChainHeadJudgment.cs index e7dc087..f47fcdc 100644 --- a/HitScoreVisualizer/Settings/ChainHeadJudgment.cs +++ b/HitScoreVisualizer/Settings/ChainHeadJudgment.cs @@ -3,9 +3,17 @@ namespace HitScoreVisualizer.Settings { - [method: JsonConstructor] - public readonly struct ChainHeadJudgment(int threshold = 0, string? text = null, List? color = null, bool fade = false) + public class ChainHeadJudgment { + [JsonConstructor] + public ChainHeadJudgment(int threshold = 0, string? text = null, List? color = null, bool fade = false) + { + Threshold = threshold; + Text = text ?? string.Empty; + Color = color ?? [0, 0, 0, 0]; + Fade = fade; + } + [JsonIgnore] internal static ChainHeadJudgment Default { get; } = new(0, "%s", [1, 1, 1, 1], false); @@ -13,22 +21,22 @@ public readonly struct ChainHeadJudgment(int threshold = 0, string? text = null, // Note that if no judgment can be applied to a note, the text will appear as in the unmodded // game. [JsonProperty("threshold")] - public int Threshold { get; } = threshold; + public int Threshold { get; } // The text to display (if judgment text is enabled). [JsonProperty("text")] - public string Text { get; } = text ?? string.Empty; + public string Text { get; } // 4 floats, 0-1; red, green, blue, glow (not transparency!) // leaving this out should look obviously wrong [JsonProperty("color")] - public List Color { get; } = color ?? [0, 0, 0, 0]; + public List Color { get; } // If true, the text color will be interpolated between this judgment's color and the previous // based on how close to the next threshold it is. // Specifying fade : true for the first judgment in the array is an error, and will crash the // plugin. [JsonProperty("fade")] - public bool Fade { get; } = fade; + public bool Fade { get; } } } \ No newline at end of file diff --git a/HitScoreVisualizer/Settings/ChainLinkDisplay.cs b/HitScoreVisualizer/Settings/ChainLinkDisplay.cs index c27a184..568a00a 100644 --- a/HitScoreVisualizer/Settings/ChainLinkDisplay.cs +++ b/HitScoreVisualizer/Settings/ChainLinkDisplay.cs @@ -3,19 +3,25 @@ namespace HitScoreVisualizer.Settings { - [method: JsonConstructor] - public readonly struct ChainLinkDisplay(string? text = null, List? color = null) + public class ChainLinkDisplay { + [JsonConstructor] + public ChainLinkDisplay(string? text = null, List? color = null) + { + Text = text ?? string.Empty; + Color = color ?? [0, 0, 0, 0]; + } + [JsonIgnore] internal static ChainLinkDisplay Default { get; } = new("20", [1, 1, 1, 1]); // The text to display for a chain segment [JsonProperty("text")] - public string Text { get; } = text ?? string.Empty; + public string Text { get; } // 4 floats, 0-1; red, green, blue, glow (not transparency!) // leaving this out should look obviously wrong [JsonProperty("color")] - public List Color { get; } = color ?? [0, 0, 0, 0]; + public List Color { get; } } } \ No newline at end of file diff --git a/HitScoreVisualizer/Settings/Configuration.cs b/HitScoreVisualizer/Settings/Configuration.cs index f2dc5d2..23b3ae8 100644 --- a/HitScoreVisualizer/Settings/Configuration.cs +++ b/HitScoreVisualizer/Settings/Configuration.cs @@ -17,6 +17,7 @@ public class Configuration IsDefaultConfig = true, DisplayMode = "format", DoIntermediateUpdates = true, + AssumeMaxPostSwing = false, TimeDependenceDecimalPrecision = 1, TimeDependenceDecimalOffset = 2, NormalJudgments = @@ -115,6 +116,9 @@ internal Version Version [JsonProperty("doIntermediateUpdates")] public bool DoIntermediateUpdates { get; internal set; } + [JsonProperty("assumeMaxPostSwing")] + public bool AssumeMaxPostSwing { get; internal set; } + [JsonProperty("timeDependencyDecimalPrecision")] [DefaultValue(1)] public int TimeDependenceDecimalPrecision { get; internal set; } diff --git a/HitScoreVisualizer/Settings/JudgmentSegment.cs b/HitScoreVisualizer/Settings/JudgmentSegment.cs index 653d6b0..f5ace4c 100644 --- a/HitScoreVisualizer/Settings/JudgmentSegment.cs +++ b/HitScoreVisualizer/Settings/JudgmentSegment.cs @@ -2,19 +2,25 @@ namespace HitScoreVisualizer.Settings { - [method: JsonConstructor] - public readonly struct JudgmentSegment(int threshold = 0, string? text = null) + public class JudgmentSegment { + [JsonConstructor] + public JudgmentSegment(int threshold = 0, string? text = null) + { + Threshold = threshold; + Text = text ?? string.Empty; + } + [JsonIgnore] internal static JudgmentSegment Default { get; } = new(0, string.Empty); // This judgment will be applied only when the appropriate part of the swing contributes score >= this number. // If no judgment can be applied, the judgment for this segment will be "" (the empty string). [JsonProperty("threshold")] - public int Threshold { get; } = threshold; + public int Threshold { get; } // The text to replace the appropriate judgment specifier with (%B, %C, %A) when this judgment applies. [JsonProperty("text")] - public string? Text { get; } = text ?? string.Empty; + public string? Text { get; } } } \ No newline at end of file diff --git a/HitScoreVisualizer/Settings/NormalJudgment.cs b/HitScoreVisualizer/Settings/NormalJudgment.cs index d2b769b..458bd1a 100644 --- a/HitScoreVisualizer/Settings/NormalJudgment.cs +++ b/HitScoreVisualizer/Settings/NormalJudgment.cs @@ -3,9 +3,17 @@ namespace HitScoreVisualizer.Settings { - [method: JsonConstructor] - public readonly struct NormalJudgment(int threshold = 0, string? text = null, List? color = null, bool fade = false) + public class NormalJudgment { + [JsonConstructor] + public NormalJudgment(int threshold = 0, string? text = null, List? color = null, bool fade = false) + { + Threshold = threshold; + Text = text ?? string.Empty; + Color = color ?? [0, 0, 0, 0]; + Fade = fade; + } + [JsonIgnore] internal static NormalJudgment Default { get; } = new(0, "%s", [1, 1, 1, 1], false); @@ -13,22 +21,22 @@ public readonly struct NormalJudgment(int threshold = 0, string? text = null, Li // Note that if no judgment can be applied to a note, the text will appear as in the unmodded // game. [JsonProperty("threshold")] - public int Threshold { get; } = threshold; + public int Threshold { get; } // The text to display (if judgment text is enabled). [JsonProperty("text")] - public string Text { get; } = text ?? string.Empty; + public string Text { get; } // 4 floats, 0-1; red, green, blue, glow (not transparency!) // leaving this out should look obviously wrong [JsonProperty("color")] - public List Color { get; } = color ?? [0, 0, 0, 0]; + public List Color { get; } // If true, the text color will be interpolated between this judgment's color and the previous // based on how close to the next threshold it is. // Specifying fade : true for the first judgment in the array is an error, and will crash the // plugin. [JsonProperty("fade")] - public bool Fade { get; } = fade; + public bool Fade { get; } } } \ No newline at end of file diff --git a/HitScoreVisualizer/Settings/TimeDependenceJudgmentSegment.cs b/HitScoreVisualizer/Settings/TimeDependenceJudgmentSegment.cs index 82e5c36..3543f64 100644 --- a/HitScoreVisualizer/Settings/TimeDependenceJudgmentSegment.cs +++ b/HitScoreVisualizer/Settings/TimeDependenceJudgmentSegment.cs @@ -2,19 +2,25 @@ namespace HitScoreVisualizer.Settings { - [method: JsonConstructor] - public readonly struct TimeDependenceJudgmentSegment(float threshold = 0f, string? text = null) + public class TimeDependenceJudgmentSegment { + [JsonConstructor] + public TimeDependenceJudgmentSegment(float threshold = 0f, string? text = null) + { + Threshold = threshold; + Text = text ?? string.Empty; + } + [JsonIgnore] internal static TimeDependenceJudgmentSegment Default { get; } = new(0, string.Empty); // This judgment will be applied only when the time dependence >= this number. // If no judgment can be applied, the judgment for this segment will be "" (the empty string). [JsonProperty("threshold")] - public float Threshold { get; } = threshold; + public float Threshold { get; } // The text to replace the appropriate judgment specifier with (%T) when this judgment applies. [JsonProperty("text")] - public string? Text { get; } = text ?? string.Empty; + public string? Text { get; } } } \ No newline at end of file diff --git a/README.md b/README.md index 7e91f9b..6d05a55 100644 --- a/README.md +++ b/README.md @@ -63,6 +63,7 @@ You can use that file as a starting point in case you want to customize it. Just | fixedPosition | The coordinate object that defines the fixed location where the hit scores have to be shown.
Either leave this out or set as `null` to fully disable. | {
"x": 0.0,
"y": 3.0,
"z": -2.0
}

null | | targetPositionOffset | The coordinate object that indicates how much the hitscore fade animation target position has to be offset.
Note: If a fixed position is defined in the config, that one will take priority over this one and this will be fully ignored.
Either leave this out or set as `null` to fully disable. | {
"x": 0.0,
"y": 3.0,
"z": -2.0
}

null | | doIntermediateUpdates | When enabled, Judgments will be updated multiple times. This will make score popups more accurate during a brief period before the note's score is finalized, at some cost of performance. | true or false | +| assumeMaxPostSwing | When enabled, the first score number will show the maximum possible post-swing score for that note cut. This can be preferable when doIntermediateUpdates is false, your swings are very slow, and you don't want to automatically use lower score thresholds as the game calculates your swing. | true or false | | timeDependencyDecimalPrecision | The number of decimal places to show the time dependence to.
**Must be between 0 and 99, inclusive** | ints | | timeDependencyDecimalOffset | Which power of 10 to multiply the time dependence by (time dependence is from 0 - 1).
**Must be between 0 and 38, inclusive** | ints | | judgments | The list of Judgments that can be used to customize the Judgments in general. | Uses judgment objects.
More info below. | @@ -108,17 +109,18 @@ You can use that file as a starting point in case you want to customize it. Just ### Format tokens -| Token | Explanation / Info | -|----------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| %b | The score contributed by the swing before cutting the block. | -| %c | The score contributed by the accuracy of the cut. | -| %a | The score contributed by the part of the swing after cutting the block. | -| %t | The time dependence of the swing. This value indicates how depedent the accuracy part of the score is upon *when* you hit the block, measured from 0 - 1. A value of 0 indicates a completely time independent swing, while a value of 1 indicates that the accuracy part of the score would vary greatly if the block was hit even slightly earlier or later. | -| %B, %C, %A, %T | Uses the Judgment text that matches the threshold as specified in either `beforeCutAngleJudgments`, `accuracyJudgments`, `afterCutAngleJudgments`, or `timeDependencyJudgments` (depending on the used token). | -| %s | The total score of the cut. | -| %p | A number representing the percentage of the maximum total score. | -| %% | A literal percent symbol. | -| %n | A newline. | +| Token | Explanation / Info | +|----------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| %b | The score contributed by the swing before cutting the block. | +| %c | The score contributed by the accuracy of the cut. | +| %a | The score contributed by the part of the swing after cutting the block. | +| %t | The time dependence of the swing. This value indicates how dependent the accuracy part of the score is upon *when* you hit the block, measured from 0 - 1. A value of 0 indicates a completely time independent swing, while a value of 1 indicates that the accuracy part of the score would vary greatly if the block was hit even slightly earlier or later. | +| %B, %C, %A, %T | Uses the Judgment text that matches the threshold as specified in either `beforeCutAngleJudgments`, `accuracyJudgments`, `afterCutAngleJudgments`, or `timeDependencyJudgments` (depending on the used token). | +| %d | An arrow that points towards the center line of the note relative to the cut line. | +| %s | The total score of the cut. | +| %p | A number representing the percentage of the maximum total score. | +| %% | A literal percent symbol. | +| %n | A newline. | ## Developers