mirror of
https://github.com/Theaninova/HitScoreVisualizer.git
synced 2026-01-08 08:42:49 +00:00
Add "format" display mode, judgments for swing segments
This commit is contained in:
@@ -43,6 +43,17 @@ namespace HitScoreVisualizer
|
|||||||
public bool fade;
|
public bool fade;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Judgments for individual parts of the swing (angle before, angle after, accuracy).
|
||||||
|
public struct SegmentJudgment
|
||||||
|
{
|
||||||
|
// 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).
|
||||||
|
[DefaultValue(0)]
|
||||||
|
public int threshold;
|
||||||
|
// The text to replace the appropriate judgment specifier with (%B, %C, %A) when this judgment applies.
|
||||||
|
public string text;
|
||||||
|
}
|
||||||
|
|
||||||
// If the version number (excluding patch version) of the config is higher than that of the plugin,
|
// If the version number (excluding patch version) of the config is higher than that of the plugin,
|
||||||
// the config will not be loaded. If the version number of the config is lower than that of the
|
// the config will not be loaded. If the version number of the config is lower than that of the
|
||||||
// plugin, the file will be automatically converted. Conversion is not guaranteed to occur, or be
|
// plugin, the file will be automatically converted. Conversion is not guaranteed to occur, or be
|
||||||
@@ -58,6 +69,15 @@ namespace HitScoreVisualizer
|
|||||||
// update rather than being converted.
|
// update rather than being converted.
|
||||||
public bool isDefaultConfig;
|
public bool isDefaultConfig;
|
||||||
|
|
||||||
|
// If set to "format", displays the judgment text, with the following format specifiers allowed:
|
||||||
|
// - %b: The score contributed by the part of 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.
|
||||||
|
// - %B, %C, %A: As above, except using the appropriate judgment from that part of the swing (as configured for "beforeCutAngleJudgments", "accuracyJudgments", or "afterCutAngleJudgments").
|
||||||
|
// - %s: The total score for the cut.
|
||||||
|
// - %%: A literal percent symbol.
|
||||||
|
// - %n: A newline.
|
||||||
|
//
|
||||||
// If set to "numeric", displays only the note score.
|
// If set to "numeric", displays only the note score.
|
||||||
// If set to "textOnly", displays only the judgment text.
|
// If set to "textOnly", displays only the judgment text.
|
||||||
// If set to "scoreOnTop", displays both (numeric score above judgment text).
|
// If set to "scoreOnTop", displays both (numeric score above judgment text).
|
||||||
@@ -68,19 +88,30 @@ namespace HitScoreVisualizer
|
|||||||
// Order from highest threshold to lowest; the first matching judgment will be applied
|
// Order from highest threshold to lowest; the first matching judgment will be applied
|
||||||
public Judgment[] judgments;
|
public Judgment[] judgments;
|
||||||
|
|
||||||
|
// Judgments for the part of the swing before cutting the block (score is from 0-70).
|
||||||
|
// Format specifier: %B
|
||||||
|
public SegmentJudgment[] beforeCutAngleJudgments;
|
||||||
|
|
||||||
|
// Judgments for the accuracy of the cut (how close to the center of the block the cut was, score is from 0-10).
|
||||||
|
// Format specifier: %C
|
||||||
|
public SegmentJudgment[] accuracyJudgments;
|
||||||
|
|
||||||
|
// Judgments for the part of the swing after cutting the block (score is from 0-30).
|
||||||
|
// Format specifier: %A
|
||||||
|
public SegmentJudgment[] afterCutAngleJudgments;
|
||||||
|
|
||||||
// path to where the config is saved
|
// path to where the config is saved
|
||||||
private const string FILE_PATH = "/UserData/HitScoreVisualizerConfig.json";
|
private const string FILE_PATH = "/UserData/HitScoreVisualizerConfig.json";
|
||||||
|
|
||||||
private const string DEFAULT_JSON = @"{
|
private const string DEFAULT_JSON = @"{
|
||||||
""majorVersion"": 2,
|
""majorVersion"": 2,
|
||||||
""minorVersion"": 0,
|
""minorVersion"": 1,
|
||||||
""patchVersion"": 2,
|
""patchVersion"": 0,
|
||||||
""isDefaultConfig"": true,
|
""displayMode"": ""format"",
|
||||||
""displayMode"": ""textOnTop"",
|
|
||||||
""judgments"": [
|
""judgments"": [
|
||||||
{
|
{
|
||||||
""threshold"": 110,
|
""threshold"": 110,
|
||||||
""text"": ""Fantastic"",
|
""text"": ""Fantastic%n%s%n%B %C %A"",
|
||||||
""color"": [
|
""color"": [
|
||||||
1.0,
|
1.0,
|
||||||
1.0,
|
1.0,
|
||||||
@@ -90,7 +121,7 @@ namespace HitScoreVisualizer
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
""threshold"": 101,
|
""threshold"": 101,
|
||||||
""text"": ""<size=80%>Excellent</size>"",
|
""text"": ""<size=80%>Excellent</size>%n%s%n%B %C %A"",
|
||||||
""color"": [
|
""color"": [
|
||||||
0.0,
|
0.0,
|
||||||
1.0,
|
1.0,
|
||||||
@@ -100,7 +131,7 @@ namespace HitScoreVisualizer
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
""threshold"": 90,
|
""threshold"": 90,
|
||||||
""text"": ""<size=80%>Great</size>"",
|
""text"": ""<size=80%>Great</size>%n%s%n%B %C %A"",
|
||||||
""color"": [
|
""color"": [
|
||||||
1.0,
|
1.0,
|
||||||
0.980392158,
|
0.980392158,
|
||||||
@@ -110,7 +141,7 @@ namespace HitScoreVisualizer
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
""threshold"": 80,
|
""threshold"": 80,
|
||||||
""text"": ""<size=80%>Good</size>"",
|
""text"": ""<size=80%>Good</size>%n%s%n%B %C %A"",
|
||||||
""color"": [
|
""color"": [
|
||||||
1.0,
|
1.0,
|
||||||
0.6,
|
0.6,
|
||||||
@@ -121,7 +152,7 @@ namespace HitScoreVisualizer
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
""threshold"": 60,
|
""threshold"": 60,
|
||||||
""text"": ""<size=80%>Decent</size>"",
|
""text"": ""<size=80%>Decent</size>%n%s%n%B %C %A"",
|
||||||
""color"": [
|
""color"": [
|
||||||
1.0,
|
1.0,
|
||||||
0.0,
|
0.0,
|
||||||
@@ -131,7 +162,7 @@ namespace HitScoreVisualizer
|
|||||||
""fade"": true
|
""fade"": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
""text"": ""<size=80%>Way Off</size>"",
|
""text"": ""<size=80%>Way Off</size>%n%s%n%B %C %A"",
|
||||||
""color"": [
|
""color"": [
|
||||||
0.5,
|
0.5,
|
||||||
0.0,
|
0.0,
|
||||||
@@ -140,6 +171,48 @@ namespace HitScoreVisualizer
|
|||||||
],
|
],
|
||||||
""fade"": true
|
""fade"": true
|
||||||
}
|
}
|
||||||
|
],
|
||||||
|
""beforeCutAngleJudgments"": [
|
||||||
|
{
|
||||||
|
""threshold"": 70,
|
||||||
|
""text"": ""+""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
""threshold"": 35,
|
||||||
|
""text"": "" ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
""threshold"": 0,
|
||||||
|
""text"": ""-""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
""accuracyJudgments"": [
|
||||||
|
{
|
||||||
|
""threshold"": 10,
|
||||||
|
""text"": ""+""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
""threshold"": 5,
|
||||||
|
""text"": "" ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
""threshold"": 0,
|
||||||
|
""text"": ""-""
|
||||||
|
}
|
||||||
|
],
|
||||||
|
""afterCutAngleJudgments"": [
|
||||||
|
{
|
||||||
|
""threshold"": 30,
|
||||||
|
""text"": ""+""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
""threshold"": 15,
|
||||||
|
""text"": "" ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
""threshold"": 0,
|
||||||
|
""text"": ""-""
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}";
|
}";
|
||||||
public static readonly Config DEFAULT_CONFIG = JsonConvert.DeserializeObject<Config>(DEFAULT_JSON,
|
public static readonly Config DEFAULT_CONFIG = JsonConvert.DeserializeObject<Config>(DEFAULT_JSON,
|
||||||
@@ -153,6 +226,12 @@ namespace HitScoreVisualizer
|
|||||||
fade = false
|
fade = false
|
||||||
};
|
};
|
||||||
|
|
||||||
|
public static readonly SegmentJudgment DEFAULT_SEGMENT_JUDGMENT = new SegmentJudgment
|
||||||
|
{
|
||||||
|
threshold = 0,
|
||||||
|
text = ""
|
||||||
|
};
|
||||||
|
|
||||||
public static string fullPath => Environment.CurrentDirectory.Replace('\\', '/') + FILE_PATH;
|
public static string fullPath => Environment.CurrentDirectory.Replace('\\', '/') + FILE_PATH;
|
||||||
|
|
||||||
public static void load()
|
public static void load()
|
||||||
@@ -180,7 +259,25 @@ namespace HitScoreVisualizer
|
|||||||
}
|
}
|
||||||
if (outdated(loaded))
|
if (outdated(loaded))
|
||||||
{
|
{
|
||||||
|
if (loaded.isDefaultConfig)
|
||||||
|
{
|
||||||
|
loaded = DEFAULT_CONFIG;
|
||||||
|
instance = loaded;
|
||||||
|
save();
|
||||||
|
return;
|
||||||
|
}
|
||||||
// put config update logic here
|
// put config update logic here
|
||||||
|
if (loaded.majorVersion == 2 && loaded.minorVersion == 0)
|
||||||
|
{
|
||||||
|
loaded.beforeCutAngleJudgments = new SegmentJudgment[] { DEFAULT_SEGMENT_JUDGMENT };
|
||||||
|
loaded.accuracyJudgments = new SegmentJudgment[] { DEFAULT_SEGMENT_JUDGMENT };
|
||||||
|
loaded.afterCutAngleJudgments = new SegmentJudgment[] { DEFAULT_SEGMENT_JUDGMENT };
|
||||||
|
loaded.minorVersion = 1;
|
||||||
|
loaded.patchVersion = 0;
|
||||||
|
instance = loaded;
|
||||||
|
save();
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
instance = loaded;
|
instance = loaded;
|
||||||
}
|
}
|
||||||
@@ -242,7 +339,7 @@ namespace HitScoreVisualizer
|
|||||||
instance = DEFAULT_CONFIG;
|
instance = DEFAULT_CONFIG;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void judge(FlyingScoreTextEffect text, ref Color color, int score)
|
public static void judge(FlyingScoreTextEffect text, NoteCutInfo noteCutInfo, SaberAfterCutSwingRatingCounter saberAfterCutSwingRatingCounter, ref Color color, int score)
|
||||||
{
|
{
|
||||||
Judgment judgment = DEFAULT_JUDGMENT;
|
Judgment judgment = DEFAULT_JUDGMENT;
|
||||||
int index; // save in case we need to fade
|
int index; // save in case we need to fade
|
||||||
@@ -268,6 +365,74 @@ namespace HitScoreVisualizer
|
|||||||
color = toColor(judgment.color);
|
color = toColor(judgment.color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (instance.displayMode == "format")
|
||||||
|
{
|
||||||
|
int beforeCutScore, accuracyScore, afterCutScore;
|
||||||
|
|
||||||
|
beforeCutScore = Mathf.RoundToInt(70f * noteCutInfo.swingRating);
|
||||||
|
float accuracy = 1f - Mathf.Clamp01(noteCutInfo.cutDistanceToCenter / 0.2f);
|
||||||
|
accuracyScore = Mathf.RoundToInt(10f * accuracy);
|
||||||
|
afterCutScore = 0;
|
||||||
|
if (saberAfterCutSwingRatingCounter != null)
|
||||||
|
{
|
||||||
|
afterCutScore = Mathf.RoundToInt(30f * saberAfterCutSwingRatingCounter.rating);
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder formattedBuilder = new StringBuilder();
|
||||||
|
string formatString = judgment.text;
|
||||||
|
int nextPercentIndex = formatString.IndexOf('%');
|
||||||
|
while (nextPercentIndex != -1)
|
||||||
|
{
|
||||||
|
formattedBuilder.Append(formatString.Substring(0, nextPercentIndex));
|
||||||
|
if (formatString.Length == nextPercentIndex + 1)
|
||||||
|
{
|
||||||
|
formatString += " ";
|
||||||
|
}
|
||||||
|
char specifier = formatString[nextPercentIndex + 1];
|
||||||
|
|
||||||
|
switch (specifier)
|
||||||
|
{
|
||||||
|
case 'b':
|
||||||
|
formattedBuilder.Append(beforeCutScore);
|
||||||
|
break;
|
||||||
|
case 'c':
|
||||||
|
formattedBuilder.Append(accuracyScore);
|
||||||
|
break;
|
||||||
|
case 'a':
|
||||||
|
formattedBuilder.Append(afterCutScore);
|
||||||
|
break;
|
||||||
|
case 'B':
|
||||||
|
formattedBuilder.Append(judgeSegment(beforeCutScore, instance.beforeCutAngleJudgments));
|
||||||
|
break;
|
||||||
|
case 'C':
|
||||||
|
formattedBuilder.Append(judgeSegment(accuracyScore, instance.accuracyJudgments));
|
||||||
|
break;
|
||||||
|
case 'A':
|
||||||
|
formattedBuilder.Append(judgeSegment(afterCutScore, instance.afterCutAngleJudgments));
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
formattedBuilder.Append(score);
|
||||||
|
break;
|
||||||
|
case '%':
|
||||||
|
formattedBuilder.Append("%");
|
||||||
|
break;
|
||||||
|
case 'n':
|
||||||
|
formattedBuilder.Append("\n");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
formattedBuilder.Append("%" + specifier);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
formatString = formatString.Remove(0, nextPercentIndex + 2);
|
||||||
|
nextPercentIndex = formatString.IndexOf('%');
|
||||||
|
}
|
||||||
|
formattedBuilder.Append(formatString);
|
||||||
|
|
||||||
|
text.text = formattedBuilder.ToString();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (instance.displayMode == "textOnly")
|
if (instance.displayMode == "textOnly")
|
||||||
{
|
{
|
||||||
text.text = judgment.text;
|
text.text = judgment.text;
|
||||||
@@ -289,5 +454,15 @@ namespace HitScoreVisualizer
|
|||||||
{
|
{
|
||||||
return new Color(rgba[0], rgba[1], rgba[2], rgba[3]);
|
return new Color(rgba[0], rgba[1], rgba[2], rgba[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string judgeSegment(int scoreForSegment, SegmentJudgment[] judgments)
|
||||||
|
{
|
||||||
|
if (judgments == null) return "";
|
||||||
|
foreach(SegmentJudgment j in judgments)
|
||||||
|
{
|
||||||
|
if (scoreForSegment >= j.threshold) return j.text;
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ namespace HitScoreVisualizer.Harmony_Patches
|
|||||||
{
|
{
|
||||||
ScoreController.ScoreWithoutMultiplier(____noteCutInfo, afterCutRating, out int before, out int after);
|
ScoreController.ScoreWithoutMultiplier(____noteCutInfo, afterCutRating, out int before, out int after);
|
||||||
int total = before + after;
|
int total = before + after;
|
||||||
Config.judge(__instance, ref ____color, total);
|
Config.judge(__instance, ____noteCutInfo, afterCutRating, ref ____color, total);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ namespace HitScoreVisualizer.Harmony_Patches
|
|||||||
{
|
{
|
||||||
ScoreController.ScoreWithoutMultiplier(noteCutInfo, saberAfterCutSwingRatingCounter, out int before, out int after);
|
ScoreController.ScoreWithoutMultiplier(noteCutInfo, saberAfterCutSwingRatingCounter, out int before, out int after);
|
||||||
int total = before + after;
|
int total = before + after;
|
||||||
Config.judge(__instance, ref ____color, total);
|
Config.judge(__instance, noteCutInfo, saberAfterCutSwingRatingCounter, ref ____color, total);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,11 +9,11 @@ namespace HitScoreVisualizer
|
|||||||
public class Plugin : IPlugin
|
public class Plugin : IPlugin
|
||||||
{
|
{
|
||||||
public string Name => "HitScoreVisualizer";
|
public string Name => "HitScoreVisualizer";
|
||||||
public string Version => "2.0.2";
|
public string Version => "2.1.0";
|
||||||
|
|
||||||
internal const int majorVersion = 2;
|
internal const int majorVersion = 2;
|
||||||
internal const int minorVersion = 0;
|
internal const int minorVersion = 1;
|
||||||
internal const int patchVersion = 2;
|
internal const int patchVersion = 0;
|
||||||
|
|
||||||
public void OnApplicationStart()
|
public void OnApplicationStart()
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user