From 482de2a12276ade9a5a4373d55bb17ca3f7dc647 Mon Sep 17 00:00:00 2001
From: EliteMasterEric <ericmyllyoja@gmail.com>
Date: Mon, 22 May 2023 20:55:53 -0400
Subject: [PATCH] Added Nightmare difficulty (stub)

---
 hmm.json                                 |  4 +-
 source/funkin/InitState.hx               |  2 +
 source/funkin/LatencyState.hx            | 15 +++----
 source/funkin/ui/story/Level.hx          |  9 +++-
 source/funkin/ui/story/StoryMenuState.hx | 56 ++++++++++++++++++++++--
 5 files changed, 69 insertions(+), 17 deletions(-)

diff --git a/hmm.json b/hmm.json
index 0ef6974ee..572d4d3d3 100644
--- a/hmm.json
+++ b/hmm.json
@@ -11,7 +11,7 @@
       "name": "flixel",
       "type": "git",
       "dir": null,
-      "ref": "d6100cc8",
+      "ref": "3de38a0",
       "url": "https://github.com/EliteMasterEric/flixel"
     },
     {
@@ -118,4 +118,4 @@
       "version": "0.2.2"
     }
   ]
-}
\ No newline at end of file
+}
diff --git a/source/funkin/InitState.hx b/source/funkin/InitState.hx
index e21cfda69..45c2645df 100644
--- a/source/funkin/InitState.hx
+++ b/source/funkin/InitState.hx
@@ -78,6 +78,7 @@ class InitState extends FlxTransitionableState
       }
     });
 
+    #if FLX_DEBUG
     FlxG.debugger.addButton(CENTER, new BitmapData(20, 20, true, 0xFF2222CC), function() {
       FlxG.game.debugger.vcr.onStep();
 
@@ -90,6 +91,7 @@ class InitState extends FlxTransitionableState
       FlxG.sound.music.pause();
       FlxG.sound.music.time += FlxG.elapsed * 1000;
     });
+    #end
 
     FlxG.sound.muteKeys = [ZERO];
     FlxG.game.focusLostFramerate = 60;
diff --git a/source/funkin/LatencyState.hx b/source/funkin/LatencyState.hx
index 256efde5c..04a14b90a 100644
--- a/source/funkin/LatencyState.hx
+++ b/source/funkin/LatencyState.hx
@@ -31,7 +31,7 @@ class LatencyState extends MusicBeatSubstate
   var offsetsPerBeat:Array<Int> = [];
   var swagSong:HomemadeMusic;
 
-  #if debug
+  #if FLX_DEBUG
   var funnyStatsGraph:CoolStatsGraph;
   var realStats:CoolStatsGraph;
   #end
@@ -44,7 +44,7 @@ class LatencyState extends MusicBeatSubstate
     FlxG.sound.music = swagSong;
     FlxG.sound.music.play();
 
-    #if debug
+    #if FLX_DEBUG
     funnyStatsGraph = new CoolStatsGraph(0, Std.int(FlxG.height / 2), FlxG.width, Std.int(FlxG.height / 2), FlxColor.PINK, "time");
     FlxG.addChildBelowMouse(funnyStatsGraph);
 
@@ -52,8 +52,7 @@ class LatencyState extends MusicBeatSubstate
     FlxG.addChildBelowMouse(realStats);
     #end
 
