From d1622040b6fd4b03f54087439839789d31b46980 Mon Sep 17 00:00:00 2001
From: EliteMasterEric <ericmyllyoja@gmail.com>
Date: Wed, 11 Sep 2024 04:22:33 -0400
Subject: [PATCH 01/41] Fix a bug where vocals would restart after a song ends

---
 source/funkin/audio/FunkinSound.hx | 8 ++++++++
 source/funkin/audio/SoundGroup.hx  | 5 +++++
 2 files changed, 13 insertions(+)

diff --git a/source/funkin/audio/FunkinSound.hx b/source/funkin/audio/FunkinSound.hx
index b33126998..2f891a1e7 100644
--- a/source/funkin/audio/FunkinSound.hx
+++ b/source/funkin/audio/FunkinSound.hx
@@ -567,6 +567,14 @@ class FunkinSound extends FlxSound implements ICloneable<FunkinSound>
 
     return sound;
   }
+
+  /**
+   * Produces a string representation suitable for debugging.
+   */
+  public function toString():String
+  {
+    return 'FunkinSound(${this._label})';
+  }
 }
 
 /**
diff --git a/source/funkin/audio/SoundGroup.hx b/source/funkin/audio/SoundGroup.hx
index 5fc2abe0e..5d53fedd6 100644
--- a/source/funkin/audio/SoundGroup.hx
+++ b/source/funkin/audio/SoundGroup.hx
@@ -113,6 +113,11 @@ class SoundGroup extends FlxTypedGroup<FunkinSound>
   public function play(forceRestart:Bool = false, startTime:Float = 0.0, ?endTime:Float)
   {
     forEachAlive(function(sound:FunkinSound) {
+      if (sound.length < startTime)
+      {
+        // trace('Queuing sound (${sound.toString()} past its length! Skipping...)');
+        return;
+      }
       sound.play(forceRestart, startTime, endTime);
     });
   }

From c63feaafbd07c376359492d4dabbbc01f0d2c9a6 Mon Sep 17 00:00:00 2001
From: EliteMasterEric <ericmyllyoja@gmail.com>
Date: Wed, 11 Sep 2024 06:00:06 -0400
Subject: [PATCH 02/41] BF force plays the unlock animation even when he would
 fist pump

---
 source/funkin/ui/freeplay/FreeplayDJ.hx | 35 +++++++++++++++++++++++++
 1 file changed, 35 insertions(+)

diff --git a/source/funkin/ui/freeplay/FreeplayDJ.hx b/source/funkin/ui/freeplay/FreeplayDJ.hx
index 51829d44d..3d9ffd4d6 100644
--- a/source/funkin/ui/freeplay/FreeplayDJ.hx
+++ b/source/funkin/ui/freeplay/FreeplayDJ.hx
@@ -375,6 +375,13 @@ class FreeplayDJ extends FlxAtlasSprite
 
   public function confirm():Void
   {
+    // We really don't want to play anything but the new character animation here.
+    if (PlayerRegistry.instance.hasNewCharacter())
+    {
+      currentState = NewUnlock;
+      return;
+    }
+
     currentState = Confirm;
   }
 
@@ -397,6 +404,13 @@ class FreeplayDJ extends FlxAtlasSprite
 
   public function fistPumpIntro():Void
   {
+    // We really don't want to play anything but the new character animation here.
+    if (PlayerRegistry.instance.hasNewCharacter())
+    {
+      currentState = NewUnlock;
+      return;
+    }
+
     currentState = FistPumpIntro;
     var animPrefix = playableCharData.getAnimationPrefix('fistPump');
     playFlashAnimation(animPrefix, true, false, false, playableCharData.getFistPumpIntroStartFrame());
@@ -404,6 +418,13 @@ class FreeplayDJ extends FlxAtlasSprite
 
   public function fistPump():Void
   {
+    // We really don't want to play anything but the new character animation here.
+    if (PlayerRegistry.instance.hasNewCharacter())
+    {
+      currentState = NewUnlock;
+      return;
+    }
+
     currentState = FistPump;
     var animPrefix = playableCharData.getAnimationPrefix('fistPump');
     playFlashAnimation(animPrefix, true, false, false, playableCharData.getFistPumpLoopStartFrame());
@@ -411,6 +432,13 @@ class FreeplayDJ extends FlxAtlasSprite
 
   public function fistPumpLossIntro():Void
   {
+    // We really don't want to play anything but the new character animation here.
+    if (PlayerRegistry.instance.hasNewCharacter())
+    {
+      currentState = NewUnlock;
+      return;
+    }
+
     currentState = FistPumpIntro;
     var animPrefix = playableCharData.getAnimationPrefix('loss');
     playFlashAnimation(animPrefix, true, false, false, playableCharData.getFistPumpIntroBadStartFrame());
@@ -418,6 +446,13 @@ class FreeplayDJ extends FlxAtlasSprite
 
   public function fistPumpLoss():Void
   {
+    // We really don't want to play anything but the new character animation here.
+    if (PlayerRegistry.instance.hasNewCharacter())
+    {
+      currentState = NewUnlock;
+      return;
+    }
+
     currentState = FistPump;
     var animPrefix = playableCharData.getAnimationPrefix('loss');
     playFlashAnimation(animPrefix, true, false, false, playableCharData.getFistPumpLoopBadStartFrame());

From 0956b692d7d61eb76e97c2a0c69cc9c4a9cb5164 Mon Sep 17 00:00:00 2001
From: EliteMasterEric <ericmyllyoja@gmail.com>
Date: Wed, 11 Sep 2024 06:18:16 -0400
Subject: [PATCH 03/41] Add a debug hotkey to set characters as not seen.

---
 source/funkin/audio/FunkinSound.hx         | 2 +-
 source/funkin/ui/mainmenu/MainMenuState.hx | 7 +++++++
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/source/funkin/audio/FunkinSound.hx b/source/funkin/audio/FunkinSound.hx
index 2f891a1e7..18a0b4da2 100644
--- a/source/funkin/audio/FunkinSound.hx
+++ b/source/funkin/audio/FunkinSound.hx
@@ -571,7 +571,7 @@ class FunkinSound extends FlxSound implements ICloneable<FunkinSound>
   /**
    * Produces a string representation suitable for debugging.
    */
-  public function toString():String
+  public override function toString():String
   {
     return 'FunkinSound(${this._label})';
   }
diff --git a/source/funkin/ui/mainmenu/MainMenuState.hx b/source/funkin/ui/mainmenu/MainMenuState.hx
index 19dc0d687..4e416abeb 100644
--- a/source/funkin/ui/mainmenu/MainMenuState.hx
+++ b/source/funkin/ui/mainmenu/MainMenuState.hx
@@ -358,6 +358,7 @@ class MainMenuState extends MusicBeatState
     // Ctrl+Alt+Shift+W = Meet requirements for Pico Unlock
     // Ctrl+Alt+Shift+L = 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
 
     if (FlxG.keys.pressed.CONTROL && FlxG.keys.pressed.ALT && FlxG.keys.pressed.SHIFT && FlxG.keys.justPressed.P)
@@ -433,6 +434,12 @@ class MainMenuState extends MusicBeatState
         });
     }
 
