import flixel.FlxG; import flixel.FlxSprite; import flixel.math.FlxBasePoint; import flixel.tweens.FlxTween; import flixel.tweens.FlxEase; import flixel.util.FlxTimer; import funkin.Conductor; import funkin.graphics.adobeanimate.FlxAtlasSprite; import funkin.graphics.FunkinSprite; import funkin.modding.base.ScriptedFlxAtlasSprite; import funkin.Paths; import funkin.data.song.SongRegistry; import funkin.play.GameOverSubState; import funkin.play.PlayState; import funkin.play.song.Song; import funkin.play.stage.StageProp; import funkin.save.Save; import funkin.audio.FunkinSound; import funkin.play.cutscene.VideoCutscene; import funkin.play.cutscene.CutsceneType; import funkin.play.PlayStatePlaylist; class DarnellSong extends Song { var hasPlayedCutscene:Bool; var hasPlayedInGameCutscene:Bool; var cutsceneMusic:FunkinSound; var cutsceneConductor:Conductor; var bgSprite:FunkinSprite; public function new() { super('darnell'); hasPlayedCutscene = false; hasPlayedInGameCutscene = false; } public function listDifficulties(variationId:String, variationIds:Array, showLocked:Bool):Array { if (showLocked || Save.instance.hasBeatenLevel('weekend1')) { return super.listDifficulties(variationId, variationIds); } // Hide all difficulties if the player has not beaten the week. return []; } public override function onCountdownStart(event:CountdownScriptEvent):Void { super.onCountdownStart(event); if (!PlayStatePlaylist.isStoryMode){ hasPlayedCutscene = true; hasPlayedInGameCutscene = true; } if(hasPlayedCutscene && !hasPlayedInGameCutscene){ trace('Pausing countdown to play in game cutscene'); hasPlayedInGameCutscene = true; event.cancel(); // CANCEL THE COUNTDOWN! PlayState.instance.camHUD.visible = false; introCutscene(); } if (!hasPlayedCutscene) { trace('Pausing countdown to play a video cutscene (`darnell`)'); hasPlayedCutscene = true; event.cancel(); // CANCEL THE COUNTDOWN! PlayState.instance.tweenCameraZoom(1.3, 0, true); // trace('Adding black background behind cutscene over UI'); bgSprite = new FunkinSprite(0, 0); bgSprite.makeSolidColor(2000, 2500, 0xFF000000); bgSprite.cameras = [PlayState.instance.camCutscene]; // Show over the HUD but below the video. // this bgSprite.zIndex = -10000; PlayState.instance.add(bgSprite); PlayState.instance.refresh(); startVideo(); } } function introCutscene(){ var picoPos:Array = [PlayState.instance.currentStage.getBoyfriend().cameraFocusPoint.x, PlayState.instance.currentStage.getBoyfriend().cameraFocusPoint.y]; var nenePos:Array = [PlayState.instance.currentStage.getGirlfriend().cameraFocusPoint.x, PlayState.instance.currentStage.getGirlfriend().cameraFocusPoint.y]; var darnellPos:Array = [PlayState.instance.currentStage.getDad().cameraFocusPoint.x, PlayState.instance.currentStage.getDad().cameraFocusPoint.y]; var cutsceneDelay:Float = 2; cutsceneMusic = FunkinSound.load(Paths.music("darnellCanCutscene/darnellCanCutscene", "weekend1"), true); cutsceneMusic.volume = 1; cutsceneConductor = new Conductor(); var songMusicData:Null = SongRegistry.instance.parseMusicData('darnellCanCutscene'); if (songMusicData != null) { cutsceneConductor.mapTimeChanges(songMusicData.timeChanges); } cutsceneConductor.onBeatHit.add(onCutsceneBeatHit); var cutsceneCan:FunkinSprite = FunkinSprite.createSparrow(darnellPos[0], darnellPos[1], 'wked1_cutscene_1_can'); cutsceneCan.animation.addByPrefix('forward', "can kick quick0", 24, false); cutsceneCan.animation.addByPrefix('up', "can kicked up0", 24, false); PlayState.instance.currentStage.add(cutsceneCan); cutsceneCan.visible = false; var spraycanPile = PlayState.instance.currentStage.getNamedProp('spraycanPile'); cutsceneCan.x = spraycanPile.x + 30; cutsceneCan.y = spraycanPile.y - 320; cutsceneCan.zIndex = spraycanPile.zIndex - 1; PlayState.instance.currentStage.refresh(); var newCan:ScriptedFlxAtlasSprite = ScriptedFlxAtlasSprite.init('SpraycanAtlasSprite', 0, 0); var spraycanPile = PlayState.instance.currentStage.getNamedProp('spraycanPile'); newCan.x = spraycanPile.x - 430; newCan.y = spraycanPile.y - 840; newCan.zIndex = 300; PlayState.instance.currentStage.add(newCan); PlayState.instance.currentStage.refresh(); newCan.visible = false; PlayState.instance.currentStage.getBoyfriend().playAnimation('intro1', true); // camera sets up, pico does his animation showing him pissed new FlxTimer().start(0.1, function(tmr) { PlayState.instance.tweenCameraToPosition(picoPos[0] + 250, picoPos[1], 0); PlayState.instance.tweenCameraZoom(1.3, 0, true, FlxEase.quadInOut); }); new FlxTimer().start(0.7, function(tmr){ cutsceneMusic.play(false); FlxTween.tween(bgSprite, { alpha: 0}, 2, {startDelay: 0.3}, function(){bgSprite.visible = false;}); }); // move camera out to show everything new FlxTimer().start(cutsceneDelay, function(tmr){ PlayState.instance.tweenCameraToPosition(darnellPos[0]+100, darnellPos[1], 2.5, FlxEase.quadInOut); PlayState.instance.tweenCameraZoom(0.66, 2.5, true, FlxEase.quadInOut); }); // darnell lights up a can new FlxTimer().start(cutsceneDelay + 3, function(tmr) { PlayState.instance.currentStage.getDad().playAnimation('lightCan', true); FunkinSound.playOnce(Paths.sound('Darnell_Lighter'), 1.0); }); // pico cocks his gun, camera shifts to his side to show this new FlxTimer().start(cutsceneDelay + 4, function(tmr) { PlayState.instance.currentStage.getBoyfriend().playAnimation('cock', true); PlayState.instance.tweenCameraToPosition(darnellPos[0]+180, darnellPos[1], 0.4, FlxEase.backOut); FunkinSound.playOnce(Paths.sound('Gun_Prep'), 1.0); }); // darnell kicks the can up new FlxTimer().start(cutsceneDelay + 4.4, function(tmr) { PlayState.instance.currentStage.getDad().playAnimation('kickCan', true); FunkinSound.playOnce(Paths.sound('Kick_Can_UP'), 1.0); cutsceneCan.animation.play('up'); cutsceneCan.visible = true; }); // darnell knees the can forward new FlxTimer().start(cutsceneDelay + 4.9, function(tmr) { PlayState.instance.currentStage.getDad().playAnimation('kneeCan', true); FunkinSound.playOnce(Paths.sound('Kick_Can_FORWARD'), 1.0); cutsceneCan.animation.play('forward'); }); // pico shoots the can, it explodes new FlxTimer().start(cutsceneDelay + 5.1, function(tmr) { PlayState.instance.currentStage.getBoyfriend().playAnimation('intro2', true, true); FunkinSound.playOnce(Paths.soundRandom('shot', 1, 4)); PlayState.instance.tweenCameraToPosition(darnellPos[0]+100, darnellPos[1], 1, FlxEase.quadInOut); newCan.scriptCall('playCanShot'); newCan.visible = true; cutsceneCan.visible = false; new FlxTimer().start(1/24, function(tmr) { darkenStageProps(); }); }); // darnell laughs new FlxTimer().start(cutsceneDelay + 5.9, function(tmr) { PlayState.instance.currentStage.getDad().playAnimation('laughCutscene', true); FunkinSound.playOnce(Paths.sound('cutscene/darnell_laugh'), 0.6); }); // nene spits and laughs new FlxTimer().start(cutsceneDelay + 6.2, function(tmr) { PlayState.instance.currentStage.getGirlfriend().playAnimation('laughCutscene', true); FunkinSound.playOnce(Paths.sound('cutscene/nene_laugh'), 0.6); }); // camera returns to normal, cutscene flags set and countdown starts. new FlxTimer().start(cutsceneDelay + 8, function(tmr) { PlayState.instance.tweenCameraZoom(0.77, 2, true, FlxEase.sineInOut); PlayState.instance.tweenCameraToPosition(darnellPos[0]+180, darnellPos[1], 2, FlxEase.sineInOut); PlayState.instance.isInCutscene = false; PlayState.instance.startCountdown(); cutsceneMusic.stop(); // stop the music!!!!!! }); } function onCutsceneBeatHit() { // Play idle if Darnell isn't busy. if (PlayState.instance.currentStage.getDad().isAnimationFinished() && PlayState.instance.currentStage.getDad().getCurrentAnimation() != 'lightCan') { PlayState.instance.currentStage.getDad().dance(true); } if (PlayState.instance.currentStage.getGirlfriend().isAnimationFinished()) { PlayState.instance.currentStage.getGirlfriend().dance(true); } } function darkenStageProps() { // Darken the background, then fade it back. for (stageProp in PlayState.instance.currentStage.members) { // Determine if the stage prop is something that should be excluded from darkening. if (Std.isOfType(stageProp, StageProp)) { if (stageProp.name == "bf" || stageProp.name == "dad" || stageProp.name == "gf") // This refers to the player. { // Exclude. continue; } } // Hacky way of selecting PicoPlayable.picoFade. if (stageProp.zIndex == (PlayState.instance.currentStage.getBoyfriend().zIndex - 3)) { // Exclude. continue; } if(stageProp.zIndex > 299){ continue; } // If not excluded, darken. stageProp.color = 0xFF111111; new FlxTimer().start(1/24, (tmr) -> { stageProp.color = 0xFF222222; FlxTween.color(stageProp, 1.4, 0xFF222222, 0xFFFFFFFF); }); } } function startVideo() { VideoCutscene.play(Paths.videos('darnellCutscene')); } /** * Don't replay the cutscene between restarts. */ function onSongRetry(event:ScriptEvent) { super.onSongRetry(event); hasPlayedCutscene = true; hasPlayedInGameCutscene = true; } /** * Replay the cutscene after leaving the song. */ function onCreate(event:ScriptEvent):Void { super.onCreate(event); hasPlayedCutscene = false; hasPlayedInGameCutscene = false; } function onUpdate(event:UpdateScriptEvent) { super.onUpdate(event); if (cutsceneConductor != null && cutsceneMusic != null) { cutsceneConductor.update(cutsceneMusic.time); } } }