From 462eece09a2a30d495e038264ea0b39d6a3a997f Mon Sep 17 00:00:00 2001 From: EliteMasterEric Date: Thu, 11 Jan 2024 00:30:00 -0500 Subject: [PATCH] Use proper difficulty rating data, proper clear percentage --- source/funkin/play/song/Song.hx | 6 + source/funkin/ui/AtlasText.hx | 1 + source/funkin/ui/freeplay/FreeplayState.hx | 144 +++++++++++++++++---- source/funkin/ui/freeplay/SongMenuItem.hx | 46 ++++--- 4 files changed, 150 insertions(+), 47 deletions(-) diff --git a/source/funkin/play/song/Song.hx b/source/funkin/play/song/Song.hx index 9e5de6143..cde068f42 100644 --- a/source/funkin/play/song/Song.hx +++ b/source/funkin/play/song/Song.hx @@ -176,6 +176,9 @@ class Song implements IPlayStateScriptedClass implements IRegistryEntry = null; + public function new(song:Song, diffId:String, variation:String) { this.song = song; diff --git a/source/funkin/ui/AtlasText.hx b/source/funkin/ui/AtlasText.hx index fea09de54..186d87c2a 100644 --- a/source/funkin/ui/AtlasText.hx +++ b/source/funkin/ui/AtlasText.hx @@ -274,4 +274,5 @@ enum abstract AtlasFont(String) from String to String { var DEFAULT = "default"; var BOLD = "bold"; + var FREEPLAY_CLEAR = "freeplay-clear"; } diff --git a/source/funkin/ui/freeplay/FreeplayState.hx b/source/funkin/ui/freeplay/FreeplayState.hx index f17c3d91e..cfe7f802a 100644 --- a/source/funkin/ui/freeplay/FreeplayState.hx +++ b/source/funkin/ui/freeplay/FreeplayState.hx @@ -1,6 +1,5 @@ package funkin.ui.freeplay; -import funkin.input.Controls; import flash.text.TextField; import flixel.addons.display.FlxGridOverlay; import flixel.addons.transition.FlxTransitionableState; @@ -23,33 +22,35 @@ import flixel.tweens.FlxTween; import flixel.util.FlxColor; import flixel.util.FlxSpriteUtil; import flixel.util.FlxTimer; -import funkin.input.Controls.Control; import funkin.data.level.LevelRegistry; import funkin.data.song.SongRegistry; import funkin.graphics.adobeanimate.FlxAtlasSprite; import funkin.graphics.shaders.AngleMask; import funkin.graphics.shaders.HSVShader; import funkin.graphics.shaders.PureColor; -import funkin.util.MathUtil; import funkin.graphics.shaders.StrokeShader; +import funkin.input.Controls; +import funkin.input.Controls.Control; import funkin.play.components.HealthIcon; import funkin.play.PlayState; import funkin.play.PlayStatePlaylist; import funkin.play.song.Song; import funkin.save.Save; import funkin.save.Save.SaveScoreData; +import funkin.ui.AtlasText; import funkin.ui.freeplay.BGScrollingText; import funkin.ui.freeplay.DifficultyStars; import funkin.ui.freeplay.DJBoyfriend; import funkin.ui.freeplay.FreeplayScore; import funkin.ui.freeplay.LetterSort; import funkin.ui.freeplay.SongMenuItem; +import funkin.ui.mainmenu.MainMenuState; import funkin.ui.MusicBeatState; import funkin.ui.MusicBeatSubState; -import funkin.ui.mainmenu.MainMenuState; import funkin.ui.transition.LoadingState; import funkin.ui.transition.StickerSubState; import funkin.util.MathUtil; +import funkin.util.MathUtil; import lime.app.Future; import lime.utils.Assets; @@ -64,7 +65,7 @@ class FreeplayState extends MusicBeatSubState var currentDifficulty:String = Constants.DEFAULT_DIFFICULTY; var fp:FreeplayScore; - var txtCompletion:FlxText; + var txtCompletion:AtlasText; var lerpCompletion:Float = 0; var intendedCompletion:Float = 0; var lerpScore:Float = 0; @@ -87,6 +88,8 @@ class FreeplayState extends MusicBeatSubState var grpCapsules:FlxTypedGroup; var curCapsule:SongMenuItem; var curPlaying:Bool = false; + var ostName:FlxText; + var difficultyStars:DifficultyStars; var dj:DJBoyfriend; @@ -150,15 +153,10 @@ class FreeplayState extends MusicBeatSubState for (songId in LevelRegistry.instance.parseEntryData(levelId).songs) { var song:Song = SongRegistry.instance.fetchEntry(songId); - var songBaseDifficulty:SongDifficulty = song.getDifficulty(Constants.DEFAULT_DIFFICULTY); - var songName = songBaseDifficulty.songName; - var songOpponent = songBaseDifficulty.characters.opponent; - var songDifficulties = song.listDifficulties(); + songs.push(new FreeplaySongData(levelId, songId, song)); - songs.push(new FreeplaySongData(songId, songName, levelId, songOpponent, songDifficulties)); - - for (difficulty in songDifficulties) + for (difficulty in song.listDifficulties()) { diffIdsTotal.pushUnique(difficulty); } @@ -334,6 +332,8 @@ class FreeplayState extends MusicBeatSubState if (diffSprite.difficultyId == currentDifficulty) diffSprite.visible = true; } + // NOTE: This is an AtlasSprite because we use an animation to bring it into view. + // TODO: Add the ability to select the album graphic. var albumArt:FlxAtlasSprite = new FlxAtlasSprite(640, 360, Paths.animateAtlas("freeplay/albumRoll")); albumArt.visible = false; add(albumArt); @@ -347,7 +347,7 @@ class FreeplayState extends MusicBeatSubState var albumTitle:FlxSprite = new FlxSprite(947, 491).loadGraphic(Paths.image('freeplay/albumTitle-fnfvol1')); var albumArtist:FlxSprite = new FlxSprite(1010, 607).loadGraphic(Paths.image('freeplay/albumArtist-kawaisprite')); - var difficultyStars:DifficultyStars = new DifficultyStars(140, 39); + difficultyStars = new DifficultyStars(140, 39); difficultyStars.stars.visible = false; albumTitle.visible = false; @@ -382,10 +382,15 @@ class FreeplayState extends MusicBeatSubState add(overhangStuff); FlxTween.tween(overhangStuff, {y: 0}, 0.3, {ease: FlxEase.quartOut}); - var fnfFreeplay:FlxText = new FlxText(0, 12, 0, "FREEPLAY", 48); + var fnfFreeplay:FlxText = new FlxText(4, 10, 0, "FREEPLAY", 48); fnfFreeplay.font = "VCR OSD Mono"; fnfFreeplay.visible = false; + ostName = new FlxText(4, 10, FlxG.width - 4 - 4, "OFFICIAL OST", 48); + ostName.font = "VCR OSD Mono"; + ostName.alignment = RIGHT; + ostName.visible = false; + exitMovers.set([overhangStuff, fnfFreeplay], { y: -overhangStuff.height, @@ -398,7 +403,7 @@ class FreeplayState extends MusicBeatSubState fnfFreeplay.shader = sillyStroke; add(fnfFreeplay); - var fnfHighscoreSpr:FlxSprite = new FlxSprite(890, 70); + var fnfHighscoreSpr:FlxSprite = new FlxSprite(860, 70); fnfHighscoreSpr.frames = Paths.getSparrowAtlas('freeplay/highscore'); fnfHighscoreSpr.animation.addByPrefix("highscore", "highscore", 24, false); fnfHighscoreSpr.visible = false; @@ -415,8 +420,10 @@ class FreeplayState extends MusicBeatSubState fp.visible = false; add(fp); - txtCompletion = new FlxText(1200, 77, 0, "0", 32); - txtCompletion.font = "VCR OSD Mono"; + var clearBoxSprite:FlxSprite = new FlxSprite(1165, 65).loadGraphic(Paths.image('freeplay/clearBox')); + add(clearBoxSprite); + + txtCompletion = new AtlasText(1185, 87, "69", AtlasFont.FREEPLAY_CLEAR); txtCompletion.visible = false; add(txtCompletion); @@ -674,9 +681,32 @@ class FreeplayState extends MusicBeatSubState lerpScore = MathUtil.coolLerp(lerpScore, intendedScore, 0.2); lerpCompletion = MathUtil.coolLerp(lerpCompletion, intendedCompletion, 0.9); + if (Math.isNaN(lerpScore)) + { + lerpScore = intendedScore; + } + + if (Math.isNaN(lerpCompletion)) + { + lerpCompletion = intendedCompletion; + } + fp.updateScore(Std.int(lerpScore)); - txtCompletion.text = Math.floor(lerpCompletion * 100) + "%"; + txtCompletion.text = '${Math.floor(lerpCompletion * 100)}'; + + // Right align the completion percentage + switch (txtCompletion.text.length) + { + case 3: + txtCompletion.x = 1185 - 10; + case 2: + txtCompletion.x = 1185; + case 1: + txtCompletion.x = 1185 + 24; + default: + txtCompletion.x = 1185; + } handleInputs(elapsed); } @@ -913,6 +943,11 @@ class FreeplayState extends MusicBeatSubState intendedCompletion = 0.0; } + if (intendedCompletion == Math.POSITIVE_INFINITY || intendedCompletion == Math.NEGATIVE_INFINITY || Math.isNaN(intendedCompletion)) + { + intendedCompletion = 0; + } + grpDifficulties.group.forEach(function(diffSprite) { diffSprite.visible = false; }); @@ -938,6 +973,27 @@ class FreeplayState extends MusicBeatSubState } } } + + if (change != 0) + { + // Update the song capsules to reflect the new difficulty info. + for (songCapsule in grpCapsules.members) + { + if (songCapsule == null) continue; + if (songCapsule.songData != null) + { + songCapsule.songData.currentDifficulty = currentDifficulty; + songCapsule.init(null, null, songCapsule.songData); + } + else + { + songCapsule.init(null, null, null); + } + } + } + + // Set the difficulty star count on the right. + difficultyStars.difficulty = daSong.songRating; } // Clears the cache of songs, frees up memory, they' ll have to be loaded in later tho function clearDaCache(actualSongTho:String) @@ -1046,6 +1102,10 @@ class FreeplayState extends MusicBeatSubState { currentDifficulty = rememberedDifficulty; } + + // Set the difficulty star count on the right. + var daSong = songs[curSelected]; + difficultyStars.difficulty = daSong?.songRating ?? 0; } function changeSelection(change:Int = 0) @@ -1176,19 +1236,47 @@ class FreeplaySongData { public var isFav:Bool = false; - public var songId:String = ""; - public var songName:String = ""; - public var levelId:String = ""; - public var songCharacter:String = ""; - public var songDifficulties:Array = []; + var song:Song; - public function new(songId:String, songName:String, levelId:String, songCharacter:String, songDifficulties:Array) + public var levelId(default, null):String = ""; + public var songId(default, null):String = ""; + + public var songDifficulties(default, null):Array = []; + + public var songName(default, null):String = ""; + public var songCharacter(default, null):String = ""; + public var songRating(default, null):Int = 0; + + public var currentDifficulty(default, set):String = Constants.DEFAULT_DIFFICULTY; + + function set_currentDifficulty(value:String):String + { + if (currentDifficulty == value) return value; + + currentDifficulty = value; + updateValues(); + return value; + } + + public function new(levelId:String, songId:String, song:Song) { - this.songId = songId; - this.songName = songName; this.levelId = levelId; - this.songCharacter = songCharacter; - this.songDifficulties = songDifficulties; + this.songId = songId; + this.song = song; + + updateValues(); + } + + function updateValues():Void + { + this.songDifficulties = song.listDifficulties(); + if (!this.songDifficulties.contains(currentDifficulty)) currentDifficulty = Constants.DEFAULT_DIFFICULTY; + + var songDifficulty:SongDifficulty = song.getDifficulty(currentDifficulty); + if (songDifficulty == null) return; + this.songName = songDifficulty.songName; + this.songCharacter = songDifficulty.characters.opponent; + this.songRating = songDifficulty.difficultyRating; } } diff --git a/source/funkin/ui/freeplay/SongMenuItem.hx b/source/funkin/ui/freeplay/SongMenuItem.hx index 833187acb..88b6aef3c 100644 --- a/source/funkin/ui/freeplay/SongMenuItem.hx +++ b/source/funkin/ui/freeplay/SongMenuItem.hx @@ -35,11 +35,6 @@ class SongMenuItem extends FlxSpriteGroup var ranks:Array = ["fail", "average", "great", "excellent", "perfect"]; - // lol... - var diffRanks:Array = [ - "00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12", "14", "15" - ]; - public var targetPos:FlxPoint = new FlxPoint(); public var doLerp:Bool = false; public var doJumpIn:Bool = false; @@ -47,10 +42,12 @@ class SongMenuItem extends FlxSpriteGroup public var doJumpOut:Bool = false; public var onConfirm:Void->Void; - public var diffGrayscale:Grayscale; + public var grayscaleShader:Grayscale; public var hsvShader(default, set):HSVShader; + var diffRatingSprite:FlxSprite; + public function new(x:Float, y:Float) { super(x, y); @@ -75,26 +72,30 @@ class SongMenuItem extends FlxSpriteGroup add(ranking); grpHide.add(ranking); - diffGrayscale = new Grayscale(1); - - var diffRank = new FlxSprite(145, 90).loadGraphic(Paths.image("freeplay/diffRankings/diff" + FlxG.random.getObject(diffRanks))); - diffRank.shader = diffGrayscale; - diffRank.visible = false; - add(diffRank); - diffRank.origin.set(capsule.origin.x - diffRank.x, capsule.origin.y - diffRank.y); - grpHide.add(diffRank); - switch (rank) { case "perfect": ranking.x -= 10; } + grayscaleShader = new Grayscale(1); + + diffRatingSprite = new FlxSprite(145, 90).loadGraphic(Paths.image("freeplay/diffRatings/diff00")); + diffRatingSprite.shader = grayscaleShader; + diffRatingSprite.visible = false; + add(diffRatingSprite); + diffRatingSprite.origin.set(capsule.origin.x - diffRatingSprite.x, capsule.origin.y - diffRatingSprite.y); + grpHide.add(diffRatingSprite); + songText = new CapsuleText(capsule.width * 0.26, 45, 'Random', Std.int(40 * realScaled)); add(songText); grpHide.add(songText); + // TODO: Use value from metadata instead of random. + updateDifficultyRating(FlxG.random.int(0, 15)); + pixelIcon = new FlxSprite(160, 35); + pixelIcon.makeGraphic(32, 32, 0x00000000); pixelIcon.antialiasing = false; pixelIcon.active = false; @@ -113,6 +114,12 @@ class SongMenuItem extends FlxSpriteGroup setVisibleGrp(false); } + function updateDifficultyRating(newRating:Int) + { + var ratingPadded:String = newRating < 10 ? '0$newRating' : '$newRating'; + diffRatingSprite.loadGraphic(Paths.image('freeplay/diffRatings/diff${ratingPadded}')); + } + function set_hsvShader(value:HSVShader):HSVShader { this.hsvShader = value; @@ -149,16 +156,17 @@ class SongMenuItem extends FlxSpriteGroup updateSelected(); } - public function init(x:Float, y:Float, songData:Null) + public function init(?x:Float, ?y:Float, songData:Null) { - this.x = x; - this.y = y; + if (x != null) this.x = x; + if (y != null) this.y = y; this.songData = songData; // Update capsule text. songText.text = songData?.songName ?? 'Random'; // Update capsule character. if (songData?.songCharacter != null) setCharacter(songData.songCharacter); + updateDifficultyRating(songData?.songRating ?? 0); // Update opacity, offsets, etc. updateSelected(); } @@ -336,7 +344,7 @@ class SongMenuItem extends FlxSpriteGroup function updateSelected():Void { - diffGrayscale.setAmount(this.selected ? 0 : 0.8); + grayscaleShader.setAmount(this.selected ? 0 : 0.8); songText.alpha = this.selected ? 1 : 0.6; songText.blurredText.visible = this.selected ? true : false; capsule.offset.x = this.selected ? 0 : -5;