+    if (FlxG.keys.pressed.CONTROL && FlxG.keys.pressed.ALT && FlxG.keys.pressed.SHIFT && FlxG.keys.justPressed.N)
+    {
+      @:privateAccess
+      funkin.save.Save.instance.data.unlocks.charactersSeen = ["bf"];
+    }
+
     if (FlxG.keys.pressed.CONTROL && FlxG.keys.pressed.ALT && FlxG.keys.pressed.SHIFT && FlxG.keys.justPressed.E)
     {
       funkin.save.Save.instance.debug_dumpSave();

From 94856a6c32667e89eb2c840f204258396ce11949 Mon Sep 17 00:00:00 2001
From: EliteMasterEric <ericmyllyoja@gmail.com>
Date: Wed, 11 Sep 2024 06:18:31 -0400
Subject: [PATCH 04/41] Fix a bug where you could select Pico inst on erect
 difficulty

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

diff --git a/assets b/assets
index 638a44fdd..5822338a5 160000
--- a/assets
+++ b/assets
@@ -1 +1 @@
-Subproject commit 638a44fdd7635814db89e96bdfdc9a9be54b39c9
+Subproject commit 5822338a50cafbb277a91d949681baea2627fa80

From c3fcc707f1db976d34e1f2bb4a0e0c05b6c4865e Mon Sep 17 00:00:00 2001
From: EliteMasterEric <ericmyllyoja@gmail.com>
Date: Wed, 11 Sep 2024 06:52:46 -0400
Subject: [PATCH 05/41] Update compilation guide

---
 docs/COMPILING.md | 22 +++++++++++++++++++---
 1 file changed, 19 insertions(+), 3 deletions(-)

diff --git a/docs/COMPILING.md b/docs/COMPILING.md
index 628eb13cc..01bcaf78a 100644
--- a/docs/COMPILING.md
+++ b/docs/COMPILING.md
@@ -14,7 +14,7 @@
 5. Run `haxelib --global install hmm` and then `haxelib --global run hmm setup` to install hmm.json
 6. Run `hmm install` to install all haxelibs of the current branch
 7. Run `haxelib run lime setup` to set up lime
-8. Platform setup
+8. Perform additional platform setup
    - For Windows, download the [Visual Studio Build Tools](https://aka.ms/vs/17/release/vs_BuildTools.exe)
         - When prompted, select "Individual Components" and make sure to download the following:
         - MSVC v143 VS 2022 C++ x64/x86 build tools
@@ -22,8 +22,24 @@
     - Mac: [`lime setup mac` Documentation](https://lime.openfl.org/docs/advanced-setup/macos/)
     - Linux: [`lime setup linux` Documentation](https://lime.openfl.org/docs/advanced-setup/linux/)
     - HTML5: Compiles without any extra setup
-9. If you are targeting for native, you may need to run `lime rebuild PLATFORM` and `lime rebuild PLATFORM -debug`
-10. `lime test PLATFORM` ! Add `-debug` to enable several debug features such as time travel (`PgUp`/`PgDn` in Play State).
+9. If you are targeting for native, you may need to run `lime rebuild <PLATFORM>` and `lime rebuild <PLATFORM> -debug`
+10. `lime test <PLATFORM>` to build and launch the game for your platform (for example, `lime test windows`)
+
+## Build Flags
+
+There are several useful build flags you can add to a build to affect how it works. A full list can be found in `project.hxp`, but here's information on some of them:
+
+- `-debug` to build the game in debug mode. This automatically enables several useful debug features.
+    - This includes enabling in-game debug functions, disables compile-time optimizations, enabling asset redirection (see below), and enabling the VSCode debug server (which can slow the game on some machines but allows for powerful debugging through breakpoints).
+    - `-DGITHUB_BUILD` will enable in-game debug functions (such as the ability to time travel in a song by pressing `PgUp`/`PgDn`), without enabling the other stuff
+- `-DFEATURE_POLYMOD_MODS` or `-DNO_FEATURE_POLYMOD_MODS` to forcibly enable or disable modding support.
+- `-DREDIRECT_ASSETS_FOLDER` or `-DNO_REDIRECT_ASSETS_FOLDER` to forcibly enable or disable asset redirection.
+    - This feature causes the game to load exported assets from the project's assets folder rather than the exported one. Great for fast iteration, but the game
+- `-DFEATURE_DISCORD_RPC` or `-DNO_FEATURE_DISCORD_RPC` to forcibly enable or disable support for Discord Rich Presence.
+- `-DFEATURE_VIDEO_PLAYBACK` or `-DNO_FEATURE_VIDEO_PLAYBACK` to forcibly enable or disable video cutscene support.
+- `-DFEATURE_CHART_EDITOR` or `-DNO_FEATURE_CHART_EDITOR` to forcibly enable or disable the chart editor in the Debug menu.
+- `-DFEATURE_STAGE_EDITOR` to forcibly enable the experimental stage editor.
+- `-DFEATURE_GHOST_TAPPING` to forcibly enable an experimental gameplay change to the anti-mash system.
 
 # Troubleshooting - GO THROUGH THESE STEPS BEFORE OPENING ISSUES ON GITHUB!
 

From c81f0416959370ad41b25f72be7eb6d936c2dc9a Mon Sep 17 00:00:00 2001
From: CheemsAndFriends <granchinvictor@gmail.com>
Date: Wed, 11 Sep 2024 20:05:39 +0200
Subject: [PATCH 06/41] Tinkering with atlassprite

---
 .../graphics/adobeanimate/FlxAtlasSprite.hx       | 15 +--------------
 1 file changed, 1 insertion(+), 14 deletions(-)

diff --git a/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx b/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx
index eeb4eccef..eef8bee2b 100644
--- a/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx
+++ b/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx
@@ -169,19 +169,6 @@ class FlxAtlasSprite extends FlxAnimate
       }
     }
 
-    anim.onComplete.removeAll();
-    anim.onComplete.add(function() {
-      if (loop)
-      {
-        this.anim.play(id, restart, false, startFrame);
-        this.currentAnimation = id;
-      }
-      else
-      {
-        onAnimationComplete.dispatch(id);
-      }
-    });
-
     looping = loop;
 
     // Prevent other animations from playing if `ignoreOther` is true.
@@ -191,7 +178,7 @@ class FlxAtlasSprite extends FlxAnimate
     // goToFrameLabel(id);
     trace('Playing animation $id');
     // Only call goToFrameLabel if there is a frame label with that name. This prevents annoying warnings!
-    if (getFrameLabelNames().indexOf(id) != -1)
+    if (getLabelIndex(id) != -1)
     {
       goToFrameLabel(id);
       fr = anim.getFrameLabel(id);

From bea23c37a81bdc1f2a2b537a3c519c95b6b48ca0 Mon Sep 17 00:00:00 2001
From: CheemsAndFriends <granchinvictor@gmail.com>
Date: Wed, 11 Sep 2024 20:47:45 +0200
Subject: [PATCH 07/41] readd FlxAtlasSprite from char unlock branch

---
 .../graphics/adobeanimate/FlxAtlasSprite.hx   | 37 ++++++++++---------
 source/funkin/ui/charSelect/IntroSubState.hx  | 27 +++++---------
 2 files changed, 30 insertions(+), 34 deletions(-)

diff --git a/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx b/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx
index eef8bee2b..6f91dbac5 100644
--- a/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx
+++ b/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx
@@ -95,7 +95,7 @@ class FlxAtlasSprite extends FlxAnimate
    */
   public function hasAnimation(id:String):Bool
   {
-    return getLabelIndex(id) != -1 || anim.symbolDictionary.exists(id) || anim.getByName(id) != null;
+    return getLabelIndex(id) != -1 || anim.symbolDictionary.exists(id);
   }
 
   /**
@@ -155,20 +155,24 @@ class FlxAtlasSprite extends FlxAnimate
       if (!anim.isPlaying)
       {
         // Resume animation if it's paused.
-        anim.play('', restart, false, startFrame);
+        anim.resume();
       }
+
       return;
     }
-    else
+    else if (!hasAnimation(id))
     {
       // Skip if the animation doesn't exist
-      if (!hasAnimation(id))
-      {
-        trace('Animation ' + id + ' not found');
-        return;
-      }
+      trace('Animation ' + id + ' not found');
+      return;
     }
 
+    this.currentAnimation = id;
+    anim.onComplete.removeAll();
+    anim.onComplete.add(function() {
+      _onAnimationComplete();
+    });
+
     looping = loop;
 
     // Prevent other animations from playing if `ignoreOther` is true.
@@ -177,20 +181,18 @@ class FlxAtlasSprite extends FlxAnimate
     // Move to the first frame of the animation.
     // goToFrameLabel(id);
     trace('Playing animation $id');
+    if (this.anim.symbolDictionary.exists(id) || (this.anim.getByName(id) != null))
+    {
+      this.anim.play(id, true, false, startFrame);
+      fr = null;
+    }
     // Only call goToFrameLabel if there is a frame label with that name. This prevents annoying warnings!
-    if (getLabelIndex(id) != -1)
+    if (getFrameLabelNames().indexOf(id) != -1)
     {
       goToFrameLabel(id);
       fr = anim.getFrameLabel(id);
       anim.curFrame += startFrame;
     }
-    else
-    {
-      this.anim.play(id, restart, false, startFrame);
-      fr = null;
-    }
-
-    this.currentAnimation = id;
   }
 
   override public function update(elapsed:Float)
@@ -288,12 +290,13 @@ class FlxAtlasSprite extends FlxAnimate
       {
         anim.pause();
         _onAnimationComplete();
+
         if (looping)
         {
           anim.curFrame = (fr != null) ? fr.index : 0;
           anim.resume();
         }
-        else
+        else if (fr != null)
         {
           anim.curFrame--;
         }
diff --git a/source/funkin/ui/charSelect/IntroSubState.hx b/source/funkin/ui/charSelect/IntroSubState.hx
index 04503cbb9..16271337b 100644
--- a/source/funkin/ui/charSelect/IntroSubState.hx
+++ b/source/funkin/ui/charSelect/IntroSubState.hx
@@ -116,24 +116,17 @@ class IntroSubState extends MusicBeatSubState
    */
   function onAttractEnd():Void
   {
-    #if html5
-    if (vid != null)
-    {
-      remove(vid);
-    }
-    #end
-
-    #if hxCodec
-    if (vid != null)
-    {
-      vid.stop();
-      remove(vid);
-    }
-    #end
-
     #if (html5 || hxCodec)
-    vid.destroy();
-    vid = null;
+    if (vid != null)
+    {
+      #if hxCodec
+      vid.stop();
+      #end
+      remove(vid);
+
+      vid.destroy();
+      vid = null;
+    }
     #end
 
     close();

From 9f5c154b1d29ac195023fd8a12856d27856d8777 Mon Sep 17 00:00:00 2001
From: CheemsAndFriends <granchinvictor@gmail.com>
Date: Wed, 11 Sep 2024 20:49:55 +0200
Subject: [PATCH 08/41] readd IntroSubState from char unlock

---
 source/funkin/ui/charSelect/IntroSubState.hx | 54 ++++++++++++--------
 1 file changed, 32 insertions(+), 22 deletions(-)

diff --git a/source/funkin/ui/charSelect/IntroSubState.hx b/source/funkin/ui/charSelect/IntroSubState.hx
index 16271337b..a0c44c225 100644
--- a/source/funkin/ui/charSelect/IntroSubState.hx
+++ b/source/funkin/ui/charSelect/IntroSubState.hx
@@ -8,22 +8,24 @@ import hxcodec.flixel.FlxVideoSprite;
 #end
 import funkin.ui.MusicBeatSubState;
 import funkin.audio.FunkinSound;
+import funkin.save.Save;
 
 /**
- * After about 2 minutes of inactivity on the title screen,
- * the game will enter the Attract state, as a reference to physical arcade machines.
- *
- * In the current version, this just plays the ~~Kickstarter trailer~~ Erect teaser, but this can be changed to
- * gameplay footage, a generic game trailer, or something more elaborate.
+ * When you first enter the character select state, it will play an introductory video opening up the lights
  */
 class IntroSubState extends MusicBeatSubState
 {
-  static final ATTRACT_VIDEO_PATH:String = Paths.stripLibrary(Paths.videos('introSelect'));
+  static final LIGHTS_VIDEO_PATH:String = Paths.stripLibrary(Paths.videos('introSelect'));
 
   var introSound:FunkinSound = null;
 
   public override function create():Void
   {
+    if (Save.instance.oldChar)
+    {
+      onLightsEnd();
+      return;
+    }
     // Pause existing music.
     if (FlxG.sound.music != null)
     {
@@ -32,15 +34,20 @@ class IntroSubState extends MusicBeatSubState
     }
 
     #if html5
-    trace('Playing web video ${ATTRACT_VIDEO_PATH}');
-    playVideoHTML5(ATTRACT_VIDEO_PATH);
+    trace('Playing web video ${LIGHTS_VIDEO_PATH}');
+    playVideoHTML5(LIGHTS_VIDEO_PATH);
     #end
 
     #if hxCodec
-    trace('Playing native video ${ATTRACT_VIDEO_PATH}');
-    playVideoNative(ATTRACT_VIDEO_PATH);
+    trace('Playing native video ${LIGHTS_VIDEO_PATH}');
+    playVideoNative(LIGHTS_VIDEO_PATH);
     #end
 
+    // Im TOO lazy to even care, so uh, yep
+    FlxG.camera.zoom = 0.66666666666666666666666666666667;
+    vid.x = -(FlxG.width - (FlxG.width * FlxG.camera.zoom));
+    vid.y = -((FlxG.height - (FlxG.height * FlxG.camera.zoom)) * 0.75);
+
     introSound = new FunkinSound();
     introSound.loadEmbedded(Paths.sound('CS_Lights'));
     introSound.pitch = 1;
@@ -64,7 +71,7 @@ class IntroSubState extends MusicBeatSubState
     {
       vid.zIndex = 0;
 
-      vid.finishCallback = onAttractEnd;
+      vid.finishCallback = onLightsEnd;
 
       add(vid);
     }
@@ -88,7 +95,7 @@ class IntroSubState extends MusicBeatSubState
     if (vid != null)
     {
       vid.zIndex = 0;
-      vid.bitmap.onEndReached.add(onAttractEnd);
+      vid.bitmap.onEndReached.add(onLightsEnd);
 
       add(vid);
       vid.play(filePath, false);
@@ -104,30 +111,33 @@ class IntroSubState extends MusicBeatSubState
   {
     super.update(elapsed);
 
-    if (controls.ACCEPT)
-    {
-      onAttractEnd();
-    }
+    // if (!introSound.paused)
+    // {
+    //   #if html5
+    //   @:privateAccess
+    //   vid.netStream.seek(introSound.time);
+    //   #elseif hxCodec
+    //   vid.bitmap.time = Std.int(introSound.time);
+    //   #end
+    // }
   }
 
   /**
-   * When the attraction state ends (after the video ends or the user presses any button),
-   * switch immediately to the title screen.
+   * When the lights video finishes, it will close the substate
    */
-  function onAttractEnd():Void
+  function onLightsEnd():Void
   {
-    #if (html5 || hxCodec)
     if (vid != null)
     {
       #if hxCodec
       vid.stop();
       #end
       remove(vid);
-
       vid.destroy();
       vid = null;
     }
-    #end
+
+    FlxG.camera.zoom = 1;
 
     close();
   }

From cfcfc773daa7ffc26dffe9574a443f5807fa4a94 Mon Sep 17 00:00:00 2001
From: CheemsAndFriends <granchinvictor@gmail.com>
Date: Wed, 11 Sep 2024 20:53:05 +0200
Subject: [PATCH 09/41] readd Save from char unlock

---
 source/funkin/save/Save.hx | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/source/funkin/save/Save.hx b/source/funkin/save/Save.hx
index 80b05e5ac..1fa283b26 100644
--- a/source/funkin/save/Save.hx
+++ b/source/funkin/save/Save.hx
@@ -125,6 +125,7 @@ class Save
         {
           // Default to having seen the default character.
           charactersSeen: ["bf"],
+          oldChar: false
         },
 
       optionsChartEditor:
@@ -406,6 +407,18 @@ class Save
     return data.unlocks.charactersSeen;
   }
 
+  public var oldChar(get, set):Bool;
+
+  function get_oldChar():Bool
+  {
+    return data.unlocks.oldChar;
+  }
+
+  function set_oldChar(value:Bool):Bool
+  {
+    return data.unlocks.oldChar = value;
+  }
+
   /**
    * When we've seen a character unlock, add it to the list of characters seen.
    * @param character
@@ -1027,6 +1040,12 @@ typedef SaveDataUnlocks =
    * add it to this list so that we don't show it again.
    */
   var charactersSeen:Array<String>;
+
+  /**
+   * This is a conditional when the player enters the character state
+   * For the first time ever
+   */
+  var oldChar:Bool;
 }
 
 /**

From 70ab000be42f62a25fb33440a3d6eee34ce163ac Mon Sep 17 00:00:00 2001
From: CheemsAndFriends <granchinvictor@gmail.com>
Date: Wed, 11 Sep 2024 21:16:02 +0200
Subject: [PATCH 10/41] Readd CharSelectSubState from char unlock

---
 assets                                        |  2 +-
 .../ui/charSelect/CharSelectSubState.hx       | 68 ++++++++-----------
 2 files changed, 30 insertions(+), 40 deletions(-)

diff --git a/assets b/assets
index 26ab9a1dc..f1813c9e4 160000
--- a/assets
+++ b/assets
@@ -1 +1 @@
-Subproject commit 26ab9a1dc8eec563717711b290c21d0e9e56a005
+Subproject commit f1813c9e4f88426554293b68d8a46f5baa5b6228
diff --git a/source/funkin/ui/charSelect/CharSelectSubState.hx b/source/funkin/ui/charSelect/CharSelectSubState.hx
index e075abca3..bd55bfdd9 100644
--- a/source/funkin/ui/charSelect/CharSelectSubState.hx
+++ b/source/funkin/ui/charSelect/CharSelectSubState.hx
@@ -35,55 +35,44 @@ import openfl.filters.ShaderFilter;
 import funkin.util.FramesJSFLParser;
 import funkin.util.FramesJSFLParser.FramesJSFLInfo;
 import funkin.util.FramesJSFLParser.FramesJSFLFrame;
+import funkin.graphics.FunkinSprite;
 
 class CharSelectSubState extends MusicBeatSubState
 {
   var cursor:FlxSprite;
+
   var cursorBlue:FlxSprite;
   var cursorDarkBlue:FlxSprite;
-
   var grpCursors:FlxTypedGroup<FlxSprite>;
-
   var cursorConfirmed:FlxSprite;
   var cursorDenied:FlxSprite;
-
   var cursorX:Int = 0;
   var cursorY:Int = 0;
-
   var cursorFactor:Float = 110;
   var cursorOffsetX:Float = -16;
   var cursorOffsetY:Float = -48;
-
   var cursorLocIntended:FlxPoint = new FlxPoint(0, 0);
   var lerpAmnt:Float = 0.95;
-
   var tmrFrames:Int = 60;
-
   var currentStage:Stage;
-
   var playerChill:CharSelectPlayer;
   var playerChillOut:CharSelectPlayer;
   var gfChill:CharSelectGF;
   var gfChillOut:CharSelectGF;
-
   var barthing:FlxAtlasSprite;
   var dipshitBacking:FlxSprite;
   var chooseDipshit:FlxSprite;
   var dipshitBlur:FlxSprite;
   var transitionGradient:FlxSprite;
-
   var curChar(default, set):String = "pico";
   var nametag:Nametag;
   var camFollow:FlxObject;
   var autoFollow:Bool = false;
-
   var availableChars:Map<Int, String> = new Map<Int, String>();
   var pressedSelect:Bool = false;
-
   var selectTimer:FlxTimer = new FlxTimer();
   var selectSound:FunkinSound;
   var unlockSound:FunkinSound;
-
   var charSelectCam:FunkinCamera;
 
   var selectedBizz:Array<BitmapFilter> = [
@@ -92,6 +81,7 @@ class CharSelectSubState extends MusicBeatSubState
   ];
 
   var bopInfo:FramesJSFLInfo;
+  var blackScreen:FunkinSprite;
 
   public function new()
   {
@@ -125,11 +115,6 @@ class CharSelectSubState extends MusicBeatSubState
 
   override public function create():Void
   {
-    openSubState(new IntroSubState());
-    subStateClosed.addOnce((_) -> {
-      camera.flash();
-      checkNewChar();
-    });
     super.create();
 
     bopInfo = FramesJSFLParser.parse(Paths.file("images/charSelect/iconBopInfo/iconBopInfo.txt"));
@@ -239,7 +224,7 @@ class CharSelectSubState extends MusicBeatSubState
     // FlxG.debugger.track(bfChill, "bf chill");
     // FlxG.debugger.track(playerChill, "player");
     // FlxG.debugger.track(nametag, "nametag");
-    // FlxG.debugger.track(selectSound, "selectSound");
+    FlxG.debugger.track(selectSound, "selectSound");
     // FlxG.debugger.track(chooseDipshit, "choose dipshit");
     // FlxG.debugger.track(barthing, "barthing");
     // FlxG.debugger.track(fgBlur, "fgBlur");
@@ -365,6 +350,20 @@ class CharSelectSubState extends MusicBeatSubState
           FlxG.camera.follow(camFollow, LOCKON, 0.01);
         }
       });
+
+    var blackScreen = new FunkinSprite().makeSolidColor(FlxG.width * 2, FlxG.height * 2, 0xFF000000);
+    blackScreen.x = -(FlxG.width * 0.5);
+    blackScreen.y = -(FlxG.height * 0.5);
+    add(blackScreen);
+
+    openSubState(new IntroSubState());
+    subStateClosed.addOnce((_) -> {
+      remove(blackScreen);
+      if (!Save.instance.oldChar) camera.flash();
+      checkNewChar();
+
+      Save.instance.oldChar = true;
+    });
   }
 
   function checkNewChar():Void
@@ -396,7 +395,6 @@ class CharSelectSubState extends MusicBeatSubState
   var grpIcons:FlxSpriteGroup;
   var grpXSpread(default, set):Float = 107;
   var grpYSpread(default, set):Float = 127;
-
   var nonLocks = [];
 
   function initLocks():Void
@@ -426,9 +424,9 @@ class CharSelectSubState extends MusicBeatSubState
         var temp:Lock = new Lock(0, 0, i);
         temp.ID = 1;
 
-        temp.onAnimationComplete.add(function(anim) {
-          if (anim == "unlock") playerChill.playAnimation("unlock", true);
-        });
+        // temp.onAnimationComplete.add(function(anim) {
+        //   if (anim == "unlock") playerChill.playAnimation("unlock", true);
+        // });
 
         grpIcons.add(temp);
       }
@@ -443,7 +441,7 @@ class CharSelectSubState extends MusicBeatSubState
   {
     var index = nonLocks[0];
 
-    // pressedSelect = true;
+    pressedSelect = true;
 
     var copy = 3;
 
@@ -478,7 +476,7 @@ class CharSelectSubState extends MusicBeatSubState
 
       syncLock = lock;
 
-      // sync = true;
+      sync = true;
 
       lock.onAnimationComplete.addOnce(function(_) {
         syncLock = null;
@@ -561,9 +559,7 @@ class CharSelectSubState extends MusicBeatSubState
   }
 
   var sync:Bool = false;
-
   var syncLock:Lock = null;
-
   var audioBizz:Float = 0;
 
   function syncAudio(elapsed:Float):Void
@@ -580,8 +576,6 @@ class CharSelectSubState extends MusicBeatSubState
       playerChillOut.anim._tick = 0;
       if (syncLock != null) syncLock.anim._tick = 0;
 
-      trace(unlockSound.time);
-
       if ((unlockSound.time - audioBizz) >= (delay * 1000))
       {
         if (syncLock != null) syncLock.anim._tick = delay;
@@ -738,7 +732,7 @@ class CharSelectSubState extends MusicBeatSubState
     {
       curChar = availableChars.get(getCurrentSelected());
 
-      if (controls.ACCEPT)
+      if (!pressedSelect && controls.ACCEPT)
       {
         cursorConfirmed.visible = true;
         cursorConfirmed.x = cursor.x - 2;
@@ -775,6 +769,7 @@ class CharSelectSubState extends MusicBeatSubState
         FlxTween.tween(FlxG.sound.music, {pitch: 1.0, volume: 1.0}, 1, {ease: FlxEase.quartInOut});
         playerChill.playAnimation("deselect");
         gfChill.playAnimation("deselect");
+        pressedSelect = false;
         FlxTween.tween(FlxG.sound.music, {pitch: 1.0}, 1,
           {
             ease: FlxEase.quartInOut,
@@ -783,7 +778,6 @@ class CharSelectSubState extends MusicBeatSubState
               gfChill.playAnimation("idle", true, false, true);
             }
           });
-        pressedSelect = false;
         selectTimer.cancel();
       }
     }
@@ -797,7 +791,7 @@ class CharSelectSubState extends MusicBeatSubState
         cursorDenied.x = cursor.x - 2;
         cursorDenied.y = cursor.y - 4;
 
-        playerChill.playAnimation("cannot select", true);
+        playerChill.playAnimation("cannot select Label", true);
         cursorDenied.animation.play("idle", true);
         cursorDenied.animation.finishCallback = (_) -> {
           cursorDenied.visible = false;
@@ -831,13 +825,9 @@ class CharSelectSubState extends MusicBeatSubState
   }
 
   var bopTimer:Float = 0;
-
   var delay = 1 / 24;
-
   var bopFr = 0;
-
   var bopPlay:Bool = false;
-
   var bopRefX:Float = 0;
   var bopRefY:Float = 0;
 
@@ -957,10 +947,10 @@ class CharSelectSubState extends MusicBeatSubState
               memb.filters = selectedBizz;
               memb.scale.set(2.6, 2.6);
             }
-            if (controls.ACCEPT && memb.animation.curAnim.name == "confirm") memb.animation.play("confirm");
-            if (pressedSelect && controls.BACK)
+            if (pressedSelect && memb.animation.curAnim.name == "idle") memb.animation.play("confirm");
+            if (!pressedSelect && memb.animation.curAnim.name != "idle")
             {
-              memb.animation.play("confirm", true, true);
+              memb.animation.play("confirm", false, true);
               member.animation.finishCallback = (_) -> {
                 member.animation.play("idle");
                 member.animation.finishCallback = null;

From fded5892c5bde073118fa91cf3a1bd5d841db98f Mon Sep 17 00:00:00 2001
From: EliteMasterEric <ericmyllyoja@gmail.com>
Date: Wed, 11 Sep 2024 15:55:38 -0400
Subject: [PATCH 11/41] Update audio compression (via Saru)

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

diff --git a/assets b/assets
index 638a44fdd..acf6f9ddf 160000
--- a/assets
+++ b/assets
@@ -1 +1 @@
-Subproject commit 638a44fdd7635814db89e96bdfdc9a9be54b39c9
+Subproject commit acf6f9ddfdb5867550ae90e5871cce3d8d3808f0

From e32dd0e5048fe77326f38a227f5336ffc85c7afc Mon Sep 17 00:00:00 2001
From: EliteMasterEric <ericmyllyoja@gmail.com>
Date: Wed, 11 Sep 2024 17:09:45 -0400
Subject: [PATCH 12/41] Update assets submodule

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

diff --git a/assets b/assets
index 638a44fdd..abe1deb43 160000
--- a/assets
+++ b/assets
@@ -1 +1 @@
-Subproject commit 638a44fdd7635814db89e96bdfdc9a9be54b39c9
+Subproject commit abe1deb4372b9bc5b97d7d30ed8eb4e70d721eb9

From 3553d008cf29147e5f878e1088236de72796efca Mon Sep 17 00:00:00 2001
From: CheemsAndFriends <granchinvictor@gmail.com>
Date: Thu, 12 Sep 2024 01:37:32 +0200
Subject: [PATCH 13/41] tinkering shit

---
 assets                                                |  2 +-
 source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx | 10 ++++++++--
 source/funkin/play/ResultState.hx                     |  5 ++++-
 source/funkin/ui/charSelect/CharSelectPlayer.hx       |  2 +-
 source/funkin/ui/freeplay/FreeplayDJ.hx               |  2 ++
 source/funkin/ui/title/TitleState.hx                  |  7 +++++--
 6 files changed, 21 insertions(+), 7 deletions(-)

diff --git a/assets b/assets
index f1813c9e4..6b84e5b48 160000
--- a/assets
+++ b/assets
@@ -1 +1 @@
-Subproject commit f1813c9e4f88426554293b68d8a46f5baa5b6228
+Subproject commit 6b84e5b4830cbdb21f0e92bd8def16b1446f2d84
diff --git a/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx b/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx
index 6f91dbac5..f245afec7 100644
--- a/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx
+++ b/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx
@@ -154,6 +154,10 @@ class FlxAtlasSprite extends FlxAnimate
     {
       if (!anim.isPlaying)
       {
+        if (fr != null) anim.curFrame = fr.index + startFrame;
+        else
+          anim.curFrame = startFrame;
+
         // Resume animation if it's paused.
         anim.resume();
       }
@@ -183,7 +187,9 @@ class FlxAtlasSprite extends FlxAnimate
     trace('Playing animation $id');
     if (this.anim.symbolDictionary.exists(id) || (this.anim.getByName(id) != null))
     {
-      this.anim.play(id, true, false, startFrame);
+      this.anim.play(id, restart, false, startFrame);
+
+      if (id == "Boyfriend DJ fist pump" || startFrame == 4) trace("PUMP COMMAND: " + anim.curFrame);
       fr = null;
     }
     // Only call goToFrameLabel if there is a frame label with that name. This prevents annoying warnings!
@@ -296,7 +302,7 @@ class FlxAtlasSprite extends FlxAnimate
           anim.curFrame = (fr != null) ? fr.index : 0;
           anim.resume();
         }
-        else if (fr != null)
+        else if (fr != null && anim.curFrame != anim.length - 1)
         {
           anim.curFrame--;
         }
diff --git a/source/funkin/play/ResultState.hx b/source/funkin/play/ResultState.hx
index e7087e340..e0ac3579d 100644
--- a/source/funkin/play/ResultState.hx
+++ b/source/funkin/play/ResultState.hx
@@ -194,6 +194,7 @@ class ResultState extends MusicBeatSubState
           {
             // Animation is not looped.
             animation.onAnimationComplete.add((_name:String) -> {
+              trace("AHAHAH 2");
               if (animation != null)
               {
                 animation.anim.pause();
@@ -203,9 +204,10 @@ class ResultState extends MusicBeatSubState
           else if (animData.loopFrameLabel != null)
           {
             animation.onAnimationComplete.add((_name:String) -> {
+              trace("AHAHAH 2");
               if (animation != null)
               {
-                animation.playAnimation(animData.loopFrameLabel ?? ''); // unpauses this anim, since it's on PlayOnce!
+                animation.playAnimation(animData.loopFrameLabel ?? '', true, false, true); // unpauses this anim, since it's on PlayOnce!
               }
             });
           }
@@ -214,6 +216,7 @@ class ResultState extends MusicBeatSubState
             animation.onAnimationComplete.add((_name:String) -> {
               if (animation != null)
               {
+                trace("AHAHAH");
                 animation.anim.curFrame = animData.loopFrame ?? 0;
                 animation.anim.play(); // unpauses this anim, since it's on PlayOnce!
               }
diff --git a/source/funkin/ui/charSelect/CharSelectPlayer.hx b/source/funkin/ui/charSelect/CharSelectPlayer.hx
index 710bdd45a..b6319f16d 100644
--- a/source/funkin/ui/charSelect/CharSelectPlayer.hx
+++ b/source/funkin/ui/charSelect/CharSelectPlayer.hx
@@ -27,7 +27,7 @@ class CharSelectPlayer extends FlxAtlasSprite implements IBPMSyncedScriptedClass
         case "deselect":
           playAnimation("deselect loop start", true, false, true);
 
-        case "slidein idle point", "cannot select", "unlock":
+        case "slidein idle point", "cannot select Label", "unlock":
           playAnimation("idle", true, false, false);
         case "idle":
           trace('Waiting for onBeatHit');
diff --git a/source/funkin/ui/freeplay/FreeplayDJ.hx b/source/funkin/ui/freeplay/FreeplayDJ.hx
index 51829d44d..a6cbab440 100644
--- a/source/funkin/ui/freeplay/FreeplayDJ.hx
+++ b/source/funkin/ui/freeplay/FreeplayDJ.hx
@@ -141,6 +141,7 @@ class FreeplayDJ extends FlxAtlasSprite
         }
         else if (getCurrentAnimation() == animPrefixB)
         {
+          trace("Loss Intro");
           var endFrame = playableCharData.getFistPumpIntroBadEndFrame();
           if (endFrame > -1 && anim.curFrame >= endFrame)
           {
@@ -166,6 +167,7 @@ class FreeplayDJ extends FlxAtlasSprite
         }
         else if (getCurrentAnimation() == animPrefixB)
         {
+          trace("Loss GYATT");
           var endFrame = playableCharData.getFistPumpLoopBadEndFrame();
           if (endFrame > -1 && anim.curFrame >= endFrame)
           {
diff --git a/source/funkin/ui/title/TitleState.hx b/source/funkin/ui/title/TitleState.hx
index df628fa87..f5c641d0c 100644
--- a/source/funkin/ui/title/TitleState.hx
+++ b/source/funkin/ui/title/TitleState.hx
@@ -273,8 +273,11 @@ class TitleState extends MusicBeatState
     }
     #end
 
-    if (Save.instance.charactersSeen.contains("pico")) Save.instance.charactersSeen.remove("pico");
-
+    if (Save.instance.charactersSeen.contains("pico"))
+    {
+      Save.instance.charactersSeen.remove("pico");
+      Save.instance.oldChar = false;
+    }
     Conductor.instance.update();
 
     /* if (FlxG.onMobile)

From bfcbc54ced6cc4e186547ffc49f1a2530bb58b6a Mon Sep 17 00:00:00 2001
From: EliteMasterEric <ericmyllyoja@gmail.com>
Date: Wed, 11 Sep 2024 20:39:31 -0400
Subject: [PATCH 14/41] Update assets submodule

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

diff --git a/assets b/assets
index abe1deb43..cbf695dd6 160000
--- a/assets
+++ b/assets
@@ -1 +1 @@
-Subproject commit abe1deb4372b9bc5b97d7d30ed8eb4e70d721eb9
+Subproject commit cbf695dd622625d11abbed594832aa41fe6a20de

From e12ed47162f709ea53e7bd6bcb056726c219c9f6 Mon Sep 17 00:00:00 2001
From: FabsTheFabs <flamingkitty24@gmail.com>
Date: Thu, 12 Sep 2024 09:25:42 +0100
Subject: [PATCH 15/41] assets submod

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

diff --git a/assets b/assets
index 638a44fdd..d7e9f6e15 160000
--- a/assets
+++ b/assets
@@ -1 +1 @@
-Subproject commit 638a44fdd7635814db89e96bdfdc9a9be54b39c9
+Subproject commit d7e9f6e15331f6d2dfee3d380e804e8274d6661d

From b7fb6105a773053162b11596865c538079e503dd Mon Sep 17 00:00:00 2001
From: FabsTheFabs <flamingkitty24@gmail.com>
Date: Thu, 12 Sep 2024 17:50:46 +0100
Subject: [PATCH 16/41] assets submod

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

diff --git a/assets b/assets
index 638a44fdd..3306aab5b 160000
--- a/assets
+++ b/assets
@@ -1 +1 @@
-Subproject commit 638a44fdd7635814db89e96bdfdc9a9be54b39c9
+Subproject commit 3306aab5b747aa5b19508d88ffb801403218b2ca

From 2c80701855cae07efd3c13185090e0fe1c5b5a32 Mon Sep 17 00:00:00 2001
From: Cameron Taylor <cameron.taylor.ninja@gmail.com>
Date: Thu, 12 Sep 2024 14:26:11 -0400
Subject: [PATCH 17/41] assets submod

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

diff --git a/assets b/assets
index acf6f9ddf..bd1bdcf5e 160000
--- a/assets
+++ b/assets
@@ -1 +1 @@
-Subproject commit acf6f9ddfdb5867550ae90e5871cce3d8d3808f0
+Subproject commit bd1bdcf5e1349e6199d9d32e617cbefa2cea093b

From d3e8938888f7c4feb27c806ca222f6a54e69b087 Mon Sep 17 00:00:00 2001
From: Cameron Taylor <cameron.taylor.ninja@gmail.com>
Date: Thu, 12 Sep 2024 14:28:51 -0400
Subject: [PATCH 18/41] assets submod

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

diff --git a/assets b/assets
index 5822338a5..3954e9564 160000
--- a/assets
+++ b/assets
@@ -1 +1 @@
-Subproject commit 5822338a50cafbb277a91d949681baea2627fa80
+Subproject commit 3954e95646643dfc729607d0da57ba0bbf273521

From 19f332ea7e0858c2998392b98ee5c09a9588718d Mon Sep 17 00:00:00 2001
From: Cameron Taylor <cameron.taylor.ninja@gmail.com>
Date: Thu, 12 Sep 2024 14:30:14 -0400
Subject: [PATCH 19/41] assets submod

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

diff --git a/assets b/assets
index cbf695dd6..a00554b4c 160000
--- a/assets
+++ b/assets
@@ -1 +1 @@
-Subproject commit cbf695dd622625d11abbed594832aa41fe6a20de
+Subproject commit a00554b4c78d3d1da18436bc285ccbe1f4ea98f2

From 96f306471cca18550cdfd6cb3d50d241d97ff07e Mon Sep 17 00:00:00 2001
From: Cameron Taylor <cameron.taylor.ninja@gmail.com>
Date: Thu, 12 Sep 2024 14:31:56 -0400
Subject: [PATCH 20/41] assets submod

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

diff --git a/assets b/assets
index 6b84e5b48..335fac6af 160000
--- a/assets
+++ b/assets
@@ -1 +1 @@
-Subproject commit 6b84e5b4830cbdb21f0e92bd8def16b1446f2d84
+Subproject commit 335fac6af6b3362b1de5f233865486eaf9fbae11

From 0b13e0fdd5f3f66a9efc81b76e8a26067109f983 Mon Sep 17 00:00:00 2001
From: Cameron Taylor <cameron.taylor.ninja@gmail.com>
Date: Thu, 12 Sep 2024 14:33:31 -0400
Subject: [PATCH 21/41] art submod (char select stuff)

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

diff --git a/art b/art
index 1206249aa..0bb988c49 160000
--- a/art
+++ b/art
@@ -1 +1 @@
-Subproject commit 1206249aa65e13df2d6a196c35222f768ad4a3f4
+Subproject commit 0bb988c49788fd25a230b56dd9e4448838bc79c9

From 260946f44f1303762cd18de0ce096926c3c66f79 Mon Sep 17 00:00:00 2001
From: Cameron Taylor <cameron.taylor.ninja@gmail.com>
Date: Thu, 12 Sep 2024 14:35:19 -0400
Subject: [PATCH 22/41] assets submod

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

diff --git a/assets b/assets
index d7e9f6e15..f1fe21240 160000
--- a/assets
+++ b/assets
@@ -1 +1 @@
-Subproject commit d7e9f6e15331f6d2dfee3d380e804e8274d6661d
+Subproject commit f1fe21240bac58a7ab729b351cb36f3f9ed07e7a

From 07c5c5d5a7affa04102357060e29e305fd7c8d03 Mon Sep 17 00:00:00 2001
From: Cameron Taylor <cameron.taylor.ninja@gmail.com>
Date: Thu, 12 Sep 2024 14:38:29 -0400
Subject: [PATCH 23/41] assets submod

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

diff --git a/assets b/assets
index 3306aab5b..bd4e2421c 160000
--- a/assets
+++ b/assets
@@ -1 +1 @@
-Subproject commit 3306aab5b747aa5b19508d88ffb801403218b2ca
+Subproject commit bd4e2421c87c31e244bc9c162850b842582c5de4

From bfb19cc67ebd82fea3133301637fd96404a38389 Mon Sep 17 00:00:00 2001
From: Cameron Taylor <cameron.taylor.ninja@gmail.com>
Date: Thu, 12 Sep 2024 14:46:29 -0400
Subject: [PATCH 24/41] lastTime error fix

---
 source/Main.hx | 1 -
 1 file changed, 1 deletion(-)

diff --git a/source/Main.hx b/source/Main.hx
index 63e2b5878..7f7d25235 100644
--- a/source/Main.hx
+++ b/source/Main.hx
@@ -73,7 +73,6 @@ class Main extends Sprite
                     var timeToCall = 0;
                     var id = window.setTimeout(function() { callback(currTime + timeToCall); },
                       timeToCall);
-                    lastTime = currTime + timeToCall;
                     return id;
                 }");
     #end

From cdd78818a7f9ca47b95fd9d24e7df21231c118e9 Mon Sep 17 00:00:00 2001
From: EliteMasterEric <ericmyllyoja@gmail.com>
Date: Thu, 12 Sep 2024 15:20:12 -0400
Subject: [PATCH 25/41] Update assets submodule and changelog

---
 CHANGELOG.md | 9 ++++++++-
 art          | 2 +-
 assets       | 2 +-
 3 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 22a36fa8e..a2031ba24 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -29,8 +29,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 - Implemented support for a new Instrumental Selector in Freeplay
   - Beating a Pico remix lets you use that instrumental when playing as Boyfriend
 - Added the first batch of Erect Stages! These graphical overhauls of the original stages will be used when playing Erect remixes and Pico remixes
+  - Week 1 Erect Stage
+  - Week 2 Erect Stage
+  - Week 3 Erect Stage
+  - Week 4 Erect Stage
+  - Week 5 Erect Stage
+  - Weekend 1 Erect Stage
+- Implemented alternate animations and music for Pico in the results screen.
+  - These display on Pico remixes, as well as when playing Weekend 1.
 - Implemented support for scripted Note Kinds. You can use HScript define a different note style to display for these notes as well as custom behavior. (community feature by lemz1)
-- Implemented a new Strumline Background option, to display a darkened background behind the strumline with your choice of opacity.
 - Implemented support for Numeric and Selector options in the Options menu. (community feature by FlooferLand)
 ## Changed
 - Girlfriend and Nene now perform previously unused animations when you achieve a large combo, or drop a large combo.
diff --git a/art b/art
index 0bb988c49..42ac06e51 160000
--- a/art
+++ b/art
@@ -1 +1 @@
-Subproject commit 0bb988c49788fd25a230b56dd9e4448838bc79c9
+Subproject commit 42ac06e51207bda89144fd20a407ed3c3e0c6673
diff --git a/assets b/assets
index bd4e2421c..90865213b 160000
--- a/assets
+++ b/assets
@@ -1 +1 @@
-Subproject commit bd4e2421c87c31e244bc9c162850b842582c5de4
+Subproject commit 90865213be704f88df8398f28b8880c13f468546

From b2b16ff2d310169c8390329c2546af6556346789 Mon Sep 17 00:00:00 2001
From: EliteMasterEric <ericmyllyoja@gmail.com>
Date: Thu, 12 Sep 2024 15:31:58 -0400
Subject: [PATCH 26/41] Update vocal delay again

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

diff --git a/assets b/assets
index 90865213b..934468c04 160000
--- a/assets
+++ b/assets
@@ -1 +1 @@
-Subproject commit 90865213be704f88df8398f28b8880c13f468546
+Subproject commit 934468c0472504c282b12c63b473e9f74b5b4517

From 386dc22d7b24464a63a4f95c6fa2aa8cc854da86 Mon Sep 17 00:00:00 2001
From: EliteMasterEric <ericmyllyoja@gmail.com>
Date: Thu, 12 Sep 2024 15:34:16 -0400
Subject: [PATCH 27/41] Debug hotkey properly resets char select cutscene

---
 source/funkin/ui/mainmenu/MainMenuState.hx | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/source/funkin/ui/mainmenu/MainMenuState.hx b/source/funkin/ui/mainmenu/MainMenuState.hx
index 4e416abeb..13d68da6d 100644
--- a/source/funkin/ui/mainmenu/MainMenuState.hx
+++ b/source/funkin/ui/mainmenu/MainMenuState.hx
@@ -437,7 +437,10 @@ class MainMenuState extends MusicBeatState
     if (FlxG.keys.pressed.CONTROL && FlxG.keys.pressed.ALT && FlxG.keys.pressed.SHIFT && FlxG.keys.justPressed.N)
     {
       @:privateAccess
-      funkin.save.Save.instance.data.unlocks.charactersSeen = ["bf"];
+      {
+        funkin.save.Save.instance.data.unlocks.charactersSeen = ["bf"];
+        funkin.save.Save.instance.data.unlocks.oldChar = false;
+      }
     }
 
     if (FlxG.keys.pressed.CONTROL && FlxG.keys.pressed.ALT && FlxG.keys.pressed.SHIFT && FlxG.keys.justPressed.E)

From e5673549cf7c17c58dfc340279c4ac0ed4377dd7 Mon Sep 17 00:00:00 2001
From: EliteMasterEric <ericmyllyoja@gmail.com>
Date: Thu, 12 Sep 2024 15:38:20 -0400
Subject: [PATCH 28/41] Fix issues with the difficulty selector showing
 non-existant difficulties in Freeplay

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

diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx
index a908e54c6..ec80a1ff6 100644
--- a/source/funkin/ui/freeplay/FreeplayState.hx
+++ b/source/funkin/ui/freeplay/FreeplayState.hx
@@ -354,10 +354,6 @@ class FreeplayState extends MusicBeatSubState
         if (availableDifficultiesForSong.length == 0) continue;
 
         songs.push(new FreeplaySongData(levelId, songId, song, displayedVariations));
-        for (difficulty in availableDifficultiesForSong)
-        {
-          diffIdsTotal.pushUnique(difficulty);
-        }
         for (difficulty in unsuffixedDifficulties)
         {
           diffIdsTotal.pushUnique(difficulty);
@@ -1764,12 +1760,13 @@ class FreeplayState extends MusicBeatSubState
       var songScore:Null<SaveScoreData> = Save.instance.getSongScore(daSong.songId, suffixedDifficulty);
       intendedScore = songScore?.score ?? 0;
       intendedCompletion = songScore == null ? 0.0 : ((songScore.tallies.sick + songScore.tallies.good) / songScore.tallies.totalNotes);
-      rememberedDifficulty = currentDifficulty;
+      rememberedDifficulty = suffixedDifficulty;
     }
     else
     {
       intendedScore = 0;
       intendedCompletion = 0.0;
+      rememberedDifficulty = currentDifficulty;
     }
 
     if (intendedCompletion == Math.POSITIVE_INFINITY || intendedCompletion == Math.NEGATIVE_INFINITY || Math.isNaN(intendedCompletion))

From 721cecd271fb8b40fe1ed26ee7908d94bd1f522e Mon Sep 17 00:00:00 2001
From: Cameron Taylor <cameron.taylor.ninja@gmail.com>
Date: Thu, 12 Sep 2024 15:38:44 -0400
Subject: [PATCH 29/41] add preference option for framerate capping

---
 source/Main.hx                              | 11 ++---
 source/funkin/Preferences.hx                | 53 +++++++++++++++++++++
 source/funkin/save/Save.hx                  |  7 +++
 source/funkin/ui/options/PreferencesMenu.hx |  6 +++
 4 files changed, 69 insertions(+), 8 deletions(-)

diff --git a/source/Main.hx b/source/Main.hx
index 7f7d25235..724b118f8 100644
--- a/source/Main.hx
+++ b/source/Main.hx
@@ -67,14 +67,9 @@ class Main extends Sprite
   function init(?event:Event):Void
   {
     #if web
-    untyped js.Syntax.code("
-    window.requestAnimationFrame = function(callback, element) {
-                    var currTime = new Date().getTime();
-                    var timeToCall = 0;
-                    var id = window.setTimeout(function() { callback(currTime + timeToCall); },
-                      timeToCall);
-                    return id;
-                }");
+    // set this variable (which is a function) from the lime version at lime/_internal/backend/html5/HTML5Application.hx
+    // The framerate cap will more thoroughly initialize via Preferences in InitState.hx
+    funkin.Preferences.lockedFramerateFunction = untyped js.Syntax.code("window.requestAnimationFrame");
     #end
 
     if (hasEventListener(Event.ADDED_TO_STAGE))
diff --git a/source/funkin/Preferences.hx b/source/funkin/Preferences.hx
index b2050c6a2..daeded897 100644
--- a/source/funkin/Preferences.hx
+++ b/source/funkin/Preferences.hx
@@ -128,6 +128,48 @@ class Preferences
     return value;
   }
 
+  public static var unlockedFramerate(get, set):Bool;
+
+  static function get_unlockedFramerate():Bool
+  {
+    return Save?.instance?.options?.unlockedFramerate;
+  }
+
+  static function set_unlockedFramerate(value:Bool):Bool
+  {
+    if (value != Save.instance.options.unlockedFramerate)
+    {
+      #if web
+      toggleFramerateCap(value);
+      #end
+    }
+
+    var save:Save = Save.instance;
+    save.options.unlockedFramerate = value;
+    save.flush();
+    return value;
+  }
+
+  #if web
+  // We create a haxe version of this just for readability.
+  // We use these to override `window.requestAnimationFrame` in Javascript to uncap the framerate / "animation" request rate
+  // Javascript is crazy since u can just do stuff like that lol
+
+  public static function unlockedFramerateFunction(callback, element)
+  {
+    var currTime = Date.now().getTime();
+    var timeToCall = 0;
+    var id = js.Browser.window.setTimeout(function() {
+      callback(currTime + timeToCall);
+    }, timeToCall);
+    return id;
+  }
+
+  // Lime already implements their own little framerate cap, so we can just use that
+  // This also gets set in the init function in Main.hx, since we need to definitely override it
+  public static var lockedFramerateFunction = untyped js.Syntax.code("window.requestAnimationFrame");
+  #end
+
   /**
    * Loads the user's preferences from the save data and apply them.
    */
@@ -137,6 +179,17 @@ class Preferences
     FlxG.autoPause = Preferences.autoPause;
     // Apply the debugDisplay setting (enables the FPS and RAM display).
     toggleDebugDisplay(Preferences.debugDisplay);
+    #if web
+    toggleFramerateCap(Preferences.unlockedFramerate);
+    #end
+  }
+
+  static function toggleFramerateCap(unlocked:Bool):Void
+  {
+    #if web
+    var framerateFunction = unlocked ? unlockedFramerateFunction : lockedFramerateFunction;
+    untyped js.Syntax.code("window.requestAnimationFrame = framerateFunction;");
+    #end
   }
 
   static function toggleDebugDisplay(show:Bool):Void
diff --git a/source/funkin/save/Save.hx b/source/funkin/save/Save.hx
index 1fa283b26..4b1649c5b 100644
--- a/source/funkin/save/Save.hx
+++ b/source/funkin/save/Save.hx
@@ -97,6 +97,7 @@ class Save
           autoPause: true,
           inputOffset: 0,
           audioVisualOffset: 0,
+          unlockedFramerate: false,
 
           controls:
             {
@@ -1171,6 +1172,12 @@ typedef SaveDataOptions =
    */
   var audioVisualOffset:Int;
 
+  /**
+   * If we want the framerate to be unlocked on HTML5.
+   * @default `false
+   */
+  var unlockedFramerate:Bool;
+
   var controls:
     {
       var p1:
diff --git a/source/funkin/ui/options/PreferencesMenu.hx b/source/funkin/ui/options/PreferencesMenu.hx
index 5fbefceed..eb7b88792 100644
--- a/source/funkin/ui/options/PreferencesMenu.hx
+++ b/source/funkin/ui/options/PreferencesMenu.hx
@@ -72,6 +72,12 @@ class PreferencesMenu extends Page
     createPrefItemCheckbox('Auto Pause', 'Automatically pause the game when it loses focus', function(value:Bool):Void {
       Preferences.autoPause = value;
     }, Preferences.autoPause);
+
+    #if web
+    createPrefItemCheckbox('Unlocked Framerate', 'Enable to unlock the framerate', function(value:Bool):Void {
+      Preferences.unlockedFramerate = value;
+    }, Preferences.unlockedFramerate);
+    #end
   }
 
   override function update(elapsed:Float):Void

From 3970189fe92dbbdac9256687174f1a9953ee83cf Mon Sep 17 00:00:00 2001
From: EliteMasterEric <ericmyllyoja@gmail.com>
Date: Thu, 12 Sep 2024 15:43:40 -0400
Subject: [PATCH 30/41] Ensure save data gets flushed when you see a character

---
 source/funkin/save/Save.hx | 13 +++++++++++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/source/funkin/save/Save.hx b/source/funkin/save/Save.hx
index 1fa283b26..43b7667da 100644
--- a/source/funkin/save/Save.hx
+++ b/source/funkin/save/Save.hx
@@ -407,6 +407,9 @@ class Save
     return data.unlocks.charactersSeen;
   }
 
+  /**
+   * Marks whether the player has seen the spotlight animation, which should only display once per save file ever.
+   */
   public var oldChar(get, set):Bool;
 
   function get_oldChar():Bool
@@ -416,7 +419,9 @@ class Save
 
   function set_oldChar(value:Bool):Bool
   {
-    return data.unlocks.oldChar = value;
+    data.unlocks.oldChar = value;
+    flush();
+    return data.unlocks.oldChar;
   }
 
   /**
@@ -425,7 +430,11 @@ class Save
    */
   public function addCharacterSeen(character:String):Void
   {
-    if (!data.unlocks.charactersSeen.contains(character)) data.unlocks.charactersSeen.push(character);
+    if (!data.unlocks.charactersSeen.contains(character))
+    {
+      data.unlocks.charactersSeen.push(character);
+      flush();
+    }
   }
 
   /**

From a9667c54f377a1207b70ba163ceebd8f239a5822 Mon Sep 17 00:00:00 2001
From: EliteMasterEric <ericmyllyoja@gmail.com>
Date: Thu, 12 Sep 2024 15:48:41 -0400
Subject: [PATCH 31/41] Fix FlxAtlasSprite completion handling and music
 looping

---
 source/funkin/audio/FunkinSound.hx                  |  2 ++
 .../funkin/graphics/adobeanimate/FlxAtlasSprite.hx  |  9 +++++++--
 source/funkin/play/ResultState.hx                   |  6 ++----
 source/funkin/play/scoring/Scoring.hx               | 13 -------------
 4 files changed, 11 insertions(+), 19 deletions(-)

diff --git a/source/funkin/audio/FunkinSound.hx b/source/funkin/audio/FunkinSound.hx
index 18a0b4da2..dae31cd07 100644
--- a/source/funkin/audio/FunkinSound.hx
+++ b/source/funkin/audio/FunkinSound.hx
@@ -340,6 +340,8 @@ class FunkinSound extends FlxSound implements ICloneable<FunkinSound>
       if (songMusicData != null)
       {
         Conductor.instance.mapTimeChanges(songMusicData.timeChanges);
+
+        if (songMusicData.looped != null && params.loop == null) params.loop = songMusicData.looped;
       }
       else
       {
diff --git a/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx b/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx
index f245afec7..952fa8b71 100644
--- a/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx
+++ b/source/funkin/graphics/adobeanimate/FlxAtlasSprite.hx
@@ -185,11 +185,12 @@ class FlxAtlasSprite extends FlxAnimate
     // Move to the first frame of the animation.
     // goToFrameLabel(id);
     trace('Playing animation $id');
-    if (this.anim.symbolDictionary.exists(id) || (this.anim.getByName(id) != null))
+    if ((id == null || id == "") || this.anim.symbolDictionary.exists(id) || (this.anim.getByName(id) != null))
     {
       this.anim.play(id, restart, false, startFrame);
 
-      if (id == "Boyfriend DJ fist pump" || startFrame == 4) trace("PUMP COMMAND: " + anim.curFrame);
+      this.currentAnimation = anim.curSymbol.name;
+
       fr = null;
     }
     // Only call goToFrameLabel if there is a frame label with that name. This prevents annoying warnings!
@@ -316,6 +317,10 @@ class FlxAtlasSprite extends FlxAnimate
     {
       onAnimationComplete.dispatch(currentAnimation);
     }
+    else
+    {
+      onAnimationComplete.dispatch('');
+    }
   }
 
   var prevFrames:Map<Int, FlxFrame> = [];
diff --git a/source/funkin/play/ResultState.hx b/source/funkin/play/ResultState.hx
index e0ac3579d..739df167d 100644
--- a/source/funkin/play/ResultState.hx
+++ b/source/funkin/play/ResultState.hx
@@ -418,8 +418,7 @@ class ResultState extends MusicBeatSubState
             {
               startingVolume: 1.0,
               overrideExisting: true,
-              restartTrack: true,
-              loop: rank.shouldMusicLoop()
+              restartTrack: true
             });
         });
       }
@@ -429,8 +428,7 @@ class ResultState extends MusicBeatSubState
           {
             startingVolume: 1.0,
             overrideExisting: true,
-            restartTrack: true,
-            loop: rank.shouldMusicLoop()
+            restartTrack: true
           });
       }
     });
diff --git a/source/funkin/play/scoring/Scoring.hx b/source/funkin/play/scoring/Scoring.hx
index 6c9f9bd97..dae098638 100644
--- a/source/funkin/play/scoring/Scoring.hx
+++ b/source/funkin/play/scoring/Scoring.hx
@@ -577,19 +577,6 @@ enum abstract ScoringRank(String)
     }
   }
 
-  public function shouldMusicLoop():Bool
-  {
-    switch (abstract)
-    {
-      case PERFECT_GOLD | PERFECT | EXCELLENT | GREAT | GOOD:
-        return true;
-      case SHIT:
-        return false;
-      default:
-        return false;
-    }
-  }
-
   public function getHorTextAsset()
   {
     switch (abstract)

From f7f311d6f2dc356b363efc8c2f6d7cdf50fd4e35 Mon Sep 17 00:00:00 2001
From: FabsTheFabs <flamingkitty24@gmail.com>
Date: Thu, 12 Sep 2024 21:07:40 +0100
Subject: [PATCH 32/41] assets submod.......

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

diff --git a/assets b/assets
index bd4e2421c..e9cb3eb69 160000
--- a/assets
+++ b/assets
@@ -1 +1 @@
-Subproject commit bd4e2421c87c31e244bc9c162850b842582c5de4
+Subproject commit e9cb3eb6922b60f43ab25b4695acfd15893ae96e

From 33df8936b10e5ee216f6c3817550945993d9466c Mon Sep 17 00:00:00 2001
From: Cameron Taylor <cameron.taylor.ninja@gmail.com>
Date: Thu, 12 Sep 2024 16:41:14 -0400
Subject: [PATCH 33/41] assets submod

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

diff --git a/assets b/assets
index 934468c04..7b5fc3055 160000
--- a/assets
+++ b/assets
@@ -1 +1 @@
-Subproject commit 934468c0472504c282b12c63b473e9f74b5b4517
+Subproject commit 7b5fc3055235c401dd711da9617b3719df1dcf27

From 1ee351c83d13b1c616ac3751675389943a715f83 Mon Sep 17 00:00:00 2001
From: Cameron Taylor <cameron.taylor.ninja@gmail.com>
Date: Thu, 12 Sep 2024 16:42:57 -0400
Subject: [PATCH 34/41] art submod

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

diff --git a/art b/art
index 42ac06e51..0dee03f11 160000
--- a/art
+++ b/art
@@ -1 +1 @@
-Subproject commit 42ac06e51207bda89144fd20a407ed3c3e0c6673
+Subproject commit 0dee03f11afc01c2883da223fa10405f7011dd33

From a4e977f60f531b90699473640be2ff0027c26b78 Mon Sep 17 00:00:00 2001
From: Cameron Taylor <cameron.taylor.ninja@gmail.com>
Date: Thu, 12 Sep 2024 16:45:20 -0400
Subject: [PATCH 35/41] assets submod

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

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

From a4bdeeaf5f9b3a7aa57a87c6d28b190e860e7749 Mon Sep 17 00:00:00 2001
From: EliteMasterEric <ericmyllyoja@gmail.com>
Date: Thu, 12 Sep 2024 17:13:40 -0400
Subject: [PATCH 36/41] Update polymod to fix a crash on missing imports

---
 hmm.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hmm.json b/hmm.json
index 50b81bb85..d967a69b3 100644
--- a/hmm.json
+++ b/hmm.json
@@ -194,7 +194,7 @@
       "name": "polymod",
       "type": "git",
       "dir": null,
-      "ref": "96cfc5fa693b017e47f7cb13b765cc68698fa6b6",
+      "ref": "0fbdf27fe124549730accd540cec8a183f8652c0",
       "url": "https://github.com/larsiusprime/polymod"
     },
     {

From ae6f431b6a9f7a05bf819c908794a16b2fb073f2 Mon Sep 17 00:00:00 2001
From: EliteMasterEric <ericmyllyoja@gmail.com>
Date: Thu, 12 Sep 2024 17:13:46 -0400
Subject: [PATCH 37/41] Update credits

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

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

From 703e8992882b8b3e70a74e74c31aa5e52137d6c2 Mon Sep 17 00:00:00 2001
From: FabsTheFabs <flamingkitty24@gmail.com>
Date: Thu, 12 Sep 2024 22:43:12 +0100
Subject: [PATCH 38/41] apply shader filter

---
 source/funkin/ui/charSelect/CharSelectSubState.hx | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/source/funkin/ui/charSelect/CharSelectSubState.hx b/source/funkin/ui/charSelect/CharSelectSubState.hx
index bd55bfdd9..00e15a299 100644
--- a/source/funkin/ui/charSelect/CharSelectSubState.hx
+++ b/source/funkin/ui/charSelect/CharSelectSubState.hx
@@ -324,6 +324,9 @@ class CharSelectSubState extends MusicBeatSubState
     // FlxG.camera.follow(camFollow, LOCKON, 0.01);
     FlxG.camera.follow(camFollow, LOCKON);
 
+    var fadeShaderFilter:ShaderFilter = new ShaderFilter(fadeShader);
+    FlxG.camera.filters = [fadeShaderFilter];
+
     var temp:FlxSprite = new FlxSprite();
     temp.loadGraphic(Paths.image('charSelect/placement'));
     add(temp);

From 5f60be6d7569862486c9eb062da60ee23305f008 Mon Sep 17 00:00:00 2001
From: FabsTheFabs <flamingkitty24@gmail.com>
Date: Thu, 12 Sep 2024 22:44:22 +0100
Subject: [PATCH 39/41] allow controls to get dialouge name from control +
 ignore brackets

---
 source/funkin/input/Controls.hx | 31 ++++++++++++++++++++++++-------
 1 file changed, 24 insertions(+), 7 deletions(-)

diff --git a/source/funkin/input/Controls.hx b/source/funkin/input/Controls.hx
index b5aefd08d..da5aaac58 100644
--- a/source/funkin/input/Controls.hx
+++ b/source/funkin/input/Controls.hx
@@ -395,20 +395,37 @@ class Controls extends FlxActionSet
     return result;
   }
 
-  public function getDialogueName(action:FlxActionDigital):String
+  public function getDialogueName(action:FlxActionDigital, ?ignoreSurrounding:Bool = false):String
   {
     var input = action.inputs[0];
-    return switch (input.device)
+    if (ignoreSurrounding == false)
     {
-      case KEYBOARD: return '[${(input.inputID : FlxKey)}]';
-      case GAMEPAD: return '(${(input.inputID : FlxGamepadInputID)})';
-      case device: throw 'unhandled device: $device';
+      return switch (input.device)
+      {
+        case KEYBOARD: return '[${(input.inputID : FlxKey)}]';
+        case GAMEPAD: return '(${(input.inputID : FlxGamepadInputID)})';
+        case device: throw 'unhandled device: $device';
+      }
+    }
+    else
+    {
+      return switch (input.device)
+      {
+        case KEYBOARD: return '${(input.inputID : FlxKey)}';
+        case GAMEPAD: return '${(input.inputID : FlxGamepadInputID)}';
+        case device: throw 'unhandled device: $device';
+      }
     }
   }
 
-  public function getDialogueNameFromToken(token:String):String
+  public function getDialogueNameFromToken(token:String, ?ignoreSurrounding:Bool = false):String
   {
-    return getDialogueName(getActionFromControl(Control.createByName(token.toUpperCase())));
+    return getDialogueName(getActionFromControl(Control.createByName(token.toUpperCase())), ignoreSurrounding);
+  }
+
+  public function getDialogueNameFromControl(control:Control, ?ignoreSurrounding:Bool = false):String
+  {
+    return getDialogueName(getActionFromControl(control), ignoreSurrounding);
   }
 
   function getActionFromControl(control:Control):FlxActionDigital

From bc86f1f459605450b092121ea295b8a3ef23541e Mon Sep 17 00:00:00 2001
From: FabsTheFabs <flamingkitty24@gmail.com>
Date: Thu, 12 Sep 2024 22:44:40 +0100
Subject: [PATCH 40/41] character select hint text

---
 source/funkin/ui/freeplay/FreeplayState.hx | 29 ++++++++++++++++++++--
 1 file changed, 27 insertions(+), 2 deletions(-)

diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx
index a908e54c6..23b9dd0bd 100644
--- a/source/funkin/ui/freeplay/FreeplayState.hx
+++ b/source/funkin/ui/freeplay/FreeplayState.hx
@@ -9,6 +9,7 @@ import flixel.group.FlxGroup.FlxTypedGroup;
 import flixel.group.FlxSpriteGroup.FlxTypedSpriteGroup;
 import flixel.input.touch.FlxTouch;
 import flixel.math.FlxAngle;
+import flixel.math.FlxMath;
 import flixel.math.FlxPoint;
 import flixel.system.debug.watch.Tracker.TrackerProfile;
 import flixel.text.FlxText;
@@ -180,6 +181,8 @@ class FreeplayState extends MusicBeatSubState
   var ostName:FlxText;
   var albumRoll:AlbumRoll;
 
+  var charSelectHint:FlxText;
+
   var letterSort:LetterSort;
   var exitMovers:ExitMoverData = new Map();
 
@@ -279,6 +282,7 @@ class FreeplayState extends MusicBeatSubState
     txtCompletion = new AtlasText(1185, 87, '69', AtlasFont.FREEPLAY_CLEAR);
 
     ostName = new FlxText(8, 8, FlxG.width - 8 - 8, 'OFFICIAL OST', 48);
+    charSelectHint = new FlxText(-40, 18, FlxG.width - 8 - 8, 'Press [ LOL ] to change characters', 32);
 
     bgDad = new FlxSprite(backingCard.pinkBack.width * 0.74, 0).loadGraphic(styleData == null ? 'freeplay/freeplayBGdad' : styleData.getBgAssetGraphic());
   }
@@ -498,7 +502,14 @@ class FreeplayState extends MusicBeatSubState
     ostName.alignment = RIGHT;
     ostName.visible = false;
 
-    exitMovers.set([overhangStuff, fnfFreeplay, ostName],
+    charSelectHint.alignment = CENTER;
+    charSelectHint.font = "5by7";
+    charSelectHint.color = 0xFF5F5F5F;
+    charSelectHint.text = 'Press [ ${controls.getDialogueNameFromControl(FREEPLAY_CHAR_SELECT, true)} ] to change characters';
+    charSelectHint.y -= 100;
+    FlxTween.tween(charSelectHint, {y: charSelectHint.y + 100}, 0.8, {ease: FlxEase.quartOut});
+
+    exitMovers.set([overhangStuff, fnfFreeplay, ostName, charSelectHint],
       {
         y: -overhangStuff.height,
         x: 0,
@@ -506,7 +517,7 @@ class FreeplayState extends MusicBeatSubState
         wait: 0
       });
 
-    exitMoversCharSel.set([overhangStuff, fnfFreeplay, ostName],
+    exitMoversCharSel.set([overhangStuff, fnfFreeplay, ostName, charSelectHint],
       {
         y: -300,
         speed: 0.8,
@@ -604,6 +615,11 @@ class FreeplayState extends MusicBeatSubState
     add(fnfFreeplay);
     add(ostName);
 
+    if (PlayerRegistry.instance.hasNewCharacter() == true)
+    {
+      add(charSelectHint);
+    }
+
     // be careful not to "add()" things in here unless it's to a group that's already added to the state
     // otherwise it won't be properly attatched to funnyCamera (relavent code should be at the bottom of create())
     var onDJIntroDone = function() {
@@ -1348,10 +1364,19 @@ class FreeplayState extends MusicBeatSubState
 
   var originalPos:FlxPoint = new FlxPoint();
 
+  var hintTimer:Float = 0;
+
   override function update(elapsed:Float):Void
   {
     super.update(elapsed);
 
+    if (charSelectHint != null)
+    {
+      hintTimer += elapsed * 2;
+      var targetAmt:Float = (Math.sin(hintTimer) + 1) / 2;
+      charSelectHint.alpha = FlxMath.lerp(0.3, 0.9, targetAmt);
+    }
+
     #if FEATURE_DEBUG_FUNCTIONS
     if (FlxG.keys.justPressed.P)
     {

From 2dc4e13b001de00318884dbbf635e26240586622 Mon Sep 17 00:00:00 2001
From: Cameron Taylor <cameron.taylor.ninja@gmail.com>
Date: Thu, 12 Sep 2024 19:08:13 -0400
Subject: [PATCH 41/41] assets submod

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

diff --git a/assets b/assets
index dd2aab796..41d20d45d 160000
--- a/assets
+++ b/assets
@@ -1 +1 @@
-Subproject commit dd2aab796d2a54cf01c534402aa922da1f820080
+Subproject commit 41d20d45d7503aaf1dfac825239620cffb512166