Chart Editor playtest option for Results Screen

This commit is contained in:
Lasercar
2025-12-09 01:12:11 -06:00
committed by Abnormal
parent 9f0a4988a3
commit eeba677da9
5 changed files with 104 additions and 12 deletions
+1 -1
Submodule assets updated: 7b5fda39cf...572aa2becd
+29 -3
View File
@@ -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
{
+58 -8
View File
@@ -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<FunkinSound> = null;
/**
* The music playing in the background of the state.
*/
var resultsMusic:Null<FunkinSound> = 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(
@@ -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,
@@ -280,6 +280,16 @@ class ChartEditorToolboxHandler
state.playtestBotPlayMode = checkboxBotPlay.selected;
};
var checkboxShowResults:Null<CheckBox> = 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<CheckBox> = toolbox.findComponent('playtestSongScriptsCheckbox', CheckBox);
if (checkboxSongScripts == null)