diff --git a/.github/changed-lines-count-labeler.yml b/.github/changed-lines-count-labeler.yml new file mode 100644 index 000000000..9637d9d19 --- /dev/null +++ b/.github/changed-lines-count-labeler.yml @@ -0,0 +1,22 @@ +# Add 'size: tiny' to any changes of at most 4 lines +'size: tiny': + max: 4 + +# Add 'size: small' to any changes between 5 and 10 lines +'size: small': + min: 5 + max: 10 + +# Add 'size: medium' to any changes between 11 and 100 lines +'size: medium': + min: 11 + max: 100 + +# Add 'size: large' to any changes between 101 and 500 lines +'size: large': + min: 101 + max: 500 + +# Add 'size: huge' to any changes of more than 500 lines +'size: huge': + min: 501 diff --git a/.github/label-actions.yml b/.github/label-actions.yml new file mode 100644 index 000000000..1779070a7 --- /dev/null +++ b/.github/label-actions.yml @@ -0,0 +1,56 @@ +# Configuration for Label Actions - https://github.com/dessant/label-actions + +# Automatically close pull requests when the `status: duplicate` label is applied +'status: duplicate': + prs: + # Post a comment + comment: > + This pull request is a duplicate. Please direct all discussion to the original pull request. + # Close the pull request + close: true + # Remove other status labels + unlabel: + - 'status: accepted' + - 'status: needs clarification' + - 'status: needs r&d' + - 'status: needs revision' + - 'status: pending triage' + - 'status: rejected' + - 'status: resolved' + - 'status: resolved internally' + - 'status: reviewing internally' + - 'status: stale' + +'status: stale': + prs: + # Close the pull request + close: true + # Remove other status labels + unlabel: + - 'status: accepted' + - 'status: duplicate' + - 'status: needs clarification' + - 'status: needs r&d' + - 'status: needs revision' + - 'status: pending triage' + - 'status: rejected' + - 'status: resolved' + - 'status: resolved internally' + - 'status: reviewing internally' + +'status: rejected': + prs: + # Close the pull request + close: true + # Remove other status labels + unlabel: + - 'status: accepted' + - 'status: duplicate' + - 'status: needs clarification' + - 'status: needs r&d' + - 'status: needs revision' + - 'status: pending triage' + - 'status: resolved' + - 'status: resolved internally' + - 'status: reviewing internally' + - 'status: stale' diff --git a/.github/labeler.yml b/.github/labeler.yml new file mode 100644 index 000000000..2637e9dc8 --- /dev/null +++ b/.github/labeler.yml @@ -0,0 +1,36 @@ +# Add Documentation tag to PR's changing markdown files, or anything in the docs folder +'pr: documentation': +- changed-files: + - any-glob-to-any-file: '**/*.md' + +# Add HScript tag to PR's changing hscript files +'pr: hscript': +- changed-files: + - any-glob-to-any-file: '**/*.hxc' + +# Add Chart tag to PR's changing chart files +'pr: chart': +- changed-files: + - any-glob-to-any-file: 'preload/data/songs/**' + +# Add Audio tag to PR's changing audio files +'pr: audio': +- changed-files: + - any-glob-to-any-file: + - '**/*.mp3' + - '**/*.ogg' + +# Add Art tag to PR's changing image or animation files +'pr: art': +- changed-files: + - any-glob-to-any-file: + - 'preload/images/**' + - 'shared/images/**' + - '**/*.png' + +# Add GitHub tag to PR's changing yml files, or anything in the .github folder +'pr: github': +- changed-files: + - any-glob-to-any-file: + - '.github/**' + - '**/*.yml' diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 000000000..5dd55bd22 --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,13 @@ + + + +## Associated Funkin PR + + +## Linked Issues + + +## Description + + +## Screenshots/Videos diff --git a/.github/workflows/cancel-merged-branches.yml b/.github/workflows/cancel-merged-branches.yml new file mode 100644 index 000000000..254b21a24 --- /dev/null +++ b/.github/workflows/cancel-merged-branches.yml @@ -0,0 +1,38 @@ +name: Cancel queued workflows on PR merge + +on: + pull_request: + types: + - closed + +jobs: + + cancel_stuff: + if: github.event.pull_request.merged == true + runs-on: build-set + permissions: + actions: write + + steps: + - name: Cancel queued workflows for ${{ github.event.pull_request.head.ref }} + uses: actions/github-script@v7 + with: + result-encoding: string + retries: 3 + script: | + let branch_workflows = await github.rest.actions.listWorkflowRuns({ + owner: context.repo.owner, + repo: context.repo.repo, + workflow_id: "build-shit.yml", + status: "queued", + branch: "${{ github.event.pull_request.head.ref }}" + }); + let runs = branch_workflows.data.workflow_runs; + runs.forEach((run) => { + github.rest.actions.cancelWorkflowRun({ + owner: context.repo.owner, + repo: context.repo.repo, + run_id: run.id + }); + }); + console.log(runs); diff --git a/.github/workflows/label-actions.yml b/.github/workflows/label-actions.yml new file mode 100644 index 000000000..bc4cf0add --- /dev/null +++ b/.github/workflows/label-actions.yml @@ -0,0 +1,29 @@ +# Perform actions when labels are applied to issues, discussions, or pull requests +# See .github/label-actions.yml +name: 'Label Actions' + +on: + issues: + types: + - labeled + - unlabeled + pull_request_target: + types: + - labeled + - unlabeled + discussion: + types: + - labeled + - unlabeled + +permissions: + contents: read + issues: write + pull-requests: write + discussions: write + +jobs: + action: + runs-on: ubuntu-latest + steps: + - uses: dessant/label-actions@v4 diff --git a/.github/workflows/label-pull-request-on-create.yml b/.github/workflows/label-pull-request-on-create.yml new file mode 100644 index 000000000..94620657d --- /dev/null +++ b/.github/workflows/label-pull-request-on-create.yml @@ -0,0 +1,19 @@ +name: "Pull Request Labeler 2 (Runs on PR creation)" +on: + pull_request_target: + types: + - opened + +jobs: + # Apply `status: pending triage` to newly created pull requests + apply-pending-triage: + permissions: + contents: read + pull-requests: write + runs-on: ubuntu-latest + steps: + - name: Apply "status pending triage" to new pull requests + uses: actions-ecosystem/action-add-labels@v1 + with: + token: ${{ secrets.GITHUB_TOKEN }} + labels: "status: pending triage" diff --git a/.github/workflows/label-pull-request.yml b/.github/workflows/label-pull-request.yml new file mode 100644 index 000000000..525e1b5a6 --- /dev/null +++ b/.github/workflows/label-pull-request.yml @@ -0,0 +1,29 @@ +name: "Pull Request Labeler" +on: +- pull_request_target + +jobs: + # Apply labels to pull requests based on which files were edited + labeler: + permissions: + contents: read + pull-requests: write + runs-on: ubuntu-latest + steps: + - name: Set basic labels + uses: actions/labeler@v5 + with: + sync-labels: true + # Apply labels to pull requests based on how many lines were edited + changed-lines-count-labeler: + permissions: + contents: read + pull-requests: write + runs-on: ubuntu-latest + name: An action for automatically labelling pull requests based on the changed lines count + steps: + - name: Set change count labels + uses: vkirilichev/changed-lines-count-labeler@v0.2 + with: + repo-token: ${{ secrets.GITHUB_TOKEN }} + configuration-path: .github/changed-lines-count-labeler.yml diff --git a/preload/scripts/songs/darnell.hxc b/preload/scripts/songs/darnell.hxc index 9ec8dc447..8a9bc1bef 100644 --- a/preload/scripts/songs/darnell.hxc +++ b/preload/scripts/songs/darnell.hxc @@ -4,6 +4,7 @@ import flixel.math.FlxBasePoint; import flixel.tweens.FlxTween; import flixel.tweens.FlxEase; import flixel.util.FlxTimer; +import flixel.util.FlxTimerManager; import funkin.Conductor; import funkin.util.Constants; import funkin.graphics.adobeanimate.FlxAtlasSprite; @@ -18,14 +19,18 @@ import funkin.save.Save; import funkin.audio.FunkinSound; import funkin.play.cutscene.VideoCutscene; import funkin.play.cutscene.CutsceneType; +import funkin.play.PauseSubState; +import funkin.play.PauseMode; import funkin.play.PlayStatePlaylist; +import funkin.ui.FullScreenScaleMode; class DarnellSong extends Song { var hasPlayedCutscene:Bool; var hasPlayedInGameCutscene:Bool; var cutsceneMusic:FunkinSound; - var cutsceneConductor:Conductor; + var cutsceneConductor:Conductor = null; + var cutsceneTimerManager:FlxTimerManager = null; var bgSprite:FunkinSprite; public function new() @@ -120,9 +125,11 @@ class DarnellSong extends Song } } + var cutsceneCan:FunkinSprite = null; + var newCan:ScriptedFlxAtlasSprite = null; + function introCutscene() { - PlayState.instance.togglePauseButton(); PlayState.instance.isInCutscene = true; PlayState.instance.mayPauseGame = false; @@ -141,8 +148,21 @@ class DarnellSong extends Song var cutsceneDelay:Float = 2; - cutsceneMusic = FunkinSound.load(Paths.music("darnellCanCutscene/darnellCanCutscene", "weekend1"), true); - cutsceneMusic.volume = 1; + if(cutsceneTimerManager == null) cutsceneTimerManager = new FlxTimerManager(); + + if(cutsceneCan != null) + { + cutsceneCan.destroy(); + cutsceneCan = null; + } + + if(newCan != null) + { + newCan.destroy(); + newCan = null; + } + + if(cutsceneMusic == null) cutsceneMusic = FunkinSound.load(Paths.music("darnellCanCutscene/darnellCanCutscene", "weekend1"), true); cutsceneConductor = new Conductor(); @@ -154,10 +174,10 @@ class DarnellSong extends Song 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 = 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'); @@ -166,70 +186,75 @@ class DarnellSong extends Song 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 = 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); + // camera sets up, pico does his animation showing him pissed + new FlxTimer(cutsceneTimerManager).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); + new FlxTimer(cutsceneTimerManager).start(0.7, function(tmr){ + cutsceneMusic.play(true); + cutsceneMusic.volume = 1; + FlxTween.tween(bgSprite, { alpha: 0}, 2, {startDelay: 0.3}, function(){bgSprite.visible = false;}); + }); + + // move camera out to show everything + new FlxTimer(cutsceneTimerManager).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(cutsceneTimerManager).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(cutsceneTimerManager).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(cutsceneTimerManager).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); + // darnell knees the can forward + new FlxTimer(cutsceneTimerManager).start(cutsceneDelay + 4.9, function(tmr) + { + PlayState.instance.currentStage.getDad().playAnimation('kneeCan', true); + cutsceneSounds.push(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); + // pico shoots the can, it explodes + new FlxTimer(cutsceneTimerManager).start(cutsceneDelay + 5.1, function(tmr) + { + PlayState.instance.currentStage.getBoyfriend().playAnimation('intro2', true, true); - FunkinSound.playOnce(Paths.soundRandom('shot', 1, 4)); + cutsceneSounds.push(FunkinSound.playOnce(Paths.soundRandom('shot', 1, 4))); PlayState.instance.tweenCameraToPosition(darnellPos[0] + 100, darnellPos[1], 1, FlxEase.quadInOut); @@ -241,31 +266,38 @@ class DarnellSong extends Song }); }); - // 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); - }); + // darnell laughs + new FlxTimer(cutsceneTimerManager).start(cutsceneDelay + 5.9, function(tmr) + { + PlayState.instance.currentStage.getDad().playAnimation('laughCutscene', true); + cutsceneSounds.push(FunkinSound.playOnce(Paths.sound('cutscene/darnell_laugh'), 0.6)); + }); + + // nene spits and laughs + new FlxTimer(cutsceneTimerManager).start(cutsceneDelay + 6.2, function(tmr) + { + PlayState.instance.currentStage.getGirlfriend().playAnimation('laughCutscene', true); + cutsceneSounds.push(FunkinSound.playOnce(Paths.sound('cutscene/nene_laugh'), 0.6)); + }); + + // camera returns to normal, cutscene flags set and countdown starts. + new FlxTimer(cutsceneTimerManager).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.mayPauseGame = true; + PlayState.instance.startCountdown(); - // 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); - }); + cutsceneMusic.stop(); // stop the music!!!!!! - // 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!!!!!! + while(cutsceneSounds.length > 0) + cutsceneSounds.shift().stop(); - PlayState.instance.togglePauseButton(true); - PlayState.instance.isInCutscene = false; - PlayState.instance.mayPauseGame = true; - }); - } + cutsceneTimerManager.destroy(); + cutsceneTimerManager = null; + }); + } function onCutsceneBeatHit() { @@ -282,6 +314,7 @@ class DarnellSong extends Song } } + var propColorTweens:Array = []; function darkenStageProps() { // Darken the background, then fade it back. @@ -309,14 +342,17 @@ class DarnellSong extends Song continue; } - // If not excluded, darken. - stageProp.color = 0xFF111111; - new FlxTimer().start(1 / 24, (tmr) -> { - stageProp.color = 0xFF222222; - FlxTween.color(stageProp, 1.4, 0xFF222222, 0xFFFFFFFF); - }); - } - } + // If not excluded, darken. + stageProp.color = 0xFF111111; + new FlxTimer().start(1/24, (tmr) -> + { + stageProp.color = 0xFF222222; + propColorTweens.push(FlxTween.color(stageProp, 1.4, 0xFF222222, 0xFFFFFFFF, {onComplete: function(tween:FlxTween) { + propColorTweens.remove(tween); + }})); + }); + } + } function startVideo() { @@ -351,13 +387,101 @@ class DarnellSong extends Song hasPlayedInGameCutscene = false; } - function onUpdate(event:UpdateScriptEvent) - { - super.onUpdate(event); - - if (cutsceneConductor != null && cutsceneMusic != null) - { - cutsceneConductor.update(cutsceneMusic.time); - } - } + function onUpdate(event:UpdateScriptEvent) { + super.onUpdate(event); + + if(cutsceneTimerManager != null && cutsceneTimerManager.active) cutsceneTimerManager.update(event.elapsed); + + if (cutsceneConductor != null && cutsceneMusic != null) { + cutsceneConductor.update(cutsceneMusic.time); + } + + if (PlayState.instance.controls.PAUSE && cutsceneTimerManager != null && !PlayState.instance.isGamePaused && !PlayState.instance.justUnpaused) + { + if(cutsceneTimerManager != null) cutsceneTimerManager.active = false; + + for(i in propColorTweens) + { + i.active = false; + } + + PlayState.instance.preparePauseUI(); + PlayState.instance.openPauseSubState(PauseMode.Cutscene( + 'Cutscene', 'In-Game Cutscene', + resumeCutscene, skipCutscene, restartCutscene + ), FullScreenScaleMode.hasFakeCutouts ? PlayState.instance.camCutouts : PlayState.instance.camCutscene, null); + } + } + + function resumeCutscene() + { + if(cutsceneTimerManager != null) cutsceneTimerManager.active = true; + + for(i in propColorTweens) + { + i.active = true; + } + } + + function skipCutscene() + { + var darnellPos:Array = [PlayState.instance.currentStage.getDad().cameraFocusPoint.x, PlayState.instance.currentStage.getDad().cameraFocusPoint.y]; + + 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.mayPauseGame = true; + PlayState.instance.startCountdown(); + cutsceneMusic.stop(); // stop the music!!!!!! + + while(cutsceneSounds.length > 0) + cutsceneSounds.shift().stop(); + + if(cutsceneCan != null) + { + cutsceneCan.destroy(); + cutsceneCan = null; + } + + if(newCan != null) + { + newCan.destroy(); + newCan = null; + } + + while(propColorTweens.length > 0) + { + var i:FlxTween = propColorTweens.shift(); + i.active = true; + i.onComplete = null; // its removed already, no need + i.finish(); + } + + cutsceneTimerManager.destroy(); + cutsceneTimerManager = null; + } + + function restartCutscene() + { + if(cutsceneTimerManager != null) cutsceneTimerManager.active = true; + + cutsceneTimerManager.clear(); + FlxTween.cancelTweensOf(bgSprite); + bgSprite.alpha = 1; + + // reset characters + PlayState.instance.currentStage.getBoyfriend().canPlayOtherAnims = true; + PlayState.instance.currentStage.getBoyfriend().dance(true); + + PlayState.instance.currentStage.getGirlfriend().scriptSet('currentState', 0); + PlayState.instance.currentStage.getGirlfriend().dance(true); + + PlayState.instance.currentStage.getDad().dance(true); + + cutsceneMusic.stop(); // stop the music!!!!!! + while(cutsceneSounds.length > 0) + cutsceneSounds.shift().stop(); + + introCutscene(); + } } diff --git a/preload/scripts/songs/eggnog.hxc b/preload/scripts/songs/eggnog.hxc index 02ba5e23d..e34bf96e5 100644 --- a/preload/scripts/songs/eggnog.hxc +++ b/preload/scripts/songs/eggnog.hxc @@ -4,6 +4,7 @@ import flixel.math.FlxBasePoint; import flixel.tweens.FlxEase; import flixel.tweens.FlxTween; import flixel.util.FlxTimer; +import flixel.util.FlxTimerManager; import funkin.audio.FunkinSound; import funkin.Conductor; import funkin.graphics.adobeanimate.FlxAtlasSprite; @@ -20,6 +21,7 @@ import flixel.text.FlxText; import flixel.text.FlxTextBorderStyle; import funkin.util.TouchUtil; import funkin.ui.FullScreenScaleMode; +import funkin.play.PauseMode; // We have to use FlxBasePoint in scripts because FlxPoint is inlined and not available in scripts class EggnogSong extends Song @@ -27,14 +29,18 @@ class EggnogSong extends Song // var santaDead:ScriptedFlxAtlasSprite; var hasPlayedCutscene:Bool = false; var cutsceneSkipped:Bool = false; - var canSkipCutscene:Bool = false; + var canPauseCutscene:Bool = false; var santaSound:FunkinSound; var shootSound:FunkinSound; var debugTesting:Bool = false; + var cutsceneTimerManager:FlxTimerManager; var isMobilePauseButtonPressed:Bool = false; + var santaDead:ScriptedFlxAtlasSprite = null; + var parentsShoot:ScriptedFlxAtlasSprite = null; + function new() { super('eggnog'); @@ -97,29 +103,14 @@ class EggnogSong extends Song } } - var skipText:FlxText; - function startCutscene() { - skipText = new FlxText(936 * FullScreenScaleMode.wideScale.x, 618 * FullScreenScaleMode.wideScale.y, 0, - 'Skip [ ' + PlayState.instance.controls.getDialogueNameFromToken("CUTSCENE_ADVANCE", true) + ' ]', 20); - if (FlxG.onMobile) - { - skipText.text = 'Skip [Pause Button]'; - skipText.x -= 136; - } - skipText.setFormat(Paths.font('vcr.ttf'), 40, 0xFFFFFFFF, "right", FlxTextBorderStyle.OUTLINE, 0xFF000000); - skipText.scrollFactor.set(); - skipText.borderSize = 2; - skipText.alpha = 0; - PlayState.instance.currentStage.add(skipText); - - skipText.cameras = [PlayState.instance.camCutscene]; + cutsceneTimerManager = new FlxTimerManager(); var normalSanta = PlayState.instance.currentStage.getNamedProp('santa'); normalSanta.visible = false; - var santaDead:ScriptedFlxAtlasSprite = ScriptedFlxAtlasSprite.init('SantaDiesSprite', 0, 0); + santaDead = ScriptedFlxAtlasSprite.init('SantaDiesSprite', 0, 0); santaDead.x = -458; santaDead.y = 498; @@ -132,7 +123,7 @@ class EggnogSong extends Song santaDead.scriptCall('playCutscene'); PlayState.instance.currentStage.getDad().visible = false; - var parentsShoot:ScriptedFlxAtlasSprite = ScriptedFlxAtlasSprite.init('DadShootsSprite', 0, 0); + parentsShoot = ScriptedFlxAtlasSprite.init('DadShootsSprite', 0, 0); parentsShoot.x = -516; parentsShoot.y = 503; @@ -163,36 +154,34 @@ class EggnogSong extends Song shootSound = FunkinSound.load(Paths.sound('santa_shot_n_falls'), 1); shootSound.volume = 1; - new FlxTimer().start(2.8, function(tmr) { + new FlxTimer(cutsceneTimerManager).start(2.8, function(tmr) { PlayState.instance.tweenCameraToPosition(santaDead.x + 150, santaDead.y, 9, FlxEase.quartInOut); PlayState.instance.tweenCameraZoom(0.79, 9, true, FlxEase.quadInOut); }); - new FlxTimer().start(11.3, function(tmr) { + new FlxTimer(cutsceneTimerManager).start(11.3, function(tmr) { // PlayState.instance.tweenCameraZoom(0.73, 0.8, true, FlxEase.backOut); // PlayState.instance.tweenCameraToPosition(santaDead.x + 220, santaDead.y, 0.8, FlxEase.expoOut); // PlayState.instance.camGame.shake(0.007, 0.4); }); - new FlxTimer().start(11.375, function(tmr) { - if (!cutsceneSkipped) shootSound.play(false); + new FlxTimer(cutsceneTimerManager).start(11.375, function(tmr) { + shootSound.play(false); }); - new FlxTimer().start(12.83, function(tmr) { + new FlxTimer(cutsceneTimerManager).start(12.83, function(tmr) { PlayState.instance.camGame.shake(0.005, 0.2); PlayState.instance.tweenCameraToPosition(santaDead.x + 160, santaDead.y + 80, 5, FlxEase.expoOut); }); - new FlxTimer().start(15, function(tmr) { + new FlxTimer(cutsceneTimerManager).start(15, function(tmr) { PlayState.instance.camHUD.fade(0xFF000000, 1, false, null, true); }); - new FlxTimer().start(16, function(tmr) { - if (!cutsceneSkipped) - { - PlayState.instance.camHUD.fade(0xFF000000, 0.5, true, null, true); - PlayState.instance.endSong(true); - } + new FlxTimer(cutsceneTimerManager).start(16, function(tmr) { + canPauseCutscene = false; + PlayState.instance.camHUD.fade(0xFF000000, 0.5, true, null, true); + PlayState.instance.endSong(true); }); } @@ -200,6 +189,8 @@ class EggnogSong extends Song { super.onUpdate(event); + if(cutsceneTimerManager != null && cutsceneTimerManager.active) cutsceneTimerManager.update(event.elapsed); + if (FlxG.onMobile) { isMobilePauseButtonPressed = TouchUtil.overlapsComplex(PlayState.instance.pauseButton) && TouchUtil.justPressed; @@ -207,31 +198,55 @@ class EggnogSong extends Song if (PlayState.instance.isInCutscene) { - if ((PlayState.instance.controls.CUTSCENE_ADVANCE || isMobilePauseButtonPressed) && cutsceneSkipped == false) + if ((PlayState.instance.controls.PAUSE || isMobilePauseButtonPressed) && canPauseCutscene) { - if (canSkipCutscene == false) - { - trace('cant skip yet!'); - FlxTween.tween(skipText, {alpha: 1}, 0.5, {ease: FlxEase.quadOut}); - new FlxTimer().start(0.5, _ -> { - canSkipCutscene = true; - trace('can skip!'); - }); - } + cutsceneTimerManager.active = false; + + PlayState.instance.preparePauseUI(); + PlayState.instance.openPauseSubState(PauseMode.Cutscene( + 'Cutscene', 'In-Game Cutscene', + resumeCutscene, skipCutscene, restartCutscene + ), FullScreenScaleMode.hasFakeCutouts ? PlayState.instance.camCutouts : PlayState.instance.camCutscene, null); } } + } - if ((PlayState.instance.controls.CUTSCENE_ADVANCE || isMobilePauseButtonPressed) && canSkipCutscene) - { - PlayState.instance.camCutscene.fade(0xFF000000, 0.5, false, null, true); - FlxTween.tween(skipText, {alpha: 0}, 0.5, {ease: FlxEase.quadOut}); - cutsceneSkipped = true; - santaSound.stop(); - shootSound.stop(); - new FlxTimer().start(0.5, function(tmr) { - PlayState.instance.endSong(true); - }); - } + public function resumeCutscene():Void + { + cutsceneTimerManager.active = true; + } + + public function skipCutscene():Void + { + canPauseCutscene = false; + PlayState.instance.camCutscene.fade(0xFF000000, 0.5, false, null, true); + + santaSound.stop(); + shootSound.stop(); + + new FlxTimer().start(0.5, function(tmr) { + PlayState.instance.endSong(true); + }); + } + + public function restartCutscene():Void + { + cutsceneTimerManager.destroy(); + cutsceneTimerManager = null; + + santaDead.destroy(); + santaDead = null; + + parentsShoot.destroy(); + parentsShoot = null; + + santaSound.destroy(); + santaSound = null; + + shootSound.destroy(); + shootSound = null; + + startCutscene(); } /** @@ -241,7 +256,7 @@ class EggnogSong extends Song { super.onCreate(event); cutsceneSkipped = false; - canSkipCutscene = false; + canPauseCutscene = true; hasPlayedCutscene = false; } } diff --git a/preload/scripts/songs/stress.hxc b/preload/scripts/songs/stress.hxc index 48824efd7..cf7cfa2ae 100644 --- a/preload/scripts/songs/stress.hxc +++ b/preload/scripts/songs/stress.hxc @@ -19,6 +19,10 @@ import flixel.tweens.FlxEase; import flixel.tweens.FlxTween; import flixel.util.FlxTimer; import flixel.util.FlxTimerManager; +import funkin.play.PauseSubState; +import funkin.play.PauseMode; +import funkin.util.TouchUtil; +import funkin.ui.FullScreenScaleMode; class StressSong extends Song { @@ -155,6 +159,9 @@ class StressSong extends Song } var hasPlayedEndCutscene:Bool = false; + var canPause:Bool = true; + + var isMobilePauseButtonPressed:Bool = false; var tankmanCutscene:ScriptedFlxAtlasSprite; var rimlightCamera:FlxCamera; @@ -166,7 +173,7 @@ class StressSong extends Song if (PlayState.instance.isInCutscene) { - if (cutsceneTimerManager != null) cutsceneTimerManager.update(event.elapsed); + if (cutsceneTimerManager != null && cutsceneTimerManager.active) cutsceneTimerManager.update(event.elapsed); if (rimlightCamera != null) { @@ -175,6 +182,24 @@ class StressSong extends Song rimlightCamera.zoom = PlayState.instance.camGame.zoom; } + if (FlxG.onMobile) + { + isMobilePauseButtonPressed = TouchUtil.overlapsComplex(PlayState.instance.pauseButton) && TouchUtil.justPressed; + } + + if ((PlayState.instance.controls.PAUSE || isMobilePauseButtonPressed) && canPause && hasPlayedEndCutscene && !PlayState.instance.isGamePaused && !PlayState.instance.justUnpaused) + { + if(cutsceneTimerManager != null) cutsceneTimerManager.active = false; + + tankmanCutscene.scriptCall('pauseSounds'); + + PlayState.instance.preparePauseUI(); + PlayState.instance.openPauseSubState(PauseMode.Cutscene( + 'Cutscene', 'In-Game Cutscene', + resumeEndCutscene, finishEndCutscene, restartEndCutscene + ), FullScreenScaleMode.hasFakeCutouts ? PlayState.instance.camCutouts : PlayState.instance.camCutscene, null); + } + if (FlxG.mouse.pressed) { // tankmanCutscene.x = FlxG.mouse.viewX - PlayState.instance.currentStage.getDad().x; @@ -237,6 +262,7 @@ class StressSong extends Song ]; cutsceneTimerManager = new FlxTimerManager(); + canPause = true; // Disable player input during cutscene, so you can't get a gameover during cutscene PlayState.instance.isInCutscene = true; @@ -277,15 +303,60 @@ class StressSong extends Song new FlxTimer(cutsceneTimerManager).start(270 / 24, _ -> { PlayState.instance.tweenCameraToPosition(tankmanPos[0] + 320, tankmanPos[1] - 370, 2, FlxEase.quadInOut); FlxTween.tween(bgSprite, {alpha: 1}, 2, null); + canPause = false; // the cutscene is literally almost done, no need }); new FlxTimer(cutsceneTimerManager).start(320 / 24, _ -> { - FlxG.cameras.remove(rimlightCamera); - rimlightCamera = null; - PlayState.instance.endSong(true); + finishEndCutscene(); }); } + function resumeEndCutscene():Void + { + if(cutsceneTimerManager != null) cutsceneTimerManager.active = true; + tankmanCutscene.scriptCall('resumeSounds'); + } + + function finishEndCutscene():Void + { + if(cutsceneTimerManager != null) + { + cutsceneTimerManager.destroy(); + cutsceneTimerManager = null; + } + + tankmanCutscene.scriptCall('cancelSounds'); + + tankmanCutscene.destroy(); + tankmanCutscene = null; + + FlxG.cameras.remove(rimlightCamera); + rimlightCamera = null; + + PlayState.instance.endSong(true); + } + + function restartEndCutscene():Void + { + if(cutsceneTimerManager != null) + { + cutsceneTimerManager.destroy(); + cutsceneTimerManager = null; + } + + tankmanCutscene.scriptCall('cancelSounds'); + + tankmanCutscene.destroy(); + tankmanCutscene = null; + + FlxG.cameras.remove(rimlightCamera); + rimlightCamera = null; + + PlayState.instance.currentStage.getBoyfriend().dance(true); + + startEndCutscene(); + } + function kill():Void { cleanupTankmanGroup(); diff --git a/preload/scripts/stages/phillyTrainErect.hxc b/preload/scripts/stages/phillyTrainErect.hxc index 02fbc412d..2984b9947 100644 --- a/preload/scripts/stages/phillyTrainErect.hxc +++ b/preload/scripts/stages/phillyTrainErect.hxc @@ -22,6 +22,8 @@ import funkin.Preferences; import funkin.util.TouchUtil; import funkin.util.HapticUtil; import funkin.ui.FullScreenScaleMode; +import funkin.play.PauseSubState; +import funkin.play.PauseMode; class PhillyTrainErectStage extends Stage { @@ -36,7 +38,7 @@ class PhillyTrainErectStage extends Stage var lightShader:FlxRuntimeShader; var trainSound:FunkinSound; var colorShader:AdjustColorShader; - var cutsceneMusic:FunkinSound; + var cutsceneMusic:FunkinSound = null; var hasPlayedInGameCutscene:Bool = false; var cutsceneSkipped:Bool = false; @@ -82,11 +84,10 @@ class PhillyTrainErectStage extends Stage } } - var picoPlayer:ScriptedFlxAtlasSprite; - var picoOpponent:ScriptedFlxAtlasSprite; - var bloodPool:ScriptedFlxAtlasSprite; - var cigarette:FlxSprite; - var skipText:FlxText; + var picoPlayer:ScriptedFlxAtlasSprite = null; + var picoOpponent:ScriptedFlxAtlasSprite = null; + var bloodPool:ScriptedFlxAtlasSprite = null; + var cigarette:FlxSprite = null; var playerShoots:Bool; var explode:Bool; @@ -96,25 +97,10 @@ class PhillyTrainErectStage extends Stage var cutsceneTimerManager:FlxTimerManager; var gaspSound:FunkinSound = null; - function doppleGangerCutscene() - { - // Disable player input during cutscene, so you can't get a gameover during cutscene - PlayState.instance.isInCutscene = true; - PlayState.instance.mayPauseGame = false; - skipText = new FlxText(936 * FullScreenScaleMode.wideScale.x, 618 * FullScreenScaleMode.wideScale.y, 0, - 'Skip [ ' + PlayState.instance.controls.getDialogueNameFromToken("CUTSCENE_ADVANCE", true) + ' ]', 20); - if (FlxG.onMobile) - { - skipText.text = 'Skip [Pause Button]'; - skipText.x -= 136; - } - skipText.setFormat(Paths.font('vcr.ttf'), 40, 0xFFFFFFFF, "right", FlxTextBorderStyle.OUTLINE, 0xFF000000); - skipText.scrollFactor.set(); - skipText.borderSize = 2; - skipText.alpha = 0; - add(skipText); - - skipText.cameras = [PlayState.instance.camCutscene]; + function doppleGangerCutscene() + { + // Disable player input during cutscene, so you can't get a gameover during cutscene + PlayState.instance.isInCutscene = true; cutsceneTimerManager = new FlxTimerManager(); @@ -149,10 +135,10 @@ class PhillyTrainErectStage extends Stage var cigarettePos:Array = []; var shooterPos:Array = []; - bloodPool = ScriptedFlxAtlasSprite.init('PicoBloodPool', 0, 0); - picoPlayer = ScriptedFlxAtlasSprite.init('PicoDopplegangerSprite', 0, 0); - picoOpponent = ScriptedFlxAtlasSprite.init('PicoDopplegangerSprite', 0, 0); - cigarette = new FlxSprite(0, 0); + if(bloodPool == null) bloodPool = ScriptedFlxAtlasSprite.init('PicoBloodPool', 0, 0); + if(picoPlayer == null) picoPlayer = ScriptedFlxAtlasSprite.init('PicoDopplegangerSprite', 0, 0); + if(picoOpponent == null) picoOpponent = ScriptedFlxAtlasSprite.init('PicoDopplegangerSprite', 0, 0); + if(cigarette == null) cigarette = new FlxSprite(0, 0); picoPlayer.setPosition(PlayState.instance.currentStage.getBoyfriend().x + 48.5, PlayState.instance.currentStage.getBoyfriend().y + 400); picoOpponent.setPosition(PlayState.instance.currentStage.getDad().x + 82, PlayState.instance.currentStage.getDad().y + 400); @@ -215,21 +201,29 @@ class PhillyTrainErectStage extends Stage PlayState.instance.currentStage.getBoyfriend().visible = false; PlayState.instance.currentStage.getDad().visible = false; - if (explode == false) - { - cutsceneMusic = FunkinSound.load(Paths.music("cutscene/cutscene", "week3"), true); - } - else - { - cutsceneMusic = FunkinSound.load(Paths.music("cutscene/cutscene2", "week3"), true); - } - cutsceneMusic.volume = 1; - cutsceneMusic.play(false); + if(cutsceneMusic == null) + { + if(explode == false) + { + cutsceneMusic = FunkinSound.load(Paths.music("cutscene/cutscene", "week3"), true); + } + else + { + cutsceneMusic = FunkinSound.load(Paths.music("cutscene/cutscene2", "week3"), true); + } + } + + cutsceneMusic.volume = 1; + cutsceneMusic.play(true); picoPlayer.scriptCall('doAnim', ['Player', playerShoots, explode, cutsceneTimerManager]); picoOpponent.scriptCall('doAnim', ['Opponent', !playerShoots, explode, cutsceneTimerManager]); - if (gaspSound == null) gaspSound = FunkinSound.playOnce(Paths.sound('cutscene/picoGasp'), 1); + if(gaspSound == null) + gaspSound = FunkinSound.load(Paths.sound('cutscene/picoGasp'), false); + + gaspSound.volume = 1; + gaspSound.play(true); PlayState.instance.resetCamera(false, true); PlayState.instance.cameraFollowPoint.setPosition(midPoint[0], midPoint[1]); @@ -242,20 +236,14 @@ class PhillyTrainErectStage extends Stage PlayState.instance.cameraFollowPoint.setPosition(shooterPos[0], shooterPos[1]); }); - new FlxTimer(cutsceneTimerManager).start(8.75, _ -> { - cutsceneSkipped = true; - canSkipCutscene = false; - FlxTween.tween(skipText, {alpha: 0}, 0.5, - { - ease: FlxEase.quadIn, - onComplete: _ -> { - skipText.visible = false; - } - }); - // cutting off skipping here. really dont think its needed after this point and it saves problems from happening - PlayState.instance.cameraFollowPoint.setPosition(cigarettePos[0], cigarettePos[1]); - if (explode == true) PlayState.instance.currentStage.getGirlfriend().playAnimation('drop70', true); - }); + new FlxTimer(cutsceneTimerManager).start(8.75, _ -> { + cutsceneSkipped = true; + canPause = false; + // cutting off pausing here. really dont think its needed after this point and it saves problems from happening + PlayState.instance.cameraFollowPoint.setPosition(cigarettePos[0], cigarettePos[1]); + if(explode == true) + PlayState.instance.currentStage.getGirlfriend().playAnimation('drop70', true); + }); new FlxTimer(cutsceneTimerManager).start(11.2, _ -> { if (explode == true) bloodPool.scriptCall('doAnim'); @@ -304,9 +292,11 @@ class PhillyTrainErectStage extends Stage { PlayState.instance.isInCutscene = false; PlayState.instance.mayPauseGame = true; - picoPlayer.visible = false; + picoPlayer.destroy(); + picoPlayer = null; PlayState.instance.currentStage.getBoyfriend().visible = true; - picoOpponent.visible = false; + picoOpponent.destroy(); + picoOpponent = null; PlayState.instance.currentStage.getDad().visible = true; } @@ -315,13 +305,13 @@ class PhillyTrainErectStage extends Stage }); } - function skipCutscene() + function skipCutscene() { - cutsceneSkipped = true; - explode = false; - hasPlayedCutscene = true; - PlayState.instance.camCutscene.fade(0xFF000000, 0.5, false, null, true); - cutsceneMusic.fadeOut(0.5, 0); + cutsceneSkipped = true; + explode = false; + hasPlayedCutscene = true; + + if(cutsceneTimerManager != null) cutsceneTimerManager.active = false; new FlxTimer().start(0.5, _ -> { PlayState.instance.justUnpaused = true; @@ -336,13 +326,15 @@ class PhillyTrainErectStage extends Stage PlayState.instance.mayPauseGame = true; PlayState.instance.startCountdown(); - skipText.visible = false; - picoPlayer.visible = false; - picoOpponent.visible = false; - PlayState.instance.currentStage.getBoyfriend().visible = true; - PlayState.instance.currentStage.getDad().visible = true; - }); - } + picoPlayer.destroy(); + picoPlayer = null; + picoOpponent.destroy(); + picoOpponent = null; + PlayState.instance.currentStage.getBoyfriend().visible = true; + PlayState.instance.currentStage.getDad().visible = true; + }); + + } function onCutsceneBeatHit() { @@ -401,13 +393,13 @@ class PhillyTrainErectStage extends Stage var trainFinishing:Bool = false; var trainCooldown:Int = 0; - function onUpdate(event:UpdateScriptEvent):Void - { - super.onUpdate(event); - if (cutsceneTimerManager != null) cutsceneTimerManager.update(event.elapsed); - // Update beat lights - var shaderInput:Float = (Conductor.instance.beatLengthMs / 1000) * event.elapsed * 1.5; - lightShader.scriptCall('update', [shaderInput]); + function onUpdate(event:UpdateScriptEvent):Void + { + super.onUpdate(event); + if(cutsceneTimerManager != null && cutsceneTimerManager.active) cutsceneTimerManager.update(event.elapsed); + // Update beat lights + var shaderInput:Float = (Conductor.instance.beatLengthMs / 1000) * event.elapsed * 1.5; + lightShader.scriptCall('update', [shaderInput]); var amount:Int = 1; @@ -428,27 +420,17 @@ class PhillyTrainErectStage extends Stage isMobilePauseButtonPressed = TouchUtil.overlapsComplex(PlayState.instance.pauseButton) && TouchUtil.justPressed; } - if ((PlayState.instance.controls.CUTSCENE_ADVANCE || isMobilePauseButtonPressed) && cutsceneSkipped == false) + if ((PlayState.instance.controls.PAUSE || isMobilePauseButtonPressed) && cutsceneSkipped == false && !PlayState.instance.isGamePaused && !PlayState.instance.justUnpaused) { - if (!canSkipCutscene) - { - trace('cant skip yet!'); - if (skipText != null) - { - FlxTween.tween(skipText, {alpha: 1}, 0.5, {ease: FlxEase.quadOut}); - new FlxTimer().start(0.5, _ -> { - canSkipCutscene = true; - trace('can skip!'); - }); - } - } - } - if ((PlayState.instance.controls.CUTSCENE_ADVANCE || isMobilePauseButtonPressed) - && cutsceneSkipped == false - && canSkipCutscene == true) - { - skipCutscene(); - trace('skipped'); + if(cutsceneTimerManager != null) cutsceneTimerManager.active = false; + + cutsceneMusic.pause(); + + PlayState.instance.preparePauseUI(); + PlayState.instance.openPauseSubState(PauseMode.Cutscene( + 'Cutscene', 'In-Game Cutscene', + resumeCutscene, skipCutscene, restartCutscene + ), FullScreenScaleMode.hasFakeCutouts ? PlayState.instance.camCutouts : PlayState.instance.camCutscene, null); } if (cutsceneConductor != null && cutsceneMusic != null) @@ -594,5 +576,35 @@ class PhillyTrainErectStage extends Stage super.kill(); if (cutsceneTimerManager != null) cutsceneTimerManager.destroy(); lightShader = null; + + if(bloodPool != null) + { + bloodPool.destroy(); + bloodPool = null; + } + + if(cigarette != null) + { + cigarette.destroy(); + cigarette = null; + } } + + function resumeCutscene():Void + { + if(cutsceneTimerManager != null) cutsceneTimerManager.active = true; + + cutsceneMusic.resume(); + } + + function restartCutscene():Void + { + if(cutsceneTimerManager != null) cutsceneTimerManager.active = true; + + cutsceneTimerManager.clear(); + picoPlayer.scriptCall('cancelSounds'); + picoOpponent.scriptCall('cancelSounds'); + cutsceneMusic.stop(); + doppleGangerCutscene(); + } } diff --git a/preload/scripts/stages/props/PicoDopplegangerSprite.hxc b/preload/scripts/stages/props/PicoDopplegangerSprite.hxc index dd73a4703..cbd6b9071 100644 --- a/preload/scripts/stages/props/PicoDopplegangerSprite.hxc +++ b/preload/scripts/stages/props/PicoDopplegangerSprite.hxc @@ -35,8 +35,17 @@ class PicoDopplegangerSprite extends FlxAtlasSprite if (cutsceneSounds != null) cutsceneSounds.destroy(); } - public function doAnim(_suffix:String, shoot:Bool = false, explode:Bool = false, timerManager:FlxTimerManager) + public function pauseSounds() { + if(cutsceneSounds != null) cutsceneSounds.pause(); + } + + public function resumeSounds() + { + if(cutsceneSounds != null) cutsceneSounds.resume(); + } + + public function doAnim(_suffix:String, shoot:Bool = false, explode:Bool = false, timerManager:FlxTimerManager){ suffix = _suffix; trace('Doppelganger: doAnim(' + suffix + ', ' + shoot + ', ' + explode + ')'); diff --git a/preload/scripts/stages/props/TankmanEndingSprite.hxc b/preload/scripts/stages/props/TankmanEndingSprite.hxc index 53c8d2351..3cb1c3351 100644 --- a/preload/scripts/stages/props/TankmanEndingSprite.hxc +++ b/preload/scripts/stages/props/TankmanEndingSprite.hxc @@ -30,9 +30,28 @@ class TankmanEndingSprite extends FlxAtlasSprite if (cutsceneSounds != null) cutsceneSounds.destroy(); } + public function pauseSounds() + { + if(cutsceneSounds != null) cutsceneSounds.pause(); + } + + public function resumeSounds() + { + if(cutsceneSounds != null) cutsceneSounds.resume(); + } + function doAnim() { playAnimation("tankman stress ending", true, false, false); - cutsceneSounds = FunkinSound.load(Paths.sound('erect/endCutscene'), 1.0, false, true, true); + + // playOnce/load makes the sound twice for whatever reason??? + var embeddedSound:String = Paths.sound('erect/endCutscene'); + cutsceneSounds = new FunkinSound(); + cutsceneSounds.loadEmbedded(embeddedSound, false, true); + cutsceneSounds.play(); + cutsceneSounds.volume = 1.0; + cutsceneSounds._label = embeddedSound; + FlxG.sound.defaultSoundGroup.add(cutsceneSounds); + FlxG.sound.list.add(cutsceneSounds); } }