From 79eb7d633c2bc2546038456dc5a19d55fe477eca Mon Sep 17 00:00:00 2001 From: afreetoplaynoob <149265233+afreetoplaynoob@users.noreply.github.com> Date: Wed, 2 Oct 2024 08:32:21 -0300 Subject: [PATCH 01/29] Properly format the chart editor playbar Minor change, but this makes the song time in the chart editor follow a proper time format. --- source/funkin/ui/debug/charting/ChartEditorState.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx index ba2f24a73f4..c279009f0d4 100644 --- a/source/funkin/ui/debug/charting/ChartEditorState.hx +++ b/source/funkin/ui/debug/charting/ChartEditorState.hx @@ -5160,7 +5160,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState var songPosSeconds:String = Std.string(Math.floor((Math.abs(songPos) / 1000) % 60)).lpad('0', 2); var songPosMinutes:String = Std.string(Math.floor((Math.abs(songPos) / 1000) / 60)).lpad('0', 2); if (songPos < 0) songPosMinutes = '-' + songPosMinutes; - var songPosString:String = '${songPosMinutes}:${songPosSeconds}:${songPosMilliseconds}'; + var songPosString:String = '${songPosMinutes}:${songPosSeconds}.${songPosMilliseconds}'; if (playbarSongPos.value != songPosString) playbarSongPos.value = songPosString; From a4ed55721ffc7fdf7675e2acdb3cb564fc08d6ad Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Fri, 4 Oct 2024 07:58:21 -0400 Subject: [PATCH 02/29] Fix duplicate combo counter on combo break Co-authored-by: Eric Co-authored-by: Hundrec --- source/funkin/play/PlayState.hx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/source/funkin/play/PlayState.hx b/source/funkin/play/PlayState.hx index d28ae6535ad..dbacf3fa967 100644 --- a/source/funkin/play/PlayState.hx +++ b/source/funkin/play/PlayState.hx @@ -2562,8 +2562,8 @@ class PlayState extends MusicBeatSubState healthChange = Constants.HEALTH_BAD_BONUS; isComboBreak = Constants.JUDGEMENT_BAD_COMBO_BREAK; case 'shit': - isComboBreak = Constants.JUDGEMENT_SHIT_COMBO_BREAK; healthChange = Constants.HEALTH_SHIT_BONUS; + isComboBreak = Constants.JUDGEMENT_SHIT_COMBO_BREAK; } // Send the note hit event. @@ -2633,8 +2633,6 @@ class PlayState extends MusicBeatSubState } vocals.playerVolume = 0; - if (Highscore.tallies.combo != 0) if (Highscore.tallies.combo >= 10) comboPopUps.displayCombo(0); - applyScore(-10, 'miss', healthChange, true); if (playSound) @@ -2853,7 +2851,7 @@ class PlayState extends MusicBeatSubState } } comboPopUps.displayRating(daRating); - if (combo >= 10 || combo == 0) comboPopUps.displayCombo(combo); + if (combo >= 10) comboPopUps.displayCombo(combo); vocals.playerVolume = 1; } From 1d2bd61119e5f418df7f11d7ef2a0fdedee17d3d Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Tue, 1 Oct 2024 00:45:56 -0400 Subject: [PATCH 03/29] fix: picos songs properly load on freeplay --- source/funkin/ui/freeplay/FreeplayState.hx | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index 7d40e85163d..e4156f7ac82 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -270,6 +270,13 @@ class FreeplayState extends MusicBeatSubState fromResultsParams = params?.fromResults; + // bf songs have no suffix, but we need to initalize the difficulty + // in case we begin playing as pico + if (currentCharacterId != 'bf') + { + currentSuffixedDifficulty = Constants.DEFAULT_DIFFICULTY + '-$currentCharacterId'; + } + if (fromResultsParams?.playRankAnim == true) { prepForNewRank = true; @@ -783,7 +790,7 @@ class FreeplayState extends MusicBeatSubState { tempSongs = tempSongs.filter(song -> { if (song == null) return true; // Random - return song.suffixedSongDifficulties.contains(currentSuffixedDifficulty); + return (song.suffixedSongDifficulties.contains(currentSuffixedDifficulty) || song.songCharacter == currentCharacterId); }); } @@ -1797,6 +1804,7 @@ class FreeplayState extends MusicBeatSubState currentSuffixedDifficulty = suffixedDiffIdsCurrent[currentDifficultyIndex]; trace('Switching to difficulty: ${currentSuffixedDifficulty}'); + trace(suffixedDiffIdsCurrent); var daSong:Null = grpCapsules.members[curSelected].songData; if (daSong != null) @@ -2382,6 +2390,7 @@ class FreeplaySongData this.isFav = Save.instance.isSongFavorited(songId); this.currentCharacter = currentCharacter; + if (displayedVariations != null) this.displayedVariations = displayedVariations; updateValues(displayedVariations); @@ -2407,6 +2416,7 @@ class FreeplaySongData function updateValues(variations:Array):Void { + trace('variations: ${variations}'); this.songDifficulties = song.listDifficulties(null, variations, false, false); this.suffixedSongDifficulties = song.listSuffixedDifficulties(variations, false, false); if (!this.songDifficulties.contains(currentUnsuffixedDifficulty)) From d7f50703174ed40673c1d493e51af2dcc7728d7b Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Tue, 1 Oct 2024 12:54:12 -0400 Subject: [PATCH 04/29] properly display pico vs darnell songs along with pico mixes --- source/funkin/ui/freeplay/FreeplayState.hx | 26 ++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index e4156f7ac82..65c28a0085c 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -790,7 +790,13 @@ class FreeplayState extends MusicBeatSubState { tempSongs = tempSongs.filter(song -> { if (song == null) return true; // Random - return (song.suffixedSongDifficulties.contains(currentSuffixedDifficulty) || song.songCharacter == currentCharacterId); + + // Include songs that match the current suffixed difficulty (`normal-pico`) + // or the current unsuffixed difficulty, `normal` + // or songs specifically for the current character `normal` w/ songCharacter == `pico` + return (song.suffixedSongDifficulties.contains(currentSuffixedDifficulty) + || song.songDifficulties.contains(currentUnsuffixedDifficulty) + || song.songCharacter == currentCharacterId); }); } @@ -1817,6 +1823,15 @@ class FreeplayState extends MusicBeatSubState } var suffixedDifficulty = suffixedDiffIdsCurrent[currentDifficultyIndex]; + var unsuffixedDifficulty = currentUnsuffixedDifficulty; + + // Check for character-specific difficulty + var characterSuffixedDifficulty = '${unsuffixedDifficulty}-${currentCharacterId}'; + if (daSong.suffixedSongDifficulties.contains(characterSuffixedDifficulty)) + { + suffixedDifficulty = characterSuffixedDifficulty; + } + var songScore:Null = Save.instance.getSongScore(daSong.songId, suffixedDifficulty); trace(songScore); intendedScore = songScore?.score ?? 0; @@ -2419,7 +2434,14 @@ class FreeplaySongData trace('variations: ${variations}'); this.songDifficulties = song.listDifficulties(null, variations, false, false); this.suffixedSongDifficulties = song.listSuffixedDifficulties(variations, false, false); - if (!this.songDifficulties.contains(currentUnsuffixedDifficulty)) + + // Add character-specific difficulties + for (difficulty in this.songDifficulties) + { + this.suffixedSongDifficulties.push('${difficulty}-${currentCharacter.id}'); + } + + if (!this.songDifficulties.contains(currentUnsuffixedDifficulty) && !this.suffixedSongDifficulties.contains(currentSuffixedDifficulty)) { currentSuffixedDifficulty = Constants.DEFAULT_DIFFICULTY; // This method gets called again by the setter-method From f862fb2c3e876f244ea52116aa347c70fc3e0ecf Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Tue, 1 Oct 2024 13:12:10 -0400 Subject: [PATCH 05/29] load in data for pico songs --- source/funkin/ui/freeplay/FreeplayState.hx | 46 +++++++++++++++++++--- 1 file changed, 41 insertions(+), 5 deletions(-) diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index 65c28a0085c..a8755b2995a 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -791,6 +791,13 @@ class FreeplayState extends MusicBeatSubState tempSongs = tempSongs.filter(song -> { if (song == null) return true; // Random + // Check for character-specific difficulty first + var characterSuffixedDifficulty = '${currentUnsuffixedDifficulty}-${currentCharacterId}'; + if (song.suffixedSongDifficulties.contains(characterSuffixedDifficulty)) + { + return true; + } + // Include songs that match the current suffixed difficulty (`normal-pico`) // or the current unsuffixed difficulty, `normal` // or songs specifically for the current character `normal` w/ songCharacter == `pico` @@ -1108,7 +1115,7 @@ class FreeplayState extends MusicBeatSubState }); } - function rankAnimSlam(fromResultsParams:Null) + function rankAnimSlam(fromResultsParams:Null):Void { // FlxTween.tween(rankCamera, {"zoom": 1.9}, 0.5, {ease: FlxEase.backOut}); FlxTween.tween(rankBg, {alpha: 0}, 0.5, {ease: FlxEase.expoIn}); @@ -1807,7 +1814,16 @@ class FreeplayState extends MusicBeatSubState if (currentDifficultyIndex < 0) currentDifficultyIndex = suffixedDiffIdsCurrent.length - 1; if (currentDifficultyIndex >= suffixedDiffIdsCurrent.length) currentDifficultyIndex = 0; - currentSuffixedDifficulty = suffixedDiffIdsCurrent[currentDifficultyIndex]; + var newSuffixedDifficulty = suffixedDiffIdsCurrent[currentDifficultyIndex]; + + // Always try to use the character-specific difficulty + var characterSuffixedDifficulty = '${newSuffixedDifficulty}-${currentCharacterId}'; + if (suffixedDiffIdsCurrent.contains(characterSuffixedDifficulty)) + { + newSuffixedDifficulty = characterSuffixedDifficulty; + } + + currentSuffixedDifficulty = newSuffixedDifficulty; trace('Switching to difficulty: ${currentSuffixedDifficulty}'); trace(suffixedDiffIdsCurrent); @@ -2201,9 +2217,18 @@ class FreeplayState extends MusicBeatSubState var previewSong:Null = SongRegistry.instance.fetchEntry(previewSongId); if (previewSong == null) return; - // var currentVariation = previewSong.getVariationsByCharacter(currentCharacter) ?? Constants.DEFAULT_VARIATION_LIST; + var targetDifficultyId:String = currentUnsuffixedDifficulty; var targetVariation:Null = currentVariation; + + // Check if character-specific difficulty exists + var characterSuffixedDifficulty:String = '${targetDifficultyId}-${currentCharacterId}'; + var suffixedSongDifficulties:Array = daSongCapsule.songData?.suffixedSongDifficulties ?? Constants.DEFAULT_DIFFICULTY_LIST; + if (suffixedSongDifficulties != null && suffixedSongDifficulties.contains(characterSuffixedDifficulty)) + { + targetDifficultyId = characterSuffixedDifficulty; + } + var songDifficulty:Null = previewSong.getDifficulty(targetDifficultyId, targetVariation ?? Constants.DEFAULT_VARIATION); var baseInstrumentalId:String = previewSong.getBaseInstrumentalId(targetDifficultyId, songDifficulty?.variation ?? Constants.DEFAULT_VARIATION) ?? ''; @@ -2438,10 +2463,21 @@ class FreeplaySongData // Add character-specific difficulties for (difficulty in this.songDifficulties) { - this.suffixedSongDifficulties.push('${difficulty}-${currentCharacter.id}'); + var characterDifficulty = '${difficulty}-${currentCharacter.id}'; + if (!this.suffixedSongDifficulties.contains(characterDifficulty)) + { + this.suffixedSongDifficulties.push(characterDifficulty); + } } - if (!this.songDifficulties.contains(currentUnsuffixedDifficulty) && !this.suffixedSongDifficulties.contains(currentSuffixedDifficulty)) + // Prioritize character-specific difficulty + var characterSuffixedDifficulty = '${currentUnsuffixedDifficulty}-${currentCharacter.id}'; + if (this.suffixedSongDifficulties.contains(characterSuffixedDifficulty)) + { + currentSuffixedDifficulty = characterSuffixedDifficulty; + } + else if (!this.songDifficulties.contains(currentUnsuffixedDifficulty) + && !this.suffixedSongDifficulties.contains(currentSuffixedDifficulty)) { currentSuffixedDifficulty = Constants.DEFAULT_DIFFICULTY; // This method gets called again by the setter-method From c0314c85ecd5116641aff3de8e9153f7fe48e79c Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Tue, 1 Oct 2024 20:32:48 -0400 Subject: [PATCH 06/29] fix(freeplay)!: Proper variation / difficulty loading for Freeplay Menu Previously the game would load variations in a `variation-difficulty` string format, but now we map it out better and filter it based on that, rather than messing around with suffixes and whatnot. If you have a mod that depended on the functionality of the `variation-difficulty` format, you should accomodate that functionality in another way re-add freeplay song preview song names and icons implemented again implement the scoring rank, bpm, and difficulty crud albumId loading fix --- source/funkin/play/song/Song.hx | 102 +++- source/funkin/ui/freeplay/FreeplayState.hx | 679 +++++++++------------ source/funkin/ui/freeplay/SongMenuItem.hx | 48 +- 3 files changed, 384 insertions(+), 445 deletions(-) diff --git a/source/funkin/play/song/Song.hx b/source/funkin/play/song/Song.hx index a6449bc1034..91e15829919 100644 --- a/source/funkin/play/song/Song.hx +++ b/source/funkin/play/song/Song.hx @@ -15,6 +15,7 @@ import funkin.data.song.SongRegistry; import funkin.modding.IScriptedClass.IPlayStateScriptedClass; import funkin.modding.events.ScriptEvent; import funkin.ui.freeplay.charselect.PlayableCharacter; +import funkin.data.freeplay.player.PlayerRegistry; import funkin.util.SortUtil; /** @@ -79,7 +80,12 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry; - final difficulties:Map; + + /** + * holds the difficulties (as in SongDifficulty) for each variation + * difficulties.get('default').get('easy') would return the easy difficulty for the default variation + */ + final difficulties:Map>; /** * The list of variations a song has. @@ -146,7 +152,7 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry(); + difficulties = new Map>(); _data = _fetchData(id); @@ -156,7 +162,8 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry + public function listAlbums(variation:String):Map { var result:Map = new Map(); - for (difficultyId in difficulties.keys()) + for (variationMap in difficulties) { - var meta:Null = difficulties.get(difficultyId); - if (meta != null && meta.album != null) + for (difficultyId in variationMap.keys()) { - result.set(difficultyId, meta.album); + var meta:Null = variationMap.get(difficultyId); + if (meta != null && meta.album != null) + { + result.set(difficultyId, meta.album); + } } } return result; } + /** + * Input a difficulty ID and a variation ID, and get the album ID. + * @param diffId + * @param variation + * @return String + */ + public function getAlbumId(diffId:String, variation:String):String + { + var diff:Null = getDifficulty(diffId, variation); + if (diff == null) return ''; + + return diff.album ?? ''; + } + /** * Populate the difficulty data from the provided metadata. * Does not load chart data (that is triggered later when we want to play the song). @@ -285,6 +309,9 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry = new Map(); + // There may be more difficulties in the chart file than in the metadata, // (i.e. non-playable charts like the one used for Pico on the speaker in Stress) // but all the difficulties in the metadata must be in the chart file. @@ -309,10 +336,9 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry = difficulties.get('$diffId$variationSuffix'); - if (difficulty == null) + // Retrieve the cached difficulty data. This one could potentially be null. + var nullDiff:Null = getDifficulty(diffId, variation); + + // if the difficulty doesn't exist, create a new one, and then proceed to fill it with data. + // I mostly do this since I don't wanna throw around ? everywhere for null check lol? + var difficulty:SongDifficulty = nullDiff ?? new SongDifficulty(this, diffId, variation); + + if (nullDiff == null) { trace('Fabricated new difficulty for $diffId.'); - difficulty = new SongDifficulty(this, diffId, variation); var metadata = _metadata.get(variation); - difficulties.set('$diffId$variationSuffix', difficulty); + difficulties.get(variation)?.set(diffId, difficulty); if (metadata != null) { @@ -396,11 +425,9 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry + * @see getVariationsByCharacter + */ + public function getVariationsByCharacterId(?charId:String):Array + { + var charPlayer = PlayerRegistry.instance.fetchEntry(charId ?? ''); + + return getVariationsByCharacter(charPlayer); + } + /** * List all the difficulties in this song. * @@ -501,6 +539,7 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry, ?showLocked:Bool, ?showHidden:Bool):Array { @@ -529,8 +568,7 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry> = []; - // List of available difficulties for the current song, without `-variation` at the end (no duplicates or nulls). - var diffIdsCurrent:Array = []; - // List of available difficulties for the total song list, without `-variation` at the end (no duplicates or nulls). - var diffIdsTotal:Array = []; - // List of available difficulties for the current song, with `-variation` at the end (no duplicates or nulls). - var suffixedDiffIdsCurrent:Array = []; - // List of available difficulties for the total song list, with `-variation` at the end (no duplicates or nulls). - var suffixedDiffIdsTotal:Array = []; - var curSelected:Int = 0; - var currentSuffixedDifficulty:String = Constants.DEFAULT_DIFFICULTY; - var currentUnsuffixedDifficulty(get, never):String; - - function get_currentUnsuffixedDifficulty():String - { - if (Constants.DEFAULT_DIFFICULTY_LIST_FULL.contains(currentSuffixedDifficulty)) return currentSuffixedDifficulty; - - // Else, we need to strip the suffix. - return currentSuffixedDifficulty.substring(0, currentSuffixedDifficulty.lastIndexOf('-')); - } - var currentVariation(get, never):String; - - function get_currentVariation():String - { - if (Constants.DEFAULT_DIFFICULTY_LIST.contains(currentSuffixedDifficulty)) return Constants.DEFAULT_VARIATION; - if (Constants.DEFAULT_DIFFICULTY_LIST_ERECT.contains(currentSuffixedDifficulty)) return 'erect'; + /** + * Currently selected difficulty, in string form. + */ + var currentDifficulty:String = Constants.DEFAULT_DIFFICULTY; - // Else, we need to isolate the suffix. - return currentSuffixedDifficulty.substring(currentSuffixedDifficulty.lastIndexOf('-') + 1, currentSuffixedDifficulty.length); - } + /** + * Current variation: default, erect, pico, bf, etc. + */ + var currentVariation:String = Constants.DEFAULT_VARIATION; public var fp:FreeplayScore; @@ -234,6 +171,11 @@ class FreeplayState extends MusicBeatSubState */ public static var rememberedCharacterId:String = Constants.DEFAULT_CHARACTER; + /** + * The remembered variation we were on when this menu was last accessed. + */ + public static var rememberedVariation:String = Constants.DEFAULT_VARIATION; + var funnyCam:FunkinCamera; var rankCamera:FunkinCamera; var rankBg:FunkinSprite; @@ -241,53 +183,43 @@ class FreeplayState extends MusicBeatSubState var backingCard:Null = null; + /** + * The backing card that has the toned dots, right now we just use that one dad graphic dave cooked up + */ public var bgDad:FlxSprite; - var fromResultsParams:Null = null; + public var angleMaskShader:AngleMask = new AngleMask(); - var prepForNewRank:Bool = false; + var fadeShader:BlueFade = new BlueFade(); + var fromResultsParams:Null = null; + var prepForNewRank:Bool = false; var styleData:Null = null; - - var fromCharSelect:Null = null; + var fromCharSelect:Bool = false; public function new(?params:FreeplayStateParams, ?stickers:StickerSubState) { currentCharacterId = params?.character ?? rememberedCharacterId; styleData = FreeplayStyleRegistry.instance.fetchEntry(currentCharacterId); + var fetchPlayableCharacter = function():PlayableCharacter { var targetCharId = params?.character ?? rememberedCharacterId; var result = PlayerRegistry.instance.fetchEntry(targetCharId); if (result == null) throw 'No valid playable character with id ${targetCharId}'; return result; }; - currentCharacter = fetchPlayableCharacter(); + currentCharacter = fetchPlayableCharacter(); + currentVariation = rememberedVariation; styleData = FreeplayStyleRegistry.instance.fetchEntry(currentCharacter.getFreeplayStyleID()); rememberedCharacterId = currentCharacter?.id ?? Constants.DEFAULT_CHARACTER; - - fromCharSelect = params?.fromCharSelect; - + fromCharSelect = params?.fromCharSelect ?? false; fromResultsParams = params?.fromResults; - - // bf songs have no suffix, but we need to initalize the difficulty - // in case we begin playing as pico - if (currentCharacterId != 'bf') - { - currentSuffixedDifficulty = Constants.DEFAULT_DIFFICULTY + '-$currentCharacterId'; - } - - if (fromResultsParams?.playRankAnim == true) - { - prepForNewRank = true; - } + prepForNewRank = fromResultsParams?.playRankAnim ?? false; super(FlxColor.TRANSPARENT); - if (stickers?.members != null) - { - stickerSubState = stickers; - } + if (stickers?.members != null) stickerSubState = stickers; switch (currentCharacterId) { @@ -322,16 +254,11 @@ class FreeplayState extends MusicBeatSubState bgDad = new FlxSprite(backingCard.pinkBack.width * 0.74, 0).loadGraphic(styleData == null ? 'freeplay/freeplayBGdad' : styleData.getBgAssetGraphic()); } - var fadeShader:BlueFade = new BlueFade(); - - public var angleMaskShader:AngleMask = new AngleMask(); - override function create():Void { super.create(); FlxG.state.persistentUpdate = false; - FlxTransitionableState.skipNextTransIn = true; var fadeShaderFilter:ShaderFilter = new ShaderFilter(fadeShader); @@ -384,23 +311,7 @@ class FreeplayState extends MusicBeatSubState continue; } - // Only display songs which actually have available difficulties for the current character. - var displayedVariations = song.getVariationsByCharacter(currentCharacter); - trace('Displayed Variations (${songId}): $displayedVariations'); - var availableDifficultiesForSong:Array = song.listSuffixedDifficulties(displayedVariations, false, false); - var unsuffixedDifficulties = song.listDifficulties(displayedVariations, false, false); - trace('Available Difficulties: $availableDifficultiesForSong'); - if (availableDifficultiesForSong.length == 0) continue; - - songs.push(new FreeplaySongData(levelId, songId, song, currentCharacter, displayedVariations)); - for (difficulty in unsuffixedDifficulties) - { - diffIdsTotal.pushUnique(difficulty); - } - for (difficulty in availableDifficultiesForSong) - { - suffixedDiffIdsTotal.pushUnique(difficulty); - } + songs.push(new FreeplaySongData(song, level)); } } @@ -493,30 +404,21 @@ class FreeplayState extends MusicBeatSubState wait: 0.1 }); - for (diffId in suffixedDiffIdsTotal) + for (diffId in Constants.DEFAULT_DIFFICULTY_LIST_FULL) { var diffSprite:DifficultySprite = new DifficultySprite(diffId); diffSprite.difficultyId = diffId; + diffSprite.visible = diffId == Constants.DEFAULT_DIFFICULTY; grpDifficulties.add(diffSprite); } - grpDifficulties.group.forEach(function(spr) { - spr.visible = false; - }); - - for (diffSprite in grpDifficulties.group.members) - { - if (diffSprite == null) continue; - if (diffSprite.difficultyId == currentSuffixedDifficulty) diffSprite.visible = true; - } - albumRoll.albumId = null; add(albumRoll); var overhangStuff:FlxSprite = new FlxSprite().makeGraphic(FlxG.width, 164, FlxColor.BLACK); overhangStuff.y -= overhangStuff.height; - if (fromCharSelect == true) + if (fromCharSelect) { blackOverlayBullshitLOLXD.x = 387.76; overhangStuff.y = -100; @@ -602,6 +504,7 @@ class FreeplayState extends MusicBeatSubState wait: 0.1 }); + // Reminder, this is a callback function being set, rather than these being called here in create() letterSort.changeSelectionCallback = (str) -> { switch (str) { @@ -650,7 +553,7 @@ class FreeplayState extends MusicBeatSubState add(fnfFreeplay); add(ostName); - if (PlayerRegistry.instance.hasNewCharacter() == true) + if (PlayerRegistry.instance.hasNewCharacter()) { add(charSelectHint); } @@ -663,10 +566,10 @@ class FreeplayState extends MusicBeatSubState // when boyfriend hits dat shiii albumRoll.playIntro(); - var daSong = grpCapsules.members[curSelected].songData; - albumRoll.albumId = daSong?.albumId; + var daSong = grpCapsules.members[curSelected].freeplayData; + albumRoll.albumId = daSong?.data.getAlbumId(currentDifficulty, currentVariation); - if (fromCharSelect == null) + if (!fromCharSelect) { // render optimisation if (_parentState != null) _parentState.persistentDraw = false; @@ -735,6 +638,7 @@ class FreeplayState extends MusicBeatSubState onDJIntroDone(); } + // Generates song list with the starter params (who our current character is, last remembered difficulty, etc.) generateSongList(null, false); // dedicated camera for the state so we don't need to fuk around with camera scrolls from the mainmenu / elsewhere @@ -762,7 +666,7 @@ class FreeplayState extends MusicBeatSubState rankCamera.fade(0xFF000000, 0, false, null, true); } - if (fromCharSelect == true) + if (fromCharSelect) { enterFromCharSel(); onDJIntroDone(); @@ -773,7 +677,8 @@ class FreeplayState extends MusicBeatSubState var currentFilteredSongs:Array> = []; /** - * Given the current filter, rebuild the current song list. + * Given the current filter, rebuild the current song list and display it. + * Automatically takes into account currentDifficulty, character, and variation * * @param filterStuff A filter to apply to the song list (regex, startswith, all, favorite) * @param force Whether the capsules should "jump" back in or not using their animation @@ -785,27 +690,18 @@ class FreeplayState extends MusicBeatSubState if (filterStuff != null) tempSongs = sortSongs(tempSongs, filterStuff); - // Filter further by current selected difficulty. - if (currentSuffixedDifficulty != null) - { - tempSongs = tempSongs.filter(song -> { - if (song == null) return true; // Random + tempSongs = tempSongs.filter(song -> { + if (song == null) return true; // Random - // Check for character-specific difficulty first - var characterSuffixedDifficulty = '${currentUnsuffixedDifficulty}-${currentCharacterId}'; - if (song.suffixedSongDifficulties.contains(characterSuffixedDifficulty)) - { - return true; - } + // Available variations for current character. We get this since bf is usually `default` variation, and `pico` is `pico` + // but sometimes pico can be the default variation (weekend 1 songs), and bf can be `bf` variation (darnell) + var characterVariations:Array = song.data.getVariationsByCharacter(currentCharacter); - // Include songs that match the current suffixed difficulty (`normal-pico`) - // or the current unsuffixed difficulty, `normal` - // or songs specifically for the current character `normal` w/ songCharacter == `pico` - return (song.suffixedSongDifficulties.contains(currentSuffixedDifficulty) - || song.songDifficulties.contains(currentUnsuffixedDifficulty) - || song.songCharacter == currentCharacterId); - }); - } + // Gets all available difficulties for our character, via our available variations + var difficultiesAvailable:Array = song.data.listDifficulties(null, characterVariations); + + return difficultiesAvailable.contains(currentDifficulty); + }); if (onlyIfChanged) { @@ -814,28 +710,20 @@ class FreeplayState extends MusicBeatSubState } // Only now do we know that the filter is actually changing. - - // If curSelected is 0, the result will be null and fall back to the rememberedSongId. - rememberedSongId = grpCapsules.members[curSelected]?.songData?.songId ?? rememberedSongId; - - for (cap in grpCapsules.members) - { - cap.songText.resetText(); - cap.kill(); - } - currentFilter = filterStuff; currentFilteredSongs = tempSongs; curSelected = 0; - var hsvShader:HSVShader = new HSVShader(); + // If curSelected is 0, the result will be null and fall back to the rememberedSongId. + // We set this so if we change the filter, we'd remain on the same song if it's still in the list. + rememberedSongId = grpCapsules.members[curSelected]?.freeplayData?.data.id ?? rememberedSongId; + grpCapsules.killMembers(); + + // Initialize the random capsule, with empty/blank info (which we display once bf/pico does his hand) var randomCapsule:SongMenuItem = grpCapsules.recycle(SongMenuItem); randomCapsule.init(FlxG.width, 0, null, styleData); - randomCapsule.onConfirm = function() { - capsuleOnConfirmRandom(randomCapsule); - }; randomCapsule.y = randomCapsule.intendedY(0) + 10; randomCapsule.targetPos.x = randomCapsule.x; randomCapsule.alpha = 0; @@ -844,14 +732,15 @@ class FreeplayState extends MusicBeatSubState randomCapsule.favIconBlurred.visible = false; randomCapsule.ranking.visible = false; randomCapsule.blurredRanking.visible = false; - if (fromCharSelect == false) - { - randomCapsule.initJumpIn(0, force); - } + randomCapsule.onConfirm = function() { + capsuleOnConfirmRandom(randomCapsule); + }; + + if (fromCharSelect) randomCapsule.forcePosition(); else - { - randomCapsule.forcePosition(); - } + randomCapsule.initJumpIn(0, force); + + var hsvShader:HSVShader = new HSVShader(); randomCapsule.hsvShader = hsvShader; grpCapsules.add(randomCapsule); @@ -870,13 +759,8 @@ class FreeplayState extends MusicBeatSubState funnyMenu.targetPos.x = funnyMenu.x; funnyMenu.ID = i; funnyMenu.capsule.alpha = 0.5; - funnyMenu.songText.visible = false; - funnyMenu.favIcon.visible = tempSong.isFav; - funnyMenu.favIconBlurred.visible = tempSong.isFav; funnyMenu.hsvShader = hsvShader; - funnyMenu.newText.animation.curAnim.curFrame = 45 - ((i * 4) % 45); - funnyMenu.checkClip(); funnyMenu.forcePosition(); grpCapsules.add(funnyMenu); @@ -885,9 +769,8 @@ class FreeplayState extends MusicBeatSubState FlxG.console.registerFunction('changeSelection', changeSelection); rememberSelection(); - changeSelection(); - changeDiff(0, true); + refreshCapsuleDisplays(); } /** @@ -899,7 +782,7 @@ class FreeplayState extends MusicBeatSubState public function sortSongs(songsToFilter:Array>, songFilter:SongFilter):Array> { var filterAlphabetically = function(a:Null, b:Null):Int { - return SortUtil.alphabetically(a?.songName ?? '', b?.songName ?? ''); + return SortUtil.alphabetically(a?.data.songName ?? '', b?.data.songName ?? ''); }; switch (songFilter.filterType) @@ -911,9 +794,9 @@ class FreeplayState extends MusicBeatSubState // if filterData looks like "A-C", the regex should look something like this: ^[A-C].* // to get every song that starts between A and C var filterRegexp:EReg = new EReg('^[' + songFilter.filterData + '].*', 'i'); - songsToFilter = songsToFilter.filter(str -> { - if (str == null) return true; // Random - return filterRegexp.match(str.songName); + songsToFilter = songsToFilter.filter(filteredSong -> { + if (filteredSong == null) return true; // Random + return filterRegexp.match(filteredSong.data.songName); }); songsToFilter.sort(filterAlphabetically); @@ -921,16 +804,16 @@ class FreeplayState extends MusicBeatSubState case STARTSWITH: // extra note: this is essentially a "search" - songsToFilter = songsToFilter.filter(str -> { - if (str == null) return true; // Random - return str.songName.toLowerCase().startsWith(songFilter.filterData ?? ''); + songsToFilter = songsToFilter.filter(filteredSong -> { + if (filteredSong == null) return true; // Random + return filteredSong.data.songName.toLowerCase().startsWith(songFilter.filterData ?? ''); }); case ALL: // no filter! case FAVORITE: - songsToFilter = songsToFilter.filter(str -> { - if (str == null) return true; // Random - return str.isFav; + songsToFilter = songsToFilter.filter(filteredSong -> { + if (filteredSong == null) return true; // Random + return filteredSong.isFav; }); songsToFilter.sort(filterAlphabetically); @@ -1298,7 +1181,7 @@ class FreeplayState extends MusicBeatSubState } } fadeShader.fade(1.0, 0.0, 0.8, {ease: FlxEase.quadIn}); - FlxG.sound.music.fadeOut(0.9, 0); + FlxG.sound.music?.fadeOut(0.9, 0); new FlxTimer().start(0.9, _ -> { FlxG.switchState(new funkin.ui.charSelect.CharSelectSubState()); }); @@ -1461,7 +1344,7 @@ class FreeplayState extends MusicBeatSubState if (controls.FREEPLAY_FAVORITE && !busy) { - var targetSong = grpCapsules.members[curSelected]?.songData; + var targetSong = grpCapsules.members[curSelected]?.freeplayData; if (targetSong != null) { var realShit:Int = curSelected; @@ -1504,7 +1387,6 @@ class FreeplayState extends MusicBeatSubState busy = true; grpCapsules.members[realShit].doLerp = false; FlxTween.tween(grpCapsules.members[realShit], {y: grpCapsules.members[realShit].y + 5}, 0.1, {ease: FlxEase.expoOut}); - FlxTween.tween(grpCapsules.members[realShit], {y: grpCapsules.members[realShit].y - 5}, 0.1, { ease: FlxEase.expoIn, @@ -1792,74 +1674,72 @@ class FreeplayState extends MusicBeatSubState public override function destroy():Void { super.destroy(); - var daSong:Null = currentFilteredSongs[curSelected]; - if (daSong != null) - { - clearDaCache(daSong.songName); - } - // remove and destroy freeplay camera FlxG.cameras.remove(funnyCam); } + /** + * changeDiff is the root of both difficulty and variation changes/management. + * It will check the difficulty of the current variation, all available variations, and all available difficulties per variation. + * It's generally recommended that after calling this you re-sort the song list, however usually it's already on the way to being sorted. + * @param change + * @param force + */ function changeDiff(change:Int = 0, force:Bool = false):Void { touchTimer = 0; - var currentDifficultyIndex:Int = suffixedDiffIdsCurrent.indexOf(currentSuffixedDifficulty); + // Available variations for current character. We get this since bf is usually `default` variation, and `pico` is `pico` + // but sometimes pico can be the default variation (weekend 1 songs), and bf can be `bf` variation (darnell) + var characterVariations:Array = grpCapsules.members[curSelected].freeplayData?.data.getVariationsByCharacter(currentCharacter) ?? Constants.DEFAULT_VARIATION_LIST; - if (currentDifficultyIndex == -1) currentDifficultyIndex = suffixedDiffIdsCurrent.indexOf(Constants.DEFAULT_DIFFICULTY); + // Gets all available difficulties for our character, via our available variations + var difficultiesAvailable:Array = grpCapsules.members[curSelected].freeplayData?.data.listDifficulties(null, + characterVariations) ?? Constants.DEFAULT_DIFFICULTY_LIST; - currentDifficultyIndex += change; + var currentDifficultyIndex:Int = difficultiesAvailable.indexOf(currentDifficulty); + + if (currentDifficultyIndex == -1) currentDifficultyIndex = difficultiesAvailable.indexOf(Constants.DEFAULT_DIFFICULTY); - if (currentDifficultyIndex < 0) currentDifficultyIndex = suffixedDiffIdsCurrent.length - 1; - if (currentDifficultyIndex >= suffixedDiffIdsCurrent.length) currentDifficultyIndex = 0; + currentDifficultyIndex += change; - var newSuffixedDifficulty = suffixedDiffIdsCurrent[currentDifficultyIndex]; + if (currentDifficultyIndex < 0) currentDifficultyIndex = Std.int(difficultiesAvailable.length - 1); + if (currentDifficultyIndex >= difficultiesAvailable.length) currentDifficultyIndex = 0; - // Always try to use the character-specific difficulty - var characterSuffixedDifficulty = '${newSuffixedDifficulty}-${currentCharacterId}'; - if (suffixedDiffIdsCurrent.contains(characterSuffixedDifficulty)) + // Update the current difficulty + currentDifficulty = difficultiesAvailable[currentDifficultyIndex]; + for (variation in characterVariations) { - newSuffixedDifficulty = characterSuffixedDifficulty; + if (grpCapsules.members[curSelected].freeplayData?.data.hasDifficulty(currentDifficulty, variation) ?? false) + { + currentVariation = variation; + rememberedVariation = variation; + break; + } } - currentSuffixedDifficulty = newSuffixedDifficulty; - - trace('Switching to difficulty: ${currentSuffixedDifficulty}'); - trace(suffixedDiffIdsCurrent); + trace('CURRENT VARIATION OF SONG: ${currentVariation}'); - var daSong:Null = grpCapsules.members[curSelected].songData; + var daSong:Null = grpCapsules.members[curSelected].freeplayData; if (daSong != null) { - var targetSong:Null = SongRegistry.instance.fetchEntry(daSong.songId); + var targetSong:Null = SongRegistry.instance.fetchEntry(daSong.data.id); if (targetSong == null) { - FlxG.log.warn('WARN: could not find song with id (${daSong.songId})'); + FlxG.log.warn('WARN: could not find song with id (${daSong.data.id})'); return; } - var suffixedDifficulty = suffixedDiffIdsCurrent[currentDifficultyIndex]; - var unsuffixedDifficulty = currentUnsuffixedDifficulty; - - // Check for character-specific difficulty - var characterSuffixedDifficulty = '${unsuffixedDifficulty}-${currentCharacterId}'; - if (daSong.suffixedSongDifficulties.contains(characterSuffixedDifficulty)) - { - suffixedDifficulty = characterSuffixedDifficulty; - } - - var songScore:Null = Save.instance.getSongScore(daSong.songId, suffixedDifficulty); - trace(songScore); + var songScore:Null = Save.instance.getSongScore(daSong.data.id, currentDifficulty); intendedScore = songScore?.score ?? 0; intendedCompletion = songScore == null ? 0.0 : ((songScore.tallies.sick + songScore.tallies.good) / songScore.tallies.totalNotes); - rememberedDifficulty = suffixedDifficulty; - currentSuffixedDifficulty = suffixedDifficulty; + rememberedDifficulty = currentDifficulty; + grpCapsules.members[curSelected].refreshDisplay(); } else { intendedScore = 0; intendedCompletion = 0.0; - rememberedDifficulty = currentSuffixedDifficulty; + rememberedDifficulty = currentDifficulty; } if (intendedCompletion == Math.POSITIVE_INFINITY || intendedCompletion == Math.NEGATIVE_INFINITY || Math.isNaN(intendedCompletion)) @@ -1867,15 +1747,15 @@ class FreeplayState extends MusicBeatSubState intendedCompletion = 0; } - grpDifficulties.group.forEach(function(diffSprite) { - diffSprite.visible = false; - }); - for (diffSprite in grpDifficulties.group.members) { if (diffSprite == null) continue; - if (diffSprite.difficultyId == currentSuffixedDifficulty) + diffSprite.visible = false; + + if (diffSprite.difficultyId == currentDifficulty) { + diffSprite.visible = true; + if (change != 0) { diffSprite.visible = true; @@ -1886,10 +1766,6 @@ class FreeplayState extends MusicBeatSubState diffSprite.updateHitbox(); }); } - else - { - diffSprite.visible = true; - } } } @@ -1899,18 +1775,12 @@ class FreeplayState extends MusicBeatSubState for (songCapsule in grpCapsules.members) { if (songCapsule == null) continue; - if (songCapsule.songData != null) + + if (songCapsule.freeplayData != null) { - songCapsule.songData.currentVariation = currentVariation; - songCapsule.songData.currentUnsuffixedDifficulty = currentUnsuffixedDifficulty; - songCapsule.songData.currentSuffixedDifficulty = currentSuffixedDifficulty; - songCapsule.init(null, null, songCapsule.songData); + songCapsule.init(null, null, songCapsule.freeplayData); songCapsule.checkClip(); } - else - { - songCapsule.init(null, null, null); - } } // Reset the song preview in case we changed variations (normal->erect etc) @@ -1918,7 +1788,7 @@ class FreeplayState extends MusicBeatSubState } // Set the album graphic and play the animation if relevant. - var newAlbumId:Null = daSong?.albumId; + var newAlbumId:Null = daSong?.data.getAlbumId(currentDifficulty, currentVariation); if (albumRoll.albumId != newAlbumId) { albumRoll.albumId = newAlbumId; @@ -1926,21 +1796,7 @@ class FreeplayState extends MusicBeatSubState } // Set difficulty star count. - albumRoll.setDifficultyStars(daSong?.difficultyRating); - } - - // Clears the cache of songs to free up memory, they'll have to be loaded in later tho - function clearDaCache(actualSongTho:String):Void - { - for (song in songs) - { - if (song == null) continue; - if (song.songName != actualSongTho) - { - trace('trying to remove: ' + song.songName); - // openfl.Assets.cache.clear(Paths.inst(song.songName)); - } - } + albumRoll.setDifficultyStars(daSong?.data.getDifficulty(currentDifficulty, currentVariation)?.difficultyRating ?? 0); } function capsuleOnConfirmRandom(randomCapsule:SongMenuItem):Void @@ -1952,11 +1808,11 @@ class FreeplayState extends MusicBeatSubState var availableSongCapsules:Array = grpCapsules.members.filter(function(cap:SongMenuItem) { // Dead capsules are ones which were removed from the list when changing filters. - return cap.alive && cap.songData != null; + return cap.alive && cap.freeplayData != null; }); trace('Available songs: ${availableSongCapsules.map(function(cap) { - return cap?.songData?.songName; + return cap?.freeplayData?.data.songName; })}'); if (availableSongCapsules.length == 0) @@ -1983,7 +1839,7 @@ class FreeplayState extends MusicBeatSubState */ function capsuleOnOpenDefault(cap:SongMenuItem):Void { - var targetSongId:String = cap?.songData?.songId ?? 'unknown'; + var targetSongId:String = cap?.freeplayData?.data.id ?? 'unknown'; var targetSongNullable:Null = SongRegistry.instance.fetchEntry(targetSongId); if (targetSongNullable == null) { @@ -1991,10 +1847,10 @@ class FreeplayState extends MusicBeatSubState return; } var targetSong:Song = targetSongNullable; - var targetDifficultyId:String = currentUnsuffixedDifficulty; + var targetDifficultyId:String = currentDifficulty; var targetVariation:Null = currentVariation; trace('target song: ${targetSongId} (${targetVariation})'); - var targetLevelId:Null = cap?.songData?.levelId; + var targetLevelId:Null = cap?.freeplayData?.levelId; PlayStatePlaylist.campaignId = targetLevelId ?? null; var targetDifficulty:Null = targetSong.getDifficulty(targetDifficultyId, targetVariation); @@ -2065,7 +1921,7 @@ class FreeplayState extends MusicBeatSubState PlayStatePlaylist.isStoryMode = false; - var targetSongId:String = cap?.songData?.songId ?? 'unknown'; + var targetSongId:String = cap?.freeplayData?.data.id ?? 'unknown'; var targetSongNullable:Null = SongRegistry.instance.fetchEntry(targetSongId); if (targetSongNullable == null) { @@ -2073,21 +1929,20 @@ class FreeplayState extends MusicBeatSubState return; } var targetSong:Song = targetSongNullable; - var targetDifficultyId:String = currentUnsuffixedDifficulty; var targetVariation:Null = currentVariation; - var targetLevelId:Null = cap?.songData?.levelId; + var targetLevelId:Null = cap?.freeplayData?.levelId; PlayStatePlaylist.campaignId = targetLevelId ?? null; - var targetDifficulty:Null = targetSong.getDifficulty(targetDifficultyId, targetVariation); + var targetDifficulty:Null = targetSong.getDifficulty(currentDifficulty, currentVariation); if (targetDifficulty == null) { - FlxG.log.warn('WARN: could not find difficulty with id (${targetDifficultyId})'); + FlxG.log.warn('WARN: could not find difficulty with id (${currentDifficulty})'); return; } if (targetInstId == null) { - var baseInstrumentalId:String = targetSong?.getBaseInstrumentalId(targetDifficultyId, targetDifficulty.variation ?? Constants.DEFAULT_VARIATION) ?? ''; + var baseInstrumentalId:String = targetSong?.getBaseInstrumentalId(currentDifficulty, targetDifficulty.variation ?? Constants.DEFAULT_VARIATION) ?? ''; targetInstId = baseInstrumentalId; } @@ -2103,12 +1958,12 @@ class FreeplayState extends MusicBeatSubState new FlxTimer().start(styleData?.getStartDelay(), function(tmr:FlxTimer) { FunkinSound.emptyPartialQueue(); - Paths.setCurrentLevel(cap?.songData?.levelId); + Paths.setCurrentLevel(cap?.freeplayData?.levelId); LoadingState.loadPlayState( { targetSong: targetSong, - targetDifficulty: targetDifficultyId, - targetVariation: targetVariation, + targetDifficulty: currentDifficulty, + targetVariation: currentVariation, targetInstrumental: targetInstId, practiceMode: false, minimalMode: false, @@ -2126,13 +1981,20 @@ class FreeplayState extends MusicBeatSubState }); } + function refreshCapsuleDisplays():Void + { + grpCapsules.forEachAlive((cap:SongMenuItem) -> { + cap.refreshDisplay(); + }); + } + function rememberSelection():Void { if (rememberedSongId != null) { curSelected = currentFilteredSongs.findIndex(function(song) { if (song == null) return false; - return song.songId == rememberedSongId; + return song.data.id == rememberedSongId; }); if (curSelected == -1) curSelected = 0; @@ -2140,7 +2002,12 @@ class FreeplayState extends MusicBeatSubState if (rememberedDifficulty != null) { - currentSuffixedDifficulty = rememberedDifficulty; + currentDifficulty = rememberedDifficulty; + } + + if (rememberedVariation != null) + { + currentVariation = rememberedVariation; } } @@ -2156,22 +2023,19 @@ class FreeplayState extends MusicBeatSubState if (curSelected >= grpCapsules.countLiving()) curSelected = 0; var daSongCapsule:SongMenuItem = grpCapsules.members[curSelected]; - if (daSongCapsule.songData != null) + if (daSongCapsule.freeplayData != null) { - var songScore:Null = Save.instance.getSongScore(daSongCapsule.songData.songId, currentSuffixedDifficulty); + var songScore:Null = Save.instance.getSongScore(daSongCapsule.freeplayData.data.id, currentDifficulty); intendedScore = songScore?.score ?? 0; intendedCompletion = songScore == null ? 0.0 : ((songScore.tallies.sick + songScore.tallies.good) / songScore.tallies.totalNotes); - diffIdsCurrent = daSongCapsule.songData.songDifficulties; - suffixedDiffIdsCurrent = daSongCapsule.songData.suffixedSongDifficulties; - rememberedSongId = daSongCapsule.songData.songId; + rememberedSongId = daSongCapsule.freeplayData.data.id; changeDiff(); + daSongCapsule.refreshDisplay(); } else { intendedScore = 0; intendedCompletion = 0.0; - diffIdsCurrent = diffIdsTotal; - suffixedDiffIdsCurrent = suffixedDiffIdsTotal; rememberedSongId = null; rememberedDifficulty = Constants.DEFAULT_DIFFICULTY; albumRoll.albumId = null; @@ -2199,7 +2063,6 @@ class FreeplayState extends MusicBeatSubState public function playCurSongPreview(?daSongCapsule:SongMenuItem):Void { if (daSongCapsule == null) daSongCapsule = grpCapsules.members[curSelected]; - if (curSelected == 0) { FunkinSound.playMusic('freeplayRandom', @@ -2212,43 +2075,25 @@ class FreeplayState extends MusicBeatSubState } else { - var previewSongId:Null = daSongCapsule?.songData?.songId; - if (previewSongId == null) return; - - var previewSong:Null = SongRegistry.instance.fetchEntry(previewSongId); + var previewSong:Null = daSongCapsule?.freeplayData?.data; if (previewSong == null) return; - var targetDifficultyId:String = currentUnsuffixedDifficulty; - var targetVariation:Null = currentVariation; - // Check if character-specific difficulty exists - var characterSuffixedDifficulty:String = '${targetDifficultyId}-${currentCharacterId}'; - var suffixedSongDifficulties:Array = daSongCapsule.songData?.suffixedSongDifficulties ?? Constants.DEFAULT_DIFFICULTY_LIST; - if (suffixedSongDifficulties != null && suffixedSongDifficulties.contains(characterSuffixedDifficulty)) - { - targetDifficultyId = characterSuffixedDifficulty; - } + var songDifficulty:Null = previewSong.getDifficulty(currentDifficulty, currentVariation); - var songDifficulty:Null = previewSong.getDifficulty(targetDifficultyId, targetVariation ?? Constants.DEFAULT_VARIATION); - - var baseInstrumentalId:String = previewSong.getBaseInstrumentalId(targetDifficultyId, songDifficulty?.variation ?? Constants.DEFAULT_VARIATION) ?? ''; - var altInstrumentalIds:Array = previewSong.listAltInstrumentalIds(targetDifficultyId, + var baseInstrumentalId:String = previewSong.getBaseInstrumentalId(currentDifficulty, songDifficulty?.variation ?? Constants.DEFAULT_VARIATION) ?? ''; + var altInstrumentalIds:Array = previewSong.listAltInstrumentalIds(currentDifficulty, songDifficulty?.variation ?? Constants.DEFAULT_VARIATION) ?? []; - var instSuffix:String = baseInstrumentalId; - #if FEATURE_DEBUG_FUNCTIONS if (altInstrumentalIds.length > 0 && FlxG.keys.pressed.CONTROL) { instSuffix = altInstrumentalIds[0]; } #end - instSuffix = (instSuffix != '') ? '-$instSuffix' : ''; - - trace('Attempting to play partial preview: ${previewSongId}:${instSuffix}'); - - FunkinSound.playMusic(previewSongId, + trace('Attempting to play partial preview: ${previewSong.id}:${instSuffix}'); + FunkinSound.playMusic(previewSong.id, { startingVolume: 0.0, overrideExisting: true, @@ -2266,7 +2111,6 @@ class FreeplayState extends MusicBeatSubState FlxG.sound.music.fadeIn(2, 0, 0.4); } }); - if (songDifficulty != null) { Conductor.instance.mapTimeChanges(songDifficulty.timeChanges); @@ -2383,57 +2227,66 @@ enum abstract FilterType(String) class FreeplaySongData { /** - * Whether or not the song has been favorited. + * We used to have a billion fields, but this SongMetadata variable should be all we need + * to be able to get most information about an available song. + * For example, you can get the artist via `data.songArtist` + * + * You can usually get various other particulars of a specific difficulty/variation by + * using data.getDifficulty(), and inputting specifics on your difficulty, variations, etc. + * See the getters here for songCharacter, fullSongName, and songStartingBpm for examples. + * + * @see Song */ - public var isFav:Bool = false; + public var data:Song; - public var isNew:Bool = false; + /** + * The level id of the song, useful for sorting from week1 -> week 7 + weekend1 + * and for properly loading PlayStatePlaylist for preloading on web + */ + public var levelId(get, never):Null; - var song:Song; + function get_levelId():Null + { + return _levelId; + } - public var levelId(default, null):String = ''; - public var songId(default, null):String = ''; + var _levelId:String; - public var songDifficulties(default, null):Array = []; - public var suffixedSongDifficulties(default, null):Array = []; + /** + * Whether or not the song has been favorited. + */ + public var isFav:Bool = false; - public var songName(default, null):String = ''; - public var songCharacter(default, null):String = ''; - public var songStartingBpm(default, null):Float = 0; - public var difficultyRating(default, null):Int = 0; - public var albumId(default, null):Null = null; + /** + * Whether the player has seen/played this song before within freeplay + */ + public var isNew:Bool = false; - public var currentCharacter:PlayableCharacter; - public var currentVariation:String = Constants.DEFAULT_VARIATION; - public var currentSuffixedDifficulty(default, set):String = Constants.DEFAULT_DIFFICULTY; - public var currentUnsuffixedDifficulty:String = Constants.DEFAULT_DIFFICULTY; + /** + * The default opponent for the song. + * Does the getter stuff for you depending on your current (or rather, rememberd) variation and difficulty. + */ + public var songCharacter(get, never):String; - public var scoringRank:Null = null; + /** + * The full song name, dynamically generated depending on your current (or rather, rememberd) variation and difficulty. + */ + public var fullSongName(get, never):String; - var displayedVariations:Array = [Constants.DEFAULT_VARIATION]; + /** + * The starting BPM of the song, dynamically generated depending on your current (or rather, rememberd) variation and difficulty. + */ + public var songStartingBpm(get, never):Float; - function set_currentSuffixedDifficulty(value:String):String - { - if (currentSuffixedDifficulty == value) return value; + public var difficultyRating(get, never):Int; - currentSuffixedDifficulty = value; - updateValues(displayedVariations); - return value; - } + public var scoringRank(get, never):Null; - public function new(levelId:String, songId:String, song:Song, currentCharacter:PlayableCharacter, ?displayedVariations:Array) + public function new(data:Song, levelData:Level) { - this.levelId = levelId; - this.songId = songId; - this.song = song; - - this.isFav = Save.instance.isSongFavorited(songId); - - this.currentCharacter = currentCharacter; - - if (displayedVariations != null) this.displayedVariations = displayedVariations; - - updateValues(displayedVariations); + this.data = data; + _levelId = levelData.id; + this.isFav = Save.instance.isSongFavorited(data.songName); } /** @@ -2445,72 +2298,96 @@ class FreeplaySongData isFav = !isFav; if (isFav) { - Save.instance.favoriteSong(this.songId); + Save.instance.favoriteSong(data.songName); } else { - Save.instance.unfavoriteSong(this.songId); + Save.instance.unfavoriteSong(data.songName); } return isFav; } function updateValues(variations:Array):Void { - trace('variations: ${variations}'); - this.songDifficulties = song.listDifficulties(null, variations, false, false); - this.suffixedSongDifficulties = song.listSuffixedDifficulties(variations, false, false); + // this.isNew = song.isSongNew(suffixedDifficulty); + } - // Add character-specific difficulties - for (difficulty in this.songDifficulties) - { - var characterDifficulty = '${difficulty}-${currentCharacter.id}'; - if (!this.suffixedSongDifficulties.contains(characterDifficulty)) - { - this.suffixedSongDifficulties.push(characterDifficulty); - } - } + function get_songCharacter():String + { + var variations:Array = data.getVariationsByCharacterId(FreeplayState.rememberedCharacterId); + return data.getDifficulty(FreeplayState.rememberedDifficulty, null, variations)?.characters.opponent ?? ''; + } - // Prioritize character-specific difficulty - var characterSuffixedDifficulty = '${currentUnsuffixedDifficulty}-${currentCharacter.id}'; - if (this.suffixedSongDifficulties.contains(characterSuffixedDifficulty)) - { - currentSuffixedDifficulty = characterSuffixedDifficulty; - } - else if (!this.songDifficulties.contains(currentUnsuffixedDifficulty) - && !this.suffixedSongDifficulties.contains(currentSuffixedDifficulty)) - { - currentSuffixedDifficulty = Constants.DEFAULT_DIFFICULTY; - // This method gets called again by the setter-method - // or the difficulty didn't change, so there's no need to continue. - return; - } + function get_fullSongName():String + { + var variations:Array = data.getVariationsByCharacterId(FreeplayState.rememberedCharacterId); - var targetVariation:Null = currentVariation; + return data.getDifficulty(FreeplayState.rememberedDifficulty, null, variations)?.songName ?? data.songName; + } - var songDifficulty:SongDifficulty = song.getDifficulty(currentUnsuffixedDifficulty, targetVariation); - if (songDifficulty == null) return; - this.songStartingBpm = songDifficulty.getStartingBPM(); - this.songName = songDifficulty.songName; - this.songCharacter = songDifficulty.characters.opponent; - this.difficultyRating = songDifficulty.difficultyRating; - if (songDifficulty.album == null) - { - FlxG.log.warn('No album for: ${songDifficulty.songName}'); - this.albumId = Constants.DEFAULT_ALBUM_ID; - } - else - { - this.albumId = songDifficulty.album; - } + function get_songStartingBpm():Float + { + var variations:Array = data.getVariationsByCharacterId(FreeplayState.rememberedCharacterId); - var suffixedDifficulty = currentSuffixedDifficulty; + return data.getDifficulty(FreeplayState.rememberedDifficulty, null, variations)?.getStartingBPM() ?? 0; + } - this.scoringRank = Save.instance.getSongRank(songId, suffixedDifficulty); + function get_difficultyRating():Int + { + var variations:Array = data.getVariationsByCharacterId(FreeplayState.rememberedCharacterId); + return data.getDifficulty(FreeplayState.rememberedDifficulty, null, variations)?.difficultyRating ?? 0; + } - this.isNew = song.isSongNew(suffixedDifficulty); + function get_scoringRank():Null + { + // TODO: Properly get/migrate the save data from the suffixed difficulty version to our new unsuffixed version + return Save.instance.getSongRank(data.songName, FreeplayState.rememberedDifficulty); } } +/** + * Parameters used to initialize the FreeplayState. + */ +typedef FreeplayStateParams = +{ + ?character:String, + + ?fromCharSelect:Bool, + + ?fromResults:FromResultsParams, +}; + +/** + * A set of parameters for transitioning to the FreeplayState from the ResultsState. + */ +typedef FromResultsParams = +{ + /** + * The previous rank the song hand, if any. Null if it had no score before. + */ + var ?oldRank:ScoringRank; + + /** + * Whether or not to play the rank animation on returning to freeplay. + */ + var playRankAnim:Bool; + + /** + * The new rank the song has. + */ + var newRank:ScoringRank; + + /** + * The song ID to play the animation on. + */ + var songId:String; + + /** + * The difficulty ID to play the animation on. + */ + var difficultyId:String; +}; + /** * The map storing information about the exit movers. */ diff --git a/source/funkin/ui/freeplay/SongMenuItem.hx b/source/funkin/ui/freeplay/SongMenuItem.hx index 864fa2d1d26..3db958bb539 100644 --- a/source/funkin/ui/freeplay/SongMenuItem.hx +++ b/source/funkin/ui/freeplay/SongMenuItem.hx @@ -36,7 +36,7 @@ class SongMenuItem extends FlxSpriteGroup * Modify this by calling `init()` * If `null`, assume this SongMenuItem is for the "Random Song" option. */ - public var songData(default, null):Null = null; + public var freeplayData(default, null):Null = null; public var selected(default, set):Bool; @@ -422,6 +422,34 @@ class SongMenuItem extends FlxSpriteGroup return evilTrail.color; } + public function refreshDisplay():Void + { + if (freeplayData == null) + { + songText.text = 'Random'; + pixelIcon.visible = false; + ranking.visible = false; + blurredRanking.visible = false; + favIcon.visible = false; + favIconBlurred.visible = false; + newText.visible = false; + } + else + { + songText.text = freeplayData.fullSongName; + if (freeplayData.songCharacter != null) pixelIcon.setCharacter(freeplayData.songCharacter); + pixelIcon.visible = true; + updateBPM(Std.int(freeplayData.songStartingBpm) ?? 0); + updateDifficultyRating(freeplayData.difficultyRating ?? 0); + updateScoringRank(freeplayData.scoringRank); + newText.visible = freeplayData.isNew; + favIcon.visible = freeplayData.isFav; + favIconBlurred.visible = freeplayData.isFav; + checkClip(); + } + updateSelected(); + } + function updateDifficultyRating(newRating:Int):Void { var ratingPadded:String = newRating < 10 ? '0$newRating' : '$newRating'; @@ -500,11 +528,11 @@ class SongMenuItem extends FlxSpriteGroup updateSelected(); } - public function init(?x:Float, ?y:Float, songData:Null, ?styleData:FreeplayStyle = null):Void + public function init(?x:Float, ?y:Float, freeplayData:Null, ?styleData:FreeplayStyle = null):Void { if (x != null) this.x = x; if (y != null) this.y = y; - this.songData = songData; + this.freeplayData = freeplayData; // im so mad i have to do this but im pretty sure with the capsules recycling i cant call the new function properly :/ // if thats possible someone Please change the new function to be something like @@ -517,21 +545,13 @@ class SongMenuItem extends FlxSpriteGroup songText.applyStyle(styleData); } - // Update capsule text. - songText.text = songData?.songName ?? 'Random'; - // Update capsule character. - if (songData?.songCharacter != null) pixelIcon.setCharacter(songData.songCharacter); - updateBPM(Std.int(songData?.songStartingBpm) ?? 0); - updateDifficultyRating(songData?.difficultyRating ?? 0); - updateScoringRank(songData?.scoringRank); - newText.visible = songData?.isNew; + updateScoringRank(freeplayData?.scoringRank); favIcon.animation.curAnim.curFrame = favIcon.animation.curAnim.numFrames - 1; favIconBlurred.animation.curAnim.curFrame = favIconBlurred.animation.curAnim.numFrames - 1; - // Update opacity, offsets, etc. - updateSelected(); + refreshDisplay(); - checkWeek(songData?.songId); + checkWeek(freeplayData?.data.id); } var frameInTicker:Float = 0; From 4fa9a0daaa67e0977460b147bd1f74a118e3e2a5 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Wed, 2 Oct 2024 20:37:37 -0400 Subject: [PATCH 07/29] docs: add additional `variation` input parameter to `Save.hasBeatenSong()` to allow usage of the function by inputting a variation id --- source/funkin/save/Save.hx | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/source/funkin/save/Save.hx b/source/funkin/save/Save.hx index 77cdcafe5c3..73e7aa77ebd 100644 --- a/source/funkin/save/Save.hx +++ b/source/funkin/save/Save.hx @@ -678,18 +678,31 @@ class Save /** * Has the provided song been beaten on one of the listed difficulties? + * Note: This function can still take in the 'difficulty-variation' format for the difficultyList parameter + * as it is used in the old save data format. However inputting a variation will append it to the difficulty + * so you can do `hasBeatenSong('dadbattle', ['easy-pico'])` to check if you've beaten the Pico mix on easy. + * or you can do `hasBeatenSong('dadbattle', ['easy'], 'pico')` to check if you've beaten the Pico mix on easy. + * however you should not mix the two as it will append '-pico' to the 'easy-pico' if it's inputted into the array. * @param songId The song ID to check. * @param difficultyList The difficulties to check. Defaults to `easy`, `normal`, and `hard`. + * @param variation The variation to check. Defaults to empty string. Appended to difficulty list with `-`, e.g. `easy-pico`. + * This is our old format for getting difficulty/variation information, however we don't want to mess around with + * save migration just yet. * @return Whether the song has been beaten on any of the listed difficulties. */ - public function hasBeatenSong(songId:String, ?difficultyList:Array):Bool + public function hasBeatenSong(songId:String, ?difficultyList:Array, ?variation:String):Bool { if (difficultyList == null) { difficultyList = ['easy', 'normal', 'hard']; } + + if (variation == null) variation = ''; + for (difficulty in difficultyList) { + if (variation != '') difficulty = '${difficulty}-${variation}'; + var score:Null = getSongScore(songId, difficulty); if (score != null) { From d2e29879fe2acc6febfe0f335f655b741d630c34 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Wed, 2 Oct 2024 20:38:47 -0400 Subject: [PATCH 08/29] fix: `Song.getFirstValidVariation()` now properly takes into account multiple variations/difficulty input freeplay implement for NEW song stuff w/ assets submod save data crap and crud rank icon fixes for fixed pico menu --- assets | 2 +- source/funkin/play/song/Song.hx | 12 ++++++++-- source/funkin/save/Save.hx | 18 ++++++++++++--- source/funkin/ui/freeplay/FreeplayState.hx | 26 ++++++++++++++++------ 4 files changed, 45 insertions(+), 13 deletions(-) diff --git a/assets b/assets index b2404b6b1cb..7efad31cf80 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit b2404b6b1cba47da8eef4910f49985d54318186b +Subproject commit 7efad31cf80a42600375bf08b397786df5c1037c diff --git a/source/funkin/play/song/Song.hx b/source/funkin/play/song/Song.hx index 91e15829919..20d2f75a4c7 100644 --- a/source/funkin/play/song/Song.hx +++ b/source/funkin/play/song/Song.hx @@ -98,7 +98,7 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry + */ public function getFirstValidVariation(?diffId:String, ?currentCharacter:PlayableCharacter, ?possibleVariations:Array):Null { if (possibleVariations == null) { possibleVariations = getVariationsByCharacter(currentCharacter); } + if (diffId == null) diffId = listDifficulties(null, possibleVariations)[0]; for (variationId in possibleVariations) { - if (difficulties.exists('$variationId')) return variationId; + if (difficulties.get('$variationId')?.exists(diffId) ?? false) return variationId; } return null; diff --git a/source/funkin/save/Save.hx b/source/funkin/save/Save.hx index 73e7aa77ebd..47467cd4519 100644 --- a/source/funkin/save/Save.hx +++ b/source/funkin/save/Save.hx @@ -543,22 +543,34 @@ class Save * * @param songId The ID of the song. * @param difficultyId The difficulty to check. + * @param variation The variation to check. Defaults to empty string. Appended to difficulty with `-`, e.g. `easy-pico`. * @return A data structure containing score, judgement counts, and accuracy. Returns `null` if no score is saved. */ - public function getSongScore(songId:String, difficultyId:String = 'normal'):Null + public function getSongScore(songId:String, difficultyId:String = 'normal', ?variation:String):Null { var song = data.scores.songs.get(songId); + trace('Getting song score for $songId $difficultyId $variation'); if (song == null) { + trace('Could not find song data for $songId $difficultyId $variation'); song = []; data.scores.songs.set(songId, song); } + + // 'default' variations are left with no suffix ('easy', 'normal', 'hard'), + // along with 'erect' variations ('erect', 'nightmare') + // otherwise, we want to add a suffix of our current variation to get the save data. + if (variation != null && variation != '' && variation != 'default' && variation != 'erect') + { + difficultyId = '${difficultyId}-${variation}'; + } + return song.get(difficultyId); } - public function getSongRank(songId:String, difficultyId:String = 'normal'):Null + public function getSongRank(songId:String, difficultyId:String = 'normal', ?variation:String):Null { - return Scoring.calculateRank(getSongScore(songId, difficultyId)); + return Scoring.calculateRank(getSongScore(songId, difficultyId, variation)); } /** diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index 312c17713fb..b4e72ef4aab 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -1717,8 +1717,6 @@ class FreeplayState extends MusicBeatSubState } } - trace('CURRENT VARIATION OF SONG: ${currentVariation}'); - var daSong:Null = grpCapsules.members[curSelected].freeplayData; if (daSong != null) { @@ -1729,7 +1727,7 @@ class FreeplayState extends MusicBeatSubState return; } - var songScore:Null = Save.instance.getSongScore(daSong.data.id, currentDifficulty); + var songScore:Null = Save.instance.getSongScore(daSong.data.id, currentDifficulty, currentVariation); intendedScore = songScore?.score ?? 0; intendedCompletion = songScore == null ? 0.0 : ((songScore.tallies.sick + songScore.tallies.good) / songScore.tallies.totalNotes); rememberedDifficulty = currentDifficulty; @@ -2025,7 +2023,7 @@ class FreeplayState extends MusicBeatSubState var daSongCapsule:SongMenuItem = grpCapsules.members[curSelected]; if (daSongCapsule.freeplayData != null) { - var songScore:Null = Save.instance.getSongScore(daSongCapsule.freeplayData.data.id, currentDifficulty); + var songScore:Null = Save.instance.getSongScore(daSongCapsule.freeplayData.data.id, currentDifficulty, currentVariation); intendedScore = songScore?.score ?? 0; intendedCompletion = songScore == null ? 0.0 : ((songScore.tallies.sick + songScore.tallies.good) / songScore.tallies.totalNotes); rememberedSongId = daSongCapsule.freeplayData.data.id; @@ -2260,7 +2258,7 @@ class FreeplaySongData /** * Whether the player has seen/played this song before within freeplay */ - public var isNew:Bool = false; + public var isNew(get, never):Bool; /** * The default opponent for the song. @@ -2312,6 +2310,18 @@ class FreeplaySongData // this.isNew = song.isSongNew(suffixedDifficulty); } + function get_isNew():Bool + { + // We use a slightly different manner to get the new status of a song than the other getters here + // `isSongNew()` only takes a single variation, and it's data that isn't accessible via the Song data/metadata + // it's stored in the song .hxc script in a function that overrides `isSongNew()` + // and is only accessible with the correct valid variation inputs + + var variations:Array = data.getVariationsByCharacterId(FreeplayState.rememberedCharacterId); + var variation:String = data.getFirstValidVariation(FreeplayState.rememberedDifficulty, null, variations); + return data.isSongNew(FreeplayState.rememberedDifficulty, variation); + } + function get_songCharacter():String { var variations:Array = data.getVariationsByCharacterId(FreeplayState.rememberedCharacterId); @@ -2340,8 +2350,10 @@ class FreeplaySongData function get_scoringRank():Null { - // TODO: Properly get/migrate the save data from the suffixed difficulty version to our new unsuffixed version - return Save.instance.getSongRank(data.songName, FreeplayState.rememberedDifficulty); + var variations:Array = data.getVariationsByCharacterId(FreeplayState.rememberedCharacterId); + var variation:String = data.getFirstValidVariation(FreeplayState.rememberedDifficulty, null, variations); + + return Save.instance.getSongRank(data.id, FreeplayState.rememberedDifficulty, variation); } } From 165ad6015539a295e9eefdaef291c312e9566b26 Mon Sep 17 00:00:00 2001 From: Burgerballs <107233412+Burgerballs@users.noreply.github.com> Date: Fri, 4 Oct 2024 13:20:39 +0100 Subject: [PATCH 09/29] fix: center preloader 'fnf' and 'dsp' text so it doesn't clip anymore --- source/funkin/ui/transition/preload/FunkinPreloader.hx | 10 +++++----- source/funkin/util/WindowUtil.hx | 2 ++ 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/source/funkin/ui/transition/preload/FunkinPreloader.hx b/source/funkin/ui/transition/preload/FunkinPreloader.hx index 9d256958840..1b39a348271 100644 --- a/source/funkin/ui/transition/preload/FunkinPreloader.hx +++ b/source/funkin/ui/transition/preload/FunkinPreloader.hx @@ -250,18 +250,18 @@ class FunkinPreloader extends FlxBasePreloader dspText.selectable = false; dspText.textColor = 0x000000; dspText.width = this._width; - dspText.height = 20; + dspText.height = 30; dspText.text = 'DSP'; dspText.x = 10; - dspText.y = -5; + dspText.y = -7; box.addChild(dspText); fnfText.selectable = false; fnfText.textColor = 0x000000; fnfText.width = this._width; - fnfText.height = 20; - fnfText.x = 75; - fnfText.y = -5; + fnfText.height = 30; + fnfText.x = 78; + fnfText.y = -7; fnfText.text = 'FNF'; box.addChild(fnfText); diff --git a/source/funkin/util/WindowUtil.hx b/source/funkin/util/WindowUtil.hx index 1d573969702..b4e99f1cd50 100644 --- a/source/funkin/util/WindowUtil.hx +++ b/source/funkin/util/WindowUtil.hx @@ -105,11 +105,13 @@ class WindowUtil // FlxG.stage.focus is set to null by the debug console stuff, // so when that's in focus, we don't want to toggle fullscreen using F // (annoying when tying "FlxG" in console... lol) + #if FLX_DEBUG @:privateAccess if (FlxG.game.debugger.visible) { return; } + #end if (e.keyCode == key) { From 1fde59f999eac94eb10fc22094885de2f5310705 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 2 Oct 2024 01:57:04 -0400 Subject: [PATCH 10/29] fix: The dialog now shows up on the animation debugger view --- source/funkin/ui/debug/anim/DebugBoundingState.hx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/source/funkin/ui/debug/anim/DebugBoundingState.hx b/source/funkin/ui/debug/anim/DebugBoundingState.hx index 4573ffbc7f8..157d20aa1b0 100644 --- a/source/funkin/ui/debug/anim/DebugBoundingState.hx +++ b/source/funkin/ui/debug/anim/DebugBoundingState.hx @@ -109,9 +109,11 @@ class DebugBoundingState extends FlxState offsetEditorDialog.cameras = [hudCam]; add(offsetEditorDialog); + offsetEditorDialog.showDialog(false); - // Anchor to the right side by default - // offsetEditorDialog.x = FlxG.width - offsetEditorDialog.width; + // Anchor to the left side by default + offsetEditorDialog.x = 16; + offsetEditorDialog.y = 16; // sets the default camera back to FlxG.camera, since we set it to hudCamera for haxeui stuf FlxG.cameras.setDefaultDrawTarget(FlxG.camera, true); From 711e0a6b7547eb04113e9318dab900f01ad576a5 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Wed, 2 Oct 2024 01:57:25 -0400 Subject: [PATCH 11/29] fix: Main menu music doesn't cut out when switching states anymore. --- source/funkin/ui/freeplay/FreeplayState.hx | 4 +++- source/funkin/ui/mainmenu/MainMenuState.hx | 4 +++- source/funkin/ui/story/StoryMenuState.hx | 4 +++- source/funkin/ui/title/TitleState.hx | 1 + 4 files changed, 10 insertions(+), 3 deletions(-) diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index b4e72ef4aab..507c4475886 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -1646,7 +1646,9 @@ class FreeplayState extends MusicBeatSubState FunkinSound.playMusic('freakyMenu', { overrideExisting: true, - restartTrack: false + restartTrack: false, + // Continue playing this music between states, until a different music track gets played. + persist: true }); FlxG.sound.music.fadeIn(4.0, 0.0, 1.0); close(); diff --git a/source/funkin/ui/mainmenu/MainMenuState.hx b/source/funkin/ui/mainmenu/MainMenuState.hx index 685626cbac3..13a7c7395c2 100644 --- a/source/funkin/ui/mainmenu/MainMenuState.hx +++ b/source/funkin/ui/mainmenu/MainMenuState.hx @@ -183,7 +183,9 @@ class MainMenuState extends MusicBeatState FunkinSound.playMusic('freakyMenu', { overrideExisting: true, - restartTrack: false + restartTrack: false, + // Continue playing this music between states, until a different music track gets played. + persist: true }); } diff --git a/source/funkin/ui/story/StoryMenuState.hx b/source/funkin/ui/story/StoryMenuState.hx index 09af08b22ee..d5a3ce89234 100644 --- a/source/funkin/ui/story/StoryMenuState.hx +++ b/source/funkin/ui/story/StoryMenuState.hx @@ -242,7 +242,9 @@ class StoryMenuState extends MusicBeatState FunkinSound.playMusic('freakyMenu', { overrideExisting: true, - restartTrack: false + restartTrack: false, + // Continue playing this music between states, until a different music track gets played. + persist: true }); } diff --git a/source/funkin/ui/title/TitleState.hx b/source/funkin/ui/title/TitleState.hx index 1b28169367a..f9a0f7a0ca0 100644 --- a/source/funkin/ui/title/TitleState.hx +++ b/source/funkin/ui/title/TitleState.hx @@ -233,6 +233,7 @@ class TitleState extends MusicBeatState startingVolume: 0.0, overrideExisting: true, restartTrack: false, + // Continue playing this music between states, until a different music track gets played. persist: true }); // Fade from 0.0 to 1 over 4 seconds From 777978f5a544e1b7c89b47dcc365f734eb6d0df1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?amyspark-ng=20=E2=9C=A8?= <92493175+amyspark-ng@users.noreply.github.com> Date: Thu, 3 Oct 2024 11:52:19 -0500 Subject: [PATCH 12/29] fix: stopped allowing F1 to create more than one help dialog window in the Charting Editor --- source/funkin/ui/debug/charting/ChartEditorState.hx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source/funkin/ui/debug/charting/ChartEditorState.hx b/source/funkin/ui/debug/charting/ChartEditorState.hx index 8b646ddb650..3fb63a4f1eb 100644 --- a/source/funkin/ui/debug/charting/ChartEditorState.hx +++ b/source/funkin/ui/debug/charting/ChartEditorState.hx @@ -5654,7 +5654,9 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState function handleHelpKeybinds():Void { // F1 = Open Help - if (FlxG.keys.justPressed.F1) this.openUserGuideDialog(); + if (FlxG.keys.justPressed.F1 && !isHaxeUIDialogOpen) { + this.openUserGuideDialog(); + } } function handleQuickWatch():Void From ab5bda3ee573a6e03595ec6941e6de38df851889 Mon Sep 17 00:00:00 2001 From: Cameron Taylor Date: Tue, 1 Oct 2024 01:02:26 -0400 Subject: [PATCH 13/29] fix: Character Select cursor moves properly at lower framerates --- source/funkin/ui/charSelect/CharSelectSubState.hx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/funkin/ui/charSelect/CharSelectSubState.hx b/source/funkin/ui/charSelect/CharSelectSubState.hx index 83bf15e9d57..4eb975e8af1 100644 --- a/source/funkin/ui/charSelect/CharSelectSubState.hx +++ b/source/funkin/ui/charSelect/CharSelectSubState.hx @@ -885,8 +885,8 @@ class CharSelectSubState extends MusicBeatSubState cursorLocIntended.x += cursorOffsetX; cursorLocIntended.y += cursorOffsetY; - cursor.x = MathUtil.coolLerp(cursor.x, cursorLocIntended.x, lerpAmnt); - cursor.y = MathUtil.coolLerp(cursor.y, cursorLocIntended.y, lerpAmnt); + cursor.x = MathUtil.smoothLerp(cursor.x, cursorLocIntended.x, elapsed, 0.1); + cursor.y = MathUtil.smoothLerp(cursor.y, cursorLocIntended.y, elapsed, 0.1); cursorBlue.x = MathUtil.coolLerp(cursorBlue.x, cursor.x, lerpAmnt * 0.4); cursorBlue.y = MathUtil.coolLerp(cursorBlue.y, cursor.y, lerpAmnt * 0.4); From f52472a4767388b22cfbab0f5f7860f6e6762856 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Tue, 1 Oct 2024 13:24:56 -0400 Subject: [PATCH 14/29] fix: Exiting the chart editor doesn't crash the game anymore --- hmm.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/hmm.json b/hmm.json index 0c0c5571bf2..8ff572b30b9 100644 --- a/hmm.json +++ b/hmm.json @@ -63,14 +63,14 @@ "name": "haxeui-core", "type": "git", "dir": null, - "ref": "c9d96b168ea2a19274ad7c766ab1a34b57baa793", + "ref": "51c23588614397089a5ce182cddea729f0be6fa0", "url": "https://github.com/haxeui/haxeui-core" }, { "name": "haxeui-flixel", "type": "git", "dir": null, - "ref": "013b9d4e56bfe9a034e028a8d685f0b274cb73c4", + "ref": "da27e833947f32ef007ed11f523aa5524f5a5d54", "url": "https://github.com/haxeui/haxeui-flixel" }, { @@ -205,4 +205,4 @@ "url": "https://github.com/fponticelli/thx.semver" } ] -} \ No newline at end of file +} From bc8f50619350872b8fb9f336abc8739c1c45016b Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Tue, 1 Oct 2024 15:32:09 -0400 Subject: [PATCH 15/29] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 68f07d35d00..0d727b223e1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [0.5.2] - 2024-10-?? ### Fixed +- Fixed an issue where exiting the Chart Editor would sometimes crash the game. - Fixed an issue where holding down a direction key then selecting a character would select the locked character and crash the game (community fix by ACrazyTown) - Fixed an issue where the player and girlfriend would disappear or overlap themselves in Character Select (community fix by gamerbross) - Fixed an issue where the game would show the wrong girlfriend in Character Select (community fix by gamerbross) From 3aa4591bab2c7c6c7a19e2ef5d3cc4ac694d7793 Mon Sep 17 00:00:00 2001 From: DaWaterMalone <128640339+DaWaterMalone@users.noreply.github.com> Date: Fri, 4 Oct 2024 12:53:40 -0500 Subject: [PATCH 16/29] Fixed Modded StrumlineNote Sprite Looping Animation Within the playStatic function on the StrumlineNote.hx, setting this.active = true; will fix looping animations for modded in StrumlineNote sprites. Leaving this.active = false; will stop any modded StrumlineNote sprite animation when the player or opponent hits chart notes. --- source/funkin/play/notes/StrumlineNote.hx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/funkin/play/notes/StrumlineNote.hx b/source/funkin/play/notes/StrumlineNote.hx index 16df9f5020b..f139d421ffb 100644 --- a/source/funkin/play/notes/StrumlineNote.hx +++ b/source/funkin/play/notes/StrumlineNote.hx @@ -103,7 +103,7 @@ class StrumlineNote extends FlxSprite public function playStatic():Void { - this.active = false; + this.active = true; this.playAnimation('static', true); } From de5cca1120d1d878bbbdc4cb348722ff7052815e Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Sat, 5 Oct 2024 13:32:58 -0400 Subject: [PATCH 17/29] Add some cutom logic to determine if this.active is needed. --- source/funkin/graphics/FunkinSprite.hx | 12 ++++++++++++ source/funkin/play/notes/StrumlineNote.hx | 12 +++++++++--- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/source/funkin/graphics/FunkinSprite.hx b/source/funkin/graphics/FunkinSprite.hx index 521553527ce..922310309ee 100644 --- a/source/funkin/graphics/FunkinSprite.hx +++ b/source/funkin/graphics/FunkinSprite.hx @@ -238,6 +238,18 @@ class FunkinSprite extends FlxSprite return true; } + /** + * @param id The animation ID to check. + * @return Whether the animation is dynamic (has multiple frames). `false` for static, one-frame animations. + */ + public function isAnimationDynamic(id:String):Bool + { + if (this.animation == null) return false; + var animData = this.animation.getByName(id); + if (animData == null) return false; + return animData.numFrames > 1; + } + /** * Acts similarly to `makeGraphic`, but with improved memory usage, * at the expense of not being able to paint onto the resulting sprite. diff --git a/source/funkin/play/notes/StrumlineNote.hx b/source/funkin/play/notes/StrumlineNote.hx index f139d421ffb..fedd71ae8fa 100644 --- a/source/funkin/play/notes/StrumlineNote.hx +++ b/source/funkin/play/notes/StrumlineNote.hx @@ -24,6 +24,12 @@ class StrumlineNote extends FlxSprite return this.direction; } + /** + * Set this flag to `true` to disable performance optimizations that cause + * the Strumline note sprite to ignore `velocity` and `acceleration`. + */ + public var forceActive:Bool = false; + public function new(noteStyle:NoteStyle, isPlayer:Bool, direction:NoteDirection) { super(0, 0); @@ -103,19 +109,19 @@ class StrumlineNote extends FlxSprite public function playStatic():Void { - this.active = true; + this.active = (forceActive || isAnimationDynamic('static')); this.playAnimation('static', true); } public function playPress():Void { - this.active = true; + this.active = (forceActive || isAnimationDynamic('press')); this.playAnimation('press', true); } public function playConfirm():Void { - this.active = true; + this.active = (forceActive || isAnimationDynamic('confirm')); this.playAnimation('confirm', true); } From bc546e86aa77ffc795b3f079de5f590289a9c583 Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Sat, 5 Oct 2024 13:33:08 -0400 Subject: [PATCH 18/29] Clean up documentation in StrumlineNote --- source/funkin/play/notes/StrumlineNote.hx | 29 +++++++++++++++++------ 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/source/funkin/play/notes/StrumlineNote.hx b/source/funkin/play/notes/StrumlineNote.hx index fedd71ae8fa..ebe95e92006 100644 --- a/source/funkin/play/notes/StrumlineNote.hx +++ b/source/funkin/play/notes/StrumlineNote.hx @@ -2,22 +2,24 @@ package funkin.play.notes; import funkin.play.notes.notestyle.NoteStyle; import flixel.graphics.frames.FlxAtlasFrames; -import flixel.FlxSprite; +import funkin.graphics.FunkinSprite; import funkin.play.notes.NoteSprite; /** * The actual receptor that you see on screen. */ -class StrumlineNote extends FlxSprite +class StrumlineNote extends FunkinSprite { + /** + * Whether this strumline note is on the player's side or the opponent's side. + */ public var isPlayer(default, null):Bool; + /** + * The direction which this strumline note is facing. + */ public var direction(default, set):NoteDirection; - var confirmHoldTimer:Float = -1; - - static final CONFIRM_HOLD_TIME:Float = 0.1; - function set_direction(value:NoteDirection):NoteDirection { this.direction = value; @@ -30,6 +32,16 @@ class StrumlineNote extends FlxSprite */ public var forceActive:Bool = false; + /** + * How long to continue the hold note animation after a note is pressed. + */ + static final CONFIRM_HOLD_TIME:Float = 0.1; + + /** + * How long the hold note animation has been playing after a note is pressed. + */ + var confirmHoldTimer:Float = -1; + public function new(noteStyle:NoteStyle, isPlayer:Bool, direction:NoteDirection) { super(0, 0); @@ -47,7 +59,10 @@ class StrumlineNote extends FlxSprite this.active = true; } - function onAnimationFrame(name:String, frameNumber:Int, frameIndex:Int):Void {} + function onAnimationFrame(name:String, frameNumber:Int, frameIndex:Int):Void + { + // Do nothing. + } function onAnimationFinished(name:String):Void { From 0d60929f187864122b691fb2106f58d211adec18 Mon Sep 17 00:00:00 2001 From: Victor G <84867412+Cheemsandfriends@users.noreply.github.com> Date: Sat, 5 Oct 2024 21:24:24 +0200 Subject: [PATCH 19/29] Fix window not closing when specified --- source/funkin/ui/title/TitleState.hx | 2 +- source/funkin/util/logging/CrashHandler.hx | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/source/funkin/ui/title/TitleState.hx b/source/funkin/ui/title/TitleState.hx index f9a0f7a0ca0..839992eea72 100644 --- a/source/funkin/ui/title/TitleState.hx +++ b/source/funkin/ui/title/TitleState.hx @@ -271,7 +271,7 @@ class TitleState extends MusicBeatState #if desktop if (FlxG.keys.justPressed.ESCAPE) { - Sys.exit(0); + openfl.Lib.application.window.close(); } #end diff --git a/source/funkin/util/logging/CrashHandler.hx b/source/funkin/util/logging/CrashHandler.hx index 1b607ddfd6b..4ec578173ea 100644 --- a/source/funkin/util/logging/CrashHandler.hx +++ b/source/funkin/util/logging/CrashHandler.hx @@ -61,6 +61,12 @@ class CrashHandler { trace('Error while handling crash: ' + e); } + + #if sys + Sys.sleep(1); // wait a few moments of margin to process. + // Exit the game. Since it threw an error, we use a non-zero exit code. + openfl.Lib.application.window.close(); + #end } static function onCriticalError(message:String):Void @@ -83,8 +89,9 @@ class CrashHandler } #if sys + Sys.sleep(1); // wait a few moments of margin to process. // Exit the game. Since it threw an error, we use a non-zero exit code. - Sys.exit(1); + openfl.Lib.application.window.close(); #end } From 903b3fc59905a70802618a1cd67407722ea956ed Mon Sep 17 00:00:00 2001 From: Kolo <67389779+JustKolosaki@users.noreply.github.com> Date: Sat, 5 Oct 2024 10:29:26 +0200 Subject: [PATCH 20/29] fix: Don't restart the FreeplayState song preview when changing the difficulty within the same variation pulled from the wrong branch, oops! last update i hope wrong spellings im gonna kms --- source/funkin/ui/freeplay/FreeplayState.hx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index 507c4475886..351de6b977e 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -1689,6 +1689,7 @@ class FreeplayState extends MusicBeatSubState function changeDiff(change:Int = 0, force:Bool = false):Void { touchTimer = 0; + var previousVariation:String = currentVariation; // Available variations for current character. We get this since bf is usually `default` variation, and `pico` is `pico` // but sometimes pico can be the default variation (weekend 1 songs), and bf can be `bf` variation (darnell) @@ -1784,7 +1785,7 @@ class FreeplayState extends MusicBeatSubState } // Reset the song preview in case we changed variations (normal->erect etc) - playCurSongPreview(); + if (currentVariation != previousVariation) playCurSongPreview(); } // Set the album graphic and play the animation if relevant. From 3267c612587017298ab9f2e7d368331e9ac59285 Mon Sep 17 00:00:00 2001 From: Abnormal <86753001+AbnormalPoof@users.noreply.github.com> Date: Sun, 6 Oct 2024 18:25:04 -0500 Subject: [PATCH 21/29] blacklist one additional class --- source/funkin/modding/PolymodHandler.hx | 1 + 1 file changed, 1 insertion(+) diff --git a/source/funkin/modding/PolymodHandler.hx b/source/funkin/modding/PolymodHandler.hx index f3d9273b243..eb0e77fc552 100644 --- a/source/funkin/modding/PolymodHandler.hx +++ b/source/funkin/modding/PolymodHandler.hx @@ -288,6 +288,7 @@ class PolymodHandler Polymod.blacklistImport('openfl.utils.Assets'); Polymod.blacklistImport('openfl.Lib'); Polymod.blacklistImport('openfl.system.ApplicationDomain'); + Polymod.blacklistImport('funkin.util.FunkinTypeResolver'); // `openfl.desktop.NativeProcess` // Can load native processes on the host operating system. From 9695e791349cb8f72814d69e6bf9c34148296fce Mon Sep 17 00:00:00 2001 From: Hundrec Date: Fri, 4 Oct 2024 21:20:45 -0700 Subject: [PATCH 22/29] Label me Docs --- .github/labeler.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/labeler.yml b/.github/labeler.yml index e8250b4e775..9cf784f4ca6 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -1,11 +1,11 @@ -# Add Documentation tag to PR's changing markdown files, or anyhting in the docs folder +# Add Documentation tag to PR's changing markdown files, or anything in the docs folder Documentation: - changed-files: - any-glob-to-any-file: - docs/* - '**/*.md' -# Adds Haxe tag to PR's changing haxe code files +# Add Haxe tag to PR's changing haxe code files Haxe: - changed-files: - any-glob-to-any-file: '**/*.hx' From f6a5a9d8ce45ea3ec358df874f05053ad35734bd Mon Sep 17 00:00:00 2001 From: Hundrec Date: Fri, 4 Oct 2024 21:27:34 -0700 Subject: [PATCH 23/29] Wait now it should do it --- docs/COMPILING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/COMPILING.md b/docs/COMPILING.md index ce3d89e7b44..f2b59acbc31 100644 --- a/docs/COMPILING.md +++ b/docs/COMPILING.md @@ -34,7 +34,7 @@ There are several useful build flags you can add to a build to affect how it wor - `-DGITHUB_BUILD` will enable in-game debug functions (such as the ability to time travel in a song by pressing `PgUp`/`PgDn`), without enabling the other stuff - `-DFEATURE_POLYMOD_MODS` or `-DNO_FEATURE_POLYMOD_MODS` to forcibly enable or disable modding support. - `-DREDIRECT_ASSETS_FOLDER` or `-DNO_REDIRECT_ASSETS_FOLDER` to forcibly enable or disable asset redirection. - - This feature causes the game to load exported assets from the project's assets folder rather than the exported one. Great for fast iteration, but the game + - This feature causes the game to load exported assets from the project's assets folder rather than the exported one. Great for fast iteration, but the game _(finish this sentence Eric)_ - `-DFEATURE_DISCORD_RPC` or `-DNO_FEATURE_DISCORD_RPC` to forcibly enable or disable support for Discord Rich Presence. - `-DFEATURE_VIDEO_PLAYBACK` or `-DNO_FEATURE_VIDEO_PLAYBACK` to forcibly enable or disable video cutscene support. - `-DFEATURE_CHART_EDITOR` or `-DNO_FEATURE_CHART_EDITOR` to forcibly enable or disable the chart editor in the Debug menu. From 5d10bb9f5489f1e693a113880fd31ab2042e3765 Mon Sep 17 00:00:00 2001 From: Hundrec Date: Fri, 4 Oct 2024 21:56:49 -0700 Subject: [PATCH 24/29] Rename troubleshooting.md to fix link in COMPILING.md --- docs/{troubleshooting.md => TROUBLESHOOTING.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename docs/{troubleshooting.md => TROUBLESHOOTING.md} (100%) diff --git a/docs/troubleshooting.md b/docs/TROUBLESHOOTING.md similarity index 100% rename from docs/troubleshooting.md rename to docs/TROUBLESHOOTING.md From 6848815e801e15064e4dfd9d3817a32eeae2f41a Mon Sep 17 00:00:00 2001 From: Hundrec Date: Fri, 4 Oct 2024 22:03:33 -0700 Subject: [PATCH 25/29] Adjust line count labeler comment --- .github/changed-lines-count-labeler.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/changed-lines-count-labeler.yml b/.github/changed-lines-count-labeler.yml index 6f890f53426..1de00e62f8f 100644 --- a/.github/changed-lines-count-labeler.yml +++ b/.github/changed-lines-count-labeler.yml @@ -7,6 +7,6 @@ medium: min: 10 max: 99 -# Add 'large' to any changes for more than 100 lines +# Add 'large' to any changes of at least 100 lines large: min: 100 From 7d5d80d515715501f8d2178539addfa16962bfba Mon Sep 17 00:00:00 2001 From: Hundrec Date: Fri, 4 Oct 2024 22:13:02 -0700 Subject: [PATCH 26/29] Fix typos in CODESTYLE.md --- CODESTYLE.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CODESTYLE.md b/CODESTYLE.md index 2641febfa80..2b6333258ad 100644 --- a/CODESTYLE.md +++ b/CODESTYLE.md @@ -4,14 +4,14 @@ Code style is enforced using Visual Studio Code extensions. ## .hx Formatting is handled by the `nadako.vshaxe` extension, which includes Haxe Formatter. -Haxe Formatter automatically resolves issues such as intentation style and line breaks, and can be configured in `hxformat.json`. +Haxe Formatter automatically resolves issues such as indentation style and line breaks, and can be configured in `hxformat.json`. Code Quality is handled by the `vshaxe.haxe-checkstyle` extension, which includes Haxe Checkstyle. ### Haxe Checkstyle Notes -* Checks can be escalated to display as different serverities in the Problems window. +* Checks can be escalated to display as different severities in the Problems window. * Checks can be disabled by setting the severity to `IGNORE`. -* `IndentationCharacter` checks what is used to indent, `Indentation` checks how deep the intentation is. +* `IndentationCharacter` checks what is used to indent, `Indentation` checks how deep the indentation is. * `CommentedOutCode` check is in place because old code should be retrieved via Git history. * TODO items: Enable these one-by-one and fix them to improve the overall code quality. - Reconfigure `MethodLength` From 880615e707accf8a5ce8a2b7fcf128c1fb0222c8 Mon Sep 17 00:00:00 2001 From: Hundrec Date: Fri, 4 Oct 2024 22:54:28 -0700 Subject: [PATCH 27/29] Remove extra asterisks in Funkin' Debug Hotkeys.md Those stars might have been indicators for something, but I don't see any note related to them. --- docs/Funkin' Debug Hotkeys.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/Funkin' Debug Hotkeys.md b/docs/Funkin' Debug Hotkeys.md index 1287d5a1bf5..416c897141f 100644 --- a/docs/Funkin' Debug Hotkeys.md +++ b/docs/Funkin' Debug Hotkeys.md @@ -15,8 +15,8 @@ Most of this functionality is only available on debug builds of the game! - `2`: ***GAIN HEALTH***: Debug function, add 10% to the player's health. - `3`: ***LOSE HEALTH***: Debug function, subtract 5% to the player's health. - `9`: NEATO! -- `PAGEUP` (MacOS: `Fn-Up`): ***FORWARDS TIME TRAVEL****: Move forward by 2 sections. Hold SHIFT to move forward by 20 sections instead. -- `PAGEDOWN` (MacOS: `Fn-Down`): ***BACKWARDS TIME TRAVEL****: Move backward by 2 sections. Hold SHIFT to move backward by 20 sections instead. +- `PAGEUP` (MacOS: `Fn-Up`): ***FORWARDS TIME TRAVEL***: Move forward by 2 sections. Hold SHIFT to move forward by 20 sections instead. +- `PAGEDOWN` (MacOS: `Fn-Down`): ***BACKWARDS TIME TRAVEL***: Move backward by 2 sections. Hold SHIFT to move backward by 20 sections instead. ## **Freeplay State** - `F` (Freeplay Menu) - Move to Favorites @@ -27,5 +27,5 @@ Most of this functionality is only available on debug builds of the game! - `Y` - WOAH ## **Main Menu** -- `~`: ***DEBUG****: Opens a menu to access the Chart Editor and other work-in-progress editors. Rebindable in the options menu. +- `~`: ***DEBUG***: Opens a menu to access the Chart Editor and other work-in-progress editors. Rebindable in the options menu. - `CTRL-ALT-SHIFT-W`: ***ALL ACCESS***: Unlocks all songs in Freeplay. Only available on debug builds. From 31d1b3e2464120c2608995e968357ef85c004535 Mon Sep 17 00:00:00 2001 From: Eric Date: Tue, 8 Oct 2024 14:12:55 -0400 Subject: [PATCH 28/29] Finish the sentence. --- docs/COMPILING.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/COMPILING.md b/docs/COMPILING.md index f2b59acbc31..6df1232b177 100644 --- a/docs/COMPILING.md +++ b/docs/COMPILING.md @@ -34,10 +34,11 @@ There are several useful build flags you can add to a build to affect how it wor - `-DGITHUB_BUILD` will enable in-game debug functions (such as the ability to time travel in a song by pressing `PgUp`/`PgDn`), without enabling the other stuff - `-DFEATURE_POLYMOD_MODS` or `-DNO_FEATURE_POLYMOD_MODS` to forcibly enable or disable modding support. - `-DREDIRECT_ASSETS_FOLDER` or `-DNO_REDIRECT_ASSETS_FOLDER` to forcibly enable or disable asset redirection. - - This feature causes the game to load exported assets from the project's assets folder rather than the exported one. Great for fast iteration, but the game _(finish this sentence Eric)_ + - This feature causes the game to load exported assets from the project's assets folder rather than the exported one. Great for fast iteration, but the game will break if you try to zip it up and send it to someone, so it's disabled for release builds. - `-DFEATURE_DISCORD_RPC` or `-DNO_FEATURE_DISCORD_RPC` to forcibly enable or disable support for Discord Rich Presence. - `-DFEATURE_VIDEO_PLAYBACK` or `-DNO_FEATURE_VIDEO_PLAYBACK` to forcibly enable or disable video cutscene support. - `-DFEATURE_CHART_EDITOR` or `-DNO_FEATURE_CHART_EDITOR` to forcibly enable or disable the chart editor in the Debug menu. +- `-DFEATURE_SCREENSHOTS` or `-DNO_FEATURE_SCREENSHOTS` to forcibly enable or disable the screenshots feature. - `-DFEATURE_STAGE_EDITOR` to forcibly enable the experimental stage editor. - `-DFEATURE_GHOST_TAPPING` to forcibly enable an experimental gameplay change to the anti-mash system. From e66290c55f7141402223644f06ec8a69edeee089 Mon Sep 17 00:00:00 2001 From: Kn1ghtNight Date: Tue, 18 Jun 2024 18:25:00 -0400 Subject: [PATCH 29/29] fix: anti alias / smooth the volume sound tray --- source/funkin/ui/options/FunkinSoundTray.hx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/source/funkin/ui/options/FunkinSoundTray.hx b/source/funkin/ui/options/FunkinSoundTray.hx index b2fb7fc0443..5a5bf1d6cc1 100644 --- a/source/funkin/ui/options/FunkinSoundTray.hx +++ b/source/funkin/ui/options/FunkinSoundTray.hx @@ -33,6 +33,7 @@ class FunkinSoundTray extends FlxSoundTray var bg:Bitmap = new Bitmap(Assets.getBitmapData(Paths.image("soundtray/volumebox"))); bg.scaleX = graphicScale; bg.scaleY = graphicScale; + bg.smoothing = true; addChild(bg); y = -height; @@ -44,6 +45,7 @@ class FunkinSoundTray extends FlxSoundTray backingBar.y = 5; backingBar.scaleX = graphicScale; backingBar.scaleY = graphicScale; + backingBar.smoothing = true; addChild(backingBar); backingBar.alpha = 0.4; @@ -60,6 +62,7 @@ class FunkinSoundTray extends FlxSoundTray bar.y = 5; bar.scaleX = graphicScale; bar.scaleY = graphicScale; + bar.smoothing = true; addChild(bar); _bars.push(bar); }