Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Chart editor play(state)test to results screen #4087

Open
wants to merge 14 commits into
base: develop
Choose a base branch
from
59 changes: 55 additions & 4 deletions source/funkin/play/PlayState.hx
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,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`
Expand Down Expand Up @@ -311,6 +316,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.
Expand Down Expand Up @@ -613,6 +623,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;
Expand Down Expand Up @@ -682,6 +693,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);

Expand Down Expand Up @@ -876,7 +888,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;
Expand Down Expand Up @@ -1919,7 +1931,7 @@ class PlayState extends MusicBeatSubState
}
}

regenNoteData();
regenNoteData(startTimestamp); // ok, who forgot to pass the startTimestamp into this?

var event:ScriptEvent = new ScriptEvent(CREATE, false);
ScriptEventDispatcher.callEvent(currentSong, event);
Expand All @@ -1937,6 +1949,8 @@ class PlayState extends MusicBeatSubState

var event:SongLoadScriptEvent = new SongLoadScriptEvent(currentChart.song.id, currentChart.difficulty, currentChart.notes.copy(), currentChart.getEvents());

var removedNotes:Int = 0;

dispatchEvent(event);

var builtNoteData = event.notes;
Expand All @@ -1952,8 +1966,26 @@ class PlayState extends MusicBeatSubState
for (songNote in builtNoteData)
{
var strumTime:Float = songNote.time;
if (strumTime < startTime) continue; // Skip notes that are before the start time.
if (strumTime < startTime)
{
if (isPlaytestResults) // only do the following if we're playtesting with the results screen
{
var noteData:Int = songNote.getDirection();
var playerNote:Bool = true;

if (noteData > 3) playerNote = false;

switch (songNote.getStrumlineIndex())
{
case 0:
// Don't add the player note to total, to make the clear percent be of only the following notes
removedNotes++;
case 1:
// Nothing!
}
}
continue; // Skip notes that are before the start time.
}
var noteData:Int = songNote.getDirection();
var playerNote:Bool = true;

Expand All @@ -1969,6 +2001,11 @@ class PlayState extends MusicBeatSubState
opponentNoteData.push(songNote);
}
}
if (isPlaytestResults)
{
trace('playtesting results! Removed ${removedNotes} notes from total');
trace('Total notes: ${Highscore.tallies.totalNotes}');
}

playerStrumline.applyNoteData(playerNoteData);
opponentStrumline.applyNoteData(opponentNoteData);
Expand Down Expand Up @@ -3092,7 +3129,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
{
Expand Down
82 changes: 66 additions & 16 deletions source/funkin/play/ResultState.hx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import funkin.save.Save.SaveScoreData;
import funkin.graphics.shaders.LeftMaskShader;
import funkin.play.components.TallyCounter;
import funkin.play.components.ClearPercentCounter;
import funkin.ui.debug.charting.ChartEditorState;

/**
* The state for the results screen after a song or week is finished.
Expand Down Expand Up @@ -76,11 +77,24 @@ class ResultState extends MusicBeatSubState

var introMusicAudio:Null<FunkinSound>;

/**
* The music playing in the background of the state.
*/
var resultsMusic:Null<FunkinSound> = null;

var rankBg:FunkinSprite;
final cameraBG:FunkinCamera;
final cameraScroll:FunkinCamera;
final cameraEverything:FunkinCamera;

public var isChartingMode(get, never):Bool;

// This is stupid, but it works
function get_isChartingMode():Bool
{
return PlayState.instance.isChartingMode;
}

public function new(params:ResultsStateParams)
{
super();
Expand Down Expand Up @@ -417,22 +431,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);
}
}
});

Expand Down Expand Up @@ -730,19 +756,22 @@ class ResultState extends MusicBeatSubState

if (controls.PAUSE)
{
if (introMusicAudio != null) {
if (introMusicAudio != null)
{
@:nullSafety(Off)
introMusicAudio.onComplete = null;

FlxTween.tween(introMusicAudio, {volume: 0}, 0.8, {
onComplete: _ -> {
if (introMusicAudio != null) {
introMusicAudio.stop();
introMusicAudio.destroy();
introMusicAudio = null;
FlxTween.tween(introMusicAudio, {volume: 0}, 0.8,
{
onComplete: _ -> {
if (introMusicAudio != null)
{
introMusicAudio.stop();
introMusicAudio.destroy();
introMusicAudio = null;
}
}
}
});
});
FlxTween.tween(introMusicAudio, {pitch: 3}, 0.1,
{
onComplete: _ -> {
Expand All @@ -752,12 +781,13 @@ class ResultState extends MusicBeatSubState
}
else if (FlxG.sound.music != null)
{
FlxTween.tween(FlxG.sound.music, {volume: 0}, 0.8, {
onComplete: _ -> {
FlxG.sound.music.stop();
FlxG.sound.music.destroy();
}
});
FlxTween.tween(FlxG.sound.music, {volume: 0}, 0.8,
{
onComplete: _ -> {
FlxG.sound.music.stop();
FlxG.sound.music.destroy();
}
});
FlxTween.tween(FlxG.sound.music, {pitch: 3}, 0.1,
{
onComplete: _ -> {
Expand Down Expand Up @@ -803,6 +833,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(
{
{
Expand All @@ -820,6 +860,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;
targetState = new funkin.ui.transition.StickerSubState(null, (sticker) -> FreeplayState.build(null, sticker));
Expand Down
6 changes: 6 additions & 0 deletions source/funkin/ui/debug/charting/ChartEditorState.hx
Original file line number Diff line number Diff line change
Expand Up @@ -618,6 +618,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.
*/
Expand Down Expand Up @@ -5735,6 +5740,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
targetVariation: selectedVariation,
practiceMode: playtestPracticeMode,
botPlayMode: playtestBotPlayMode,
playtestResults: playtestShowResults,
minimalMode: minimal,
startTimestamp: startTimestamp,
playbackRate: playbackRate,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,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)
Expand Down
1 change: 1 addition & 0 deletions source/funkin/ui/freeplay/FreeplayState.hx
Original file line number Diff line number Diff line change
Expand Up @@ -1664,6 +1664,7 @@ class FreeplayState extends MusicBeatSubState
{
grpCapsules.members[curSelected].onConfirm();
}

}

override function beatHit():Bool
Expand Down