From cf7139f70d526096758c179dd7114e448b3e6851 Mon Sep 17 00:00:00 2001 From: NSGolova Date: Sat, 17 Dec 2022 09:16:37 +0000 Subject: [PATCH 01/12] Experimental scoring --- .gitignore | 11 +- .../BeatLeaderModifiers.csproj | 269 +++++++++--------- .../HarmonyPatches/CutScoreBufferPatch.cs | 35 +++ .../StandardLevelBlaBlaPatch.cs | 29 ++ 4 files changed, 209 insertions(+), 135 deletions(-) create mode 100644 BeatLeaderModifiers/HarmonyPatches/CutScoreBufferPatch.cs create mode 100644 BeatLeaderModifiers/HarmonyPatches/StandardLevelBlaBlaPatch.cs diff --git a/.gitignore b/.gitignore index b285a22..cd68fdf 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,9 @@ -bin/ -obj/ -.idea/ /packages/ riderModule.iml -/_ReSharper.Caches/ \ No newline at end of file +/_ReSharper.Caches/ +.idea +.vscode +.vs +bin +obj +./BeatLeaderModifiers/BeatLeaderModifiers.csproj.user \ No newline at end of file diff --git a/BeatLeaderModifiers/BeatLeaderModifiers.csproj b/BeatLeaderModifiers/BeatLeaderModifiers.csproj index 238abe1..b011e80 100644 --- a/BeatLeaderModifiers/BeatLeaderModifiers.csproj +++ b/BeatLeaderModifiers/BeatLeaderModifiers.csproj @@ -1,134 +1,141 @@  - - Debug - AnyCPU - 8.0.30703 - 2.0 - {A652D071-E511-4BD2-B49A-992C12385342} - Library - Properties - BeatLeaderModifiers - BeatLeaderModifiers - v4.7.2 - 512 - true - portable - ..\Refs - $(LocalRefsDir) - $(MSBuildProjectDirectory)\ - - prompt - 4 - latest - - - false - bin\Debug\ - DEBUG;TRACE - - - true - bin\Release\ - prompt - 4 - - - True - - - True - True - - - - $(BeatSaberDir)\Libs\0Harmony.dll - - - $(BeatSaberDir)\Beat Saber_Data\Managed\BeatmapCore.dll - - - $(BeatSaberDir)\Plugins\BSML.dll - - - $(BeatSaberDir)\Plugins\SiraUtil.dll - - - $(BeatSaberDir)\Plugins\SongCore.dll - - - - - - - - - $(BeatSaberDir)\Beat Saber_Data\Managed\Main.dll - - - $(BeatSaberDir)\Beat Saber_Data\Managed\HMLib.dll - - - $(BeatSaberDir)\Beat Saber_Data\Managed\HMUI.dll - - - $(BeatSaberDir)\Beat Saber_Data\Managed\IPA.Loader.dll - - - $(BeatSaberDir)\Beat Saber_Data\Managed\Unity.TextMeshPro.dll - - - $(BeatSaberDir)\Beat Saber_Data\Managed\UnityEngine.dll - - - $(BeatSaberDir)\Beat Saber_Data\Managed\UnityEngine.AssetBundleModule.dll - - - $(BeatSaberDir)\Beat Saber_Data\Managed\UnityEngine.CoreModule.dll - - - $(BeatSaberDir)\Beat Saber_Data\Managed\UnityEngine.UI.dll - - - $(BeatSaberDir)\Beat Saber_Data\Managed\UnityEngine.UIElementsModule.dll - - - $(BeatSaberDir)\Beat Saber_Data\Managed\UnityEngine.UIModule.dll - - - $(BeatSaberDir)\Beat Saber_Data\Managed\UnityEngine.VRModule.dll - - - $(BeatSaberDir)\Beat Saber_Data\Managed\Zenject.dll - - - $(BeatSaberDir)\Beat Saber_Data\Managed\Zenject-usage.dll - - - - - - - - - - - - - - - - - - - - - - - 1.2.3 - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - + + Debug + AnyCPU + 8.0.30703 + 2.0 + {A652D071-E511-4BD2-B49A-992C12385342} + Library + Properties + BeatLeaderModifiers + BeatLeaderModifiers + v4.7.2 + 512 + true + portable + ..\Refs + $(LocalRefsDir) + $(MSBuildProjectDirectory)\ + + prompt + 4 + latest + + + false + bin\Debug\ + DEBUG;TRACE + + + true + bin\Release\ + prompt + 4 + + + True + + + True + True + + + + $(BeatSaberDir)\Libs\0Harmony.dll + + + $(BeatSaberDir)\Beat Saber_Data\Managed\BeatmapCore.dll + + + $(BeatSaberDir)\Plugins\BSML.dll + + + False + $(BeatSaberDir)\Beat Saber_Data\Managed\GameplayCore.dll + False + + + $(BeatSaberDir)\Plugins\SiraUtil.dll + + + $(BeatSaberDir)\Plugins\SongCore.dll + + + + + + + + + $(BeatSaberDir)\Beat Saber_Data\Managed\Main.dll + + + $(BeatSaberDir)\Beat Saber_Data\Managed\HMLib.dll + + + $(BeatSaberDir)\Beat Saber_Data\Managed\HMUI.dll + + + $(BeatSaberDir)\Beat Saber_Data\Managed\IPA.Loader.dll + + + $(BeatSaberDir)\Beat Saber_Data\Managed\Unity.TextMeshPro.dll + + + $(BeatSaberDir)\Beat Saber_Data\Managed\UnityEngine.dll + + + $(BeatSaberDir)\Beat Saber_Data\Managed\UnityEngine.AssetBundleModule.dll + + + $(BeatSaberDir)\Beat Saber_Data\Managed\UnityEngine.CoreModule.dll + + + $(BeatSaberDir)\Beat Saber_Data\Managed\UnityEngine.UI.dll + + + $(BeatSaberDir)\Beat Saber_Data\Managed\UnityEngine.UIElementsModule.dll + + + $(BeatSaberDir)\Beat Saber_Data\Managed\UnityEngine.UIModule.dll + + + $(BeatSaberDir)\Beat Saber_Data\Managed\UnityEngine.VRModule.dll + + + $(BeatSaberDir)\Beat Saber_Data\Managed\Zenject.dll + + + $(BeatSaberDir)\Beat Saber_Data\Managed\Zenject-usage.dll + + + + + + + + + + + + + + + + + + + + + + + + + 1.2.3 + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + \ No newline at end of file diff --git a/BeatLeaderModifiers/HarmonyPatches/CutScoreBufferPatch.cs b/BeatLeaderModifiers/HarmonyPatches/CutScoreBufferPatch.cs new file mode 100644 index 0000000..1c17c4d --- /dev/null +++ b/BeatLeaderModifiers/HarmonyPatches/CutScoreBufferPatch.cs @@ -0,0 +1,35 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using HarmonyLib; +using IPA.Utilities; +using JetBrains.Annotations; +using UnityEngine; + +namespace BeatLeaderModifiers { + [HarmonyPatch(typeof(CutScoreBuffer), "cutScore", MethodType.Getter)] + internal class CutScoreBufferPatch { + + [UsedImplicitly] + private static bool Prefix( + ref int __result, + int ____afterCutScore, + int ____beforeCutScore, + NoteCutInfo ____noteCutInfo) { + if (StandardLevelBlaBlaPatch.customCharacterisitic == CustomCharacterisitic.betterScoring) { + int timingScore = Mathf.RoundToInt(Mathf.Max(0.1f - Mathf.Abs(____noteCutInfo.timeDeviation) - 0.02f, 0.0f) * 200); + int beforeCutScore = Mathf.RoundToInt(((float)____beforeCutScore / 30.0f) * 20); + int afterCutScore = Mathf.RoundToInt(((float)____afterCutScore / 70.0f) * 20f); + int centerDistanceCutScore = Mathf.RoundToInt(45f * (1f - Mathf.Clamp01(____noteCutInfo.cutDistanceToCenter / 0.3f))); + int angleScore = Mathf.RoundToInt((1f - Mathf.Min(Mathf.Abs(____noteCutInfo.cutAngle), 180f) / 180f) * 10f); + + __result = timingScore + beforeCutScore + afterCutScore + centerDistanceCutScore + angleScore; + + return false; + } else { + return true; + } + + } + } +} diff --git a/BeatLeaderModifiers/HarmonyPatches/StandardLevelBlaBlaPatch.cs b/BeatLeaderModifiers/HarmonyPatches/StandardLevelBlaBlaPatch.cs new file mode 100644 index 0000000..aa04f91 --- /dev/null +++ b/BeatLeaderModifiers/HarmonyPatches/StandardLevelBlaBlaPatch.cs @@ -0,0 +1,29 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using HarmonyLib; +using IPA.Utilities; +using JetBrains.Annotations; +using static PlayerSaveData; + +enum CustomCharacterisitic { + standard = 0, + betterScoring = 1 +} + +namespace BeatLeaderModifiers { + [HarmonyPatch(typeof(StandardLevelScenesTransitionSetupDataSO), nameof(StandardLevelScenesTransitionSetupDataSO.Init))] + class StandardLevelBlaBlaPatch + { + public static CustomCharacterisitic customCharacterisitic; + static void Postfix(StandardLevelScenesTransitionSetupDataSO __instance, string gameMode, IDifficultyBeatmap difficultyBeatmap, IPreviewBeatmapLevel previewBeatmapLevel, OverrideEnvironmentSettings overrideEnvironmentSettings, + GameplayModifiers gameplayModifiers, ColorScheme overrideColorScheme, PlayerSpecificSettings playerSpecificSettings, ref PracticeSettings practiceSettings, string backButtonText, bool useTestNoteCutSoundEffects) + { + if (difficultyBeatmap.parentDifficultyBeatmapSet.beatmapCharacteristic.serializedName == CharacteristicsManager.BetterScoringCharacteristic.SerializedName) { + customCharacterisitic = CustomCharacterisitic.betterScoring; + } else { + customCharacterisitic = CustomCharacterisitic.standard; + } + } + } +} From 996a5ed8da424b9c33509af02e694e206cf479bf Mon Sep 17 00:00:00 2001 From: NSGolova Date: Sat, 17 Dec 2022 09:59:10 +0000 Subject: [PATCH 02/12] Ver 2 --- .../HarmonyPatches/CutScoreBufferPatch.cs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/BeatLeaderModifiers/HarmonyPatches/CutScoreBufferPatch.cs b/BeatLeaderModifiers/HarmonyPatches/CutScoreBufferPatch.cs index 1c17c4d..bf531eb 100644 --- a/BeatLeaderModifiers/HarmonyPatches/CutScoreBufferPatch.cs +++ b/BeatLeaderModifiers/HarmonyPatches/CutScoreBufferPatch.cs @@ -17,11 +17,13 @@ private static bool Prefix( int ____beforeCutScore, NoteCutInfo ____noteCutInfo) { if (StandardLevelBlaBlaPatch.customCharacterisitic == CustomCharacterisitic.betterScoring) { - int timingScore = Mathf.RoundToInt(Mathf.Max(0.1f - Mathf.Abs(____noteCutInfo.timeDeviation) - 0.02f, 0.0f) * 200); - int beforeCutScore = Mathf.RoundToInt(((float)____beforeCutScore / 30.0f) * 20); - int afterCutScore = Mathf.RoundToInt(((float)____afterCutScore / 70.0f) * 20f); - int centerDistanceCutScore = Mathf.RoundToInt(45f * (1f - Mathf.Clamp01(____noteCutInfo.cutDistanceToCenter / 0.3f))); - int angleScore = Mathf.RoundToInt((1f - Mathf.Min(Mathf.Abs(____noteCutInfo.cutAngle), 180f) / 180f) * 10f); + int timingScore = Mathf.RoundToInt(Mathf.Max(0.1f - (Mathf.Abs(____noteCutInfo.timeDeviation) - 0.02f), 0.0f) * 400); + int beforeCutScore = Mathf.RoundToInt(((float)____beforeCutScore / 70.0f) * 20); + int afterCutScore = Mathf.RoundToInt(((float)____afterCutScore / 30.0f) * 20f); + int centerDistanceCutScore = Mathf.RoundToInt(15f * (1f - Mathf.Clamp01(____noteCutInfo.cutDistanceToCenter / 0.3f))); + int angleScore = Mathf.RoundToInt(Mathf.Max(60f - Mathf.Abs(Mathf.Abs(____noteCutInfo.cutAngle) - 90f), 0f) / 3f); + + Plugin.Log.Debug(timingScore + " " + beforeCutScore + " " + afterCutScore + " " + centerDistanceCutScore + " " + angleScore); __result = timingScore + beforeCutScore + afterCutScore + centerDistanceCutScore + angleScore; From de68619deaaffbf8c2163781e01a46a7d92af114 Mon Sep 17 00:00:00 2001 From: NSGolova Date: Sun, 18 Dec 2022 11:25:45 +0000 Subject: [PATCH 03/12] Force modifiers and move ratings to counter --- .../HarmonyPatches/CutScoreBufferPatch.cs | 42 ++++++++++++------- .../StandardLevelBlaBlaPatch.cs | 6 ++- 2 files changed, 31 insertions(+), 17 deletions(-) diff --git a/BeatLeaderModifiers/HarmonyPatches/CutScoreBufferPatch.cs b/BeatLeaderModifiers/HarmonyPatches/CutScoreBufferPatch.cs index bf531eb..e4ea2eb 100644 --- a/BeatLeaderModifiers/HarmonyPatches/CutScoreBufferPatch.cs +++ b/BeatLeaderModifiers/HarmonyPatches/CutScoreBufferPatch.cs @@ -7,31 +7,43 @@ using UnityEngine; namespace BeatLeaderModifiers { - [HarmonyPatch(typeof(CutScoreBuffer), "cutScore", MethodType.Getter)] + + [HarmonyPatch(typeof(CutScoreBuffer), "RefreshScores")] internal class CutScoreBufferPatch { + private static float beforeCutMaxScore = 40f; + private static float angleMaxScore = 30f; + + private static float goodAngle = 7.5f; + private static float badAngle = 45f; + + private static float badTiming = 0.1f; + private static float goodTiming = 0.02f; + [UsedImplicitly] - private static bool Prefix( - ref int __result, - int ____afterCutScore, + private static void Prefix( + SaberSwingRatingCounter ____saberSwingRatingCounter, int ____beforeCutScore, NoteCutInfo ____noteCutInfo) { + if (StandardLevelBlaBlaPatch.customCharacterisitic == CustomCharacterisitic.betterScoring) { - int timingScore = Mathf.RoundToInt(Mathf.Max(0.1f - (Mathf.Abs(____noteCutInfo.timeDeviation) - 0.02f), 0.0f) * 400); - int beforeCutScore = Mathf.RoundToInt(((float)____beforeCutScore / 70.0f) * 20); - int afterCutScore = Mathf.RoundToInt(((float)____afterCutScore / 30.0f) * 20f); - int centerDistanceCutScore = Mathf.RoundToInt(15f * (1f - Mathf.Clamp01(____noteCutInfo.cutDistanceToCenter / 0.3f))); - int angleScore = Mathf.RoundToInt(Mathf.Max(60f - Mathf.Abs(Mathf.Abs(____noteCutInfo.cutAngle) - 90f), 0f) / 3f); + + int beforeCutScore = Mathf.RoundToInt(((float)____beforeCutScore / 70.0f) * beforeCutMaxScore); - Plugin.Log.Debug(timingScore + " " + beforeCutScore + " " + afterCutScore + " " + centerDistanceCutScore + " " + angleScore); + float angleRating = 1f - Mathf.Clamp01((Mathf.Abs(Mathf.Abs(____noteCutInfo.cutAngle) - 90f) - goodAngle) / badAngle); + int angleScore = Mathf.RoundToInt(angleRating * angleMaxScore); - __result = timingScore + beforeCutScore + afterCutScore + centerDistanceCutScore + angleScore; + Plugin.Log.Debug(beforeCutScore + " " + angleScore); - return false; - } else { - return true; - } + float beforeCutScoreRating = (float)(beforeCutScore + angleScore) / 70f; + + ____saberSwingRatingCounter.SetField("_beforeCutRating", Mathf.Min(beforeCutScoreRating, 0.999f)); + float timingRating = 1.0f - Mathf.Clamp01((Mathf.Abs(____noteCutInfo.timeDeviation) - goodTiming) / badTiming); + + ____saberSwingRatingCounter.SetField("_afterCutRating", Mathf.Min(timingRating, 0.999f)); + Plugin.Log.Debug(timingRating + " "); + } } } } diff --git a/BeatLeaderModifiers/HarmonyPatches/StandardLevelBlaBlaPatch.cs b/BeatLeaderModifiers/HarmonyPatches/StandardLevelBlaBlaPatch.cs index aa04f91..85730ab 100644 --- a/BeatLeaderModifiers/HarmonyPatches/StandardLevelBlaBlaPatch.cs +++ b/BeatLeaderModifiers/HarmonyPatches/StandardLevelBlaBlaPatch.cs @@ -16,10 +16,12 @@ namespace BeatLeaderModifiers { class StandardLevelBlaBlaPatch { public static CustomCharacterisitic customCharacterisitic; - static void Postfix(StandardLevelScenesTransitionSetupDataSO __instance, string gameMode, IDifficultyBeatmap difficultyBeatmap, IPreviewBeatmapLevel previewBeatmapLevel, OverrideEnvironmentSettings overrideEnvironmentSettings, - GameplayModifiers gameplayModifiers, ColorScheme overrideColorScheme, PlayerSpecificSettings playerSpecificSettings, ref PracticeSettings practiceSettings, string backButtonText, bool useTestNoteCutSoundEffects) + static void Prefix(StandardLevelScenesTransitionSetupDataSO __instance, string gameMode, IDifficultyBeatmap difficultyBeatmap, IPreviewBeatmapLevel previewBeatmapLevel, OverrideEnvironmentSettings overrideEnvironmentSettings, + ref GameplayModifiers gameplayModifiers, ColorScheme overrideColorScheme, PlayerSpecificSettings playerSpecificSettings, ref PracticeSettings practiceSettings, string backButtonText, bool useTestNoteCutSoundEffects) { if (difficultyBeatmap.parentDifficultyBeatmapSet.beatmapCharacteristic.serializedName == CharacteristicsManager.BetterScoringCharacteristic.SerializedName) { + gameplayModifiers = gameplayModifiers.CopyWith(proMode: true, strictAngles: true); + customCharacterisitic = CustomCharacterisitic.betterScoring; } else { customCharacterisitic = CustomCharacterisitic.standard; From 1426839b9e9657ba3789b32c716882536cc223a1 Mon Sep 17 00:00:00 2001 From: Reezonate Date: Mon, 19 Dec 2022 17:00:13 +0900 Subject: [PATCH 04/12] Timing interpolation --- .../BeatLeaderModifiers.csproj | 3 + .../BeatLeaderModifiers.csproj.user | 2 +- .../Installers/OnGameplayCoreInstaller.cs | 7 +- .../Managers/CutInterpolationManager.cs | 166 ++++++++++++++++++ BeatLeaderModifiers/Utils/HarmonyUtils.cs | 27 +++ .../Utils/InterpolationUtils.cs | 60 +++++++ 6 files changed, 263 insertions(+), 2 deletions(-) create mode 100644 BeatLeaderModifiers/Managers/CutInterpolationManager.cs create mode 100644 BeatLeaderModifiers/Utils/HarmonyUtils.cs create mode 100644 BeatLeaderModifiers/Utils/InterpolationUtils.cs diff --git a/BeatLeaderModifiers/BeatLeaderModifiers.csproj b/BeatLeaderModifiers/BeatLeaderModifiers.csproj index b011e80..707f736 100644 --- a/BeatLeaderModifiers/BeatLeaderModifiers.csproj +++ b/BeatLeaderModifiers/BeatLeaderModifiers.csproj @@ -119,8 +119,11 @@ + + + diff --git a/BeatLeaderModifiers/BeatLeaderModifiers.csproj.user b/BeatLeaderModifiers/BeatLeaderModifiers.csproj.user index d0e407e..44fc3d0 100644 --- a/BeatLeaderModifiers/BeatLeaderModifiers.csproj.user +++ b/BeatLeaderModifiers/BeatLeaderModifiers.csproj.user @@ -1,7 +1,7 @@  - 1.27.0 + 1.27.0 Ree D:\Games\Steam\steamapps\common\Beat Saber v$(BeatSaberVersion) $(BeatSaberDir)\Libs;$(BeatSaberDir)\Plugins;$(BeatSaberDir)\Beat Saber_Data\Managed; diff --git a/BeatLeaderModifiers/Installers/OnGameplayCoreInstaller.cs b/BeatLeaderModifiers/Installers/OnGameplayCoreInstaller.cs index b435abe..268123a 100644 --- a/BeatLeaderModifiers/Installers/OnGameplayCoreInstaller.cs +++ b/BeatLeaderModifiers/Installers/OnGameplayCoreInstaller.cs @@ -5,7 +5,12 @@ namespace BeatLeaderModifiers.Installers { [UsedImplicitly] public class OnGameplayCoreInstaller : Installer { public override void InstallBindings() { - Plugin.Log.Debug("OnGameplayCoreInstaller"); + var difficultyBeatmap = Container.TryResolve(); + var characteristic = difficultyBeatmap.parentDifficultyBeatmapSet.beatmapCharacteristic; + + if (characteristic.serializedName == CharacteristicsManager.BetterScoringCharacteristic.SerializedName) { + Container.BindInterfacesTo().AsSingle(); + } } } } \ No newline at end of file diff --git a/BeatLeaderModifiers/Managers/CutInterpolationManager.cs b/BeatLeaderModifiers/Managers/CutInterpolationManager.cs new file mode 100644 index 0000000..0312a87 --- /dev/null +++ b/BeatLeaderModifiers/Managers/CutInterpolationManager.cs @@ -0,0 +1,166 @@ +using System; +using System.Collections.Generic; +using System.Reflection; +using HarmonyLib; +using JetBrains.Annotations; +using UnityEngine; +using Zenject; + +namespace BeatLeaderModifiers; + +[UsedImplicitly] +internal class CutInterpolationManager : IInitializable, IDisposable, ILateTickable { + #region Harmony + + private static Harmony _harmony; + private static CutInterpolationManager _instance; + + private void ApplyPatches() { + _harmony = new Harmony(nameof(CutInterpolationManager)); + _instance = this; + + _harmony.Patch(NoteWasCutEventPatch); + } + + private static void RemovePatches() { + _harmony.UnpatchSelf(); + _harmony = default; + _instance = default; + } + + #endregion + + #region NoteWasCutEventPatch + + private static HarmonyPatchDescriptor NoteWasCutEventPatch => new( + typeof(NoteController).GetMethod("SendNoteWasCutEvent", BindingFlags.Instance | BindingFlags.NonPublic), + typeof(CutInterpolationManager).GetMethod(nameof(OnSendNoteWasCutEvent), BindingFlags.Static | BindingFlags.NonPublic) + ); + + // ReSharper disable InconsistentNaming + private static bool OnSendNoteWasCutEvent( + NoteController __instance, + NoteCutInfo noteCutInfo, + LazyCopyHashSet ____noteWasCutEvent + ) { + _instance.OnBeforeNoteWasCutEvent(__instance, ref noteCutInfo); + foreach (var controllerNoteWasCutEvent in ____noteWasCutEvent.items) + controllerNoteWasCutEvent.HandleNoteControllerNoteWasCut(__instance, in noteCutInfo); + return false; + } + + #endregion + + #region Initialize/Dispose + + [Inject, UsedImplicitly] + private BeatmapObjectManager _beatmapObjectManager; + + [Inject, UsedImplicitly] + private AudioTimeSyncController _audioTimeSyncController; + + public void Initialize() { + ApplyPatches(); + _beatmapObjectManager.noteWasSpawnedEvent += OnNoteWasSpawned; + _beatmapObjectManager.noteWasDespawnedEvent += OnNoteWasDespawned; + } + + public void Dispose() { + RemovePatches(); + _beatmapObjectManager.noteWasSpawnedEvent -= OnNoteWasSpawned; + _beatmapObjectManager.noteWasDespawnedEvent -= OnNoteWasDespawned; + } + + #endregion + + #region NoteMovementTracker + + private readonly HashSet _notesCache = new(10); + private readonly Dictionary _noteMovementCache = new(10); + + public void LateTick() { + var songTime = _audioTimeSyncController.songTime; + + foreach (var noteController in _notesCache) { + _noteMovementCache[noteController] = new NoteMovementData( + songTime, + noteController.transform.position + ); + } + } + + private void OnNoteWasSpawned(NoteController noteController) { + _noteMovementCache[noteController] = default; + _notesCache.Add(noteController); + } + + private void OnNoteWasDespawned(NoteController noteController) { + _noteMovementCache.Remove(noteController); + _notesCache.Remove(noteController); + } + + private struct NoteMovementData { + public readonly float SongTime; + public readonly Vector3 NotePosition; + + public NoteMovementData(float songTime, Vector3 notePosition) { + SongTime = songTime; + NotePosition = notePosition; + } + } + + #endregion + + #region Events + + private void OnBeforeNoteWasCutEvent(NoteController noteController, ref NoteCutInfo noteCutInfo) { + if (!_noteMovementCache.ContainsKey(noteController)) return; + var previousNoteMovementData = _noteMovementCache[noteController]; + var currentNotePosition = noteCutInfo.notePosition; + + var saberMovementData = (SaberMovementData)noteCutInfo.saberMovementData; + var previousBladeData = saberMovementData.prevAddedData; + var currentBladeData = saberMovementData.lastAddedData; + + var previousFrameData = new InterpolationUtils.FrameData( + previousNoteMovementData.SongTime, + previousBladeData.bottomPos, + previousBladeData.topPos - previousBladeData.bottomPos, + previousNoteMovementData.NotePosition + ); + + var currentFrameData = new InterpolationUtils.FrameData( + _audioTimeSyncController.songTime, + currentBladeData.bottomPos, + currentBladeData.topPos - currentBladeData.bottomPos, + currentNotePosition + ); + + InterpolationUtils.CalculateClosestApproach(previousFrameData, currentFrameData, out var newTime, out var newDistance); + var newTimeDeviation = noteCutInfo.noteData.time - newTime; + + noteCutInfo = new NoteCutInfo( + noteCutInfo.noteData, + noteCutInfo.speedOK, + noteCutInfo.directionOK, + noteCutInfo.saberTypeOK, + noteCutInfo.wasCutTooSoon, + noteCutInfo.saberSpeed, + noteCutInfo.saberDir, + noteCutInfo.saberType, + newTimeDeviation, + noteCutInfo.cutDirDeviation, + noteCutInfo.cutPoint, + noteCutInfo.cutNormal, + noteCutInfo.cutDistanceToCenter, + noteCutInfo.cutAngle, + noteCutInfo.worldRotation, + noteCutInfo.inverseWorldRotation, + noteCutInfo.noteRotation, + noteCutInfo.notePosition, + noteCutInfo.saberMovementData + ); + } + + #endregion +} \ No newline at end of file diff --git a/BeatLeaderModifiers/Utils/HarmonyUtils.cs b/BeatLeaderModifiers/Utils/HarmonyUtils.cs new file mode 100644 index 0000000..37024d1 --- /dev/null +++ b/BeatLeaderModifiers/Utils/HarmonyUtils.cs @@ -0,0 +1,27 @@ +using System.Reflection; +using HarmonyLib; +using JetBrains.Annotations; + +namespace BeatLeaderModifiers { + internal static class HarmonyUtils { + public static void Patch(this Harmony harmony, HarmonyPatchDescriptor patchDescriptor) { + harmony.Patch(patchDescriptor.Original, patchDescriptor.Prefix, patchDescriptor.Postfix); + } + } + + internal class HarmonyPatchDescriptor { + public readonly MethodInfo Original; + [CanBeNull] public readonly HarmonyMethod Prefix; + [CanBeNull] public readonly HarmonyMethod Postfix; + + public HarmonyPatchDescriptor( + MethodInfo original, + [CanBeNull] MethodInfo prefix = null, + [CanBeNull] MethodInfo postfix = null + ) { + Original = original; + Prefix = prefix == null ? null : new HarmonyMethod(prefix); + Postfix = postfix == null ? null : new HarmonyMethod(postfix); + } + } +} \ No newline at end of file diff --git a/BeatLeaderModifiers/Utils/InterpolationUtils.cs b/BeatLeaderModifiers/Utils/InterpolationUtils.cs new file mode 100644 index 0000000..609e03c --- /dev/null +++ b/BeatLeaderModifiers/Utils/InterpolationUtils.cs @@ -0,0 +1,60 @@ +using UnityEngine; + +namespace BeatLeaderModifiers; + +public static class InterpolationUtils { + #region FrameData + + public readonly struct FrameData { + public readonly float Time; + public readonly Vector3 SaberPosition; + public readonly Vector3 SaberDirection; + public readonly Vector3 NotePosition; + + public FrameData(float time, Vector3 saberPosition, Vector3 saberDirection, Vector3 notePosition) { + Time = time; + SaberPosition = saberPosition; + SaberDirection = saberDirection; + NotePosition = notePosition; + } + + public static FrameData Lerp(FrameData a, FrameData b, float t) { + return new FrameData( + Mathf.LerpUnclamped(a.Time, b.Time, t), + Vector3.LerpUnclamped(a.SaberPosition, b.SaberPosition, t), + Vector3.LerpUnclamped(a.SaberDirection, b.SaberDirection, t).normalized, + Vector3.LerpUnclamped(a.NotePosition, b.NotePosition, t) + ); + } + } + + #endregion + + #region CalculateClosestApproach + + private const int Resolution = 200; + + public static void CalculateClosestApproach(FrameData a, FrameData b, out float time, out float distance) { + time = 0.0f; + distance = float.MaxValue; + + for (var i = 0; i <= Resolution; i++) { + var t = (float)i / (Resolution); + t = -1 + 3 * t; + + var f = FrameData.Lerp(a, b, t); + var d = GetDistance(f.SaberPosition, f.SaberDirection, f.NotePosition); + if (d >= distance) continue; + time = f.Time; + distance = d; + } + } + + private static float GetDistance(Vector3 lineFrom, Vector3 lineDirection, Vector3 point) { + var v = point - lineFrom; + var angle = Vector3.Angle(v, lineDirection) * Mathf.Deg2Rad; + return Mathf.Sin(angle) * v.magnitude; + } + + #endregion +} \ No newline at end of file From ef3dadb1be89f452597eab0a52f0b550f6e85439 Mon Sep 17 00:00:00 2001 From: Reezonate Date: Mon, 19 Dec 2022 17:38:11 +0900 Subject: [PATCH 05/12] BL Patch --- .../BeatLeaderModifiers.csproj | 1 + .../Managers/BeatLeaderInteropManager.cs | 31 +++++++++++++++++++ BeatLeaderModifiers/Plugin.cs | 1 + BeatLeaderModifiers/manifest.json | 3 ++ 4 files changed, 36 insertions(+) create mode 100644 BeatLeaderModifiers/Managers/BeatLeaderInteropManager.cs diff --git a/BeatLeaderModifiers/BeatLeaderModifiers.csproj b/BeatLeaderModifiers/BeatLeaderModifiers.csproj index 707f736..6df32c2 100644 --- a/BeatLeaderModifiers/BeatLeaderModifiers.csproj +++ b/BeatLeaderModifiers/BeatLeaderModifiers.csproj @@ -118,6 +118,7 @@ + diff --git a/BeatLeaderModifiers/Managers/BeatLeaderInteropManager.cs b/BeatLeaderModifiers/Managers/BeatLeaderInteropManager.cs new file mode 100644 index 0000000..0841e7f --- /dev/null +++ b/BeatLeaderModifiers/Managers/BeatLeaderInteropManager.cs @@ -0,0 +1,31 @@ +using System.Reflection; +using HarmonyLib; +using IPA.Loader; + +namespace BeatLeaderModifiers; + +internal static class BeatLeaderInteropManager { + private static Harmony _harmony; + + public static void ApplyPatches() { + var plugin = PluginManager.GetPluginFromId("BeatLeader"); + if (plugin == null) return; + + var assembly = plugin.Assembly; + var swingRatingEnhancerType = assembly.GetType("BeatLeader.Core.Managers.NoteEnhancer.SwingRatingEnhancer"); + + var patch = new HarmonyPatchDescriptor( + swingRatingEnhancerType.GetMethod("ChooseSwingRating", BindingFlags.Static | BindingFlags.NonPublic), + typeof(BeatLeaderInteropManager).GetMethod(nameof(ChooseSwingRating), BindingFlags.Static | BindingFlags.NonPublic) + ); + + _harmony = new Harmony(nameof(BeatLeaderInteropManager)); + _harmony.Patch(patch); + } + + private static bool ChooseSwingRating(float real, float unclamped, ref float __result) { + if (StandardLevelBlaBlaPatch.customCharacterisitic != CustomCharacterisitic.betterScoring) return true; + __result = real; + return false; + } +} \ No newline at end of file diff --git a/BeatLeaderModifiers/Plugin.cs b/BeatLeaderModifiers/Plugin.cs index 48988f6..8e363be 100644 --- a/BeatLeaderModifiers/Plugin.cs +++ b/BeatLeaderModifiers/Plugin.cs @@ -27,6 +27,7 @@ public Plugin(IPALogger logger, Zenjector zenjector) { [OnStart, UsedImplicitly] public void OnApplicationStart() { HarmonyHelper.ApplyPatches(); + BeatLeaderInteropManager.ApplyPatches(); CharacteristicsManager.RegisterCharacteristics(); } diff --git a/BeatLeaderModifiers/manifest.json b/BeatLeaderModifiers/manifest.json index b68aa24..6de97bc 100644 --- a/BeatLeaderModifiers/manifest.json +++ b/BeatLeaderModifiers/manifest.json @@ -10,5 +10,8 @@ "BSIPA": "^4.2.2", "SiraUtil": "^3.1.0" }, + "loadAfter": [ + "BeatLeader" + ], "features": [] } \ No newline at end of file From 1d67a4fc122e551d9120a6601c920e8ac2636a1d Mon Sep 17 00:00:00 2001 From: NSGolova Date: Mon, 19 Dec 2022 11:56:42 +0000 Subject: [PATCH 06/12] Added icon and count only timing rating --- .../BeatLeaderModifiers.csproj | 3 ++ .../HarmonyPatches/CutScoreBufferPatch.cs | 36 ++++++++++-------- BeatLeaderModifiers/Icons/RhythmGame.png | Bin 0 -> 5955 bytes .../Managers/CharacteristicsManager.cs | 10 ++--- .../Managers/CutInterpolationManager.cs | 3 ++ 5 files changed, 32 insertions(+), 20 deletions(-) create mode 100644 BeatLeaderModifiers/Icons/RhythmGame.png diff --git a/BeatLeaderModifiers/BeatLeaderModifiers.csproj b/BeatLeaderModifiers/BeatLeaderModifiers.csproj index 6df32c2..b434198 100644 --- a/BeatLeaderModifiers/BeatLeaderModifiers.csproj +++ b/BeatLeaderModifiers/BeatLeaderModifiers.csproj @@ -141,5 +141,8 @@ all + + + \ No newline at end of file diff --git a/BeatLeaderModifiers/HarmonyPatches/CutScoreBufferPatch.cs b/BeatLeaderModifiers/HarmonyPatches/CutScoreBufferPatch.cs index e4ea2eb..f4490a6 100644 --- a/BeatLeaderModifiers/HarmonyPatches/CutScoreBufferPatch.cs +++ b/BeatLeaderModifiers/HarmonyPatches/CutScoreBufferPatch.cs @@ -11,37 +11,43 @@ namespace BeatLeaderModifiers { [HarmonyPatch(typeof(CutScoreBuffer), "RefreshScores")] internal class CutScoreBufferPatch { - private static float beforeCutMaxScore = 40f; - private static float angleMaxScore = 30f; + //private static float beforeCutMaxScore = 40f; + //private static float angleMaxScore = 30f; - private static float goodAngle = 7.5f; - private static float badAngle = 45f; + //private static float goodAngle = 7.5f; + //private static float badAngle = 45f; - private static float badTiming = 0.1f; - private static float goodTiming = 0.02f; + private static float badTiming = 0.04f; + private static float timingOffset = 0.0f; + private static float goodTiming = 0.03f; [UsedImplicitly] private static void Prefix( + CutScoreBuffer __instance, SaberSwingRatingCounter ____saberSwingRatingCounter, int ____beforeCutScore, NoteCutInfo ____noteCutInfo) { if (StandardLevelBlaBlaPatch.customCharacterisitic == CustomCharacterisitic.betterScoring) { - int beforeCutScore = Mathf.RoundToInt(((float)____beforeCutScore / 70.0f) * beforeCutMaxScore); + //int beforeCutScore = Mathf.RoundToInt(((float)____beforeCutScore / 70.0f) * beforeCutMaxScore); - float angleRating = 1f - Mathf.Clamp01((Mathf.Abs(Mathf.Abs(____noteCutInfo.cutAngle) - 90f) - goodAngle) / badAngle); - int angleScore = Mathf.RoundToInt(angleRating * angleMaxScore); + //float angleRating = 1f - Mathf.Clamp01((Mathf.Abs(Mathf.Abs(____noteCutInfo.cutAngle) - 90f) - goodAngle) / badAngle); + //if (____noteCutInfo.noteData.cutDirection == NoteCutDirection.Any) { + // angleRating = 1f; + //} + //int angleScore = Mathf.RoundToInt(angleRating * angleMaxScore); - Plugin.Log.Debug(beforeCutScore + " " + angleScore); + //Plugin.Log.Debug(beforeCutScore + " " + angleScore); - float beforeCutScoreRating = (float)(beforeCutScore + angleScore) / 70f; - - ____saberSwingRatingCounter.SetField("_beforeCutRating", Mathf.Min(beforeCutScoreRating, 0.999f)); + //float beforeCutScoreRating = (float)(beforeCutScore + angleScore) / 70f; - float timingRating = 1.0f - Mathf.Clamp01((Mathf.Abs(____noteCutInfo.timeDeviation) - goodTiming) / badTiming); - ____saberSwingRatingCounter.SetField("_afterCutRating", Mathf.Min(timingRating, 0.999f)); + float timingRating = 1.0f - Mathf.Clamp01((Mathf.Abs(____noteCutInfo.timeDeviation - timingOffset) - goodTiming) / badTiming); + + ____saberSwingRatingCounter.SetField("_afterCutRating", timingRating); + ____saberSwingRatingCounter.SetField("_beforeCutRating", timingRating); + __instance.SetField("_centerDistanceCutScore", Mathf.RoundToInt(15f * timingRating)); Plugin.Log.Debug(timingRating + " "); } } diff --git a/BeatLeaderModifiers/Icons/RhythmGame.png b/BeatLeaderModifiers/Icons/RhythmGame.png new file mode 100644 index 0000000000000000000000000000000000000000..b8a55b4f71180fcedca958368cc577216f0a04fe GIT binary patch literal 5955 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.FirstOrDefault(it => it.name == icon); + Icon = SongCoreUtilities.LoadSpriteFromResources(icon); } } diff --git a/BeatLeaderModifiers/Managers/CutInterpolationManager.cs b/BeatLeaderModifiers/Managers/CutInterpolationManager.cs index 0312a87..7fcd83f 100644 --- a/BeatLeaderModifiers/Managers/CutInterpolationManager.cs +++ b/BeatLeaderModifiers/Managers/CutInterpolationManager.cs @@ -139,6 +139,9 @@ private void OnBeforeNoteWasCutEvent(NoteController noteController, ref NoteCutI InterpolationUtils.CalculateClosestApproach(previousFrameData, currentFrameData, out var newTime, out var newDistance); var newTimeDeviation = noteCutInfo.noteData.time - newTime; + Plugin.Log.Debug("" + noteCutInfo.timeDeviation + " " + newTimeDeviation); + Plugin.Log.Debug("" + currentNotePosition.x + " " + currentNotePosition.y + " " + currentNotePosition.z + " " + previousNoteMovementData.NotePosition.x + " " + previousNoteMovementData.NotePosition.y + " " + previousNoteMovementData.NotePosition.z); + noteCutInfo = new NoteCutInfo( noteCutInfo.noteData, noteCutInfo.speedOK, From 0a102579cab989835e1885892b68e33f51faf27a Mon Sep 17 00:00:00 2001 From: NSGolova Date: Mon, 19 Dec 2022 12:24:32 +0000 Subject: [PATCH 07/12] Lesser multipliers and fix cut distance --- BeatLeaderModifiers/HarmonyPatches/CutScoreBufferPatch.cs | 6 +++--- BeatLeaderModifiers/Managers/CutInterpolationManager.cs | 8 +++++++- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/BeatLeaderModifiers/HarmonyPatches/CutScoreBufferPatch.cs b/BeatLeaderModifiers/HarmonyPatches/CutScoreBufferPatch.cs index f4490a6..bdc1577 100644 --- a/BeatLeaderModifiers/HarmonyPatches/CutScoreBufferPatch.cs +++ b/BeatLeaderModifiers/HarmonyPatches/CutScoreBufferPatch.cs @@ -17,9 +17,9 @@ internal class CutScoreBufferPatch { //private static float goodAngle = 7.5f; //private static float badAngle = 45f; - private static float badTiming = 0.04f; + private static float badTiming = 0.05f; private static float timingOffset = 0.0f; - private static float goodTiming = 0.03f; + private static float goodTiming = 0.035f; [UsedImplicitly] private static void Prefix( @@ -47,7 +47,7 @@ private static void Prefix( ____saberSwingRatingCounter.SetField("_afterCutRating", timingRating); ____saberSwingRatingCounter.SetField("_beforeCutRating", timingRating); - __instance.SetField("_centerDistanceCutScore", Mathf.RoundToInt(15f * timingRating)); + Plugin.Log.Debug(timingRating + " "); } } diff --git a/BeatLeaderModifiers/Managers/CutInterpolationManager.cs b/BeatLeaderModifiers/Managers/CutInterpolationManager.cs index 7fcd83f..e06aa65 100644 --- a/BeatLeaderModifiers/Managers/CutInterpolationManager.cs +++ b/BeatLeaderModifiers/Managers/CutInterpolationManager.cs @@ -113,6 +113,10 @@ public NoteMovementData(float songTime, Vector3 notePosition) { #region Events + private static float badTiming = 0.05f; + private static float timingOffset = 0.0f; + private static float goodTiming = 0.035f; + private void OnBeforeNoteWasCutEvent(NoteController noteController, ref NoteCutInfo noteCutInfo) { if (!_noteMovementCache.ContainsKey(noteController)) return; var previousNoteMovementData = _noteMovementCache[noteController]; @@ -142,6 +146,8 @@ private void OnBeforeNoteWasCutEvent(NoteController noteController, ref NoteCutI Plugin.Log.Debug("" + noteCutInfo.timeDeviation + " " + newTimeDeviation); Plugin.Log.Debug("" + currentNotePosition.x + " " + currentNotePosition.y + " " + currentNotePosition.z + " " + previousNoteMovementData.NotePosition.x + " " + previousNoteMovementData.NotePosition.y + " " + previousNoteMovementData.NotePosition.z); + float timingRating = Mathf.Clamp01((Mathf.Abs(newTimeDeviation - timingOffset) - goodTiming) / badTiming); + noteCutInfo = new NoteCutInfo( noteCutInfo.noteData, noteCutInfo.speedOK, @@ -155,7 +161,7 @@ private void OnBeforeNoteWasCutEvent(NoteController noteController, ref NoteCutI noteCutInfo.cutDirDeviation, noteCutInfo.cutPoint, noteCutInfo.cutNormal, - noteCutInfo.cutDistanceToCenter, + timingRating * 3, noteCutInfo.cutAngle, noteCutInfo.worldRotation, noteCutInfo.inverseWorldRotation, From a323021924e09db6940d9e8f429be10f55449257 Mon Sep 17 00:00:00 2001 From: Reezonate Date: Mon, 19 Dec 2022 21:53:35 +0900 Subject: [PATCH 08/12] Standard only --- BeatLeaderModifiers/HarmonyPatches/SetContentPatch.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/BeatLeaderModifiers/HarmonyPatches/SetContentPatch.cs b/BeatLeaderModifiers/HarmonyPatches/SetContentPatch.cs index 90ea3e9..5389a3d 100644 --- a/BeatLeaderModifiers/HarmonyPatches/SetContentPatch.cs +++ b/BeatLeaderModifiers/HarmonyPatches/SetContentPatch.cs @@ -32,6 +32,8 @@ private static async void AddCustomCharacteristic(IBeatmapLevel level) { var difficultyBeatmapSets = new List(level.beatmapLevelData.difficultyBeatmapSets); foreach (var originalBeatmapSet in level.beatmapLevelData.difficultyBeatmapSets) { + if (originalBeatmapSet.beatmapCharacteristic.serializedName != "Standard") continue; + var beatmapSet = new CustomDifficultyBeatmapSet(characteristicSO); var customDifficulties = await CreateCustomDifficulties(originalBeatmapSet.difficultyBeatmaps, beatmapSet); beatmapSet.SetCustomDifficultyBeatmaps(customDifficulties); From ae78b67a9e433d65405c9ec5eb801f9633189a1c Mon Sep 17 00:00:00 2001 From: Reezonate Date: Mon, 19 Dec 2022 22:21:37 +0900 Subject: [PATCH 09/12] LUL --- .../Managers/CharacteristicsManager.cs | 24 +------------------ 1 file changed, 1 insertion(+), 23 deletions(-) diff --git a/BeatLeaderModifiers/Managers/CharacteristicsManager.cs b/BeatLeaderModifiers/Managers/CharacteristicsManager.cs index bb220d1..059fda6 100644 --- a/BeatLeaderModifiers/Managers/CharacteristicsManager.cs +++ b/BeatLeaderModifiers/Managers/CharacteristicsManager.cs @@ -25,35 +25,13 @@ public static void RegisterCharacteristics() { } private static void RegisterCustomCharacteristic(CharacteristicDescriptor characteristicDescriptor) { - Collections.RegisterCustomCharacteristic( + characteristicDescriptor.CharacteristicSO = Collections.RegisterCustomCharacteristic( characteristicDescriptor.Icon, characteristicDescriptor.Name, characteristicDescriptor.HintText, characteristicDescriptor.SerializedName, characteristicDescriptor.Name ); - - characteristicDescriptor.CharacteristicSO = CreateCharacteristicSO(characteristicDescriptor); - } - - #endregion - - #region CreateCharacteristicSO - - private static BeatmapCharacteristicSO CreateCharacteristicSO(CharacteristicDescriptor characteristicDescriptor) { - var beatmapCharacteristicSO = ScriptableObject.CreateInstance(); - - beatmapCharacteristicSO.SetField("_icon", characteristicDescriptor.Icon); - beatmapCharacteristicSO.SetField("_characteristicNameLocalizationKey", characteristicDescriptor.Name); - beatmapCharacteristicSO.SetField("_descriptionLocalizationKey", characteristicDescriptor.HintText); - beatmapCharacteristicSO.SetField("_serializedName", characteristicDescriptor.SerializedName); - beatmapCharacteristicSO.SetField("_compoundIdPartName", characteristicDescriptor.Name); - beatmapCharacteristicSO.SetField("_sortingOrder", 100); - beatmapCharacteristicSO.SetField("_containsRotationEvents", false); - beatmapCharacteristicSO.SetField("_requires360Movement", false); - beatmapCharacteristicSO.SetField("_numberOfColors", 2); - - return beatmapCharacteristicSO; } #endregion From b72b5133eeecb09f66d6cb4e664d7502f01b60e7 Mon Sep 17 00:00:00 2001 From: NSGolova Date: Thu, 22 Dec 2022 00:10:39 +0000 Subject: [PATCH 10/12] Scale note hitboxes --- .../BeatLeaderModifiers.csproj | 1 + .../HarmonyPatches/CutScoreBufferPatch.cs | 7 ++-- .../HarmonyPatches/NoteControllerPatch.cs | 42 +++++++++++++++++++ .../StandardLevelBlaBlaPatch.cs | 4 +- .../Managers/CutInterpolationManager.cs | 7 ++-- 5 files changed, 50 insertions(+), 11 deletions(-) create mode 100644 BeatLeaderModifiers/HarmonyPatches/NoteControllerPatch.cs diff --git a/BeatLeaderModifiers/BeatLeaderModifiers.csproj b/BeatLeaderModifiers/BeatLeaderModifiers.csproj index b434198..9ad33a3 100644 --- a/BeatLeaderModifiers/BeatLeaderModifiers.csproj +++ b/BeatLeaderModifiers/BeatLeaderModifiers.csproj @@ -113,6 +113,7 @@ + diff --git a/BeatLeaderModifiers/HarmonyPatches/CutScoreBufferPatch.cs b/BeatLeaderModifiers/HarmonyPatches/CutScoreBufferPatch.cs index bdc1577..e6e1508 100644 --- a/BeatLeaderModifiers/HarmonyPatches/CutScoreBufferPatch.cs +++ b/BeatLeaderModifiers/HarmonyPatches/CutScoreBufferPatch.cs @@ -17,9 +17,8 @@ internal class CutScoreBufferPatch { //private static float goodAngle = 7.5f; //private static float badAngle = 45f; - private static float badTiming = 0.05f; - private static float timingOffset = 0.0f; - private static float goodTiming = 0.035f; + private static float badTiming = 0.04f; + private static float goodTiming = 0.045f; [UsedImplicitly] private static void Prefix( @@ -43,7 +42,7 @@ private static void Prefix( //float beforeCutScoreRating = (float)(beforeCutScore + angleScore) / 70f; - float timingRating = 1.0f - Mathf.Clamp01((Mathf.Abs(____noteCutInfo.timeDeviation - timingOffset) - goodTiming) / badTiming); + float timingRating = 1.0f - Mathf.Clamp01((Mathf.Abs(____noteCutInfo.timeDeviation) - goodTiming) / badTiming); ____saberSwingRatingCounter.SetField("_afterCutRating", timingRating); ____saberSwingRatingCounter.SetField("_beforeCutRating", timingRating); diff --git a/BeatLeaderModifiers/HarmonyPatches/NoteControllerPatch.cs b/BeatLeaderModifiers/HarmonyPatches/NoteControllerPatch.cs new file mode 100644 index 0000000..84cff18 --- /dev/null +++ b/BeatLeaderModifiers/HarmonyPatches/NoteControllerPatch.cs @@ -0,0 +1,42 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using HarmonyLib; +using IPA.Utilities; +using JetBrains.Annotations; +using UnityEngine; + +namespace BeatLeaderModifiers { + + [HarmonyPatch(typeof(GameNoteController), "Init")] + internal class NoteControllerPatch { + private static float colliderScale = 0.58f; + + static void ScaleColider(BoxCuttableBySaber box, float value) { + var localScale = box.transform.localScale; + + localScale.x *= value; + localScale.y *= value; + localScale.z *= value; + + box.transform.localScale = localScale; + } + + [UsedImplicitly] + private static void Postfix( + BoxCuttableBySaber[] ____bigCuttableBySaberList, + BoxCuttableBySaber[] ____smallCuttableBySaberList) { + + if (StandardLevelBlaBlaPatch.customCharacterisitic == CustomCharacterisitic.betterScoring) { + foreach (var item in ____bigCuttableBySaberList) + { + ScaleColider(item, colliderScale); + } + foreach (var item in ____smallCuttableBySaberList) + { + ScaleColider(item, colliderScale); + } + } + } + } +} diff --git a/BeatLeaderModifiers/HarmonyPatches/StandardLevelBlaBlaPatch.cs b/BeatLeaderModifiers/HarmonyPatches/StandardLevelBlaBlaPatch.cs index 85730ab..ab1ea51 100644 --- a/BeatLeaderModifiers/HarmonyPatches/StandardLevelBlaBlaPatch.cs +++ b/BeatLeaderModifiers/HarmonyPatches/StandardLevelBlaBlaPatch.cs @@ -17,11 +17,9 @@ class StandardLevelBlaBlaPatch { public static CustomCharacterisitic customCharacterisitic; static void Prefix(StandardLevelScenesTransitionSetupDataSO __instance, string gameMode, IDifficultyBeatmap difficultyBeatmap, IPreviewBeatmapLevel previewBeatmapLevel, OverrideEnvironmentSettings overrideEnvironmentSettings, - ref GameplayModifiers gameplayModifiers, ColorScheme overrideColorScheme, PlayerSpecificSettings playerSpecificSettings, ref PracticeSettings practiceSettings, string backButtonText, bool useTestNoteCutSoundEffects) + GameplayModifiers gameplayModifiers, ColorScheme overrideColorScheme, PlayerSpecificSettings playerSpecificSettings, ref PracticeSettings practiceSettings, string backButtonText, bool useTestNoteCutSoundEffects) { if (difficultyBeatmap.parentDifficultyBeatmapSet.beatmapCharacteristic.serializedName == CharacteristicsManager.BetterScoringCharacteristic.SerializedName) { - gameplayModifiers = gameplayModifiers.CopyWith(proMode: true, strictAngles: true); - customCharacterisitic = CustomCharacterisitic.betterScoring; } else { customCharacterisitic = CustomCharacterisitic.standard; diff --git a/BeatLeaderModifiers/Managers/CutInterpolationManager.cs b/BeatLeaderModifiers/Managers/CutInterpolationManager.cs index e06aa65..699fe07 100644 --- a/BeatLeaderModifiers/Managers/CutInterpolationManager.cs +++ b/BeatLeaderModifiers/Managers/CutInterpolationManager.cs @@ -113,9 +113,8 @@ public NoteMovementData(float songTime, Vector3 notePosition) { #region Events - private static float badTiming = 0.05f; - private static float timingOffset = 0.0f; - private static float goodTiming = 0.035f; + private static float badTiming = 0.04f; + private static float goodTiming = 0.045f; private void OnBeforeNoteWasCutEvent(NoteController noteController, ref NoteCutInfo noteCutInfo) { if (!_noteMovementCache.ContainsKey(noteController)) return; @@ -146,7 +145,7 @@ private void OnBeforeNoteWasCutEvent(NoteController noteController, ref NoteCutI Plugin.Log.Debug("" + noteCutInfo.timeDeviation + " " + newTimeDeviation); Plugin.Log.Debug("" + currentNotePosition.x + " " + currentNotePosition.y + " " + currentNotePosition.z + " " + previousNoteMovementData.NotePosition.x + " " + previousNoteMovementData.NotePosition.y + " " + previousNoteMovementData.NotePosition.z); - float timingRating = Mathf.Clamp01((Mathf.Abs(newTimeDeviation - timingOffset) - goodTiming) / badTiming); + float timingRating = Mathf.Clamp01((Mathf.Abs(newTimeDeviation) - goodTiming) / badTiming); noteCutInfo = new NoteCutInfo( noteCutInfo.noteData, From acc49596ed9cf43bb9f7b21469360ffb15839838 Mon Sep 17 00:00:00 2001 From: NSGolova Date: Fri, 23 Dec 2022 11:51:29 +0000 Subject: [PATCH 11/12] SongCore interop for the custom data --- .../BeatLeaderModifiers.csproj | 1 + .../Managers/SongCoreInteropManager.cs | 46 +++++++++++++++++++ BeatLeaderModifiers/Plugin.cs | 1 + 3 files changed, 48 insertions(+) create mode 100644 BeatLeaderModifiers/Managers/SongCoreInteropManager.cs diff --git a/BeatLeaderModifiers/BeatLeaderModifiers.csproj b/BeatLeaderModifiers/BeatLeaderModifiers.csproj index 9ad33a3..d301e3c 100644 --- a/BeatLeaderModifiers/BeatLeaderModifiers.csproj +++ b/BeatLeaderModifiers/BeatLeaderModifiers.csproj @@ -119,6 +119,7 @@ + diff --git a/BeatLeaderModifiers/Managers/SongCoreInteropManager.cs b/BeatLeaderModifiers/Managers/SongCoreInteropManager.cs new file mode 100644 index 0000000..2f9e3d8 --- /dev/null +++ b/BeatLeaderModifiers/Managers/SongCoreInteropManager.cs @@ -0,0 +1,46 @@ +using System.Linq; +using System.Reflection; +using HarmonyLib; +using IPA.Loader; +using SongCore; +using SongCore.Data; +using SongCore.Utilities; + +namespace BeatLeaderModifiers; + +internal static class SongCoreInteropManager { + private static Harmony _harmony; + + public static void ApplyPatches() { + var plugin = PluginManager.GetPluginFromId("SongCore"); + if (plugin == null) return; + + var assembly = plugin.Assembly; + var swingRatingEnhancerType = assembly.GetType("SongCore.Collections"); + + var patch = new HarmonyPatchDescriptor( + swingRatingEnhancerType.GetMethod("RetrieveDifficultyData", BindingFlags.Static | BindingFlags.Public), + typeof(SongCoreInteropManager).GetMethod(nameof(RetrieveDifficultyData), BindingFlags.Static | BindingFlags.Public) + ); + + _harmony = new Harmony(nameof(SongCoreInteropManager)); + _harmony.Patch(patch); + } + + public static bool RetrieveDifficultyData(IDifficultyBeatmap beatmap, ref ExtraSongData.DifficultyData? __result) { + ExtraSongData? songData = null; + + if (beatmap.level is CustomPreviewBeatmapLevel customLevel) + { + songData = Collections.RetrieveExtraSongData(Hashing.GetCustomLevelHash(customLevel)); + } + + __result = songData?._difficulties.FirstOrDefault(x => + x._difficulty == beatmap.difficulty && + (x._beatmapCharacteristicName == beatmap.parentDifficultyBeatmapSet.beatmapCharacteristic.characteristicNameLocalizationKey || + x._beatmapCharacteristicName == beatmap.parentDifficultyBeatmapSet.beatmapCharacteristic.serializedName || + (x._beatmapCharacteristicName == "Standard" && beatmap.parentDifficultyBeatmapSet.beatmapCharacteristic.serializedName == CharacteristicsManager.BetterScoringCharacteristic.SerializedName))); + + return false; + } +} \ No newline at end of file diff --git a/BeatLeaderModifiers/Plugin.cs b/BeatLeaderModifiers/Plugin.cs index 8e363be..041de76 100644 --- a/BeatLeaderModifiers/Plugin.cs +++ b/BeatLeaderModifiers/Plugin.cs @@ -28,6 +28,7 @@ public Plugin(IPALogger logger, Zenjector zenjector) { public void OnApplicationStart() { HarmonyHelper.ApplyPatches(); BeatLeaderInteropManager.ApplyPatches(); + SongCoreInteropManager.ApplyPatches(); CharacteristicsManager.RegisterCharacteristics(); } From 56b81ce36b6ee69531d9ae954107f4c3290012b4 Mon Sep 17 00:00:00 2001 From: NSGolova Date: Fri, 23 Dec 2022 18:48:46 +0000 Subject: [PATCH 12/12] Hide custom mode in Multiplayer --- BeatLeaderModifiers/HarmonyPatches/SetContentPatch.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BeatLeaderModifiers/HarmonyPatches/SetContentPatch.cs b/BeatLeaderModifiers/HarmonyPatches/SetContentPatch.cs index 5389a3d..66d80ae 100644 --- a/BeatLeaderModifiers/HarmonyPatches/SetContentPatch.cs +++ b/BeatLeaderModifiers/HarmonyPatches/SetContentPatch.cs @@ -12,7 +12,7 @@ internal class SetContentPatch { [UsedImplicitly] private static void Prefix(IBeatmapLevel level) { - if (!level.levelID.StartsWith("custom_level")) return; + if (!level.levelID.StartsWith("custom_level") || !(level.beatmapLevelData is BeatmapLevelData)) return; if (level.beatmapLevelData.difficultyBeatmapSets.Any(x => x.beatmapCharacteristic.serializedName.Equals(CharacteristicsManager.BetterScoringCharacteristic.SerializedName))) {