From 178389ea0bd00bb7d1822abaff2aa3524f3f3f61 Mon Sep 17 00:00:00 2001
From: EliteMasterEric <ericmyllyoja@gmail.com>
Date: Thu, 12 Sep 2024 23:28:43 -0400
Subject: [PATCH 01/22] Fix two song credits

---
 assets | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/assets b/assets
index bc7009b42..c3041be56 160000
--- a/assets
+++ b/assets
@@ -1 +1 @@
-Subproject commit bc7009b4242691faa5c4552f7ca8a2f28e8cb1d2
+Subproject commit c3041be56396cda92f87d071f74d36113ed25e1f

From 3fba55a4229139de0f64925f2bfc77ce1f689b0f Mon Sep 17 00:00:00 2001
From: FabsTheFabs <flamingkitty24@gmail.com>
Date: Fri, 13 Sep 2024 21:36:20 +0100
Subject: [PATCH 02/22] assets submod

---
 assets | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/assets b/assets
index 8762fd51c..eaab81b1a 160000
--- a/assets
+++ b/assets
@@ -1 +1 @@
-Subproject commit 8762fd51c26abdc9a45657eab9018aa48e972cd6
+Subproject commit eaab81b1a76d18f356cf0a38f3feed463aed28cb

From 517984d1200f0fe43a7a7bec4bd62cd6032a8997 Mon Sep 17 00:00:00 2001
From: EliteMasterEric <ericmyllyoja@gmail.com>
Date: Fri, 13 Sep 2024 18:46:49 -0400
Subject: [PATCH 03/22] Fix a bug where Shit judgement would always display
 with anti-aliasing.

---
 source/funkin/play/notes/notestyle/NoteStyle.hx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/source/funkin/play/notes/notestyle/NoteStyle.hx b/source/funkin/play/notes/notestyle/NoteStyle.hx
index ee07703f1..83aae6fcf 100644
--- a/source/funkin/play/notes/notestyle/NoteStyle.hx
+++ b/source/funkin/play/notes/notestyle/NoteStyle.hx
@@ -575,7 +575,7 @@ class NoteStyle implements IRegistryEntry<NoteStyleData>
         var result = _data.assets.judgementBad?.isPixel;
         if (result == null && fallback != null) result = fallback.isJudgementSpritePixel(rating);
         return result ?? false;
-      case "GO":
+      case "shit":
         var result = _data.assets.judgementShit?.isPixel;
         if (result == null && fallback != null) result = fallback.isJudgementSpritePixel(rating);
         return result ?? false;

From df87d677e1b155049bc254904a965989b53fa160 Mon Sep 17 00:00:00 2001
From: EliteMasterEric <ericmyllyoja@gmail.com>
Date: Sat, 14 Sep 2024 17:00:41 -0400
Subject: [PATCH 04/22] Typo lol

---
 source/funkin/modding/PolymodHandler.hx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/source/funkin/modding/PolymodHandler.hx b/source/funkin/modding/PolymodHandler.hx
index 75c69e506..e0b27e744 100644
--- a/source/funkin/modding/PolymodHandler.hx
+++ b/source/funkin/modding/PolymodHandler.hx
@@ -258,7 +258,7 @@ class PolymodHandler
     Polymod.blacklistImport('cpp.Lib');
 
     // `Unserializer`
-    // Unserializerr.DEFAULT_RESOLVER.resolveClass() can access blacklisted packages
+    // Unserializer.DEFAULT_RESOLVER.resolveClass() can access blacklisted packages
     Polymod.blacklistImport('Unserializer');
 
     // `lime.system.CFFI`

From 688abb557134d6b786628c206db126cfcba6d579 Mon Sep 17 00:00:00 2001
From: EliteMasterEric <ericmyllyoja@gmail.com>
Date: Sat, 14 Sep 2024 20:25:45 -0400
Subject: [PATCH 05/22] Update example mod's API version so it actually loads.

---
 example_mods/introMod/_polymod_meta.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/example_mods/introMod/_polymod_meta.json b/example_mods/introMod/_polymod_meta.json
index 4dc0cd804..74c4a2504 100644
--- a/example_mods/introMod/_polymod_meta.json
+++ b/example_mods/introMod/_polymod_meta.json
@@ -6,7 +6,7 @@
       "name": "EliteMasterEric"
     }
   ],
-  "api_version": "0.1.0",
+  "api_version": "0.5.0",
   "mod_version": "1.0.0",
   "license": "Apache-2.0"
 }

From d5c7e4ffdb0076d1c54ee9e9703fb0a3a682fd96 Mon Sep 17 00:00:00 2001
From: EliteMasterEric <ericmyllyoja@gmail.com>
Date: Sat, 14 Sep 2024 20:26:19 -0400
Subject: [PATCH 06/22] Fix bug where Pico would become locked on every game
 restart.

---
 source/funkin/save/Save.hx                 | 20 +++++++---
 source/funkin/save/changelog.md            |  6 +++
 source/funkin/ui/mainmenu/MainMenuState.hx | 43 ++++++++++++----------
 source/funkin/ui/title/TitleState.hx       |  5 ---
 4 files changed, 43 insertions(+), 31 deletions(-)

