11using System . Reflection ;
22using System . Runtime . CompilerServices ;
33using System . Runtime . InteropServices ;
4- using System . Text . Json . Nodes ;
4+ using CustomAlbums . Data ;
55using CustomAlbums . Managers ;
66using CustomAlbums . Utilities ;
77using HarmonyLib ;
1313using Il2CppAssets . Scripts . PeroTools . Commons ;
1414using Il2CppAssets . Scripts . PeroTools . Platforms . Steam ;
1515using Il2CppAssets . Scripts . Structs ;
16- using Il2CppAssets . Scripts . UI . Panels ;
1716using Il2CppInterop . Common ;
1817using Il2CppPeroPeroGames . DataStatistics ;
1918using MelonLoader . NativeUtils ;
@@ -53,7 +52,7 @@ internal static class SavePatch
5352 /// <param name="panel">The PnlRecord instance to set.</param>
5453 /// <param name="data">The custom chart data.</param>
5554 /// <param name="isFullCombo">If the selected chart has been FCed.</param>
56- private static void SetPanelWithData ( PnlRecord panel , JsonNode data , bool isFullCombo )
55+ private static void SetPanelWithData ( PnlRecord panel , CustomChartSave data , bool isFullCombo )
5756 {
5857 // Enables the FC icon if chart has been FCed
5958 // Also sets the combo text to a gold color if it has been FCed
@@ -64,13 +63,13 @@ private static void SetPanelWithData(PnlRecord panel, JsonNode data, bool isFull
6463 }
6564
6665 // Sets all the PnlRecord data to custom chart data.
67- var evaluate = data [ "Evaluate" ] ! . GetValue < int > ( ) ;
68- panel . txtAccuracy . text = data [ "AccuracyStr" ] ! . GetValue < string > ( ) ;
69- panel . txtClear . text = data [ "Clear" ] ! . GetValue < float > ( ) . ToStringInvariant ( ) ;
70- panel . txtCombo . text = data [ "Combo" ] ! . GetValue < int > ( ) . ToStringInvariant ( ) ;
66+ var evaluate = data . Evaluate ;
67+ panel . txtAccuracy . text = data . AccuracyStr ;
68+ panel . txtClear . text = data . Clear . ToStringInvariant ( ) ;
69+ panel . txtCombo . text = data . Combo . ToStringInvariant ( ) ;
7170 panel . txtGrade . text = EvalToGrade [ evaluate ] ;
7271 panel . txtGrade . color = panel . gradeColor [ evaluate ] ;
73- panel . txtScore . text = data [ "Score" ] ! . GetValue < int > ( ) . ToStringInvariant ( ) ;
72+ panel . txtScore . text = data . Score . ToStringInvariant ( ) ;
7473 }
7574
7675 /// <summary>
@@ -114,37 +113,30 @@ private static bool InjectPnlPreparation(PnlPreparation __instance, bool forceRe
114113 {
115114 var currentMusicInfo = GlobalDataBase . s_DbMusicTag . CurMusicInfo ( ) ;
116115
117- // If the chart is not custom, run the original method, otherwise continue and don't run the original method
116+ // If the chart is not custom, run the original method; otherwise, run our modified one
118117 if ( currentMusicInfo . albumJsonIndex != AlbumManager . Uid + 1 ) return true ;
119118
120119 // Reset the panel to its default
121120 ClearAndRefreshPanels ( __instance , forceReload ) ;
122121 __instance . designerLongNameController ? . Refresh ( ) ;
122+
123123 if ( ! ModSettings . SavingEnabled ) return false ;
124124
125125 var recordPanel = __instance . pnlRecord ;
126126 var currentChartData = SaveData . GetChartSaveDataFromUid ( currentMusicInfo . uid ) ;
127- var highestExists = currentChartData . TryGetPropertyValue ( "Highest" , out var currentChartHighest ) ;
128127
129128 // If no highest data exists then early return
130- if ( ! highestExists || currentChartHighest is null )
129+ if ( ( currentChartData . Highest ? . Count ?? 0 ) == 0 )
131130 {
132131 Logger . Msg ( $ "No save data found for { currentMusicInfo . uid } , nothing to inject") ;
133132 return false ;
134133 }
135134
136135 var difficulty = GetDifficulty ( currentMusicInfo . uid ) ;
137136
138- currentChartData . TryGetPropertyValue ( "FullCombo" , out var currentChartFullCombo ) ;
139-
140- // LINQ query to see if difficulty is in the full combo list
141- // If currentChartFullCombo is null then there is no full combo so isFullCombo is false
142- var isFullCombo = currentChartFullCombo ? . AsArray ( ) . Any ( x => ( int ) x == difficulty ) ?? false ;
143-
144- // Get the highest score for the difficulty that is selected
145- currentChartHighest = currentChartHighest [ difficulty . ToString ( ) ] ;
137+ var isFullCombo = currentChartData . FullCombo ? . Contains ( difficulty ) ?? false ;
138+ var currentChartHighest = currentChartData . Highest . GetValueOrDefault ( difficulty ) ;
146139
147- // If the current chart has no data for the selected difficulty then early return
148140 if ( currentChartHighest is null )
149141 {
150142 Logger . Msg ( $ "Save data was found for the chart, but not for difficulty { difficulty } ") ;
@@ -210,7 +202,6 @@ private static void CleanCustomData()
210202
211203 if ( ModSettings . SavingEnabled ) SaveData . SelectedAlbum = AlbumManager . GetAlbumNameFromUid ( DataHelper . selectedMusicUidFromInfoList ) ;
212204 DataHelper . selectedMusicUidFromInfoList = "0-0" ;
213- DataHelper . unlockMasters . RemoveAll ( ( Il2CppSystem . Predicate < string > ) ( uid => uid . StartsWith ( $ "{ AlbumManager . Uid } -") ) ) ;
214205 }
215206
216207 private static void InjectCustomData ( )
@@ -220,30 +211,44 @@ private static void InjectCustomData()
220211 DataHelper . hides . AddManagedRange ( SaveData . Hides . GetAlbumUidsFromNames ( ) ) ;
221212 DataHelper . history . AddManagedRange ( SaveData . History . GetAlbumUidsFromNames ( ) ) ;
222213 DataHelper . collections . AddManagedRange ( SaveData . Collections . GetAlbumUidsFromNames ( ) ) ;
223- DataHelper . unlockMasters . AddManagedRange ( SaveData . UnlockedMasters . GetAlbumUidsFromNames ( ) ) ;
224214
225215 if ( ! SaveData . SelectedAlbum . StartsWith ( "album_" ) ) return ;
226216 DataHelper . selectedAlbumUid = "music_package_999" ;
227217 DataHelper . selectedAlbumTagIndex = 999 ;
228218 DataHelper . selectedMusicUidFromInfoList = AlbumManager . LoadedAlbums . TryGetValue ( SaveData . SelectedAlbum , out var album ) ? album . Uid : "0-0" ;
229219 }
230220
231- // Dumb hack that fixes the chart appearing locked on game start even if it is unlocked
232- [ HarmonyPatch ( typeof ( PnlStage ) , nameof ( PnlStage . Start ) ) ]
233- internal class StartPatch
221+ [ HarmonyPatch ( typeof ( DataHelper ) , nameof ( DataHelper . CheckMusicUnlockMaster ) ) ]
222+ internal class CheckUnlockMasterPatch
234223 {
235- private static void Postfix ( PnlStage __instance )
224+ private static bool Prefix ( MusicInfo musicInfo , ref bool __result )
236225 {
237- var uid = DataHelper . selectedMusicUid ;
238- if ( ! DataHelper . selectedMusicUid ? . StartsWith ( $ "{ AlbumManager . Uid } -") ?? true ) return ;
226+ SaveData . Ability = Math . Max ( SaveData . Ability , GlobalDataBase . dbUi . ability ) ;
227+ var ability = GameAccountSystem . instance . IsLoggedIn ( ) ? SaveData . Ability : 0 ;
228+ var uid = musicInfo ? . uid ;
239229
240- var album = AlbumManager . GetByUid ( uid ) ;
230+ // If musicInfo or uid is null, run original
231+ if ( uid is null ) return true ;
241232
242- if ( album == null || ( ! DataHelper . isUnlockAllMaster && ! SaveData . UnlockedMasters . Contains ( album ! . AlbumName ) ) ) return ;
233+ // Bugged vanilla state, do manual logic
234+ if ( GlobalDataBase . dbUi . ability == 0 && ability != 0 )
235+ {
236+ Logger . Msg ( "Fixing bugged vanilla state for master lock" ) ;
237+ var vanillaParse = Formatting . TryParseAsInt ( musicInfo . difficulty3 , out var difficulty ) ;
238+ var cond = ! vanillaParse || ability >= difficulty ;
239+ __result = cond || DataHelper . unlockMasters . Contains ( uid ) || SaveData . UnlockedMasters . Contains ( AlbumManager . GetAlbumNameFromUid ( uid ) ) || ( ! AlbumManager . GetByUid ( musicInfo . uid ) ? . IsPackaged ?? false ) ;
240+ return false ;
241+ }
243242
244- __instance . difficulty3Lock . SetActive ( false ) ;
245- __instance . difficulty3Master . SetActive ( true ) ;
246- __instance . difficulty3 . enabled = true ;
243+ // Non-bugged vanilla case
244+ if ( ! uid . StartsWith ( $ "{ AlbumManager . Uid } -") ) return true ;
245+
246+ // Non-bugged custom case
247+ var successParse = Formatting . TryParseAsInt ( musicInfo . difficulty3 , out var diffNum ) ;
248+ var abilityConditionOrGimmick = ! successParse || ability >= diffNum ;
249+
250+ __result = abilityConditionOrGimmick || SaveData . UnlockedMasters . Contains ( AlbumManager . GetAlbumNameFromUid ( uid ) ) || ! AlbumManager . GetByUid ( musicInfo . uid ) . IsPackaged ;
251+ return false ;
247252 }
248253 }
249254
@@ -395,24 +400,6 @@ private static void Postfix(string musicUid, int musicDifficulty, string charact
395400 }
396401 }
397402
398- /// <summary>
399- /// Stops the game from sending analytics of custom charts.
400- /// </summary>
401- [ HarmonyPatch ( typeof ( ThinkingDataBattleHelper ) ) ]
402- internal class SendMDPatch
403- {
404- private static MethodInfo[ ] TargetMethods ( )
405- {
406- return typeof ( ThinkingDataBattleHelper ) . GetMethods ( BindingFlags . Instance | BindingFlags . Public )
407- . Where ( method => method . Name . StartsWith ( "Send" ) ) . ToArray ( ) ;
408- }
409-
410- private static bool Prefix( )
411- {
412- return ! BattleHelper. MusicInfo ( ) . uid . StartsWith ( $ "{ AlbumManager . Uid } -") ;
413- }
414- }
415-
416403 /// <summary>
417404 /// Enables the PnlVictory screen logic when the chart is custom.
418405 /// </summary>
0 commit comments