This commit is contained in:
Til 2025-04-04 12:32:04 -07:00 committed by GitHub
commit a5f0077f9e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 123 additions and 40 deletions

View file

@ -375,6 +375,7 @@ class FunkinSound extends FlxSound implements ICloneable<FunkinSound>
music.future.onComplete(function(partialMusic:Null<FunkinSound>) {
FlxG.sound.music = partialMusic;
FlxG.sound.list.remove(FlxG.sound.music);
pool.remove(cast FlxG.sound.music);
if (FlxG.sound.music != null && params.onLoad != null) params.onLoad();
});
@ -395,6 +396,7 @@ class FunkinSound extends FlxSound implements ICloneable<FunkinSound>
// Prevent repeat update() and onFocus() calls.
FlxG.sound.list.remove(FlxG.sound.music);
pool.remove(cast FlxG.sound.music);
if (FlxG.sound.music != null && params.onLoad != null) params.onLoad();

View file

@ -6,6 +6,8 @@ import openfl.filters.ColorMatrixFilter;
class RetroCameraFade
{
static var fadeTimer:FlxTimer;
// im lazy, but we only use this for week 6
// and also sorta yoinked for djflixel, lol !
public static function fadeWhite(camera:FlxCamera, camSteps:Int = 5, time:Float = 1):Void
@ -13,7 +15,13 @@ class RetroCameraFade
var steps:Int = 0;
var stepsTotal:Int = camSteps;
new FlxTimer().start(time / stepsTotal, _ -> {
if (fadeTimer != null)
{
fadeTimer.cancel();
fadeTimer.destroy();
}
fadeTimer = new FlxTimer().start(time / stepsTotal, _ -> {
var V:Float = (1 / stepsTotal) * steps;
if (steps == stepsTotal) V = 1;
@ -41,7 +49,13 @@ class RetroCameraFade
];
camera.filters = [new ColorMatrixFilter(matrixDerp)];
new FlxTimer().start(time / stepsTotal, _ -> {
if (fadeTimer != null)
{
fadeTimer.cancel();
fadeTimer.destroy();
}
fadeTimer = new FlxTimer().start(time / stepsTotal, _ -> {
var V:Float = (1 / stepsTotal) * steps;
if (steps == stepsTotal) V = 1;
@ -61,7 +75,13 @@ class RetroCameraFade
var steps:Int = 0;
var stepsTotal:Int = camSteps;
new FlxTimer().start(time / stepsTotal, _ -> {
if (fadeTimer != null)
{
fadeTimer.cancel();
fadeTimer.destroy();
}
fadeTimer = new FlxTimer().start(time / stepsTotal, _ -> {
var V:Float = (1 / stepsTotal) * steps;
if (steps == stepsTotal) V = 1;
@ -89,7 +109,13 @@ class RetroCameraFade
];
camera.filters = [new ColorMatrixFilter(matrixDerp)];
new FlxTimer().start(time / stepsTotal, _ -> {
if (fadeTimer != null)
{
fadeTimer.cancel();
fadeTimer.destroy();
}
fadeTimer = new FlxTimer().start(time / stepsTotal, _ -> {
var V:Float = (1 / stepsTotal) * steps;
if (steps == stepsTotal) V = 1;

View file

@ -63,6 +63,11 @@ class GameOverSubState extends MusicBeatSubState
*/
var boyfriend:Null<BaseCharacter> = null;
/**
* If this instance is a "fakeout death".
*/
var isFakeout:Bool;
/**
* The invisible object in the scene which the camera focuses on.
*/
@ -73,6 +78,11 @@ class GameOverSubState extends MusicBeatSubState
*/
var gameOverMusic:Null<FunkinSound> = null;
/**
* The sound effect playing for this state.
*/
var gameOverSfx:Null<FunkinSound> = null;
/**
* Whether the player has confirmed and prepared to restart the level or to go back to the freeplay menu.
* This means the animation and transition have already started.
@ -90,6 +100,8 @@ class GameOverSubState extends MusicBeatSubState
var transparent:Bool;
var confirmTimer:FlxTimer;
static final CAMERA_ZOOM_DURATION:Float = 0.5;
var targetCameraZoom:Float = 1.0;
@ -101,7 +113,10 @@ class GameOverSubState extends MusicBeatSubState
this.isChartingMode = params?.isChartingMode ?? false;
transparent = params.transparent;
isFakeout = FlxG.random.bool((1 / 4096) * 100);
cameraFollowPoint = new FlxObject(PlayState.instance.cameraFollowPoint.x, PlayState.instance.cameraFollowPoint.y, 1, 1);
confirmTimer = new FlxTimer();
}
/**
@ -130,8 +145,6 @@ class GameOverSubState extends MusicBeatSubState
// Set up the visuals
//
var playState = PlayState.instance;
// Add a black background to the screen.
var bg:FunkinSprite = new FunkinSprite().makeSolidColor(FlxG.width * 2, FlxG.height * 2, FlxColor.BLACK);
// We make this transparent so that we can see the stage underneath during debugging,
@ -218,22 +231,27 @@ class GameOverSubState extends MusicBeatSubState
{
hasStartedAnimation = true;
if (boyfriend == null || PlayState.instance.isMinimalMode)
if (!isFakeout)
{
// Play the "blue balled" sound. May play a variant if one has been assigned.
playBlueBalledSFX();
gameOverSfx = playBlueBalledSFX();
if (gameOverSfx != null)
{
// Destroy when finished.
gameOverSfx.onComplete = destroyGameOverSfx;
}
}
else
if (boyfriend != null && !PlayState.instance.isMinimalMode)
{
if (boyfriend.hasAnimation('fakeoutDeath') && FlxG.random.bool((1 / 4096) * 100))
if (boyfriend.hasAnimation('fakeoutDeath') && isFakeout)
{
boyfriend.playAnimation('fakeoutDeath', true, false);
}
else
{
boyfriend.playAnimation('firstDeath', true, false); // ignoreOther is set to FALSE since you WANT to be able to mash and confirm game over!
// Play the "blue balled" sound. May play a variant if one has been assigned.
playBlueBalledSFX();
}
}
}
@ -241,6 +259,17 @@ class GameOverSubState extends MusicBeatSubState
// Smoothly lerp the camera
FlxG.camera.zoom = MathUtil.smoothLerp(FlxG.camera.zoom, targetCameraZoom, elapsed, CAMERA_ZOOM_DURATION);
if (controls.ACCEPT && !blueballed && !mustNotExit)
{
resetPlaying(musicSuffix == '-pixel');
if (confirmTimer != null)
{
confirmTimer.cancel();
confirmTimer.destroy();
}
}
//
// Handle user inputs.
//
@ -404,32 +433,8 @@ class GameOverSubState extends MusicBeatSubState
}
// After the animation finishes...
new FlxTimer().start(0.7, function(tmr:FlxTimer) {
// ...fade out the graphics. Then after that happens...
var resetPlaying = function(pixel:Bool = false) {
// ...close the GameOverSubState.
if (pixel) RetroCameraFade.fadeBlack(FlxG.camera, 10, 1);
else
FlxG.camera.fade(FlxColor.BLACK, 1, true, null, true);
PlayState.instance.needsReset = true;
if (PlayState.instance.isMinimalMode || boyfriend == null) {}
else
{
// Readd Boyfriend to the stage.
boyfriend.isDead = false;
remove(boyfriend);
PlayState.instance.currentStage.addCharacter(boyfriend, BF);
}
// Snap reset the camera which may have changed because of the player character data.
resetCameraZoom();
// Close the substate.
close();
};
confirmTimer.start(0.7, function(tmr:FlxTimer) {
// ...fade out the graphics.
if (musicSuffix == '-pixel')
{
RetroCameraFade.fadeToBlack(FlxG.camera, 10, 2);
@ -448,6 +453,37 @@ class GameOverSubState extends MusicBeatSubState
}
}
public function resetPlaying(pixel:Bool = false)
{
// close the GameOverSubState.
if (pixel) RetroCameraFade.fadeBlack(FlxG.camera, 10, 1);
else
FlxG.camera.fade(FlxColor.BLACK, 1, true, null, true);
PlayState.instance.needsReset = true;
if (PlayState.instance.isMinimalMode || boyfriend == null) {}
else
{
// Readd Boyfriend to the stage.
boyfriend.isDead = false;
remove(boyfriend);
PlayState.instance.currentStage.addCharacter(boyfriend, BF);
}
// If you mash a little too fast...
if (gameOverMusic != null)
{
// Stop playing the music.
gameOverMusic.stop();
}
// Snap reset the camera which may have changed because of the player character data.
resetCameraZoom();
// Close the substate.
close();
}
public override function dispatchEvent(event:ScriptEvent):Void
{
super.dispatchEvent(event);
@ -486,6 +522,10 @@ class GameOverSubState extends MusicBeatSubState
var musicPath:Null<String> = resolveMusicPath(musicSuffix, isStarting, isEnding);
var onComplete:() -> Void = () -> {};
if (gameOverSfx != null && isEnding) destroyGameOverSfx();
if (FlxG.sound.music != null) FlxG.sound.music.pause();
if (isStarting)
{
if (musicPath == null)
@ -531,17 +571,32 @@ class GameOverSubState extends MusicBeatSubState
/**
* Play the sound effect that occurs when
* boyfriend's testicles get utterly annihilated.
* @return The `FunkinSound` object. Will be null if none is found.
*/
public static function playBlueBalledSFX():Void
public static function playBlueBalledSFX():Null<FunkinSound>
{
blueballed = true;
if (Assets.exists(Paths.sound('gameplay/gameover/fnf_loss_sfx' + blueBallSuffix)))
{
FunkinSound.playOnce(Paths.sound('gameplay/gameover/fnf_loss_sfx' + blueBallSuffix));
return FunkinSound.playOnce(Paths.sound('gameplay/gameover/fnf_loss_sfx' + blueBallSuffix));
}
else
{
FlxG.log.error('Missing blue ball sound effect: ' + Paths.sound('gameplay/gameover/fnf_loss_sfx' + blueBallSuffix));
return null;
}
}
/**
* Destroy the Death Sound Effect used in this instance.
* Used to clean up memory.
*/
public function destroyGameOverSfx():Void
{
if (gameOverSfx != null)
{
gameOverSfx.destroy();
gameOverSfx = null;
}
}