diff --git a/source/funkin/save/Save.hx b/source/funkin/save/Save.hx
index 2bbda15c0..eb9f6005e 100644
--- a/source/funkin/save/Save.hx
+++ b/source/funkin/save/Save.hx
@@ -17,7 +17,7 @@ import thx.semver.Version;
 @:nullSafety
 class Save
 {
-  public static final SAVE_DATA_VERSION:thx.semver.Version = "2.0.5";
+  public static final SAVE_DATA_VERSION:thx.semver.Version = "2.0.4";
   public static final SAVE_DATA_VERSION_RULE:thx.semver.VersionRule = "2.0.x";
 
   // We load this version's saves from a new save path, to maintain SOME level of backwards compatibility.
@@ -34,19 +34,19 @@ class Save
   {
     if (_instance == null)
     {
-      _instance = new Save(FlxG.save.data);
+      return _instance = load();
     }
     return _instance;
   }
 
   var data:RawSaveData;
 
-  public static function load():Void
+  public static function load():Save
   {
     trace("[SAVE] Loading save...");
 
     // Bind save data.
-    loadFromSlot(1);
+    return loadFromSlot(1);
   }
 
   /**
@@ -65,7 +65,9 @@ class Save
   public static function getDefault():RawSaveData
   {
     return {
-      version: Save.SAVE_DATA_VERSION,
+      // Version number is an abstract(Array) internally.
+      // This means it copies by reference, so merging save data overides the version number lol.
+      version: thx.Dynamics.clone(Save.SAVE_DATA_VERSION),
 
       volume: 1.0,
       mute: false,
@@ -433,7 +435,9 @@ class Save
   {
     if (!data.unlocks.charactersSeen.contains(character))
     {
+      trace('Character seen: ' + character);
       data.unlocks.charactersSeen.push(character);
+      trace('New characters seen list: ' + data.unlocks.charactersSeen);
       flush();
     }
   }
@@ -832,7 +836,7 @@ class Save
    * If you set slot to `2`, it will load an independe
    * @param slot
    */
-  static function loadFromSlot(slot:Int):Void
+  static function loadFromSlot(slot:Int):Save
   {
     trace("[SAVE] Loading save from slot " + slot + "...");
 
@@ -850,12 +854,14 @@ class Save
         trace('[SAVE] Found legacy save data, converting...');
         var gameSave = SaveDataMigrator.migrateFromLegacy(legacySaveData);
         FlxG.save.mergeData(gameSave.data, true);
+        return gameSave;
       }
       else
       {
         trace('[SAVE] No legacy save data found.');
         var gameSave = new Save();
         FlxG.save.mergeData(gameSave.data, true);
+        return gameSave;
       }
     }
     else
@@ -863,6 +869,8 @@ class Save
       trace('[SAVE] Found existing save data.');
       var gameSave = SaveDataMigrator.migrate(FlxG.save.data);
       FlxG.save.mergeData(gameSave.data, true);
+
+      return gameSave;
     }
   }
 
diff --git a/source/funkin/save/changelog.md b/source/funkin/save/changelog.md
index e3038373d..41d6e68ae 100644
--- a/source/funkin/save/changelog.md
+++ b/source/funkin/save/changelog.md
@@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file.
 The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
 and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
 
+## [2.0.4] - 2024-09-12
+Note to self: Only update to 2.1.0 when migration is needed.
+### Added
+- `unlocks.charactersSeen:Array<String>` to `Save`
+- `unlocks.oldChar:Bool` to `Save`
+
 ## [2.0.5] - 2024-05-21
 ### Fixed
 - Resolved an issue where HTML5 wouldn't store the semantic version properly, causing the game to fail to load the save.
diff --git a/source/funkin/ui/mainmenu/MainMenuState.hx b/source/funkin/ui/mainmenu/MainMenuState.hx
index 13d68da6d..a436848d2 100644
--- a/source/funkin/ui/mainmenu/MainMenuState.hx
+++ b/source/funkin/ui/mainmenu/MainMenuState.hx
@@ -356,7 +356,7 @@ class MainMenuState extends MusicBeatState
     #if FEATURE_DEBUG_FUNCTIONS
     // Ctrl+Alt+Shift+P = Character Unlock screen
     // Ctrl+Alt+Shift+W = Meet requirements for Pico Unlock
-    // Ctrl+Alt+Shift+L = Revoke requirements for Pico Unlock
+    // Ctrl+Alt+Shift+M = Revoke requirements for Pico Unlock
     // Ctrl+Alt+Shift+R = Score/Rank conflict test
     // Ctrl+Alt+Shift+N = Mark all characters as not seen
     // Ctrl+Alt+Shift+E = Dump save data
@@ -369,7 +369,7 @@ class MainMenuState extends MusicBeatState
     if (FlxG.keys.pressed.CONTROL && FlxG.keys.pressed.ALT && FlxG.keys.pressed.SHIFT && FlxG.keys.justPressed.W)
     {
       FunkinSound.playOnce(Paths.sound('confirmMenu'));
-      // Give the user a score of 1 point on Weekend 1 story mode.
+      // Give the user a score of 1 point on Weekend 1 story mode (Easy difficulty).
       // This makes the level count as cleared and displays the songs in Freeplay.
       funkin.save.Save.instance.setLevelScore('weekend1', 'easy',
         {
@@ -389,27 +389,30 @@ class MainMenuState extends MusicBeatState
         });
     }
 
-    if (FlxG.keys.pressed.CONTROL && FlxG.keys.pressed.ALT && FlxG.keys.pressed.SHIFT && FlxG.keys.justPressed.L)
+    if (FlxG.keys.pressed.CONTROL && FlxG.keys.pressed.ALT && FlxG.keys.pressed.SHIFT && FlxG.keys.justPressed.M)
     {
       FunkinSound.playOnce(Paths.sound('confirmMenu'));
-      // Give the user a score of 0 points on Weekend 1 story mode.
+      // Give the user a score of 0 points on Weekend 1 story mode (all difficulties).
       // This makes the level count as uncleared and no longer displays the songs in Freeplay.
-      funkin.save.Save.instance.setLevelScore('weekend1', 'easy',
-        {
-          score: 1,
-          tallies:
-            {
-              sick: 0,
-              good: 0,
-              bad: 0,
-              shit: 0,
-              missed: 0,
-              combo: 0,
-              maxCombo: 0,
-              totalNotesHit: 0,
-              totalNotes: 0,
-            }
-        });
+      for (diff in ['easy', 'normal', 'hard'])
+      {
+        funkin.save.Save.instance.setLevelScore('weekend1', diff,
+          {
+            score: 0,
+            tallies:
+              {
+                sick: 0,
+                good: 0,
+                bad: 0,
+                shit: 0,
+                missed: 0,
+                combo: 0,
+                maxCombo: 0,
+                totalNotesHit: 0,
+                totalNotes: 0,
+              }
+          });
+      }
     }
 
     if (FlxG.keys.pressed.CONTROL && FlxG.keys.pressed.ALT && FlxG.keys.pressed.SHIFT && FlxG.keys.justPressed.R)
