Implement a botplay checkbox in the chart editor

This commit is contained in:
EliteMasterEric 2024-03-05 22:27:07 -05:00
parent 67788d762d
commit 1b1834e98b
6 changed files with 88 additions and 12 deletions

2
assets

@ -1 +1 @@
Subproject commit 69ebdb6a7aa57b6762ce509243679ab959615120
Subproject commit 51b02f0d47e5b34bf8589065c092953c10c5040d

View file

@ -111,6 +111,11 @@ typedef PlayStateParams =
* @default `false`
*/
?practiceMode:Bool,
/**
* Whether the song should start in Bot Play Mode.
* @default `false`
*/
?botPlayMode:Bool,
/**
* Whether the song should be in minimal mode.
* @default `false`
@ -282,6 +287,12 @@ class PlayState extends MusicBeatSubState
*/
public var isPracticeMode:Bool = false;
/**
* Whether the game is currently in Bot Play Mode.
* If true, player will not lose gain or lose score from notes.
*/
public var isBotPlayMode:Bool = false;
/**
* Whether the player has dropped below zero health,
* and we are just waiting for an animation to play out before transitioning.
@ -566,6 +577,7 @@ class PlayState extends MusicBeatSubState
if (params.targetDifficulty != null) currentDifficulty = params.targetDifficulty;
if (params.targetVariation != null) currentVariation = params.targetVariation;
isPracticeMode = params.practiceMode ?? false;
isBotPlayMode = params.botPlayMode ?? false;
isMinimalMode = params.minimalMode ?? false;
startTimestamp = params.startTimestamp ?? 0.0;
playbackRate = params.playbackRate ?? 1.0;
@ -1614,7 +1626,7 @@ class PlayState extends MusicBeatSubState
var noteStyle:NoteStyle = NoteStyleRegistry.instance.fetchEntry(noteStyleId);
if (noteStyle == null) noteStyle = NoteStyleRegistry.instance.fetchDefault();
playerStrumline = new Strumline(noteStyle, true);
playerStrumline = new Strumline(noteStyle, !isBotPlayMode);
opponentStrumline = new Strumline(noteStyle, false);
add(playerStrumline);
add(opponentStrumline);
@ -1876,7 +1888,14 @@ class PlayState extends MusicBeatSubState
function updateScoreText():Void
{
// TODO: Add functionality for modules to update the score text.
scoreText.text = 'Score:' + songScore;
if (isBotPlayMode)
{
scoreText.text = 'Bot Play Enabled';
}
else
{
scoreText.text = 'Score:' + songScore;
}
}
/**
@ -1884,7 +1903,14 @@ class PlayState extends MusicBeatSubState
*/
function updateHealthBar():Void
{
healthLerp = FlxMath.lerp(healthLerp, health, 0.15);
if (isBotPlayMode)
{
healthLerp = Constants.HEALTH_MAX;
}
else
{
healthLerp = FlxMath.lerp(healthLerp, health, 0.15);
}
}
/**
@ -1928,13 +1954,16 @@ class PlayState extends MusicBeatSubState
if (Conductor.instance.songPosition > hitWindowEnd)
{
if (note.hasMissed) continue;
if (note.hasMissed || note.hasBeenHit) continue;
note.tooEarly = false;
note.mayHit = false;
note.hasMissed = true;
if (note.holdNoteSprite != null) note.holdNoteSprite.missedNote = true;
if (note.holdNoteSprite != null)
{
note.holdNoteSprite.missedNote = true;
}
}
else if (Conductor.instance.songPosition > hitWindowCenter)
{
@ -2021,10 +2050,38 @@ class PlayState extends MusicBeatSubState
if (Conductor.instance.songPosition > hitWindowEnd)
{
if (note.hasMissed || note.hasBeenHit) continue;
note.tooEarly = false;
note.mayHit = false;
note.hasMissed = true;
if (note.holdNoteSprite != null) note.holdNoteSprite.missedNote = true;
if (note.holdNoteSprite != null)
{
note.holdNoteSprite.missedNote = true;
}
}
else if (isBotPlayMode && Conductor.instance.songPosition > hitWindowCenter)
{
if (note.hasBeenHit) continue;
// We call onHitNote to play the proper animations,
// but not goodNoteHit! This means zero score and zero notes hit for the results screen!
// Call an event to allow canceling the note hit.
// NOTE: This is what handles the character animations!
var event:NoteScriptEvent = new HitNoteScriptEvent(note, 0.0, 0, 'perfect', 0);
dispatchEvent(event);
// Calling event.cancelEvent() skips all the other logic! Neat!
if (event.eventCanceled) continue;
// Command the bot to hit the note on time.
// NOTE: This is what handles the strumline and cleaning up the note itself!
playerStrumline.hitNote(note);
if (note.holdNoteSprite != null)
{
playerStrumline.playNoteHoldCover(note.holdNoteSprite);
}
}
else if (Conductor.instance.songPosition > hitWindowStart)
{
@ -2069,7 +2126,7 @@ class PlayState extends MusicBeatSubState
if (holdNote == null || !holdNote.alive) continue;
// While the hold note is being hit, and there is length on the hold note...
if (holdNote.hitNote && !holdNote.missedNote && holdNote.sustainLength > 0)
if (!isBotPlayMode && holdNote.hitNote && !holdNote.missedNote && holdNote.sustainLength > 0)
{
// Grant the player health.
health += Constants.HEALTH_HOLD_BONUS_PER_SECOND * elapsed;

View file

@ -38,6 +38,10 @@ class Strumline extends FlxSpriteGroup
return FlxG.height / 0.45;
}
/**
* Whether this strumline is controlled by the player's inputs.
* False means it's controlled by the opponent or Bot Play.
*/
public var isPlayer:Bool;
/**

View file

@ -592,6 +592,11 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
*/
var playtestPracticeMode:Bool = false;
/**
* If true, playtesting a chart will make the computer do it for you!
*/
var playtestBotPlayMode:Bool = false;
/**
* Enables or disables the "debugger" popup that appears when you run into a flixel error.
*/
@ -5359,6 +5364,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
targetDifficulty: selectedDifficulty,
targetVariation: selectedVariation,
practiceMode: playtestPracticeMode,
botPlayMode: playtestBotPlayMode,
minimalMode: minimal,
startTimestamp: startTimestamp,
playbackRate: playbackRate,

