diff --git a/source/funkin/modding/IScriptedClass.hx b/source/funkin/modding/IScriptedClass.hx index 14aa6b494c..15e2940bbc 100644 --- a/source/funkin/modding/IScriptedClass.hx +++ b/source/funkin/modding/IScriptedClass.hx @@ -140,7 +140,7 @@ interface IPlayStateScriptedClass extends INoteScriptedClass extends IBPMSyncedS /** * Called when the player restarts the song, either via pause menu or restarting after a game over. */ - public function onSongRetry(event:ScriptEvent):Void; + public function onSongRetry(event:SongRetryEvent):Void; /** * Called when the player presses a key when no note is on the strumline. diff --git a/source/funkin/modding/events/ScriptEvent.hx b/source/funkin/modding/events/ScriptEvent.hx index 0624c2503a..414448b8c7 100644 --- a/source/funkin/modding/events/ScriptEvent.hx +++ b/source/funkin/modding/events/ScriptEvent.hx @@ -414,6 +414,28 @@ class SongLoadScriptEvent extends ScriptEvent } } +/** + * AAn event that is fired when the player retries the song. + */ +class SongRetryEvent extends ScriptEvent +{ + /** + * The new difficulty of the song. + */ + public var difficulty(default, null):String; + + public function new(difficulty:String):Void + { + super(SONG_RETRY, false); + this.difficulty = difficulty; + } + + public override function toString():String + { + return 'SongRetryEvent(difficulty=$difficulty)'; + } +} + /** * An event that is fired when moving out of or into an FlxState. */ diff --git a/source/funkin/modding/events/ScriptEventDispatcher.hx b/source/funkin/modding/events/ScriptEventDispatcher.hx index 7e19173c46..7f6d00347a 100644 --- a/source/funkin/modding/events/ScriptEventDispatcher.hx +++ b/source/funkin/modding/events/ScriptEventDispatcher.hx @@ -124,7 +124,7 @@ class ScriptEventDispatcher t.onSongEnd(event); return; case SONG_RETRY: - t.onSongRetry(event); + t.onSongRetry(cast event); return; case GAME_OVER: t.onGameOver(event); diff --git a/source/funkin/modding/module/Module.hx b/source/funkin/modding/module/Module.hx index be9b7146b0..38fcfe7933 100644 --- a/source/funkin/modding/module/Module.hx +++ b/source/funkin/modding/module/Module.hx @@ -117,5 +117,5 @@ class Module implements IPlayStateScriptedClass implements IStateChangingScripte public function onSubStateCloseEnd(event:SubStateScriptEvent) {} - public function onSongRetry(event:ScriptEvent) {} + public function onSongRetry(event:SongRetryEvent) {} } diff --git a/source/funkin/play/PauseSubState.hx b/source/funkin/play/PauseSubState.hx index 9ff70bee57..3c9a670888 100644 --- a/source/funkin/play/PauseSubState.hx +++ b/source/funkin/play/PauseSubState.hx @@ -649,6 +649,7 @@ class PauseSubState extends MusicBeatSubState // So if you switch difficulty on the last song of a week you get a really low overall score. PlayStatePlaylist.campaignScore = 0; PlayStatePlaylist.campaignDifficulty = difficulty; + PlayState.instance.previousDifficulty = PlayState.instance.currentDifficulty; PlayState.instance.currentDifficulty = PlayStatePlaylist.campaignDifficulty; FreeplayState.rememberedDifficulty = difficulty; diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index dbacf3fa96..0ccda459ee 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -344,6 +344,11 @@ class PlayState extends MusicBeatSubState */ public var disableKeys:Bool = false; + /** + * The previous difficulty the player was playing on. + */ + public var previousDifficulty:String = Constants.DEFAULT_DIFFICULTY; + public var isSubState(get, never):Bool; function get_isSubState():Bool @@ -615,6 +620,7 @@ class PlayState extends MusicBeatSubState // Apply parameters. currentSong = params.targetSong; if (params.targetDifficulty != null) currentDifficulty = params.targetDifficulty; + previousDifficulty = currentDifficulty; if (params.targetVariation != null) currentVariation = params.targetVariation; if (params.targetInstrumental != null) currentInstrumental = params.targetInstrumental; isPracticeMode = params.practiceMode ?? false; @@ -843,7 +849,11 @@ class PlayState extends MusicBeatSubState prevScrollTargets = []; - dispatchEvent(new ScriptEvent(SONG_RETRY)); + var retryEvent = new SongRetryEvent(currentDifficulty); + + previousDifficulty = currentDifficulty; + + dispatchEvent(retryEvent); resetCamera(); diff --git a/source/funkin/play/notes/Strumline.hx b/source/funkin/play/notes/Strumline.hx index e894f9c627..1a1b43ae40 100644 --- a/source/funkin/play/notes/Strumline.hx +++ b/source/funkin/play/notes/Strumline.hx @@ -36,11 +36,31 @@ class Strumline extends FlxSpriteGroup static var RENDER_DISTANCE_MS(get, never):Float; + /** + * The custom render distance for the strumline. + * This should be in miliseconds only! Not pixels. + */ + public static var CUSTOM_RENDER_DISTANCE_MS:Float = 0.0; + + /** + * Whether to use the custom render distance. + * If false, the render distance will be calculated based on the screen height. + */ + public static var USE_CUSTOM_RENDER_DISTANCE:Bool = false; + static function get_RENDER_DISTANCE_MS():Float { + if (USE_CUSTOM_RENDER_DISTANCE) return CUSTOM_RENDER_DISTANCE_MS; return FlxG.height / Constants.PIXELS_PER_MS; } + /** + * Whether to play note splashes or not + * TODO: Make this a setting! + * IE: Settings.noSplash + */ + public var showNotesplash:Bool = true; + /** * Whether this strumline is controlled by the player's inputs. * False means it's controlled by the opponent or Bot Play. @@ -74,6 +94,11 @@ class Strumline extends FlxSpriteGroup return _conductorInUse = value; } + /** + * Whether the game should auto position notes. + */ + public var customPositionData:Bool = false; + /** * The notes currently being rendered on the strumline. * This group iterates over this every frame to update note positions. @@ -376,7 +401,7 @@ class Strumline extends FlxSpriteGroup var vwoosh:Bool = note.holdNoteSprite == null; // Set the note's position. - note.y = this.y - INITIAL_OFFSET + calculateNoteYPos(note.strumTime, vwoosh); + if (!customPositionData) note.y = this.y - INITIAL_OFFSET + calculateNoteYPos(note.strumTime, vwoosh); // If the note is miss var isOffscreen = Preferences.downscroll ? note.y > FlxG.height : note.y < -note.height; @@ -446,13 +471,16 @@ class Strumline extends FlxSpriteGroup var vwoosh:Bool = false; - if (Preferences.downscroll) + if (!customPositionData) { - holdNote.y = this.y - INITIAL_OFFSET + calculateNoteYPos(holdNote.strumTime, vwoosh) - holdNote.height + STRUMLINE_SIZE / 2; - } - else - { - holdNote.y = this.y - INITIAL_OFFSET + calculateNoteYPos(holdNote.strumTime, vwoosh) + yOffset + STRUMLINE_SIZE / 2; + if (Preferences.downscroll) + { + holdNote.y = this.y - INITIAL_OFFSET + calculateNoteYPos(holdNote.strumTime, vwoosh) - holdNote.height + STRUMLINE_SIZE / 2; + } + else + { + holdNote.y = this.y - INITIAL_OFFSET + calculateNoteYPos(holdNote.strumTime, vwoosh) + yOffset + STRUMLINE_SIZE / 2; + } } // Clean up the cover. @@ -475,13 +503,16 @@ class Strumline extends FlxSpriteGroup holdNote.visible = false; } - if (Preferences.downscroll) + if (!customPositionData) { - holdNote.y = this.y - INITIAL_OFFSET - holdNote.height + STRUMLINE_SIZE / 2; - } - else - { - holdNote.y = this.y - INITIAL_OFFSET + STRUMLINE_SIZE / 2; + if (Preferences.downscroll) + { + holdNote.y = this.y - INITIAL_OFFSET - holdNote.height + STRUMLINE_SIZE / 2; + } + else + { + holdNote.y = this.y - INITIAL_OFFSET + STRUMLINE_SIZE / 2; + } } } else @@ -490,13 +521,16 @@ class Strumline extends FlxSpriteGroup holdNote.visible = true; var vwoosh:Bool = false; - if (Preferences.downscroll) - { - holdNote.y = this.y - INITIAL_OFFSET + calculateNoteYPos(holdNote.strumTime, vwoosh) - holdNote.height + STRUMLINE_SIZE / 2; - } - else + if (!customPositionData) { - holdNote.y = this.y - INITIAL_OFFSET + calculateNoteYPos(holdNote.strumTime, vwoosh) + STRUMLINE_SIZE / 2; + if (Preferences.downscroll) + { + holdNote.y = this.y - INITIAL_OFFSET + calculateNoteYPos(holdNote.strumTime, vwoosh) - holdNote.height + STRUMLINE_SIZE / 2; + } + else + { + holdNote.y = this.y - INITIAL_OFFSET + calculateNoteYPos(holdNote.strumTime, vwoosh) + STRUMLINE_SIZE / 2; + } } } } @@ -708,8 +742,7 @@ class Strumline extends FlxSpriteGroup public function playNoteSplash(direction:NoteDirection):Void { - // TODO: Add a setting to disable note splashes. - // if (Settings.noSplash) return; + if (!showNotesplash) return; if (!noteStyle.isNoteSplashEnabled()) return; var splash:NoteSplash = this.constructNoteSplash(); @@ -729,8 +762,7 @@ class Strumline extends FlxSpriteGroup public function playNoteHoldCover(holdNote:SustainTrail):Void { - // TODO: Add a setting to disable note splashes. - // if (Settings.noSplash) return; + if (!showNotesplash) return; if (!noteStyle.isHoldNoteCoverEnabled()) return; var cover:NoteHoldCover = this.constructNoteHoldCover(); diff --git a/source/funkin/play/notes/SustainTrail.hx b/source/funkin/play/notes/SustainTrail.hx index a9af468b94..52241ea9c2 100644 --- a/source/funkin/play/notes/SustainTrail.hx +++ b/source/funkin/play/notes/SustainTrail.hx @@ -86,6 +86,11 @@ class SustainTrail extends FlxSprite */ public var bottomClip:Float = 0.9; + /** + * Whether the note will recieve custom vertex data + */ + public var customVertexData:Bool = false; + public var isPixel:Bool; public var noteStyleOffsets:Array; @@ -110,11 +115,68 @@ class SustainTrail extends FlxSprite setupHoldNoteGraphic(noteStyle); noteStyleOffsets = noteStyle.getHoldNoteOffsets(); - indices = new DrawData(12, true, TRIANGLE_VERTEX_INDICES); + setIndices(TRIANGLE_VERTEX_INDICES); this.active = true; // This NEEDS to be true for the note to be drawn! } + /** + * Sets the indices for the triangles. + * @param indices The indices to set. + */ + public function setIndices(indices:Array):Void + { + if (this.indices.length == indices.length) + { + for (i in 0...indices.length) + { + this.indices[i] = indices[i]; + } + } + else + { + this.indices = new DrawData(indices.length, false, indices); + } + } + + /** + * Sets the vertices for the triangles. + * @param vertices The vertices to set. + */ + public function setVertices(vertices:Array):Void + { + if (this.vertices.length == vertices.length) + { + for (i in 0...vertices.length) + { + this.vertices[i] = vertices[i]; + } + } + else + { + this.vertices = new DrawData(vertices.length, false, vertices); + } + } + + /** + * Sets the UV data for the triangles. + * @param uvtData The UV data to set. + */ + public function setUVTData(uvtData:Array):Void + { + if (this.uvtData.length == uvtData.length) + { + for (i in 0...uvtData.length) + { + this.uvtData[i] = uvtData[i]; + } + } + else + { + this.uvtData = new DrawData(uvtData.length, false, uvtData); + } + } + /** * Creates hold note graphic and applies correct zooming * @param noteStyle The note style @@ -214,7 +276,7 @@ class SustainTrail extends FlxSprite */ public function updateClipping(songTime:Float = 0):Void { - if (graphic == null) + if (graphic == null || customVertexData) { return; } diff --git a/source/funkin/play/song/Song.hx b/source/funkin/play/song/Song.hx index 20d2f75a4c..12dbd5a52f 100644 --- a/source/funkin/play/song/Song.hx +++ b/source/funkin/play/song/Song.hx @@ -643,11 +643,11 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry