diff --git a/assets b/assets index 927578f48..fd112e293 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 927578f482b23dc4511fd8203560d631442d91a8 +Subproject commit fd112e293ee0f823ee98d5b8bd8a85e934f772f6 diff --git a/source/funkin/play/song/Song.hx b/source/funkin/play/song/Song.hx index e71ae3213..23d8d2198 100644 --- a/source/funkin/play/song/Song.hx +++ b/source/funkin/play/song/Song.hx @@ -399,6 +399,27 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry<SongMeta return null; } + /** + * Given that this character is selected in the Freeplay menu, + * which variations should be available? + * @param charId The character ID to query. + * @return An array of available variations. + */ + public function getVariationsByCharId(?charId:String):Array<String> + { + if (charId == null) charId = Constants.DEFAULT_CHARACTER; + + if (variations.contains(charId)) + { + return [charId]; + } + else + { + // TODO: How to exclude character variations while keeping other custom variations? + return variations; + } + } + /** * List all the difficulties in this song. * diff --git a/source/funkin/ui/freeplay/AlbumRoll.hx b/source/funkin/ui/freeplay/AlbumRoll.hx index 35facf131..50f4a432c 100644 --- a/source/funkin/ui/freeplay/AlbumRoll.hx +++ b/source/funkin/ui/freeplay/AlbumRoll.hx @@ -38,7 +38,7 @@ class AlbumRoll extends FlxSpriteGroup var newAlbumArt:FlxAtlasSprite; - // var difficultyStars:DifficultyStars; + var difficultyStars:DifficultyStars; var _exitMovers:Null<FreeplayState.ExitMoverData>; var albumData:Album; @@ -65,9 +65,9 @@ class AlbumRoll extends FlxSpriteGroup add(newAlbumArt); - // difficultyStars = new DifficultyStars(140, 39); - // difficultyStars.stars.visible = false; - // add(difficultyStars); + difficultyStars = new DifficultyStars(140, 39); + difficultyStars.stars.visible = false; + add(difficultyStars); } function onAlbumFinish(animName:String):Void @@ -86,9 +86,14 @@ class AlbumRoll extends FlxSpriteGroup { if (albumId == null) { - // difficultyStars.stars.visible = false; + this.visible = false; + difficultyStars.stars.visible = false; return; } + else + { + this.visible = true; + } albumData = AlbumRegistry.instance.fetchEntry(albumId); @@ -144,10 +149,10 @@ class AlbumRoll extends FlxSpriteGroup newAlbumArt.visible = true; newAlbumArt.playAnimation(animNames.get('$albumId-active'), false, false, false); - // difficultyStars.stars.visible = false; + difficultyStars.stars.visible = false; new FlxTimer().start(0.75, function(_) { // showTitle(); - // showStars(); + showStars(); }); } @@ -156,16 +161,17 @@ class AlbumRoll extends FlxSpriteGroup newAlbumArt.playAnimation(animNames.get('$albumId-trans'), false, false, false); } - // public function setDifficultyStars(?difficulty:Int):Void - // { - // if (difficulty == null) return; - // difficultyStars.difficulty = difficulty; - // } - // /** - // * Make the album stars visible. - // */ - // public function showStars():Void - // { - // difficultyStars.stars.visible = false; // true; - // } + public function setDifficultyStars(?difficulty:Int):Void + { + if (difficulty == null) return; + difficultyStars.difficulty = difficulty; + } + + /** + * Make the album stars visible. + */ + public function showStars():Void + { + difficultyStars.stars.visible = true; // true; + } } diff --git a/source/funkin/ui/freeplay/DifficultyStars.hx b/source/funkin/ui/freeplay/DifficultyStars.hx new file mode 100644 index 000000000..51526bcbe --- /dev/null +++ b/source/funkin/ui/freeplay/DifficultyStars.hx @@ -0,0 +1,106 @@ +package funkin.ui.freeplay; + +import flixel.group.FlxSpriteGroup; +import funkin.graphics.adobeanimate.FlxAtlasSprite; +import funkin.graphics.shaders.HSVShader; + +class DifficultyStars extends FlxSpriteGroup +{ + /** + * Internal handler var for difficulty... ranges from 0... to 15 + * 0 is 1 star... 15 is 0 stars! + */ + var curDifficulty(default, set):Int = 0; + + /** + * Range between 0 and 15 + */ + public var difficulty(default, set):Int = 1; + + public var stars:FlxAtlasSprite; + + var flames:FreeplayFlames; + + var hsvShader:HSVShader; + + public function new(x:Float, y:Float) + { + super(x, y); + + hsvShader = new HSVShader(); + + flames = new FreeplayFlames(0, 0); + add(flames); + + stars = new FlxAtlasSprite(0, 0, Paths.animateAtlas("freeplay/freeplayStars")); + stars.anim.play("diff stars"); + add(stars); + + stars.shader = hsvShader; + + for (memb in flames.members) + memb.shader = hsvShader; + } + + override function update(elapsed:Float):Void + { + super.update(elapsed); + + // "loops" the current animation + // for clarity, the animation file looks like + // frame : stars + // 0-99: 1 star + // 100-199: 2 stars + // ...... + // 1300-1499: 15 stars + // 1500 : 0 stars + if (curDifficulty < 15 && stars.anim.curFrame >= (curDifficulty + 1) * 100) + { + stars.anim.play("diff stars", true, false, curDifficulty * 100); + } + } + + function set_difficulty(value:Int):Int + { + difficulty = value; + + if (difficulty <= 0) + { + difficulty = 0; + curDifficulty = 15; + } + else if (difficulty <= 15) + { + difficulty = value; + curDifficulty = difficulty - 1; + } + else + { + difficulty = 15; + curDifficulty = difficulty - 1; + } + + if (difficulty > 10) flames.flameCount = difficulty - 10; + else + flames.flameCount = 0; + + return difficulty; + } + + function set_curDifficulty(value:Int):Int + { + curDifficulty = value; + if (curDifficulty == 15) + { + stars.anim.play("diff stars", true, false, 1500); + stars.anim.pause(); + } + else + { + stars.anim.curFrame = Std.int(curDifficulty * 100); + stars.anim.play("diff stars", true, false, curDifficulty * 100); + } + + return curDifficulty; + } +} diff --git a/source/funkin/ui/freeplay/FreeplayFlames.hx b/source/funkin/ui/freeplay/FreeplayFlames.hx index c20d85898..f6b6f5c3d 100644 --- a/source/funkin/ui/freeplay/FreeplayFlames.hx +++ b/source/funkin/ui/freeplay/FreeplayFlames.hx @@ -50,8 +50,19 @@ class FreeplayFlames extends FlxSpriteGroup } } + var timers:Array<FlxTimer> = []; + function set_flameCount(value:Int):Int { + // Stop all existing timers. + // This fixes a bug where quickly switching difficulties would show flames. + for (timer in timers) + { + timer.active = false; + timer.destroy(); + timers.remove(timer); + } + this.flameCount = value; var visibleCount:Int = 0; for (i in 0...5) @@ -62,10 +73,18 @@ class FreeplayFlames extends FlxSpriteGroup { if (!flame.visible) { - new FlxTimer().start(flameTimer * visibleCount, function(_) { + var nextTimer:FlxTimer = new FlxTimer().start(flameTimer * visibleCount, function(currentTimer:FlxTimer) { + if (i >= this.flameCount) + { + trace('EARLY EXIT'); + return; + } + timers.remove(currentTimer); flame.animation.play("flame", true); flame.visible = true; }); + timers.push(nextTimer); + visibleCount++; } } diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index 7b7543845..239068288 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -120,8 +120,6 @@ class FreeplayState extends MusicBeatSubState var curCapsule:SongMenuItem; var curPlaying:Bool = false; - var displayedVariations:Array<String>; - var dj:DJBoyfriend; var ostName:FlxText; @@ -184,10 +182,6 @@ class FreeplayState extends MusicBeatSubState // Add a null entry that represents the RANDOM option songs.push(null); - // TODO: This makes custom variations disappear from Freeplay. Figure out a better solution later. - // Default character (BF) shows default and Erect variations. Pico shows only Pico variations. - displayedVariations = (currentCharacter == 'bf') ? [Constants.DEFAULT_VARIATION, 'erect'] : [currentCharacter]; - // programmatically adds the songs via LevelRegistry and SongRegistry for (levelId in LevelRegistry.instance.listSortedLevelIds()) { @@ -195,7 +189,8 @@ class FreeplayState extends MusicBeatSubState { var song:Song = SongRegistry.instance.fetchEntry(songId); - // Only display songs which actually have available charts for the current character. + // Only display songs which actually have available difficulties for the current character. + var displayedVariations = song.getVariationsByCharId(currentCharacter); var availableDifficultiesForSong:Array<String> = song.listDifficulties(displayedVariations, false); if (availableDifficultiesForSong.length == 0) continue; @@ -488,10 +483,6 @@ class FreeplayState extends MusicBeatSubState albumRoll.playIntro(); - new FlxTimer().start(0.75, function(_) { - // albumRoll.showTitle(); - }); - FlxTween.tween(grpDifficulties, {x: 90}, 0.6, {ease: FlxEase.quartOut}); diffSelLeft.visible = true; @@ -1072,6 +1063,9 @@ class FreeplayState extends MusicBeatSubState albumRoll.albumId = newAlbumId; albumRoll.skipIntro(); } + + // Set difficulty star count. + albumRoll.setDifficultyStars(daSong?.difficultyRating); } // Clears the cache of songs, frees up memory, they' ll have to be loaded in later tho function clearDaCache(actualSongTho:String) @@ -1383,11 +1377,12 @@ class FreeplaySongData public var songName(default, null):String = ''; public var songCharacter(default, null):String = ''; - public var songRating(default, null):Int = 0; + public var difficultyRating(default, null):Int = 0; public var albumId(default, null):Null<String> = null; public var currentDifficulty(default, set):String = Constants.DEFAULT_DIFFICULTY; - public var displayedVariations(default, null):Array<String> = [Constants.DEFAULT_VARIATION]; + + var displayedVariations:Array<String> = [Constants.DEFAULT_VARIATION]; function set_currentDifficulty(value:String):String { @@ -1417,7 +1412,7 @@ class FreeplaySongData if (songDifficulty == null) return; this.songName = songDifficulty.songName; this.songCharacter = songDifficulty.characters.opponent; - this.songRating = songDifficulty.difficultyRating; + this.difficultyRating = songDifficulty.difficultyRating; if (songDifficulty.album == null) { FlxG.log.warn('No album for: ${songDifficulty.songName}'); diff --git a/source/funkin/ui/freeplay/SongMenuItem.hx b/source/funkin/ui/freeplay/SongMenuItem.hx index f6d85e56e..cf9b52482 100644 --- a/source/funkin/ui/freeplay/SongMenuItem.hx +++ b/source/funkin/ui/freeplay/SongMenuItem.hx @@ -168,7 +168,7 @@ class SongMenuItem extends FlxSpriteGroup songText.text = songData?.songName ?? 'Random'; // Update capsule character. if (songData?.songCharacter != null) setCharacter(songData.songCharacter); - updateDifficultyRating(songData?.songRating ?? 0); + updateDifficultyRating(songData?.difficultyRating ?? 0); // Update opacity, offsets, etc. updateSelected(); }