-    FlxG.stage.addEventListener(KeyboardEvent.KEY_DOWN, key ->
-    {
+    FlxG.stage.addEventListener(KeyboardEvent.KEY_DOWN, key -> {
       trace(key.charCode);
 
       if (key.charCode == 120) generateBeatStuff();
@@ -154,8 +153,7 @@ class LatencyState extends MusicBeatSubstate
 
   override function beatHit():Bool
   {
-    if (curBeat % 8 == 0) blocks.forEach(blok ->
-    {
+    if (curBeat % 8 == 0) blocks.forEach(blok -> {
       blok.alpha = 0;
     });
 
@@ -172,7 +170,7 @@ class LatencyState extends MusicBeatSubstate
       trace(FlxG.sound.music._channel.position);
      */
 
-    #if debug
+    #if FLX_DEBUG
     funnyStatsGraph.update(FlxG.sound.music.time % 500);
     realStats.update(swagSong.getTimeWithDiff() % 500);
     #end
@@ -248,8 +246,7 @@ class LatencyState extends MusicBeatSubstate
         FlxG.resetState();
     }*/
 
-    noteGrp.forEach(function(daNote:Note)
-    {
+    noteGrp.forEach(function(daNote:Note) {
       daNote.y = (strumLine.y - ((Conductor.songPosition - Conductor.audioOffset) - daNote.data.strumTime) * 0.45);
       daNote.x = strumLine.x + 30;
 
diff --git a/source/funkin/ui/story/Level.hx b/source/funkin/ui/story/Level.hx
index f44023690..5d24de312 100644
--- a/source/funkin/ui/story/Level.hx
+++ b/source/funkin/ui/story/Level.hx
@@ -116,9 +116,12 @@ class Level implements IRegistryEntry<LevelData>
     var firstSongId:String = songList[0];
     var firstSong:Song = funkin.play.song.SongData.SongDataParser.fetchSong(firstSongId);
 
-    for (difficulty in firstSong.listDifficulties())
+    if (firstSong != null)
     {
-      difficulties.push(difficulty);
+      for (difficulty in firstSong.listDifficulties())
+      {
+        difficulties.push(difficulty);
+      }
     }
 
     // Filter to only include difficulties that are present in all songs
@@ -138,6 +141,8 @@ class Level implements IRegistryEntry<LevelData>
       }
     }
 
+    if (difficulties.length == 0) difficulties = ['normal'];
+
     return difficulties;
   }
 
diff --git a/source/funkin/ui/story/StoryMenuState.hx b/source/funkin/ui/story/StoryMenuState.hx
index 9a854128b..8a856baf6 100644
--- a/source/funkin/ui/story/StoryMenuState.hx
+++ b/source/funkin/ui/story/StoryMenuState.hx
@@ -1,5 +1,6 @@
 package funkin.ui.story;
 
+import openfl.utils.Assets;
 import flixel.addons.transition.FlxTransitionableState;
 import flixel.FlxSprite;
 import flixel.group.FlxGroup.FlxTypedGroup;
@@ -202,14 +203,29 @@ class StoryMenuState extends MusicBeatState
     if (difficultySprite == null)
     {
       difficultySprite = new FlxSprite(leftDifficultyArrow.x + leftDifficultyArrow.width + 10, leftDifficultyArrow.y);
-      difficultySprite.loadGraphic(Paths.image('storymenu/difficulties/${currentDifficultyId}'));
+
+      if (Assets.exists(Paths.file('images/storymenu/difficulties/${currentDifficultyId}.xml')))
+      {
+        difficultySprite.frames = Paths.getSparrowAtlas('storymenu/difficulties/${currentDifficultyId}');
+        difficultySprite.animation.addByPrefix('idle', 'idle0', 24, true);
+        difficultySprite.animation.play('idle');
+      }
+      else
+      {
+        difficultySprite.loadGraphic(Paths.image('storymenu/difficulties/${currentDifficultyId}'));
+      }
+
       difficultySprites.set(currentDifficultyId, difficultySprite);
 
       difficultySprite.x += (difficultySprites.get('normal').width - difficultySprite.width) / 2;
     }
     difficultySprite.alpha = 0;
+
     difficultySprite.y = leftDifficultyArrow.y - 15;
-    FlxTween.tween(difficultySprite, {y: leftDifficultyArrow.y + 15, alpha: 1}, 0.07);
+    var targetY:Float = leftDifficultyArrow.y + 10;
+    targetY -= (difficultySprite.height - difficultySprites.get('normal').height) / 2;
+    FlxTween.tween(difficultySprite, {y: targetY, alpha: 1}, 0.07);
+
     add(difficultySprite);
   }
 
@@ -218,7 +234,7 @@ class StoryMenuState extends MusicBeatState
     levelTitles.clear();
 
     var levelIds:Array<String> = displayingModdedLevels ? LevelRegistry.instance.listModdedLevelIds() : LevelRegistry.instance.listBaseGameLevelIds();
-    if (levelIds.length == 0) levelIds = ['tutorial'];
+    if (levelIds.length == 0) levelIds = ['tutorial']; // Make sure there's at least one level to display.
 
     for (levelIndex in 0...levelIds.length)
     {
@@ -267,11 +283,13 @@ class StoryMenuState extends MusicBeatState
         if (controls.UI_UP_P)
         {
           changeLevel(-1);
+          changeDifficulty(0);
         }
 
         if (controls.UI_DOWN_P)
         {
           changeLevel(1);
+          changeDifficulty(0);
         }
 
         if (controls.UI_RIGHT)
@@ -385,9 +403,39 @@ class StoryMenuState extends MusicBeatState
     if (currentIndex < 0) currentIndex = difficultyList.length - 1;
     if (currentIndex >= difficultyList.length) currentIndex = 0;
 
+    var hasChanged:Bool = currentDifficultyId != difficultyList[currentIndex];
     currentDifficultyId = difficultyList[currentIndex];
 
-    buildDifficultySprite();
+    if (difficultyList.length <= 1)
+    {
+      leftDifficultyArrow.visible = false;
+      rightDifficultyArrow.visible = false;
+    }
+    else
+    {
+      leftDifficultyArrow.visible = true;
+      rightDifficultyArrow.visible = true;
+    }
+
+    if (hasChanged)
+    {
+      buildDifficultySprite();
+      funnyMusicThing();
+    }
+  }
+
+  final FADE_OUT_TIME:Float = 1.5;
+
+  function funnyMusicThing():Void
+  {
+    if (currentDifficultyId == "nightmare")
+    {
+      FlxG.sound.music.fadeOut(FADE_OUT_TIME, 0.0);
+    }
+    else
+    {
+      FlxG.sound.music.fadeOut(FADE_OUT_TIME, 1.0);
+    }
   }
 
   override function dispatchEvent(event:ScriptEvent):Void