View file

@ -299,6 +299,15 @@ class ChartEditorToolboxHandler
state.playtestStartTime = checkboxStartTime.selected;
};
var checkboxBotPlay:Null<CheckBox> = toolbox.findComponent('playtestBotPlayCheckbox', CheckBox);
if (checkboxBotPlay == null) throw 'ChartEditorToolboxHandler.buildToolboxPlaytestPropertiesLayout() - Could not find playtestBotPlayCheckbox component.';
checkboxBotPlay.selected = state.playtestBotPlayMode;
checkboxBotPlay.onClick = _ -> {
state.playtestBotPlayMode = checkboxBotPlay.selected;
};
var checkboxDebugger:Null<CheckBox> = toolbox.findComponent('playtestDebuggerCheckbox', CheckBox);
if (checkboxDebugger == null) throw 'ChartEditorToolboxHandler.buildToolboxPlaytestPropertiesLayout() - Could not find playtestDebuggerCheckbox component.';

View file

@ -1143,12 +1143,12 @@ class FreeplayState extends MusicBeatSubState
targetSong: targetSong,
targetDifficulty: targetDifficulty,
targetVariation: targetVariation,
// TODO: Make this an option!
// startTimestamp: 0.0,
// TODO: Make this an option!
// playbackRate: 0.5,
practiceMode: false,
minimalMode: false,
// TODO: Make these an option! It's currently only accessible via chart editor.
// startTimestamp: 0.0,
// playbackRate: 0.5,
// botPlayMode: true,
}, true);
});
}