diff --git a/source/funkin/ui/title/TitleState.hx b/source/funkin/ui/title/TitleState.hx
index f5c641d0c..10e7dfaae 100644
--- a/source/funkin/ui/title/TitleState.hx
+++ b/source/funkin/ui/title/TitleState.hx
@@ -273,11 +273,6 @@ class TitleState extends MusicBeatState
     }
     #end
 
-    if (Save.instance.charactersSeen.contains("pico"))
-    {
-      Save.instance.charactersSeen.remove("pico");
-      Save.instance.oldChar = false;
-    }
     Conductor.instance.update();
 
     /* if (FlxG.onMobile)

From fd6ca6e267d5ffbbb63f9e01e7ca92935a6785f4 Mon Sep 17 00:00:00 2001
From: EliteMasterEric <ericmyllyoja@gmail.com>
Date: Sat, 14 Sep 2024 20:26:33 -0400
Subject: [PATCH 07/22] Remove some spammy log traces.

---
 source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx | 2 +-
 source/funkin/ui/charSelect/CharSelectPlayer.hx       | 1 -
 2 files changed, 1 insertion(+), 2 deletions(-)

diff --git a/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx b/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx
index 952fa8b71..7ea97e39b 100644
--- a/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx
+++ b/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx
@@ -184,7 +184,7 @@ class FlxAtlasSprite extends FlxAnimate
 
     // Move to the first frame of the animation.
     // goToFrameLabel(id);
-    trace('Playing animation $id');
+    // trace('Playing animation $id');
     if ((id == null || id == "") || this.anim.symbolDictionary.exists(id) || (this.anim.getByName(id) != null))
     {
       this.anim.play(id, restart, false, startFrame);
diff --git a/source/funkin/ui/charSelect/CharSelectPlayer.hx b/source/funkin/ui/charSelect/CharSelectPlayer.hx
index b6319f16d..1eef52bed 100644
--- a/source/funkin/ui/charSelect/CharSelectPlayer.hx
+++ b/source/funkin/ui/charSelect/CharSelectPlayer.hx
@@ -47,7 +47,6 @@ class CharSelectPlayer extends FlxAtlasSprite implements IBPMSyncedScriptedClass
     //
     if (getCurrentAnimation() == "idle")
     {
-      trace('Player beat hit');
       playAnimation("idle", true, false, false);
     }
   };

From e23a85682a89c049c41cd0b67e434fcce6cc0b29 Mon Sep 17 00:00:00 2001
From: EliteMasterEric <ericmyllyoja@gmail.com>
Date: Sat, 14 Sep 2024 20:26:39 -0400
Subject: [PATCH 08/22] Update some script files.

---
 assets | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/assets b/assets
index bc7009b42..616551146 160000
--- a/assets
+++ b/assets
@@ -1 +1 @@
-Subproject commit bc7009b4242691faa5c4552f7ca8a2f28e8cb1d2
+Subproject commit 61655114603807b651109af282c2e2aefa9dccf2

From 9f3af1ab944d41ba56edc7336b6b795fdae89c32 Mon Sep 17 00:00:00 2001
From: EliteMasterEric <ericmyllyoja@gmail.com>
Date: Sat, 14 Sep 2024 20:56:21 -0400
Subject: [PATCH 09/22] Add a separate Gold Perfect animation for modders

---
 assets                                                    | 2 +-
 source/funkin/data/freeplay/player/PlayerData.hx          | 1 +
 source/funkin/ui/freeplay/charselect/PlayableCharacter.hx | 4 +++-
 source/funkin/util/Constants.hx                           | 4 ----
 4 files changed, 5 insertions(+), 6 deletions(-)

diff --git a/assets b/assets
index bc7009b42..ef7386d74 160000
--- a/assets
+++ b/assets
@@ -1 +1 @@
-Subproject commit bc7009b4242691faa5c4552f7ca8a2f28e8cb1d2
+Subproject commit ef7386d741e715bd809c913a7d50dfa7b8176e2d
diff --git a/source/funkin/data/freeplay/player/PlayerData.hx b/source/funkin/data/freeplay/player/PlayerData.hx
index de293c24e..867fe7113 100644
--- a/source/funkin/data/freeplay/player/PlayerData.hx
+++ b/source/funkin/data/freeplay/player/PlayerData.hx
@@ -270,6 +270,7 @@ typedef PlayerResultsData =
 {
   var music:PlayerResultsMusicData;
 
+  var perfectGold:Array<PlayerResultsAnimationData>;
   var perfect:Array<PlayerResultsAnimationData>;
   var excellent:Array<PlayerResultsAnimationData>;
   var great:Array<PlayerResultsAnimationData>;
diff --git a/source/funkin/ui/freeplay/charselect/PlayableCharacter.hx b/source/funkin/ui/freeplay/charselect/PlayableCharacter.hx
index 93d643ae4..408a91672 100644
--- a/source/funkin/ui/freeplay/charselect/PlayableCharacter.hx
+++ b/source/funkin/ui/freeplay/charselect/PlayableCharacter.hx
@@ -113,7 +113,9 @@ class PlayableCharacter implements IRegistryEntry<PlayerData>
 
     switch (rank)
     {
-      case PERFECT | PERFECT_GOLD:
+      case PERFECT_GOLD:
+        return _data.results.perfectGold;
+      case PERFECT:
         return _data.results.perfect;
       case EXCELLENT:
         return _data.results.excellent;
diff --git a/source/funkin/util/Constants.hx b/source/funkin/util/Constants.hx
index 57fc484b8..cf58d191a 100644
--- a/source/funkin/util/Constants.hx
+++ b/source/funkin/util/Constants.hx
@@ -481,10 +481,6 @@ class Constants
   public static final JUDGEMENT_BAD_COMBO_BREAK:Bool = true;
   public static final JUDGEMENT_SHIT_COMBO_BREAK:Bool = true;
 
-  // % Sick
-  public static final RANK_PERFECT_PLAT_THRESHOLD:Float = 1.0; // % Sick
-  public static final RANK_PERFECT_GOLD_THRESHOLD:Float = 0.85; // % Sick
-
   // % Hit
   public static final RANK_PERFECT_THRESHOLD:Float = 1.00;
   public static final RANK_EXCELLENT_THRESHOLD:Float = 0.90;

From 16aff6e7c35152c4b3fd86ec73fc798b75847016 Mon Sep 17 00:00:00 2001
From: EliteMasterEric <ericmyllyoja@gmail.com>
Date: Sat, 14 Sep 2024 21:37:02 -0400
Subject: [PATCH 10/22] Fix bugs with highscore display in Freeplay

---
 source/funkin/ui/freeplay/FreeplayState.hx | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx
index af0a9b841..15633ff9d 100644
--- a/source/funkin/ui/freeplay/FreeplayState.hx
+++ b/source/funkin/ui/freeplay/FreeplayState.hx
@@ -586,13 +586,13 @@ class FreeplayState extends MusicBeatSubState
       }
     };
 
-    exitMovers.set([fp, txtCompletion, fnfHighscoreSpr, txtCompletion, clearBoxSprite],
+    exitMovers.set([fp, txtCompletion, fnfHighscoreSpr, clearBoxSprite],
       {
         x: FlxG.width,
         speed: 0.3
       });
 
-    exitMoversCharSel.set([fp, txtCompletion, fnfHighscoreSpr, txtCompletion, clearBoxSprite],
+    exitMoversCharSel.set([fp, txtCompletion, fnfHighscoreSpr, clearBoxSprite],
       {
         y: -270,
         speed: 0.8,
@@ -1376,7 +1376,7 @@ class FreeplayState extends MusicBeatSubState
     #if FEATURE_DEBUG_FUNCTIONS
     if (FlxG.keys.justPressed.P)
     {
-      FlxG.switchState(FreeplayState.build(
+      FlxG.switchState(() -> FreeplayState.build(
         {
           {
             character: currentCharacterId == "pico" ? Constants.DEFAULT_CHARACTER : "pico",
@@ -1777,12 +1777,13 @@ class FreeplayState extends MusicBeatSubState
         FlxG.log.warn('WARN: could not find song with id (${daSong.songId})');
         return;
       }
-      var targetVariation:String = targetSong.getFirstValidVariation(currentDifficulty) ?? '';
+      var targetVariation:String = targetSong.getFirstValidVariation(currentDifficulty, currentCharacter) ?? '';
 
       // TODO: This line of code makes me sad, but you can't really fix it without a breaking migration.
       var suffixedDifficulty = (targetVariation != Constants.DEFAULT_VARIATION
         && targetVariation != 'erect') ? '$currentDifficulty-${targetVariation}' : currentDifficulty;
       var songScore:Null<SaveScoreData> = Save.instance.getSongScore(daSong.songId, suffixedDifficulty);
+      trace(songScore);
       intendedScore = songScore?.score ?? 0;
       intendedCompletion = songScore == null ? 0.0 : ((songScore.tallies.sick + songScore.tallies.good) / songScore.tallies.totalNotes);
       rememberedDifficulty = suffixedDifficulty;

From 367e3e90083f95a13a5b4e76339f2d4eac534203 Mon Sep 17 00:00:00 2001
From: Cameron Taylor <cameron.taylor.ninja@gmail.com>
Date: Mon, 16 Sep 2024 17:18:42 -0400
Subject: [PATCH 11/22] priv modules

---
 .gitmodules | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/.gitmodules b/.gitmodules
index be5e0aaa8..ad8099e60 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,6 +1,6 @@
 [submodule "assets"]
 	path = assets
-	url = https://github.com/FunkinCrew/funkin.assets
+	url = https://github.com/FunkinCrew/Funkin-assets-secret
 [submodule "art"]
 	path = art
-	url = https://github.com/FunkinCrew/funkin.art
+	url = https://github.com/FunkinCrew/Funkin-art-secret

From 535ac0e5283ecd83866907920cac52444fcd0e9c Mon Sep 17 00:00:00 2001
From: Kade <26305836+Kade-github@users.noreply.github.com>
Date: Mon, 16 Sep 2024 15:25:13 -0700
Subject: [PATCH 12/22] add milliseconds to the playbar in charting state

remove laggy redundant traces

Revert "remove laggy redundant traces"

This reverts commit 204113840473dd5069f5d508d50e15e21104b45a.
---
 source/funkin/ui/debug/charting/ChartEditorState.hx | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx
index 811e08e5d..f778b11f3 100644
--- a/source/funkin/ui/debug/charting/ChartEditorState.hx
+++ b/source/funkin/ui/debug/charting/ChartEditorState.hx
@@ -5139,10 +5139,11 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
     }
 
     var songPos:Float = Conductor.instance.songPosition + Conductor.instance.instrumentalOffset;
+    var songPosMilliseconds:String = Std.string(Math.floor(Math.abs(songPos) % 1000)).lpad('0', 2);
     var songPosSeconds:String = Std.string(Math.floor((Math.abs(songPos) / 1000) % 60)).lpad('0', 2);
     var songPosMinutes:String = Std.string(Math.floor((Math.abs(songPos) / 1000) / 60)).lpad('0', 2);
     if (songPos < 0) songPosMinutes = '-' + songPosMinutes;
-    var songPosString:String = '${songPosMinutes}:${songPosSeconds}';
+    var songPosString:String = '${songPosMinutes}:${songPosSeconds}:${songPosMilliseconds}';
 
     if (playbarSongPos.value != songPosString) playbarSongPos.value = songPosString;
 

From 5a877a14a0d468d0592be6edfaa21b05dc8b3ebf Mon Sep 17 00:00:00 2001
From: Kade <26305836+Kade-github@users.noreply.github.com>
Date: Mon, 16 Sep 2024 15:39:56 -0700
Subject: [PATCH 13/22] only show last two digits

digit
---
 source/funkin/ui/debug/charting/ChartEditorState.hx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx
index f778b11f3..024de8ec6 100644
--- a/source/funkin/ui/debug/charting/ChartEditorState.hx
+++ b/source/funkin/ui/debug/charting/ChartEditorState.hx
@@ -5139,7 +5139,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
     }
 
     var songPos:Float = Conductor.instance.songPosition + Conductor.instance.instrumentalOffset;
-    var songPosMilliseconds:String = Std.string(Math.floor(Math.abs(songPos) % 1000)).lpad('0', 2);
+    var songPosMilliseconds:String = Std.string(Math.floor(Math.abs(songPos) % 1000)).lpad('0', 2).substr(0, 2);
     var songPosSeconds:String = Std.string(Math.floor((Math.abs(songPos) / 1000) % 60)).lpad('0', 2);
     var songPosMinutes:String = Std.string(Math.floor((Math.abs(songPos) / 1000) / 60)).lpad('0', 2);
     if (songPos < 0) songPosMinutes = '-' + songPosMinutes;

From 7d2b946e9c1f885af6ccc9a937ed5af4774d9599 Mon Sep 17 00:00:00 2001
From: Kade <26305836+Kade-github@users.noreply.github.com>
Date: Mon, 16 Sep 2024 16:42:53 -0700
Subject: [PATCH 14/22] depreciated screen X/Y to view X/Y

---
 .../ui/debug/charting/ChartEditorState.hx     | 58 +++++++++----------
 1 file changed, 29 insertions(+), 29 deletions(-)

diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx
index 024de8ec6..c0c2e6309 100644
--- a/source/funkin/ui/debug/charting/ChartEditorState.hx
+++ b/source/funkin/ui/debug/charting/ChartEditorState.hx
@@ -700,7 +700,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
 
   function get_isCursorOverHaxeUI():Bool
   {
-    return Screen.instance.hasSolidComponentUnderPoint(FlxG.mouse.screenX, FlxG.mouse.screenY);
+    return Screen.instance.hasSolidComponentUnderPoint(FlxG.mouse.viewX, FlxG.mouse.viewY);
   }
 
   /**
@@ -3830,7 +3830,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
   function handleScrollKeybinds():Void
   {
     // Don't scroll when the user is interacting with the UI, unless a playbar button (the << >> ones) is pressed.
-    if ((isHaxeUIFocused || isCursorOverHaxeUI) && playbarButtonPressed == null) return;
+    if ((isHaxeUIFocused || isHaxeUIDialogOpen) && playbarButtonPressed == null) return;
 
     var scrollAmount:Float = 0; // Amount to scroll the grid.
     var playheadAmount:Float = 0; // Amount to scroll the playhead relative to the grid.
@@ -3840,7 +3840,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
     // Handle scroll anchor
     if (scrollAnchorScreenPos != null)
     {
-      var currentScreenPos = new FlxPoint(FlxG.mouse.screenX, FlxG.mouse.screenY);
+      var currentScreenPos = new FlxPoint(FlxG.mouse.viewX, FlxG.mouse.viewX);
       var distance = currentScreenPos - scrollAnchorScreenPos;
 
       var verticalDistance = distance.y;
@@ -4121,8 +4121,8 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
       var overlapsRenderedEvents:Bool = FlxG.mouse.overlaps(renderedEvents);
 
       // Cursor position relative to the grid.
-      var cursorX:Float = FlxG.mouse.screenX - gridTiledSprite.x;
-      var cursorY:Float = FlxG.mouse.screenY - gridTiledSprite.y;
+      var cursorX:Float = FlxG.mouse.viewX - gridTiledSprite.x;
+      var cursorY:Float = FlxG.mouse.viewY - gridTiledSprite.y;
 
       var overlapsSelectionBorder:Bool = overlapsGrid
         && ((cursorX % 40) < (GRID_SELECTION_BORDER_WIDTH / 2)
@@ -4137,7 +4137,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
       {
         if (scrollAnchorScreenPos == null)
         {
-          scrollAnchorScreenPos = new FlxPoint(FlxG.mouse.screenX, FlxG.mouse.screenY);
+          scrollAnchorScreenPos = new FlxPoint(FlxG.mouse.viewX, FlxG.mouse.viewY);
           selectionBoxStartPos = null;
         }
         else
@@ -4159,11 +4159,11 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
         else if (notePreview != null && FlxG.mouse.overlaps(notePreview) && !isCursorOverHaxeUI)
         {
           // Clicked note preview
-          notePreviewScrollAreaStartPos = new FlxPoint(FlxG.mouse.screenX, FlxG.mouse.screenY);
+          notePreviewScrollAreaStartPos = new FlxPoint(FlxG.mouse.viewX, FlxG.mouse.viewY);
         }
         else if (!isCursorOverHaxeUI && (!overlapsGrid || overlapsSelectionBorder))
         {
-          selectionBoxStartPos = new FlxPoint(FlxG.mouse.screenX, FlxG.mouse.screenY);
+          selectionBoxStartPos = new FlxPoint(FlxG.mouse.viewX, FlxG.mouse.viewY);
           // Drawing selection box.
           targetCursorMode = Crosshair;
         }
@@ -4188,7 +4188,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
       {
         // Clicked on the playhead scroll area.
         // Move the playhead to the cursor position.
-        this.playheadPositionInPixels = FlxG.mouse.screenY - (GRID_INITIAL_Y_POS);
+        this.playheadPositionInPixels = FlxG.mouse.viewY - (GRID_INITIAL_Y_POS);
         moveSongToScrollPosition();
 
         // Cursor should be a grabby hand.
@@ -4313,27 +4313,27 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
             // Clicking and dragging.
 
             // Scroll the screen if the mouse is above or below the grid.
-            if (FlxG.mouse.screenY < MENU_BAR_HEIGHT)
+            if (FlxG.mouse.viewY < MENU_BAR_HEIGHT)
             {
               // Scroll up.
-              var diff:Float = MENU_BAR_HEIGHT - FlxG.mouse.screenY;
+              var diff:Float = MENU_BAR_HEIGHT - FlxG.mouse.viewY;
               scrollPositionInPixels -= diff * 0.5; // Too fast!
               moveSongToScrollPosition();
             }
-            else if (FlxG.mouse.screenY > (playbarHeadLayout?.y ?? 0.0))
+            else if (FlxG.mouse.viewY > (playbarHeadLayout?.y ?? 0.0))
             {
               // Scroll down.
-              var diff:Float = FlxG.mouse.screenY - (playbarHeadLayout?.y ?? 0.0);
+              var diff:Float = FlxG.mouse.viewY - (playbarHeadLayout?.y ?? 0.0);
               scrollPositionInPixels += diff * 0.5; // Too fast!
               moveSongToScrollPosition();
             }
 
             // Render the selection box.
             var selectionRect:FlxRect = new FlxRect();
-            selectionRect.x = Math.min(FlxG.mouse.screenX, selectionBoxStartPos.x);
-            selectionRect.y = Math.min(FlxG.mouse.screenY, selectionBoxStartPos.y);
-            selectionRect.width = Math.abs(FlxG.mouse.screenX - selectionBoxStartPos.x);
-            selectionRect.height = Math.abs(FlxG.mouse.screenY - selectionBoxStartPos.y);
+            selectionRect.x = Math.min(FlxG.mouse.viewX, selectionBoxStartPos.x);
+            selectionRect.y = Math.min(FlxG.mouse.viewY, selectionBoxStartPos.y);
+            selectionRect.width = Math.abs(FlxG.mouse.viewX - selectionBoxStartPos.x);
+            selectionRect.height = Math.abs(FlxG.mouse.viewY - selectionBoxStartPos.y);
             setSelectionBoxBounds(selectionRect);
 
             targetCursorMode = Crosshair;
@@ -4461,8 +4461,8 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
         // Player is clicking and holding on note preview to scrub around.
         targetCursorMode = Grabbing;
 
-        var clickedPosInPixels:Float = FlxMath.remapToRange(FlxG.mouse.screenY, (notePreview?.y ?? 0.0),
-          (notePreview?.y ?? 0.0) + (notePreview?.height ?? 0.0), 0, songLengthInPixels);
+        var clickedPosInPixels:Float = FlxMath.remapToRange(FlxG.mouse.viewY, (notePreview?.y ?? 0.0), (notePreview?.y ?? 0.0) + (notePreview?.height ?? 0.0),
+          0, songLengthInPixels);
 
         scrollPositionInPixels = clickedPosInPixels;
         moveSongToScrollPosition();
@@ -4520,17 +4520,17 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
           targetCursorMode = Grabbing;
 
           // Scroll the screen if the mouse is above or below the grid.
-          if (FlxG.mouse.screenY < MENU_BAR_HEIGHT)
+          if (FlxG.mouse.viewY < MENU_BAR_HEIGHT)
           {
             // Scroll up.
-            var diff:Float = MENU_BAR_HEIGHT - FlxG.mouse.screenY;
+            var diff:Float = MENU_BAR_HEIGHT - FlxG.mouse.viewY;
             scrollPositionInPixels -= diff * 0.5; // Too fast!
             moveSongToScrollPosition();
           }
-          else if (FlxG.mouse.screenY > (playbarHeadLayout?.y ?? 0.0))
+          else if (FlxG.mouse.viewY > (playbarHeadLayout?.y ?? 0.0))
           {
             // Scroll down.
-            var diff:Float = FlxG.mouse.screenY - (playbarHeadLayout?.y ?? 0.0);
+            var diff:Float = FlxG.mouse.viewY - (playbarHeadLayout?.y ?? 0.0);
             scrollPositionInPixels += diff * 0.5; // Too fast!
             moveSongToScrollPosition();
           }
@@ -4811,11 +4811,11 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
               // Show the context menu connected to the note.
               if (useSingleNoteContextMenu)
               {
-                this.openNoteContextMenu(FlxG.mouse.screenX, FlxG.mouse.screenY, highlightedNote.noteData);
+                this.openNoteContextMenu(FlxG.mouse.viewX, FlxG.mouse.viewY, highlightedNote.noteData);
               }
               else
               {
-                this.openSelectionContextMenu(FlxG.mouse.screenX, FlxG.mouse.screenY);
+                this.openSelectionContextMenu(FlxG.mouse.viewX, FlxG.mouse.viewY);
               }
             }
             else
@@ -4835,11 +4835,11 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
                 || (isHighlightedEventSelected && currentEventSelection.length == 1);
               if (useSingleEventContextMenu)
               {
-                this.openEventContextMenu(FlxG.mouse.screenX, FlxG.mouse.screenY, highlightedEvent.eventData);
+                this.openEventContextMenu(FlxG.mouse.viewX, FlxG.mouse.viewY, highlightedEvent.eventData);
               }
               else
               {
-                this.openSelectionContextMenu(FlxG.mouse.screenX, FlxG.mouse.screenY);
+                this.openSelectionContextMenu(FlxG.mouse.viewX, FlxG.mouse.viewY);
               }
             }
             else
@@ -4860,11 +4860,11 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
               // Show the context menu connected to the note.
               if (useSingleNoteContextMenu)
               {
-                this.openHoldNoteContextMenu(FlxG.mouse.screenX, FlxG.mouse.screenY, highlightedHoldNote.noteData);
+                this.openHoldNoteContextMenu(FlxG.mouse.viewX, FlxG.mouse.viewY, highlightedHoldNote.noteData);
               }
               else
               {
-                this.openSelectionContextMenu(FlxG.mouse.screenX, FlxG.mouse.screenY);
+                this.openSelectionContextMenu(FlxG.mouse.viewX, FlxG.mouse.viewY);
               }
             }
             else

From 9624b57e4447925a3f7764ffae8442585221bde3 Mon Sep 17 00:00:00 2001
From: Kade <26305836+Kade-github@users.noreply.github.com>
Date: Mon, 16 Sep 2024 17:23:49 -0700
Subject: [PATCH 15/22] This does fix it now

---
 source/funkin/ui/debug/charting/ChartEditorState.hx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx
index c0c2e6309..922138a10 100644
--- a/source/funkin/ui/debug/charting/ChartEditorState.hx
+++ b/source/funkin/ui/debug/charting/ChartEditorState.hx
@@ -3830,7 +3830,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
   function handleScrollKeybinds():Void
   {
     // Don't scroll when the user is interacting with the UI, unless a playbar button (the << >> ones) is pressed.
-    if ((isHaxeUIFocused || isHaxeUIDialogOpen) && playbarButtonPressed == null) return;
+    if ((isHaxeUIFocused || isCursorOverHaxeUI) && playbarButtonPressed == null) return;
 
     var scrollAmount:Float = 0; // Amount to scroll the grid.
     var playheadAmount:Float = 0; // Amount to scroll the playhead relative to the grid.

From d710318830c73d333fdaf347c8250169dc856857 Mon Sep 17 00:00:00 2001
From: EliteMasterEric <ericmyllyoja@gmail.com>
Date: Mon, 16 Sep 2024 21:54:24 -0400
Subject: [PATCH 16/22] Update HaxeUI

---
 hmm.json | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/hmm.json b/hmm.json
index d967a69b3..edc0529aa 100644
--- a/hmm.json
+++ b/hmm.json
@@ -77,14 +77,14 @@
       "name": "haxeui-core",
       "type": "git",
       "dir": null,
-      "ref": "22f7c5a8ffca90d4677cffd6e570f53761709fbc",
+      "ref": "c9d96b168ea2a19274ad7c766ab1a34b57baa793",
       "url": "https://github.com/haxeui/haxeui-core"
     },
     {
       "name": "haxeui-flixel",
       "type": "git",
       "dir": null,
-      "ref": "28bb710d0ae5d94b5108787593052165be43b980",
+      "ref": "013b9d4e56bfe9a034e028a8d685f0b274cb73c4",
       "url": "https://github.com/haxeui/haxeui-flixel"
     },
     {

From 811caf6b704674ffd0c9dd31ed6be5f8575c1b1f Mon Sep 17 00:00:00 2001
From: EliteMasterEric <ericmyllyoja@gmail.com>
Date: Mon, 16 Sep 2024 21:54:33 -0400
Subject: [PATCH 17/22] Suppress a spammy log trace

---
 source/funkin/ui/debug/charting/ChartEditorState.hx | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx
index 922138a10..2e259d3f5 100644
--- a/source/funkin/ui/debug/charting/ChartEditorState.hx
+++ b/source/funkin/ui/debug/charting/ChartEditorState.hx
@@ -5615,7 +5615,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
     }
     else
     {
-      trace('Ignoring keybinds for View menu items because we are in live input mode (${currentLiveInputStyle}).');
+      // trace('Ignoring keybinds for View menu items because we are in live input mode (${currentLiveInputStyle}).');
     }
   }
 

From d54dc6179a305d05d33ebb360410076dcf03a566 Mon Sep 17 00:00:00 2001
From: EliteMasterEric <ericmyllyoja@gmail.com>
Date: Wed, 18 Sep 2024 06:02:13 -0400
Subject: [PATCH 18/22] Add several new Github Actions for issue management

---
 .github/label-actions.yml                     | 23 ++++++++
 .github/workflows/label-actions.yml           | 29 +++++++++++
 .github/workflows/label-issue.yml             | 52 +++++++++++++++++++
 .../{labeler.yml => label-pull-request.yml}   |  2 +
 4 files changed, 106 insertions(+)
 create mode 100644 .github/label-actions.yml
 create mode 100644 .github/workflows/label-actions.yml
 create mode 100644 .github/workflows/label-issue.yml
 rename .github/workflows/{labeler.yml => label-pull-request.yml} (84%)

diff --git a/.github/label-actions.yml b/.github/label-actions.yml
new file mode 100644
index 000000000..00fb390aa
--- /dev/null
+++ b/.github/label-actions.yml
@@ -0,0 +1,23 @@
+# Configuration for Label Actions - https://github.com/dessant/label-actions
+
+# Automatically close issues and pull requests when the `status: duplicate` label is applied
+'status: duplicate':
+  issues:
+    # Post a comment
+    comment: >
+      This issue is a duplicate. Please direct all discussion to the original issue.
+    # Close the issue
+    close: true
+    # Remove other status labels
+    unlabel:
+      - 'status: pending triage'
+    # Set a close reason
+    close-reason: 'not planned'
+  prs:
+    # Post a comment
+    comment: >
+      This pull request is a duplicate. Please direct all discussion to the original pull request.
+    # Close the pull request
+    close: true
+    # Set a close reason
+    close-reason: 'not planned'
diff --git a/.github/workflows/label-actions.yml b/.github/workflows/label-actions.yml
new file mode 100644
index 000000000..bc4cf0add
--- /dev/null
+++ b/.github/workflows/label-actions.yml
@@ -0,0 +1,29 @@
+# Perform actions when labels are applied to issues, discussions, or pull requests
+# See .github/label-actions.yml
+name: 'Label Actions'
+
+on:
+  issues:
+    types:
+      - labeled
+      - unlabeled
+  pull_request_target:
+    types:
+      - labeled
+      - unlabeled
+  discussion:
+    types:
+      - labeled
+      - unlabeled
+
+permissions:
+  contents: read
+  issues: write
+  pull-requests: write
+  discussions: write
+
+jobs:
+  action:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: dessant/label-actions@v4
diff --git a/.github/workflows/label-issue.yml b/.github/workflows/label-issue.yml
new file mode 100644
index 000000000..eeb83350c
--- /dev/null
+++ b/.github/workflows/label-issue.yml
@@ -0,0 +1,52 @@
+name: "Issue Labeler"
+on:
+  issues:
+    types:
+      - opened
+      - reopened
+      - edited
+
+jobs:
+  # When an issue is opened, perform a similarity check for potential duplicates.
+  # If some are found, add a label and comment listing the potential duplicate issues.
+  potential-duplicate:
+    name: Detect potential duplicate issues
+    runs-on: ubuntu-latest
+    steps:
+      - uses: wow-actions/potential-duplicates@v1
+        with:
+          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+          # Issue title filter work with anymatch https://www.npmjs.com/package/anymatch.
+          # Any matched issue will stop detection immediately.
+          # You can specify multi filters in each line.
+          filter: ''
+          # Exclude keywords in title before detecting.
+          exclude: ''
+          # Label to set, when potential duplicates are detected.
+          label: 'potential duplicate'
+          # Get issues with state to compare. Supported state: 'all', 'closed', 'open'.
+          state: all
+          # If similarity is higher than this threshold([0,1]), issue will be marked as duplicate.
+          # Turn this up if the detection is too sensitive
+          threshold: 0.6
+          # Reactions to be add to comment when potential duplicates are detected.
+          # Available reactions: "-1", "+1", "confused", "laugh", "heart", "hooray", "rocket", "eyes"
+          # reactions: '-1'
+          # Comment to post when potential duplicates are detected.
+          comment: >
+            Potential duplicates: {{#issues}}
+              - [#{{ number }}] {{ title }} ({{ accuracy }}%)
+            {{/issues}}
+  # When an issue is opened, detect if it has an empty body or incomplete issue form.
+  # If it does, close the issue immediately.
+  empty-issues:
+    name: Close empty issues
+    runs-on: ubuntu-latest
+    steps:
+    - name: Run empty issues closer action
+      uses: rickstaa/empty-issues-closer-action@v1
+      env:
+        github_token: ${{ secrets.GITHUB_TOKEN }}
+      with:
+        close_comment: Closing this issue because it appears to be empty. Please update the issue for it to be reopened.
+        open_comment: Reopening this issue because the author provided more information.
diff --git a/.github/workflows/labeler.yml b/.github/workflows/label-pull-request.yml
similarity index 84%
rename from .github/workflows/labeler.yml
rename to .github/workflows/label-pull-request.yml
index a861af578..525e1b5a6 100644
--- a/.github/workflows/labeler.yml
+++ b/.github/workflows/label-pull-request.yml
@@ -3,6 +3,7 @@ on:
 - pull_request_target
 
 jobs:
+  # Apply labels to pull requests based on which files were edited
   labeler:
     permissions:
       contents: read
@@ -13,6 +14,7 @@ jobs:
       uses: actions/labeler@v5
       with:
         sync-labels: true
+  # Apply labels to pull requests based on how many lines were edited
   changed-lines-count-labeler:
     permissions:
       contents: read

From ba90a6abe04b15058a9c32a0ba1dd5338605c57a Mon Sep 17 00:00:00 2001
From: EliteMasterEric <ericmyllyoja@gmail.com>
Date: Wed, 18 Sep 2024 06:08:18 -0400
Subject: [PATCH 19/22] Add behavior when setting status: rejected

---
 .github/label-actions.yml | 21 +++++++++++++++++++++
 1 file changed, 21 insertions(+)

diff --git a/.github/label-actions.yml b/.github/label-actions.yml
index 00fb390aa..1234d1526 100644
--- a/.github/label-actions.yml
+++ b/.github/label-actions.yml
@@ -17,7 +17,28 @@
     # Post a comment
     comment: >
       This pull request is a duplicate. Please direct all discussion to the original pull request.
+    # Remove other status labels
+    unlabel:
+      - 'status: pending triage'
     # Close the pull request
     close: true
     # Set a close reason
     close-reason: 'not planned'
+
+'status: rejected':
+  issues:
+    # Close the issue
+    close: true
+    # Remove other status labels
+    unlabel:
+      - 'status: pending triage'
+    # Set a close reason
+    close-reason: 'not planned'
+  prs:
+    # Close the pull request
+    close: true
+    # Remove other status labels
+    unlabel:
+      - 'status: pending triage'
+    # Set a close reason
+    close-reason: 'not planned'

From ab3b976f3c979d04e713b47de607335a58917db7 Mon Sep 17 00:00:00 2001
From: Cameron Taylor <cameron.taylor.ninja@gmail.com>
Date: Wed, 18 Sep 2024 15:07:15 -0400
Subject: [PATCH 20/22] fix rounding for sound results sfx

---
 source/funkin/play/ResultState.hx | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/source/funkin/play/ResultState.hx b/source/funkin/play/ResultState.hx
index 739df167d..33f3587ea 100644
--- a/source/funkin/play/ResultState.hx
+++ b/source/funkin/play/ResultState.hx
@@ -472,9 +472,12 @@ class ResultState extends MusicBeatSubState
       {
         ease: FlxEase.quartOut,
         onUpdate: _ -> {
+          clearPercentLerp = Math.round(clearPercentLerp);
+          clearPercentCounter.curNumber = Math.round(clearPercentCounter.curNumber);
           // Only play the tick sound if the number increased.
           if (clearPercentLerp != clearPercentCounter.curNumber)
           {
+            trace('$clearPercentLerp and ${clearPercentCounter.curNumber}');
             clearPercentLerp = clearPercentCounter.curNumber;
             FunkinSound.playOnce(Paths.sound('scrollMenu'));
           }

From 62149aea39687fc84f79e7a7ce4edf636cef416e Mon Sep 17 00:00:00 2001
From: Cameron Taylor <cameron.taylor.ninja@gmail.com>
Date: Wed, 18 Sep 2024 15:16:56 -0400
Subject: [PATCH 21/22] assets submod

---
 assets | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/assets b/assets
index 616551146..da96dc519 160000
--- a/assets
+++ b/assets
@@ -1 +1 @@
-Subproject commit 61655114603807b651109af282c2e2aefa9dccf2
+Subproject commit da96dc519a00bb8eb24a164bae64a4c6c064e87d

From fc6e194d20968d010c5d4c22511cd8fd400d9058 Mon Sep 17 00:00:00 2001
From: Cameron Taylor <cameron.taylor.ninja@gmail.com>
Date: Wed, 18 Sep 2024 15:20:15 -0400
Subject: [PATCH 22/22] assets submod

---
 assets | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/assets b/assets
index ef7386d74..252d48f4c 160000
--- a/assets
+++ b/assets
@@ -1 +1 @@
-Subproject commit ef7386d741e715bd809c913a7d50dfa7b8176e2d
+Subproject commit 252d48f4c996d5832cb981fb2f3ed945c020f289