diff --git a/assets b/assets index b2f8b6a78..5479e17b1 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit b2f8b6a780316959d0a79adc6dbf61f9e4ca675f +Subproject commit 5479e17b1085f72e05f1c1f9e0a668ef832d3341 diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index cc9debf13..763c05640 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -87,6 +87,12 @@ typedef PlayStateParams = * @default `bf`, or the first character in the song's character list. */ ?targetCharacter:String, + /** + * The instrumental to play with. + * Significant if the `targetSong` supports alternate instrumentals. + * @default `null` + */ + ?targetInstrumental:String, /** * Whether the song should start in Practice Mode. * @default `false` @@ -448,7 +454,7 @@ class PlayState extends MusicBeatSubState function get_currentChart():SongDifficulty { if (currentSong == null || currentDifficulty == null) return null; - return currentSong.getDifficulty(currentDifficulty); + return currentSong.getDifficulty(currentDifficulty, currentPlayerId); } /** @@ -2650,13 +2656,16 @@ class PlayState extends MusicBeatSubState { // Stop the music. FlxG.sound.music.pause(); - vocals.stop(); + if (vocals != null) vocals.stop(); } else { FlxG.sound.music.pause(); - vocals.pause(); - remove(vocals); + if (vocals != null) + { + vocals.pause(); + remove(vocals); + } } // Remove reference to stage and remove sprites from it to save memory. diff --git a/source/funkin/play/song/Song.hx b/source/funkin/play/song/Song.hx index 0434607f3..52a1ba6f8 100644 --- a/source/funkin/play/song/Song.hx +++ b/source/funkin/play/song/Song.hx @@ -184,7 +184,10 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry + public inline function getDifficulty(?diffId:String, ?variation:String):Null { if (diffId == null) diffId = listDifficulties()[0]; - return difficulties.get(diffId); + if (variation == null) variation = Constants.DEFAULT_VARIATION; + var variationSuffix = (variation != null && variation != '' && variation != Constants.DEFAULT_VARIATION) ? '-$variation' : ''; + + return difficulties.get('$diffId$variationSuffix'); } /** @@ -272,12 +279,16 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry = difficulties.keys().array().filter(function(diffId:String):Bool { - if (variationId == null) return true; + // The difficulties array contains entries like 'normal', 'nightmare-erect', and 'normal-pico', + // so we have to map it to the actual difficulty names. + // We also filter out difficulties that don't match the variation or that don't exist. + + var diffFiltered:Array = difficulties.keys().array().map(function(diffId:String):Null { var difficulty:Null = difficulties.get(diffId); - if (difficulty == null) return false; - return difficulty.variation == variationId; - }); + if (difficulty == null) return null; + if (variationId != null && difficulty.variation != variationId) return null; + return difficulty.difficulty; + }).nonNull().unique(); diffFiltered.sort(SortUtil.defaultsThenAlphabetically.bind(Constants.DEFAULT_DIFFICULTY_LIST)); @@ -286,8 +297,9 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry = difficulties.get(diffId); + if (variationId == '') variationId = Constants.DEFAULT_VARIATION; + var variationSuffix:String = (variationId == Constants.DEFAULT_VARIATION) ? '' : '-$variationId'; + var difficulty:Null = difficulties.get('$diffId$variationSuffix'); return variationId == null ? (difficulty != null) : (difficulty != null && difficulty.variation == variationId); } diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index de6484fd3..f981357cf 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -54,6 +54,14 @@ import funkin.util.MathUtil; import lime.app.Future; import lime.utils.Assets; +/** + * Parameters used to initialize the FreeplayState. + */ +typedef FreeplayStateParams = +{ + ?character:String; +}; + class FreeplayState extends MusicBeatSubState { var songs:Array> = []; @@ -64,6 +72,9 @@ class FreeplayState extends MusicBeatSubState var curSelected:Int = 0; var currentDifficulty:String = Constants.DEFAULT_DIFFICULTY; + // Params + var currentCharacter:String; + var fp:FreeplayScore; var txtCompletion:AtlasText; var lerpCompletion:Float = 0; @@ -99,12 +110,13 @@ class FreeplayState extends MusicBeatSubState var stickerSubState:StickerSubState; - // static var rememberedDifficulty:Null = Constants.DEFAULT_DIFFICULTY; static var rememberedSongId:Null = null; - public function new(?stickers:StickerSubState = null) + public function new(?params:FreeplayParams, ?stickers:StickerSubState) { + currentCharacter = params?.character ?? Constants.DEFAULT_CHARACTER; + if (stickers != null) { stickerSubState = stickers; @@ -844,6 +856,13 @@ class FreeplayState extends MusicBeatSubState changeDiff(1); } + // TODO: DEBUG REMOVE THIS + if (FlxG.keys.justPressed.P) + { + currentCharacter = (currentCharacter == "bf") ? "pico" : "bf"; + changeSelection(0); + } + if (controls.BACK && !typing.hasFocus) { FlxTween.globalManager.clear(); diff --git a/source/funkin/util/tools/ArrayTools.hx b/source/funkin/util/tools/ArrayTools.hx index 0209cfc19..caf8e8aab 100644 --- a/source/funkin/util/tools/ArrayTools.hx +++ b/source/funkin/util/tools/ArrayTools.hx @@ -23,6 +23,24 @@ class ArrayTools return result; } + /** + * Returns a copy of the array with all `null` elements removed. + * @param array The array to remove `null` elements from. + * @return A copy of the array with all `null` elements removed. + */ + public static function nonNull(array:Array>):Array + { + var result:Array = []; + for (element in array) + { + if (element != null) + { + result.push(element); + } + } + return result; + } + /** * Return the first element of the array that satisfies the predicate, or null if none do. * @param input The array to search