diff --git a/assets/data/characters/bf-dead.xml b/assets/data/characters/bf-dead.xml
new file mode 100644
index 00000000..c7ddf764
--- /dev/null
+++ b/assets/data/characters/bf-dead.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/assets/data/scripts/pixel.hx b/assets/data/scripts/pixel.hx
index 736fb8c9..3d4addf2 100644
--- a/assets/data/scripts/pixel.hx
+++ b/assets/data/scripts/pixel.hx
@@ -4,6 +4,7 @@ import funkin.scripting.events.NoteHitEvent;
public var pixelNotesForBF = true;
public var pixelNotesForDad = true;
public var enablePixelUI = true;
+public var enablePixelGameOver = true;
public var enableCameraHacks = true;
public var enablePauseMenu = true;
public var isSpooky = false;
@@ -91,6 +92,11 @@ function postCreate() {
makeCameraPixely(camGame);
defaultCamZoom /= daPixelZoom;
}
+ if (enablePixelGameOver) {
+ gameOverSong = "pixel/gameOver";
+ lossSFX = "pixel/gameOverSFX";
+ retrySFX = "pixel/gameOverEnd";
+ }
}
function onStartCountdown() {
diff --git a/assets/images/characters/bf-dead.png b/assets/images/characters/bf-dead.png
new file mode 100644
index 00000000..ab244180
Binary files /dev/null and b/assets/images/characters/bf-dead.png differ
diff --git a/assets/images/characters/bf-dead.xml b/assets/images/characters/bf-dead.xml
new file mode 100644
index 00000000..b42e3cd2
--- /dev/null
+++ b/assets/images/characters/bf-dead.xml
@@ -0,0 +1,131 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/assets/music/gameOverEnd.mp3 b/assets/music/gameOverEnd.mp3
deleted file mode 100644
index 684181be..00000000
Binary files a/assets/music/gameOverEnd.mp3 and /dev/null differ
diff --git a/assets/music/gameOverEnd.ogg b/assets/music/gameOverEnd.ogg
deleted file mode 100644
index f1010742..00000000
Binary files a/assets/music/gameOverEnd.ogg and /dev/null differ
diff --git a/assets/music/pixel/gameOver-pixel.mp3 b/assets/music/pixel/gameOver.mp3
similarity index 100%
rename from assets/music/pixel/gameOver-pixel.mp3
rename to assets/music/pixel/gameOver.mp3
diff --git a/assets/music/pixel/gameOver-pixel.ogg b/assets/music/pixel/gameOver.ogg
similarity index 100%
rename from assets/music/pixel/gameOver-pixel.ogg
rename to assets/music/pixel/gameOver.ogg
diff --git a/assets/sounds/gameOverEnd.mp3 b/assets/sounds/gameOverEnd.mp3
new file mode 100644
index 00000000..cd77340c
Binary files /dev/null and b/assets/sounds/gameOverEnd.mp3 differ
diff --git a/assets/sounds/gameOverEnd.ogg b/assets/sounds/gameOverEnd.ogg
new file mode 100644
index 00000000..b1c2c219
Binary files /dev/null and b/assets/sounds/gameOverEnd.ogg differ
diff --git a/assets/sounds/fnf_loss_sfx.mp3 b/assets/sounds/gameOverSFX.mp3
similarity index 100%
rename from assets/sounds/fnf_loss_sfx.mp3
rename to assets/sounds/gameOverSFX.mp3
diff --git a/assets/sounds/fnf_loss_sfx.ogg b/assets/sounds/gameOverSFX.ogg
similarity index 100%
rename from assets/sounds/fnf_loss_sfx.ogg
rename to assets/sounds/gameOverSFX.ogg
diff --git a/assets/music/pixel/gameOverEnd-pixel.mp3 b/assets/sounds/pixel/gameOverEnd.mp3
similarity index 100%
rename from assets/music/pixel/gameOverEnd-pixel.mp3
rename to assets/sounds/pixel/gameOverEnd.mp3
diff --git a/assets/music/pixel/gameOverEnd-pixel.ogg b/assets/sounds/pixel/gameOverEnd.ogg
similarity index 100%
rename from assets/music/pixel/gameOverEnd-pixel.ogg
rename to assets/sounds/pixel/gameOverEnd.ogg
diff --git a/assets/sounds/fnf_loss_sfx-pixel.mp3 b/assets/sounds/pixel/gameOverSFX.mp3
similarity index 100%
rename from assets/sounds/fnf_loss_sfx-pixel.mp3
rename to assets/sounds/pixel/gameOverSFX.mp3
diff --git a/assets/sounds/fnf_loss_sfx-pixel.ogg b/assets/sounds/pixel/gameOverSFX.ogg
similarity index 100%
rename from assets/sounds/fnf_loss_sfx-pixel.ogg
rename to assets/sounds/pixel/gameOverSFX.ogg
diff --git a/buildnumber.txt b/buildnumber.txt
index aede7734..6f5d72ea 100644
--- a/buildnumber.txt
+++ b/buildnumber.txt
@@ -1 +1 @@
-1384
\ No newline at end of file
+1391
\ No newline at end of file
diff --git a/source/funkin/game/Character.hx b/source/funkin/game/Character.hx
index 0b5aab40..a04e7a03 100644
--- a/source/funkin/game/Character.hx
+++ b/source/funkin/game/Character.hx
@@ -47,6 +47,7 @@ class Character extends FlxSprite implements IBeatReceiver implements IOffsetCom
public var playerOffsets:Bool = false;
public var icon:String = null;
+ public var gameOverCharacter:String = "bf-dead";
public var cameraOffset:FlxPoint = new FlxPoint(0, 0);
public var globalOffset:FlxPoint = new FlxPoint(0, 0);
@@ -111,6 +112,7 @@ class Character extends FlxSprite implements IBeatReceiver implements IOffsetCom
if (xml.has.isGF) isGF = (xml.att.isGF == "true");
if (xml.has.x) globalOffset.x = Std.parseFloat(xml.att.x);
if (xml.has.y) globalOffset.y = Std.parseFloat(xml.att.y);
+ if (xml.has.gameOverChar) gameOverCharacter = xml.att.gameOverChar;
if (xml.has.camx) cameraOffset.x = Std.parseFloat(xml.att.camx);
if (xml.has.camy) cameraOffset.y = Std.parseFloat(xml.att.camy);
if (xml.has.holdTime) holdTime = CoolUtil.getDefault(Std.parseFloat(xml.att.holdTime), 4);
@@ -142,56 +144,6 @@ class Character extends FlxSprite implements IBeatReceiver implements IOffsetCom
/**
NON CONVERTED CHARACTERS - DO NOT REMOVE
**/
- // case 'gf-pixel':
- // tex = Paths.getSparrowAtlas('weeb/gfPixel');
- // frames = tex;
- // animation.addByIndices('singUP', 'GF IDLE', [2], "", 24, false);
- // animation.addByIndices('danceLeft', 'GF IDLE', [30, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14], "", 24, false);
- // animation.addByIndices('danceRight', 'GF IDLE', [15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29], "", 24, false);
-
- // addOffset('danceLeft', 0);
- // addOffset('danceRight', 0);
-
- // playAnim('danceRight');
-
- // setGraphicSize(Std.int(width * PlayState.daPixelZoom));
- // updateHitbox();
- // antialiasing = false;
- // flipX = true;
-
- // case 'bf-pixel':
- // frames = Paths.getSparrowAtlas('weeb/bfPixel');
- // animation.addByPrefix('idle', 'BF IDLE', 24, false);
- // animation.addByPrefix('singUP', 'BF UP NOTE', 24, false);
- // animation.addByPrefix('singLEFT', 'BF LEFT NOTE', 24, false);
- // animation.addByPrefix('singRIGHT', 'BF RIGHT NOTE', 24, false);
- // animation.addByPrefix('singDOWN', 'BF DOWN NOTE', 24, false);
- // animation.addByPrefix('singUPmiss', 'BF UP MISS', 24, false);
- // animation.addByPrefix('singLEFTmiss', 'BF LEFT MISS', 24, false);
- // animation.addByPrefix('singRIGHTmiss', 'BF RIGHT MISS', 24, false);
- // animation.addByPrefix('singDOWNmiss', 'BF DOWN MISS', 24, false);
-
- // addOffset('idle');
- // addOffset("singUP");
- // addOffset("singRIGHT");
- // addOffset("singLEFT");
- // addOffset("singDOWN");
- // addOffset("singUPmiss");
- // addOffset("singRIGHTmiss");
- // addOffset("singLEFTmiss");
- // addOffset("singDOWNmiss");
-
- // setGraphicSize(Std.int(width * 6));
- // updateHitbox();
-
- // playAnim('idle');
-
- // width -= 100;
- // height -= 100;
-
- // antialiasing = false;
-
- // flipX = true;
// case 'bf-pixel-dead':
// frames = Paths.getSparrowAtlas('weeb/bfPixelsDEAD');
// animation.addByPrefix('singUP', "BF Dies pixel", 24, false);
@@ -210,67 +162,6 @@ class Character extends FlxSprite implements IBeatReceiver implements IOffsetCom
// antialiasing = false;
// flipX = true;
- // case 'senpai':
- // frames = Paths.getSparrowAtlas('weeb/senpai');
- // animation.addByPrefix('idle', 'Senpai Idle', 24, false);
- // animation.addByPrefix('singUP', 'SENPAI UP NOTE', 24, false);
- // animation.addByPrefix('singLEFT', 'SENPAI LEFT NOTE', 24, false);
- // animation.addByPrefix('singRIGHT', 'SENPAI RIGHT NOTE', 24, false);
- // animation.addByPrefix('singDOWN', 'SENPAI DOWN NOTE', 24, false);
-
- // addOffset('idle');
- // addOffset("singUP", 5, 37);
- // addOffset("singRIGHT");
- // addOffset("singLEFT", 40);
- // addOffset("singDOWN", 14);
-
- // playAnim('idle');
-
- // setGraphicSize(Std.int(width * 6));
- // updateHitbox();
-
- // antialiasing = false;
- // case 'senpai-angry':
- // frames = Paths.getSparrowAtlas('weeb/senpai');
- // animation.addByPrefix('idle', 'Angry Senpai Idle', 24, false);
- // animation.addByPrefix('singUP', 'Angry Senpai UP NOTE', 24, false);
- // animation.addByPrefix('singLEFT', 'Angry Senpai LEFT NOTE', 24, false);
- // animation.addByPrefix('singRIGHT', 'Angry Senpai RIGHT NOTE', 24, false);
- // animation.addByPrefix('singDOWN', 'Angry Senpai DOWN NOTE', 24, false);
-
- // addOffset('idle');
- // addOffset("singUP", 5, 37);
- // addOffset("singRIGHT");
- // addOffset("singLEFT", 40);
- // addOffset("singDOWN", 14);
- // playAnim('idle');
-
- // setGraphicSize(Std.int(width * 6));
- // updateHitbox();
-
- // antialiasing = false;
-
- // case 'spirit':
- // frames = Paths.getPackerAtlas('weeb/spirit');
- // animation.addByPrefix('idle', "idle spirit_", 24, false);
- // animation.addByPrefix('singUP', "up_", 24, false);
- // animation.addByPrefix('singRIGHT', "right_", 24, false);
- // animation.addByPrefix('singLEFT', "left_", 24, false);
- // animation.addByPrefix('singDOWN', "spirit down_", 24, false);
-
- // addOffset('idle', -220, -280);
- // addOffset('singUP', -220, -240);
- // addOffset("singRIGHT", -220, -280);
- // addOffset("singLEFT", -200, -280);
- // addOffset("singDOWN", 170, 110);
-
- // setGraphicSize(Std.int(width * 6));
- // updateHitbox();
-
- // playAnim('idle');
-
- // antialiasing = false;
-
isDanceLeftDanceRight = (animation.getByName("danceLeft") != null && animation.getByName("danceRight") != null);
diff --git a/source/funkin/game/GameOverSubstate.hx b/source/funkin/game/GameOverSubstate.hx
index c467c04b..01641dce 100644
--- a/source/funkin/game/GameOverSubstate.hx
+++ b/source/funkin/game/GameOverSubstate.hx
@@ -14,24 +14,26 @@ import funkin.system.Conductor;
class GameOverSubstate extends MusicBeatSubstate
{
- var bf:Character;
- public var character:String;
+ var character:Character;
+ public var characterName:String;
public var gameOverSong:String;
+ public var lossSFXName:String;
+ public var retrySFX:String;
var camFollow:FlxObject;
- var stageSuffix:String = "";
-
var x:Float = 0;
var y:Float = 0;
public var lossSFX:FlxSound;
- public function new(x:Float, y:Float, character:String = "bf", gameOverSong:String = "gameOver") {
+ public function new(x:Float, y:Float, character:String = "bf-dead", gameOverSong:String = "gameOver", lossSFX:String = "gameOverSFX", retrySFX:String = "gameOverEnd") {
super();
this.x = x;
this.y = y;
- this.character = character;
+ this.characterName = character;
this.gameOverSong = gameOverSong;
+ this.lossSFXName = lossSFX;
+ this.retrySFX = retrySFX;
}
public override function create()
@@ -40,18 +42,18 @@ class GameOverSubstate extends MusicBeatSubstate
if (FlxG.sound.music != null)
FlxG.sound.music.stop();
- bf = new Character(x, y, character, true);
- add(bf);
+ character = new Character(x, y, characterName, true);
+ character.danceOnBeat = false;
+ character.playAnim('firstDeath');
+ add(character);
- camFollow = new FlxObject(bf.getGraphicMidpoint().x, bf.getGraphicMidpoint().y, 1, 1);
+ var camPos = character.getCameraPosition();
+ camFollow = new FlxObject(camPos.x, camPos.y, 1, 1);
add(camFollow);
FlxG.camera.target = camFollow;
- lossSFX = FlxG.sound.play(Paths.sound('fnf_loss_sfx' + stageSuffix));
+ lossSFX = FlxG.sound.play(Paths.sound(lossSFXName));
Conductor.changeBPM(100);
-
- bf.danceOnBeat = false;
- bf.playAnim('firstDeath');
}
override function update(elapsed:Float)
@@ -67,6 +69,7 @@ class GameOverSubstate extends MusicBeatSubstate
{
if (FlxG.sound.music != null)
FlxG.sound.music.stop();
+ FlxG.sound.music = null;
if (PlayState.isStoryMode)
FlxG.switchState(new StoryMenuState());
@@ -74,7 +77,7 @@ class GameOverSubstate extends MusicBeatSubstate
FlxG.switchState(new FreeplayState());
}
- if (!lossSFX.playing && (FlxG.sound.music == null || !FlxG.sound.music.playing))
+ if (!isEnding && ((!lossSFX.playing) || (character.animation.curAnim != null && character.animation.curAnim.name == "firstDeath" && character.animation.curAnim.finished)) && (FlxG.sound.music == null || !FlxG.sound.music.playing))
CoolUtil.playMusic(Paths.music(gameOverSong), 100);
}
@@ -82,7 +85,7 @@ class GameOverSubstate extends MusicBeatSubstate
{
super.beatHit(curBeat);
if (!lossSFX.playing)
- bf.playAnim("deathLoop", DANCE);
+ character.playAnim("deathLoop", true, DANCE);
}
var isEnding:Bool = false;
@@ -92,12 +95,22 @@ class GameOverSubstate extends MusicBeatSubstate
if (!isEnding)
{
isEnding = true;
- bf.playAnim('deathConfirm', true);
+ character.playAnim('deathConfirm', true);
FlxG.sound.music.stop();
- FlxG.sound.play(Paths.music('gameOverEnd' + stageSuffix));
- new FlxTimer().start(0.7, function(tmr:FlxTimer)
+ var sound = FlxG.sound.play(Paths.sound(retrySFX));
+
+ var secsLength:Float = sound.length / 1000;
+ var waitTime = 0.7;
+ var fadeOutTime = secsLength - 0.7;
+
+ if (fadeOutTime < 0.5) {
+ fadeOutTime = secsLength;
+ waitTime = 0;
+ }
+
+ new FlxTimer().start(waitTime, function(tmr:FlxTimer)
{
- FlxG.camera.fade(FlxColor.BLACK, 2, false, function()
+ FlxG.camera.fade(FlxColor.BLACK, fadeOutTime, false, function()
{
FlxTransitionableState.skipNextTransOut = true;
FlxG.switchState(new PlayState());
diff --git a/source/funkin/game/PlayState.hx b/source/funkin/game/PlayState.hx
index 6184a2b6..69f44ce6 100644
--- a/source/funkin/game/PlayState.hx
+++ b/source/funkin/game/PlayState.hx
@@ -80,7 +80,12 @@ class PlayState extends MusicBeatState
public var scripts:ScriptPack;
public var halloweenLevel:Bool = false;
+ public var gameOverSong:String = "gameOver";
+ public var lossSFX:String = "fnf_loss_sfx";
+ public var retrySFX:String = "gameOverEnd";
+
public var stage:Stage;
+ public var canDie:Bool = true;
public var scrollSpeed:Float = 0;
public var downscroll(get, set):Bool;
@@ -782,6 +787,8 @@ class PlayState extends MusicBeatState
super.closeSubState();
}
+ var __wereVocalsPlaying:Bool = false;
+ var __wasAutoPause:Bool = false;
override public function onFocus():Void
{
scripts.call("onFocus");
@@ -798,6 +805,8 @@ class PlayState extends MusicBeatState
}
}
#end
+ if (__wasAutoPause && __wereVocalsPlaying)
+ vocals.play();
super.onFocus();
}
@@ -811,6 +820,11 @@ class PlayState extends MusicBeatState
DiscordClient.changePresence(detailsPausedText, SONG.song + " (" + difficultyText + ")", iconRPC);
}
#end
+ if (__wasAutoPause = FlxG.autoPause) {
+ __wereVocalsPlaying = vocals.playing;
+ vocals.pause();
+ }
+
super.onFocusLost();
}
@@ -1003,31 +1017,8 @@ class PlayState extends MusicBeatState
trace("User is cheating!");
}
- if (health <= 0)
- {
- boyfriend.stunned = true;
-
- persistentUpdate = false;
- persistentDraw = false;
- paused = true;
-
- vocals.stop();
- FlxG.sound.music.stop();
-
- openSubState(new GameOverSubstate(boyfriend.x, boyfriend.y));
-
- // FlxG.switchState(new GameOverState(boyfriend.getScreenPosition().x, boyfriend.getScreenPosition().y));
-
- #if desktop
- // Game Over doesn't get his own variable because it's only used here
- DiscordClient.changePresence("Game Over - " + detailsText, SONG.song + " (" + difficultyText + ")", iconRPC);
- #end
- }
-
- // while(unspawnNotes[0] != null && unspawnNotes[0].strumTime - Conductor.songPosition < 1500)
- // notes.add(unspawnNotes.shift());
-
-
+ if (health <= 0 && canDie)
+ gameOver();
if (generatedMusic)
{
@@ -1091,6 +1082,30 @@ class PlayState extends MusicBeatState
scripts.call("postUpdate", [elapsed]);
}
+ function gameOver(?character:String, ?gameOverSong:String, ?lossSFX:String, ?retrySFX:String) {
+ character = character.getDefault((boyfriend != null) ? boyfriend.gameOverCharacter : "bf-dead");
+ gameOverSong.getDefault(this.gameOverSong);
+ lossSFX.getDefault(this.lossSFX);
+ retrySFX.getDefault(this.retrySFX);
+
+ boyfriend.stunned = true;
+
+ persistentUpdate = false;
+ persistentDraw = false;
+ paused = true;
+
+ vocals.stop();
+ if (FlxG.sound.music != null)
+ FlxG.sound.music.stop();
+
+ openSubState(new GameOverSubstate(boyfriend.x, boyfriend.y, character, gameOverSong, lossSFX, retrySFX));
+
+ #if desktop
+ // Game Over doesn't get his own variable because it's only used here
+ DiscordClient.changePresence("Game Over - " + detailsText, SONG.song + " (" + difficultyText + ")", iconRPC);
+ #end
+ }
+
function endSong():Void
{
scripts.call("onSongEnd");