From 3e093510af31fa3261bf4dcb10ae9008a766046b Mon Sep 17 00:00:00 2001
From: EliteMasterEric <ericmyllyoja@gmail.com>
Date: Fri, 4 Aug 2023 12:35:01 -0400
Subject: [PATCH] Fixed a bug where beat hit events were called multiple times
 during the conductor

---
 source/funkin/play/Countdown.hx    |  6 +++---
 source/funkin/play/PlayState.hx    | 10 ----------
 source/funkin/play/song/Song.hx    | 20 ++++++++++++++++----
 source/funkin/play/stage/Bopper.hx |  2 ++
 source/funkin/play/stage/Stage.hx  |  6 +++++-
 5 files changed, 26 insertions(+), 18 deletions(-)

diff --git a/source/funkin/play/Countdown.hx b/source/funkin/play/Countdown.hx
index 48e98e84f..33c0f852f 100644
--- a/source/funkin/play/Countdown.hx
+++ b/source/funkin/play/Countdown.hx
@@ -54,9 +54,9 @@ class Countdown
 
       countdownStep = decrement(countdownStep);
 
-      // Handle onBeatHit events manually
-      @:privateAccess
-      PlayState.instance.dispatchEvent(new SongTimeScriptEvent(ScriptEvent.SONG_BEAT_HIT, 0, 0));
+      // onBeatHit events are now properly dispatched by the Conductor even at negative timestamps,
+      // so calling this is no longer necessary.
+      // PlayState.instance.dispatchEvent(new SongTimeScriptEvent(ScriptEvent.SONG_BEAT_HIT, 0, 0));
 
       // Countdown graphic.
       showCountdownGraphic(countdownStep, isPixelStyle);
diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx
index 297f14d69..e3d14289e 100644
--- a/source/funkin/play/PlayState.hx
+++ b/source/funkin/play/PlayState.hx
@@ -811,16 +811,6 @@ class PlayState extends MusicBeatSubState
       FlxG.watch.addQuick('bfAnim', currentStage.getBoyfriend().getCurrentAnimation());
     }
 
-    if (currentStage.getBoyfriend() != null)
-    {
-      FlxG.watch.addQuick('bfCameraFocus', currentStage.getBoyfriend().cameraFocusPoint);
-    }
-
-    if (currentStage.getDad() != null)
-    {
-      FlxG.watch.addQuick('dadCameraFocus', currentStage.getDad().cameraFocusPoint);
-    }
-
     // TODO: Add a song event for Handle GF dance speed.
 
     // Handle player death.
diff --git a/source/funkin/play/song/Song.hx b/source/funkin/play/song/Song.hx
index ab22ad9e9..398c28753 100644
--- a/source/funkin/play/song/Song.hx
+++ b/source/funkin/play/song/Song.hx
@@ -51,13 +51,23 @@ class Song implements IPlayStateScriptedClass
     difficultyIds = [];
     difficulties = new Map<String, SongDifficulty>();
 
-    _metadata = SongDataParser.loadSongMetadata(songId);
-    if (_metadata == null || _metadata.length == 0 && !ignoreErrors)
+    try
+    {
+      _metadata = SongDataParser.loadSongMetadata(songId);
+    }
+    catch (e)
+    {
+      _metadata = [];
+    }
+
+    if (_metadata.length == 0 && !ignoreErrors)
     {
       throw 'Could not find song data for songId: $songId';
     }
-
-    populateFromMetadata();
+    else
+    {
+      populateFromMetadata();
+    }
   }
 
   @:allow(funkin.play.song.Song)
@@ -97,6 +107,8 @@ class Song implements IPlayStateScriptedClass
    */
   function populateFromMetadata():Void
   {
+    if (_metadata == null || _metadata.length == 0) return;
+
     // Variations may have different artist, time format, generatedBy, etc.
     for (metadata in _metadata)
     {
diff --git a/source/funkin/play/stage/Bopper.hx b/source/funkin/play/stage/Bopper.hx
index d88618f8a..a144026f5 100644
--- a/source/funkin/play/stage/Bopper.hx
+++ b/source/funkin/play/stage/Bopper.hx
@@ -203,10 +203,12 @@ class Bopper extends StageProp implements IPlayStateScriptedClass
     {
       if (hasDanced)
       {
+        trace('DanceRight (alternate)');
         playAnimation('danceRight$idleSuffix', forceRestart);
       }
       else
       {
+        trace('DanceLeft (alternate)');
         playAnimation('danceLeft$idleSuffix', forceRestart);
       }
       hasDanced = !hasDanced;
diff --git a/source/funkin/play/stage/Stage.hx b/source/funkin/play/stage/Stage.hx
index d2b157acd..f4f380a0b 100644
--- a/source/funkin/play/stage/Stage.hx
+++ b/source/funkin/play/stage/Stage.hx
@@ -241,7 +241,11 @@ class Stage extends FlxSpriteGroup implements IPlayStateScriptedClass
         propSprite.animation.play(dataProp.startingAnimation);
       }
 
-      if (Std.isOfType(propSprite, Bopper))
+      if (Std.isOfType(propSprite, BaseCharacter))
+      {
+        // Character stuff.
+      }
+      else if (Std.isOfType(propSprite, Bopper))
       {
         addBopper(cast propSprite, dataProp.name);
       }