diff --git a/assets b/assets index 7b5fda39c..572aa2bec 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 7b5fda39cf8af42f2435373137e42b58813209d6 +Subproject commit 572aa2becda9b6fc44beb382413070166a6ac348 diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index 1d988b13d..4c9b15461 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -121,6 +121,11 @@ typedef PlayStateParams = * @default `false` */ ?botPlayMode:Bool, + /** + * Whether the results screen should show up before returning to the chart editor. + * @default `false` + */ + ?playtestResults:Bool, /** * Whether the song should be in minimal mode. * @default `false` @@ -362,6 +367,11 @@ class PlayState extends MusicBeatSubState */ public var isBotPlayMode:Bool = false; + /** + * Whether the results screen should show up before returning to the chart editor. + */ + public var isPlaytestResults:Bool = false; + /** * Whether the player has dropped below zero health, * and we are just waiting for an animation to play out before transitioning. @@ -723,6 +733,7 @@ class PlayState extends MusicBeatSubState if (params.targetInstrumental != null) currentInstrumental = params.targetInstrumental; isPracticeMode = params.practiceMode ?? false; isBotPlayMode = params.botPlayMode ?? false; + isPlaytestResults = params.playtestResults ?? false; isMinimalMode = params.minimalMode ?? false; startTimestamp = params.startTimestamp ?? 0.0; playbackRate = params.playbackRate ?? 1.0; @@ -837,6 +848,7 @@ class PlayState extends MusicBeatSubState var pre:Float = (Conductor.instance.beatLengthMs * -5) + startTimestamp; trace('Attempting to start at ' + pre); + trace('startTimestamp ${startTimestamp}'); Conductor.instance.update(pre); @@ -1071,7 +1083,7 @@ class PlayState extends MusicBeatSubState opponentStrumline.clean(); // Delete all notes and reset the arrays. - regenNoteData(); + regenNoteData(startTimestamp); // Reset camera zooming cameraBopIntensity = Constants.DEFAULT_BOP_INTENSITY; @@ -2388,7 +2400,7 @@ class PlayState extends MusicBeatSubState } } - regenNoteData(); + regenNoteData(startTimestamp); var event:ScriptEvent = new ScriptEvent(CREATE, false); ScriptEventDispatcher.callEvent(currentSong, event); @@ -3598,7 +3610,21 @@ class PlayState extends MusicBeatSubState { if (isSubState) { - this.close(); + if (isPlaytestResults) + { + var talliesToUse:Tallies = PlayStatePlaylist.isStoryMode ? Highscore.talliesLevel : Highscore.tallies; + var clearPercentFloat = talliesToUse.totalNotes == 0 ? 0.0 : (talliesToUse.sick + talliesToUse.good) / talliesToUse.totalNotes * 100; + /* + Only move to the score screen if more than 30% of the song was successfully hit. + While that might sound like a low clear percent, consider the fact that some songs are hard, + and the user might be only playtesting one third or half the song. + */ + if (clearPercentFloat >= 30) moveToResultsScreen(false, prevScoreData); + else + this.close(); + } + else + this.close(); } else { diff --git a/source/funkin/play/ResultState.hx b/source/funkin/play/ResultState.hx index 9fd2b1c5e..40c1b0b7d 100644 --- a/source/funkin/play/ResultState.hx +++ b/source/funkin/play/ResultState.hx @@ -35,6 +35,7 @@ import funkin.ui.MusicBeatSubState; import funkin.ui.story.StoryMenuState; import funkin.util.HapticUtil; import funkin.graphics.ScriptedFunkinSprite; +import funkin.ui.debug.charting.ChartEditorState; #if FEATURE_NEWGROUNDS import funkin.api.newgrounds.Medals; #end @@ -93,6 +94,11 @@ class ResultState extends MusicBeatSubState var introMusicAudio:Null = null; + /** + * The music playing in the background of the state. + */ + var resultsMusic:Null = null; + var rankBg:FunkinSprite; final cameraBG:FunkinCamera; final cameraScroll:FunkinCamera; @@ -102,6 +108,15 @@ class ResultState extends MusicBeatSubState var busy:Bool = false; + public var isChartingMode(get, never):Bool; + + function get_isChartingMode():Bool + { + if (PlayState.instance != null) return PlayState.instance.isChartingMode; + else + return false; + } + public function new(params:ResultsStateParams) { super(); @@ -487,22 +502,34 @@ class ResultState extends MusicBeatSubState // Play the intro music. introMusicAudio = FunkinSound.load(introMusic, 1.0, false, true, true, () -> { introMusicAudio = null; + if (!isChartingMode) // Don't override the music and cause problems on the chart editor FunkinSound.playMusic(getMusicPath(playerCharacter, rank), { startingVolume: 1.0, overrideExisting: true, restartTrack: true }); + else // Play the results music as a looped sound instead (that we cancel before closing and returning to the chart editor) + { + resultsMusic = FunkinSound.load(Paths.music(getMusicPath(playerCharacter, rank) + '/' + getMusicPath(playerCharacter, rank)), 1.0, true, false, + true); + false; // Why is this necessary for this to work? + } }); + } else { - FunkinSound.playMusic(getMusicPath(playerCharacter, rank), + if (!isChartingMode) FunkinSound.playMusic(getMusicPath(playerCharacter, rank), { startingVolume: 1.0, overrideExisting: true, restartTrack: true }); + else + { + resultsMusic = FunkinSound.load(Paths.music(getMusicPath(playerCharacter, rank) + '/' + getMusicPath(playerCharacter, rank)), 1.0, true, false, true); + } } }); @@ -780,6 +807,7 @@ class ResultState extends MusicBeatSubState if (_parentState is funkin.ui.debug.results.ResultsDebugSubState) { if (introMusicAudio != null) + { introMusicAudio.stop(); introMusicAudio.destroy(); @@ -793,16 +821,18 @@ class ResultState extends MusicBeatSubState introMusicAudio.onComplete = null; FlxTween.tween(introMusicAudio, {volume: 0}, 0.8, + { - onComplete: _ -> { - if (introMusicAudio != null) + onComplete: _ -> { + if (introMusicAudio != null) + { - introMusicAudio.stop(); - introMusicAudio.destroy(); - introMusicAudio = null; + introMusicAudio.stop(); + introMusicAudio.destroy(); + introMusicAudio = null; + } } - } - }); + }); FlxTween.tween(introMusicAudio, {pitch: 3}, 0.1, { onComplete: _ -> { @@ -893,6 +923,16 @@ class ResultState extends MusicBeatSubState trace('THE RANK IS Higher.....'); shouldTween = true; + if (isChartingMode) + { + PlayState.instance?.close(); + FlxTimer.globalManager.clear(); + FlxTween.globalManager.clear(); + if (introMusicAudio != null) introMusicAudio.stop(); + if (resultsMusic != null) resultsMusic.stop(); + this.close(); + return; + } targetState = FreeplayState.build( { { @@ -910,6 +950,16 @@ class ResultState extends MusicBeatSubState } else { + if (isChartingMode) + { + PlayState.instance?.close(); + FlxTimer.globalManager.clear(); + FlxTween.globalManager.clear(); + if (introMusicAudio != null) introMusicAudio.stop(); + if (resultsMusic != null) resultsMusic.stop(); + this.close(); + return; + } shouldTween = false; shouldUseSubstate = true; targetStateFactory = () -> new StickerSubState( diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx index f88d33640..b7db9dc65 100644 --- a/source/funkin/ui/debug/charting/ChartEditorState.hx +++ b/source/funkin/ui/debug/charting/ChartEditorState.hx @@ -603,6 +603,11 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState */ var playtestBotPlayMode:Bool = false; + /** + * If true, after playtesting a chart the results screen will show your score. + */ + var playtestShowResults:Bool = false; + /** * Enables or disables the "debugger" popup that appears when you run into a flixel error. */ @@ -6260,6 +6265,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState targetVariation: selectedVariation, practiceMode: playtestPracticeMode, botPlayMode: playtestBotPlayMode, + playtestResults: playtestShowResults, minimalMode: minimal, startTimestamp: startTimestamp, playbackRate: playbackRate, diff --git a/source/funkin/ui/debug/charting/handlers/ChartEditorToolboxHandler.hx b/source/funkin/ui/debug/charting/handlers/ChartEditorToolboxHandler.hx index da3852233..9df85edaa 100644 --- a/source/funkin/ui/debug/charting/handlers/ChartEditorToolboxHandler.hx +++ b/source/funkin/ui/debug/charting/handlers/ChartEditorToolboxHandler.hx @@ -280,6 +280,16 @@ class ChartEditorToolboxHandler state.playtestBotPlayMode = checkboxBotPlay.selected; }; + var checkboxShowResults:Null = toolbox.findComponent('playtestShowResultsCheckbox', CheckBox); + if (checkboxShowResults == null) + throw 'ChartEditorToolboxHandler.buildToolboxPlaytestPropertiesLayout() - Could not find playtestShowResultsCheckbox component.'; + + checkboxShowResults.selected = state.playtestShowResults; + + checkboxShowResults.onClick = _ -> { + state.playtestShowResults = checkboxShowResults.selected; + }; + var checkboxSongScripts:Null = toolbox.findComponent('playtestSongScriptsCheckbox', CheckBox); if (checkboxSongScripts == null)